编译器

1. 构建 VariateType

public enum VariateType {
    /**
     * <p>Variate type, include <type>STRING</type>, <type>NUMERIC</type>,
     * <type>ARRAY</type>, <type>BOOLEAN</type>, <type>FUNCTION</type>,
     * <type>SYMBOL</type>, <type>SYMBOL</type> and <type>ORIGINAL</type>.</p>
     */
    STRING, NUMERIC, FUNCTION, SYMBOL, BOOLEAN, ORIGINAL, ARRAY, ERROR, STREAM,
}

2. 构建 Variate

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import com.neusoft.rsapm.brain.common.exception.CompilerException;
import com.neusoft.rsapm.brain.common.util.Util;
import lombok.Getter;
import lombok.ToString;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.neusoft.rsapm.compile.VariateType.*;

/**
 * @author Muxin Sun
 * @date 2019/05/20
 */
@Getter
@ToString
public class Variate {

    /**
     * @date 2019/05/20
     * <p>Supported operators, sort operational character by priority level. <char>'</char> is max level,
     *   Note: <char>=</char> is not mutator method.</p>
     */

    public static final String LEFT_PARENTHESIS = "(";
    public static final String RIGHT_PARENTHESIS = ")";
    public static final String GREATER_THAN = ">";
    public static final String LESS_THAN = "<";
    public static final String EQUAL = "=";
    public static final String PLUS = "+";
    public static final String MINUS = "-";
    public static final String COMMA = ",";
    public static final String TIMES = "*";
    public static final String DIVISION = "/";
    public static final String DOT = ".";

    public static final String QUERY = "#";
    public static final String GREATER_EQUAL = ">=";
    public static final String LESS_EQUAL = "<=";

    public static final String OR = " or ";
    public static final String AND = " and ";

    public static final Variate LEFT_PARENTHESIS_VARIATE = build(SYMBOL, LEFT_PARENTHESIS);
    public static final Variate RIGHT_PARENTHESIS_VARIATE = build(SYMBOL, RIGHT_PARENTHESIS);
    public static final Variate GREATER_THAN_VARIATE = build(SYMBOL, GREATER_THAN);
    public static final Variate LESS_THAN_VARIATE = build(SYMBOL, LESS_THAN);
    public static final Variate EQUAL_VARIATE = build(SYMBOL, EQUAL);
    public static final Variate PLUS_VARIATE = build(SYMBOL, PLUS);
    public static final Variate MINUS_VARIATE = build(SYMBOL, MINUS);
    public static final Variate COMMA_VARIATE = build(SYMBOL, COMMA);
    public static final Variate TIMES_VARIATE = build(SYMBOL, TIMES);
    public static final Variate DIVISION_VARIATE = build(SYMBOL, DIVISION);
    public static final Variate QUERY_VARIATE = build(SYMBOL, QUERY);
    public static final Variate GREATER_EQUAL_VARIATE = build(SYMBOL, GREATER_EQUAL);
    public static final Variate LESS_EQUAL_VARIATE = build(SYMBOL, LESS_EQUAL);
    public static final Variate OR_VARIATE = build(SYMBOL, OR);
    public static final Variate AND_VARIATE = build(SYMBOL, AND);


    public static final String[] OPERATORS = {LEFT_PARENTHESIS, RIGHT_PARENTHESIS, QUERY,
            GREATER_THAN, GREATER_EQUAL, LESS_THAN, LESS_EQUAL, EQUAL, PLUS, MINUS, COMMA, TIMES,
            DIVISION, OR, AND};

    /**
     * <p>check {@code op} is OPERATOR?</p>
     *
     * @return ture if {@code op} is in {@code OPERATORS}, else false
     * @see #OPERATORS
     */
    public static boolean isOperator(String op) {
        return Arrays.asList(OPERATORS).contains(op);
    }

    public static List<String> spliteExpr(String expr) throws CompilerException {
        return spliteExpr(expr, new BaseQuery());
    }

    public static List<String> spliteExpr(final String expr, final BaseQuery baseQuery) throws CompilerException {
        List<String> words = new ArrayList<>();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < expr.length();) {
            if (expr.substring(i).startsWith(OR)) {
                words.add(sb.toString().trim());
                words.add(OR);
                sb = new StringBuffer();
                i += OR.length();
            } else if (expr.substring(i).startsWith(AND)) {
                words.add(sb.toString().trim());
                words.add(AND);
                sb = new StringBuffer();
                i += AND.length();
            } else if (expr.substring(i).startsWith(LESS_EQUAL)) {
                words.add(sb.toString().trim());
                words.add(LESS_EQUAL);
                sb = new StringBuffer();
                i += LESS_EQUAL.length();
            } else if (expr.substring(i).startsWith(GREATER_EQUAL)) {
                words.add(sb.toString().trim());
                words.add(GREATER_EQUAL);
                sb = new StringBuffer();
                i += GREATER_EQUAL.length();
            } else if (expr.substring(i).startsWith(QUERY)) {
                words.add(sb.toString().trim());
                words.add(QUERY);
                sb = new StringBuffer();
                i += QUERY.length();
                if (expr.substring(i).contains(QUERY)) {
                    final String query = expr.substring(i).substring(0, expr.substring(i).indexOf(QUERY));
                    baseQuery.addQuery(query);
                    words.add(query);
                    i += query.length();
                    words.add(QUERY);
                    i += QUERY.length();
                } else {
                    throw new CompilerException("expr query no match.");
                }
            } else if (expr.substring(i).startsWith(DIVISION)) {
                words.add(sb.toString().trim());
                words.add(DIVISION);
                sb = new StringBuffer();
                i += DIVISION.length();
            } else if (expr.substring(i).startsWith(TIMES)) {
                words.add(sb.toString().trim());
                words.add(TIMES);
                sb = new StringBuffer();
                i += TIMES.length();
            } else if (expr.substring(i).startsWith(COMMA)) {
                words.add(sb.toString().trim());
                words.add(COMMA);
                sb = new StringBuffer();
                i += COMMA.length();
            } else if (expr.substring(i).startsWith(MINUS)) {
                words.add(sb.toString().trim());
                words.add(MINUS);
                sb = new StringBuffer();
                i += MINUS.length();
            } else if (expr.substring(i).startsWith(PLUS)) {
                words.add(sb.toString().trim());
                words.add(PLUS);
                sb = new StringBuffer();
                i += PLUS.length();
            } else if (expr.substring(i).startsWith(EQUAL)) {
                words.add(sb.toString().trim());
                words.add(EQUAL);
                sb = new StringBuffer();
                i += EQUAL.length();
            } else if (expr.substring(i).startsWith(LESS_THAN)) {
                words.add(sb.toString().trim());
                words.add(LESS_THAN);
                sb = new StringBuffer();
                i += LESS_THAN.length();
            } else if (expr.substring(i).startsWith(GREATER_THAN)) {
                words.add(sb.toString().trim());
                words.add(GREATER_THAN);
                sb = new StringBuffer();
                i += GREATER_THAN.length();
            } else if (expr.substring(i).startsWith(RIGHT_PARENTHESIS)) {
                words.add(sb.toString().trim());
                words.add(RIGHT_PARENTHESIS);
                sb = new StringBuffer();
                i += RIGHT_PARENTHESIS.length();
            } else if (expr.substring(i).startsWith(LEFT_PARENTHESIS)) {
                words.add(sb.toString().trim());
                words.add(LEFT_PARENTHESIS);
                sb = new StringBuffer();
                i += LEFT_PARENTHESIS.length();
            } else if (expr.substring(i).startsWith(DOT) && StringUtils.isAlpha(expr.substring(i+1,i+2))) {
                words.add(sb.toString().trim());
                words.add(DOT);
                sb = new StringBuffer();
                i += DOT.length();

                StringBuffer func_name = new StringBuffer();
                while((!LEFT_PARENTHESIS.equals(String.valueOf(expr.charAt(i)))) && i<expr.length()) {
                    func_name.append(expr.charAt(i));
                    i++;
                }
                words.add(func_name.toString().trim());
                words.add(LEFT_PARENTHESIS);
                int stack = 1;
                StringBuffer func_body = new StringBuffer();
                while(stack > 0 && i<expr.length()) {
                    i++;
                    if (LEFT_PARENTHESIS.equals(String.valueOf(expr.charAt(i)))) {
                        stack += 1;
                    } else if (RIGHT_PARENTHESIS.equals(String.valueOf(expr.charAt(i)))) {
                        stack -= 1;
                    }
                    if (stack > 0) {
                        func_body.append(expr.charAt(i));
                    }

                }
                words.add(func_body.toString().trim());
                words.add(RIGHT_PARENTHESIS);

                i++;
            } else {
                sb.append(expr.charAt(i));
                i += 1;
            }
        }
        if (sb.length() > 0) {
            words.add(sb.toString().trim());
        }
        return words.stream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
    }

    /**
     * <p>Lexical compiler triple: <code>type</code> is variate type,
     *    <code>name</code> is variate name, <code>value</code> is variate value. </p>
     *
     * @date 2019/05/21
     */
    private VariateType type;
    private JsonElement value;
    private StringBuffer sb;

    /**
     * <p> Variate Constructor. </p>
     *
     * @param type variate type.
     * @param value variate value.
     */
    private Variate(VariateType type, JsonPrimitive value, StringBuffer sb) {
        this.type = type;
        this.value = value;
        this.sb = sb;
    }

    /**
     * <p> Variate Constructor. </p>
     *
     * @param type variate type.
     * @param value variate value.
     */
    private Variate(VariateType type, JsonArray value, StringBuffer sb) {
        this.type = type;
        this.value = value;
        this.sb = sb;
    }

    /**
     * <p>build <code>type</code> variate</p>
     *
     * @param obj variate value.
     * @return <code>Variate</code> Variate type is <code>type</code>, name is null, value is empty
     */
    public static Variate build(Object obj) {
        if (obj instanceof JsonArray) {
            return new Variate(ARRAY, (JsonArray) obj, new StringBuffer());
        }
        return build(ORIGINAL, obj);
    }

    /**
     * <p>build <code>type</code> variate</p>
     *
     * @param type datum type.
     * @param obj variate value.
     * @return <code>Variate</code> Variate type is <code>type</code>, name is null, value is empty
     */
    public static Variate build(VariateType type, Object obj) {
        if (type.equals(ARRAY) || type.equals(STREAM)) {
            if (obj instanceof JsonArray) {
                return new Variate(type, (JsonArray) obj, new StringBuffer());
            }
        }
        if (type == ORIGINAL) {
            return new Variate(ORIGINAL, new JsonPrimitive(""), new StringBuffer(obj.toString()));
        }
        if (obj instanceof Integer) {
            return new Variate(type, new JsonPrimitive((int) obj), new StringBuffer());
        } else if (obj instanceof Long) {
            return new Variate(type, new JsonPrimitive((long) obj), new StringBuffer());
        } else if (obj instanceof Short) {
            return new Variate(type, new JsonPrimitive((short) obj), new StringBuffer());
        } else if (obj instanceof Float) {
            return new Variate(type, new JsonPrimitive((float) obj), new StringBuffer());
        } else if (obj instanceof Double) {
            return new Variate(type, new JsonPrimitive((double) obj), new StringBuffer());
        } else if (obj instanceof Byte) {
            return new Variate(type, new JsonPrimitive((byte) obj), new StringBuffer());
        } else if (obj instanceof Boolean) {
            return new Variate(type, new JsonPrimitive((boolean) obj), new StringBuffer());
        } else if (obj instanceof Character) {
            return new Variate(type, new JsonPrimitive((char) obj), new StringBuffer());
        } else if (obj instanceof Number) {
            return new Variate(type, new JsonPrimitive((Number) obj), new StringBuffer());
        }
        return new Variate(type, new JsonPrimitive(obj.toString()), new StringBuffer());
    }

    /**
     * <p>check {@code value} is empty?</p>
     *
     * @return ture if {@code value} is null or the size of {@code value} is 0, else false
     * @see #value
     */
    boolean isEmpty() {
        return (Objects.isNull(this.value) || StringUtils.isEmpty(this.value.getAsString()))
                && Objects.deepEquals(this.sb.length(), 0);
    }

    /**
     * <p>expand <code>value</code></p>
     *
     * @param ch the next of variate <char>ch</char>
     */
    void expand(String ch) throws CompilerException {
        if (this.type.equals(ORIGINAL)) {
            this.sb.append(ch);
            return;
        }
        throw new CompilerException("expand error: type is not ORIGINAL. ");
    }

    /**
     * <p>check {@code value} is empty?</p>
     *
     * @return true ior false
     * @see #isEmpty()
     */
    private boolean isValid() {
        if (this.type.equals(ORIGINAL)) {
            return true;
        } else if (this.type.equals(FUNCTION)) {
            return StringUtils.isAlpha(getValue().getAsString()) && Objects.deepEquals(isEmpty(), false);
        } else if (this.type.equals(NUMERIC)) {
            return Util.isNumeric(value.getAsNumber());
        } else if (this.type.equals(STRING)) {
            return true;
        } else if (this.type.equals(SYMBOL)) {
            return isOperator(getValue().getAsString());
        } else if (this.type.equals(BOOLEAN)) {
            getValue().getAsBoolean();
            return true;
        } else if (this.type.equals(ARRAY)) {
            return getValue().isJsonArray();
        } else if (this.type.equals(STREAM)) {
            return getValue().isJsonArray();
        }
        return false;
    }

    /**
     * <p>transform {@code type}</p>
     *
     * @return void
     * @throws CompilerException type and value do not match
     * @throws CompilerException type is not {@code original} and @{code this.type.equals(type)}
     */
    private void transformType(VariateType type) throws CompilerException {
        if (this.type.equals(type)) {
            return ;
        }
        if (isORIGINAL()) {
            this.type = type;
            switch (type) {
                case BOOLEAN:
                    value = new JsonPrimitive(Boolean.valueOf(sb.toString()));
                    break;
                case NUMERIC:
                    value = new JsonPrimitive(Double.valueOf(sb.toString()));
                    break;
                case ORIGINAL:
                case ERROR:
                    break;
                case ARRAY:
                    value = new JsonParser().parse(sb.toString());
                    break;
                case STRING:
                case SYMBOL:
                case FUNCTION:
                    value = new JsonPrimitive(sb.toString());
                    break;
            }
            if (!isValid()) {
                this.type = ORIGINAL;
                throw new CompilerException("transform error: type and value do not match. ");
            }
            sb = new StringBuffer();
        } else {
            throw new CompilerException("transform error: original type is not {@code original}. ");
        }
    }

    /**
     * <p>transform {@code FUNCTION} type</p>
     *
     * @return void
     * @throws CompilerException type and value do not match
     * @throws CompilerException original type is not {@code original}
     *
     * @see #transformType(VariateType)
     */
    void toFUNCTION()  throws CompilerException {
        transformType(FUNCTION);
    }

    /**
     * <p>transform {@code STRING} type</p>
     *
     * @return void
     * @throws CompilerException type and value do not match
     * @throws CompilerException original type is not {@code original}
     *
     * @see #transformType(VariateType)
     */
    void toSTRING()  throws CompilerException {
        transformType(STRING);
    }

    /**
     * <p>transform {@code FUNCTION} type</p>
     *
     * @return void
     * @throws CompilerException type and value do not match
     * @throws CompilerException original type is not {@code original}
     *
     * @see #transformType(VariateType)
     */
    void toSYMBOL()  throws CompilerException {
        transformType(SYMBOL);
    }

    /**
     * <p>transform {@code NUMERIC} type</p>
     *
     * @return void
     * @throws CompilerException type and value do not match
     * @throws CompilerException original type is not {@code original}
     *
     * @see #transformType(VariateType)
     */
    void toNUMERIC()  throws CompilerException {
        transformType(NUMERIC);
    }

    /**
     * <p>transform {@code BOOLEAN} type</p>
     *
     * @return void
     *
     * @see #transformType(VariateType)
     */
    void toBOOLEAN() {
        type = BOOLEAN;
    }

    /**
     * <p>transform {@code STREAM} type</p>
     *
     * @return void
     *
     * @see #transformType(VariateType)
     */
    void toSTREAM() {
        type = STREAM;
    }

    /**
     * <p>transform {@code ARRAY} type</p>
     *
     * @return void
     *
     * @see #transformType(VariateType)
     */
    void toARRAY() {
        type = ARRAY;
    }

    /**
     * <p>transform {@code NUMERIC} type</p>
     *
     * @return void
     *
     * @see #transformType(VariateType)
     */
    void toERROR() {
        type = ERROR;
    }

    /**
     * <p>check variate {@code type}</p>
     *
     * @return true if {@code type} is {@code STRING}, else false
     */
    public boolean isSTRING() {
        return this.type.equals(STRING) && this.isValid();
    }

    /**
     * <p>check variate {@code type}</p>
     *
     * @return true if {@code type} is {@code NUMERIC}, else false
     */
    public boolean isNUMERIC() {
        return this.type.equals(NUMERIC) && this.isValid();
    }

    /**
     * <p>check variate {@code type}</p>
     *
     * @return true if {@code type} is {@code FUNCTION}, else false
     */
    public boolean isFUNCTION() {
        return this.type.equals(FUNCTION) && this.isValid();
    }

    /**
     * <p>check variate {@code type}</p>
     *
     * @return true if {@code type} is {@code SYMBOL}, else false
     */
    public boolean isSYMBOL() {
        return this.type.equals(SYMBOL) && this.isValid();
    }

    /**
     * <p>check variate {@code type}</p>
     *
     * @return true if {@code type} is {@code STREAM}, else false
     */
    public boolean isSTREAM() {
        return this.type.equals(STREAM) && this.isValid();
    }

    /**
     * <p>check variate {@code type}</p>
     *
     * @return true if {@code type} is {@code ARRAY}, else false
     */
    public boolean isARRAY() {
        return this.type.equals(ARRAY) && this.isValid();
    }

    /**
     * <p>check variate {@code type}</p>
     *
     * @return true if {@code type} is {@code BOOLEAN}, else false
     */
    public boolean isBOOLEAN() {
        return this.type.equals(BOOLEAN) && this.isValid();
    }

    /**
     * <p>check variate {@code type}</p>
     *
     * @return true if {@code type} is {@code ORIGINAL}, else false
     */
    public boolean isORIGINAL() {
        return this.type.equals(ORIGINAL) && this.isValid();
    }

    /**
     * <p>check variate {@code type}</p>
     *
     * @return true if {@code type} is {@code ERROR}, else false
     */
    public boolean isERROR() {
        return this.type.equals(ERROR) && this.isValid();
    }

    /**
     * <p>check variate {@code value}</p>
     *
     * @param value string value
     * @return true if {@code value} is value, else false
     */
    public boolean equals(String value) {
        return getValue().getAsString().equals(value);
    }

    /**
     * <p>check variate {@code value}</p>
     *
     * @param v Variate
     * @return true if {@code value} is value, else false
     */
    public boolean equals(Variate v) {
        return v.type.equals(this.type) && v.value.getAsString().equals(this.value.getAsString());
    }
}

3. 构建 Lexical


import com.neusoft.rsapm.brain.common.exception.CompilerException;
import com.neusoft.rsapm.brain.common.exception.MessageException;
import com.neusoft.rsapm.brain.common.util.Util;
import org.apache.commons.lang.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.neusoft.rsapm.compile.VariateType.*;

/**
 * Lexocal for metric cal
 *
 * @author Muxin Sun
 * @date 2018/12/20
 */
public interface Lexical {

    /**
     * <p>function name</p>
     */
    String MIN_FUNCTION = "min";
    String MAX_FUNCTION = "max";
    String SUM_FUNCTION = "sum";
    String AVG_FUNCTION = "avg";
    String COUNT_FUNCTION = "count";

    String NAME_PREFIX = "v";
    AtomicInteger SEQUENCE = new AtomicInteger(0);

    /**
     * <p>variate to values</p>
     */
    Map<String, Variate> NAME_VARIATE = new HashMap<>();

    /**
     * <p>gt sign</p>
     *
     * @param valueA valueA is numeric
     * @param valueB valueB is numeric
     * @return 1 if valueA grant than valueB, else 0
     * @throws CompilerException Non-numeric type cannot be multiplied.
     */
    default Variate gt(Variate valueA, Variate valueB) throws CompilerException {
        if (valueA.isNUMERIC() && valueB.isNUMERIC()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsDouble()>valueB.getValue().getAsDouble()?1:0);
        } else if (valueA.isSTRING() && valueB.isSTRING()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsString().compareTo(valueB.getValue().getAsString())>0?1:0);
        }
        throw new CompilerException("Operator type cannot be compared.");
    }

    /**
     * <p>lt sign</p>
     *
     * @param valueA valueA is numeric
     * @param valueB valueB is numeric
     * @return 1 if valueA less than valueB, else 0
     * @throws CompilerException Non-numeric type cannot be multiplied.
     */
    default Variate lt(Variate valueA, Variate valueB) throws CompilerException {
        if (valueA.isNUMERIC() && valueB.isNUMERIC()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsDouble()<valueB.getValue().getAsDouble()?1:0);
        } else if (valueA.isSTRING() && valueB.isSTRING()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsString().compareTo(valueB.getValue().getAsString())<0?1:0);
        }
        throw new CompilerException("Operator type cannot be compared.");
    }

    /**
     * <p>eq sign</p>
     *
     * @param valueA valueA is numeric
     * @param valueB valueB is numeric
     * @return 1 if valueA less than valueB, else 0
     * @throws CompilerException Non-numeric type cannot be multiplied.
     */
    default Variate eq(Variate valueA, Variate valueB) throws CompilerException {
        if (valueA.isNUMERIC() && valueB.isNUMERIC()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsDouble()==valueB.getValue().getAsDouble()?1:0);
        } else if (valueA.isSTRING() && valueB.isSTRING()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsString().compareTo(valueB.getValue().getAsString())==0?1:0);
        }
        throw new CompilerException("Operator type cannot be compared.");
    }

    /**
     * <p>eq sign</p>
     *
     * @param valueA valueA is numeric
     * @param valueB valueB is numeric
     * @return 1 if valueA less than valueB, else 0
     * @throws CompilerException Non-numeric type cannot be multiplied.
     */
    default Variate ge(Variate valueA, Variate valueB) throws CompilerException {
        if (valueA.isNUMERIC() && valueB.isNUMERIC()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsDouble()>=valueB.getValue().getAsDouble()?1:0);
        } else if (valueA.isSTRING() && valueB.isSTRING()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsString().compareTo(valueB.getValue().getAsString())>=0?1:0);
        }
        throw new CompilerException("Operator type cannot be compared.");
    }

    /**
     * <p>eq sign</p>
     *
     * @param valueA valueA is numeric
     * @param valueB valueB is numeric
     * @return 1 if valueA less than or equal valueB, else 0
     * @throws CompilerException Non-numeric type cannot be multiplied.
     */
    default Variate le(Variate valueA, Variate valueB) throws CompilerException {
        if (valueA.isNUMERIC() && valueB.isNUMERIC()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsDouble()<=valueB.getValue().getAsDouble()?1:0);
        } else if (valueA.isSTRING() && valueB.isSTRING()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsString().compareTo(valueB.getValue().getAsString())<=0?1:0);
        }
        throw new CompilerException("Operator type cannot be compared.");
    }

    /**
     * <p>plus sign</p>
     *
     * @param valueA valueA is numeric
     * @param valueB valueB is numeric
     * @return <code>valueA+valueB</code>
     * @throws CompilerException Non-numeric types cannot be added.
     */
    default Variate plus(Variate valueA, Variate valueB) throws CompilerException {
        if (valueA.isNUMERIC() && valueB.isNUMERIC()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsDouble() + valueB.getValue().getAsDouble());
        }
        throw new CompilerException("Non-numeric types cannot be added.");
    }

    /**
     * <p>minus sign</p>
     *
     * @param valueA valueA is numeric
     * @param valueB valueB is numeric
     * @return <code>valueA-valueB</code>
     * @throws CompilerException Non-numeric type cannot be subtracted.
     */
    default Variate minus(Variate valueA, Variate valueB) throws CompilerException {
        if (valueA.isNUMERIC() && valueB.isNUMERIC()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsDouble() - valueB.getValue().getAsDouble());
        }
        throw new CompilerException("Non-numeric type cannot be subtracted.");
    }

    /**
     * <p>times sign</p>
     *
     * @param valueA valueA is numeric
     * @param valueB valueB is numeric
     * @return <code>valueA*valueB</code>
     * @throws CompilerException Non-numeric type cannot be multiplied.
     */
    default Variate times(Variate valueA, Variate valueB) throws CompilerException {
        if (valueA.isNUMERIC() && valueB.isNUMERIC()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsDouble() * valueB.getValue().getAsDouble());
        }
        throw new CompilerException("Non-numeric type cannot be multiplied.");
    }

    /**
     * <p>divide sign</p>
     *
     * @param valueA valueA is numeric
     * @param valueB valueB is numeric
     * @return <code>valueA/valueB</code> valueB is no-null
     * @throws CompilerException Non-numeric type cannot be divided.
     */
    default Variate division(Variate valueA, Variate valueB) throws CompilerException {
        if (valueA.isNUMERIC() && valueB.isNUMERIC()) {
            return Variate.build(NUMERIC, valueA.getValue().getAsDouble() / valueB.getValue().getAsDouble());
        }
        throw new CompilerException("Non-numeric type cannot be divided.");
    }

    /**
     * <p>execute function and </p>
     *
     * @param function function name
     * @param parameters parameters is variate_stream
     * @return <code>execute result</code>
     * @throws CompilerException if function is not def.
     */
    default Variate execute(String function, List<Variate> parameters) throws CompilerException {
        if (MIN_FUNCTION.equals(function)) {
            if (parameters.stream().allMatch(Variate::isNUMERIC)) {
                return Variate.build(NUMERIC, parameters.stream().map(Variate::getValue).mapToDouble(Util::getNumeric).min().orElse(Double.NaN));
            }
            throw new CompilerException("min function do not accept non-numeric parameters.");
        }
        if (MAX_FUNCTION.equals(function)) {
            if (parameters.stream().allMatch(Variate::isNUMERIC)) {
                return Variate.build(NUMERIC, parameters.stream().map(Variate::getValue).mapToDouble(Util::getNumeric).max().orElse(Double.NaN));
            }
            throw new CompilerException("max function do not accept non-numeric parameters.");
        }
        if (SUM_FUNCTION.equals(function)) {
            if (parameters.stream().allMatch(Variate::isNUMERIC)) {
                return Variate.build(NUMERIC, parameters.stream().map(Variate::getValue).mapToDouble(Util::getNumeric).sum());
            }
            throw new CompilerException("sum function do not accept non-numeric parameters.");
        }
        if (AVG_FUNCTION.equals(function)) {
            if (parameters.stream().allMatch(Variate::isNUMERIC)) {
                return Variate.build(NUMERIC, parameters.stream().map(Variate::getValue).mapToDouble(Util::getNumeric).average().orElse(Double.NaN));
            }
            throw new CompilerException("avg function do not accept non-numeric parameters.");
        }
        if (COUNT_FUNCTION.equals(function)) {
            return Variate.build(NUMERIC, parameters.stream().count());
        }
        throw new CompilerException("function is not def.");
    }

    /**
     * <p>execute function, and args is array</p>
     *
     * @param function function name
     * @param parameters function parameters
     * @return <code>execute result</code>
     */
    default Variate execute(String function, Variate... parameters) throws CompilerException, MessageException {
        return execute(function, Stream.of(parameters).collect(Collectors.toList()));
    }

    /**
     * <p>check operator is a function? </p>
     * <pre>
     * isFunction(null)   = false
     * isFunction("")     = true
     * isFunction("  ")   = false
     * isFunction("abc")  = true
     * isFunction("ab2c") = false
     * isFunction("ab-c") = false
     * </pre>
     * @param operator operator name
     * @return <code>true</code> if only contains letters, and is non-null
     */
    default boolean isFunction(String operator) {
        return StringUtils.isAlpha(operator);
    }

    /**
     * <p>store variate value function, return random variate</p>
     *
     * @param variate {@link #NAME_VARIATE}
     * @return <code>variate name</code>, name is auto-created
     */
    default String putVariate(final Variate variate) {
        NAME_VARIATE.put(String.format("%s-%d", NAME_PREFIX, SEQUENCE.incrementAndGet()), variate);
        return String.valueOf(String.format("%s-%d", NAME_PREFIX, SEQUENCE.get()));
    }

    /**
     * <p>get variate value, by name</p>
     *
     * @param name variate name
     * @return <code>variate</code>
     * @throws CompilerException if <code>variate</code> is not exist
     */
    default boolean isVariate(String name) throws CompilerException {
        return NAME_VARIATE.containsKey(name);
    }

    /**
     * <p>get variate value, by name</p>
     *
     * @param name variate name
     * @return <code>variate</code>
     * @throws CompilerException if <code>variate</code> is not exist
     */
    default Variate getVariate(String name) throws CompilerException {
        if (NAME_VARIATE.containsKey(name)) {
            return NAME_VARIATE.get(name);
        }
        throw new CompilerException("variate {"+name+"} is not exist");
    }
}

4. 构建 Syntactic

import com.neusoft.rsapm.brain.common.exception.CompilerException;
import com.neusoft.rsapm.brain.common.util.Util;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Stack;

import static com.neusoft.rsapm.compile.Variate.*;
import static com.neusoft.rsapm.compile.Variate.COMMA_VARIATE;
import static com.neusoft.rsapm.compile.VariateType.*;

/**
 * @author Muxin Sun
 * @date 2018/12/20
 */
public class Syntactic {

    private static Variate transform(final Lexical lexical, final Variate variate) throws CompilerException {
        if (variate.isORIGINAL() && Util.isNumeric(variate.getSb().toString())) {
            variate.toNUMERIC();
            return variate;
        } else if (variate.isORIGINAL() && lexical.isVariate(variate.getSb().toString())) {
            return lexical.getVariate(variate.getSb().toString());
        } else if (variate.isORIGINAL()) {
            throw new CompilerException("no variate.");
        }
        return variate;
    }

    /**
     * <p>calculate expr value</p>
     *
     * @param lexical lexical
     * @param expr expr
     * @return Variate
     */
    public static Variate getExprValue(final Lexical lexical, final String expr) throws CompilerException {
        final BaseQuery baseQuery = new BaseQuery();
        List<String> words = Variate.spliteExpr(expr, baseQuery);
        baseQuery.exeQuery();
        return getExprValue(lexical, baseQuery, words);
    }

    /**
     * <p>calculate expr value</p>
     *
     * @param lexical lexical
     * @param baseQuery baseQuery
     * @param words words
     * @return Variate
     */
    public static Variate getExprValue(final Lexical lexical, final BaseQuery baseQuery,
                                       final List<String> words) throws CompilerException {

        boolean isQuery = false;

        Stack<Variate> operators = new Stack<>();
        Stack<Variate> numbers = new Stack<>();

        Variate variate = Variate.build("");

        for (String word : words) {
            switch (word) {
                case LEFT_PARENTHESIS:
                    if (Objects.deepEquals(variate.isEmpty(), false)) {
                        variate.toFUNCTION();
                        operators.push(variate);
                    }
                    operators.push(LEFT_PARENTHESIS_VARIATE);
                    variate = Variate.build("");
                    break;
                case RIGHT_PARENTHESIS:
                    List<Variate> variates = new ArrayList<>();
                    variate = transform(lexical, variate);
                    while (!operators.isEmpty()) {
                        if (operators.peek().equals(LEFT_PARENTHESIS_VARIATE)) {
                            operators.pop();
                            variates.add(variate);
                            if (!operators.isEmpty() && operators.peek().isFUNCTION()) {
                                variate = lexical.execute(operators.pop().getValue().getAsString(), variates);
                            }
                            break;
                        } else if (operators.peek().equals(COMMA_VARIATE)) {
                            operators.pop();
                            variates.add(numbers.pop());
                        } else if (operators.peek().equals(GREATER_THAN_VARIATE)) {
                            operators.pop();
                            variate = lexical.gt(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_THAN_VARIATE)) {
                            operators.pop();
                            variate = lexical.lt(numbers.pop(), variate);
                        } else if (operators.peek().equals(EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.eq(numbers.pop(), variate);
                        } else if (operators.peek().equals(GREATER_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.ge(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.le(numbers.pop(), variate);
                        } else if (operators.peek().equals(PLUS_VARIATE)) {
                            operators.pop();
                            variate = lexical.plus(numbers.pop(), variate);
                        } else if (operators.peek().equals(MINUS_VARIATE)) {
                            operators.pop();
                            variate = lexical.minus(numbers.pop(), variate);
                        } else if (operators.peek().equals(TIMES_VARIATE)) {
                            operators.pop();
                            variate = lexical.times(numbers.pop(), variate);
                        } else if (operators.peek().equals(DIVISION_VARIATE)) {
                            operators.pop();
                            variate = lexical.division(numbers.pop(), variate);
                        } else {
                            throw new CompilerException(
                                    "operators error : " + operators.peek());
                        }
                    }
                    break;
                case COMMA:
                    variate = transform(lexical, variate);
                    while (!operators.isEmpty()) {
                        if (operators.peek().equals(LEFT_PARENTHESIS_VARIATE) || operators.peek().equals(COMMA_VARIATE)) {
                            break;
                        } else if (operators.peek().equals(GREATER_THAN_VARIATE)) {
                            operators.pop();
                            variate = lexical.gt(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_THAN_VARIATE)) {
                            operators.pop();
                            variate = lexical.lt(numbers.pop(), variate);
                        } else if (operators.peek().equals(EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.eq(numbers.pop(), variate);
                        } else if (operators.peek().equals(GREATER_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.ge(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.le(numbers.pop(), variate);
                        } else if (operators.peek().equals(PLUS_VARIATE)) {
                            operators.pop();
                            variate = lexical.plus(numbers.pop(), variate);
                        } else if (operators.peek().equals(MINUS_VARIATE)) {
                            operators.pop();
                            variate = lexical.minus(numbers.pop(), variate);
                        } else if (operators.peek().equals(TIMES_VARIATE)) {
                            operators.pop();
                            variate = lexical.times(numbers.pop(), variate);
                        } else if (operators.peek().equals(DIVISION_VARIATE)) {
                            operators.pop();
                            variate = lexical.division(numbers.pop(), variate);
                        } else {
                            throw new CompilerException(
                                    "operators error : " + operators.peek());
                        }
                    }
                    numbers.push(variate);
                    operators.push(COMMA_VARIATE);
                    variate = Variate.build("");
                    break;
                case GREATER_THAN:
                    variate = transform(lexical, variate);
                    while (!operators.isEmpty()) {
                        if (operators.peek().equals(LEFT_PARENTHESIS_VARIATE) || operators.peek().equals(COMMA_VARIATE)) {
                            break;
                        } else if (operators.peek().equals(GREATER_THAN_VARIATE)) {
                            operators.pop();
                            variate = lexical.gt(numbers.pop(), variate);
                        } else if (operators.peek().equals(GREATER_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.ge(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_THAN)) {
                            operators.pop();
                            variate = lexical.lt(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.le(numbers.pop(), variate);
                        } else if (operators.peek().equals(EQUAL)) {
                            operators.pop();
                            variate = lexical.eq(numbers.pop(), variate);
                        } else if (operators.peek().equals(PLUS)) {
                            operators.pop();
                            variate = lexical.plus(numbers.pop(), variate);
                        } else if (operators.peek().equals(MINUS)) {
                            operators.pop();
                            variate = lexical.minus(numbers.pop(), variate);
                        } else if (operators.peek().equals(TIMES)) {
                            operators.pop();
                            variate = lexical.times(numbers.pop(), variate);
                        } else if (operators.peek().equals(DIVISION)) {
                            operators.pop();
                            variate = lexical.division(numbers.pop(), variate);
                        } else {
                            throw new CompilerException(
                                    "operators error : " + operators.peek());
                        }
                    }
                    numbers.push(variate);
                    operators.push(GREATER_THAN_VARIATE);
                    variate = Variate.build("");
                    break;
                case GREATER_EQUAL:
                    variate = transform(lexical, variate);
                    while (!operators.isEmpty()) {
                        if (operators.peek().equals(LEFT_PARENTHESIS_VARIATE) || operators.peek().equals(COMMA_VARIATE)) {
                            break;
                        } else if (operators.peek().equals(GREATER_THAN_VARIATE)) {
                            operators.pop();
                            variate = lexical.gt(numbers.pop(), variate);
                        } else if (operators.peek().equals(GREATER_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.ge(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_THAN)) {
                            operators.pop();
                            variate = lexical.lt(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.le(numbers.pop(), variate);
                        } else if (operators.peek().equals(EQUAL)) {
                            operators.pop();
                            variate = lexical.eq(numbers.pop(), variate);
                        } else if (operators.peek().equals(PLUS)) {
                            operators.pop();
                            variate = lexical.plus(numbers.pop(), variate);
                        } else if (operators.peek().equals(MINUS)) {
                            operators.pop();
                            variate = lexical.minus(numbers.pop(), variate);
                        } else if (operators.peek().equals(TIMES)) {
                            operators.pop();
                            variate = lexical.times(numbers.pop(), variate);
                        } else if (operators.peek().equals(DIVISION)) {
                            operators.pop();
                            variate = lexical.division(numbers.pop(), variate);
                        } else {
                            throw new CompilerException(
                                    "operators error : " + operators.peek());
                        }
                    }
                    numbers.push(variate);
                    operators.push(GREATER_EQUAL_VARIATE);
                    variate = Variate.build("");
                    break;
                case LESS_THAN:
                    variate = transform(lexical, variate);
                    while (!operators.isEmpty()) {
                        if (operators.peek().equals(LEFT_PARENTHESIS_VARIATE) || operators.peek().equals(COMMA_VARIATE)) {
                            break;
                        } else if (operators.peek().equals(GREATER_THAN_VARIATE)) {
                            operators.pop();
                            variate = lexical.gt(numbers.pop(), variate);
                        } else if (operators.peek().equals(GREATER_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.ge(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_THAN)) {
                            operators.pop();
                            variate = lexical.lt(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.le(numbers.pop(), variate);
                        } else if (operators.peek().equals(EQUAL)) {
                            operators.pop();
                            variate = lexical.eq(numbers.pop(), variate);
                        } else if (operators.peek().equals(PLUS)) {
                            operators.pop();
                            variate = lexical.plus(numbers.pop(), variate);
                        } else if (operators.peek().equals(MINUS)) {
                            operators.pop();
                            variate = lexical.minus(numbers.pop(), variate);
                        } else if (operators.peek().equals(TIMES)) {
                            operators.pop();
                            variate = lexical.times(numbers.pop(), variate);
                        } else if (operators.peek().equals(DIVISION)) {
                            operators.pop();
                            variate = lexical.division(numbers.pop(), variate);
                        } else {
                            throw new CompilerException(
                                    "operators error : " + operators.peek());
                        }
                    }
                    numbers.push(variate);
                    operators.push(LESS_THAN_VARIATE);
                    variate = Variate.build("");
                    break;
                case LESS_EQUAL:
                    variate = transform(lexical, variate);
                    while (!operators.isEmpty()) {
                        if (operators.peek().equals(LEFT_PARENTHESIS_VARIATE) || operators.peek().equals(COMMA_VARIATE)) {
                            break;
                        } else if (operators.peek().equals(GREATER_THAN_VARIATE)) {
                            operators.pop();
                            variate = lexical.gt(numbers.pop(), variate);
                        } else if (operators.peek().equals(GREATER_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.ge(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_THAN)) {
                            operators.pop();
                            variate = lexical.lt(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.le(numbers.pop(), variate);
                        } else if (operators.peek().equals(EQUAL)) {
                            operators.pop();
                            variate = lexical.eq(numbers.pop(), variate);
                        } else if (operators.peek().equals(PLUS)) {
                            operators.pop();
                            variate = lexical.plus(numbers.pop(), variate);
                        } else if (operators.peek().equals(MINUS)) {
                            operators.pop();
                            variate = lexical.minus(numbers.pop(), variate);
                        } else if (operators.peek().equals(TIMES)) {
                            operators.pop();
                            variate = lexical.times(numbers.pop(), variate);
                        } else if (operators.peek().equals(DIVISION)) {
                            operators.pop();
                            variate = lexical.division(numbers.pop(), variate);
                        } else {
                            throw new CompilerException(
                                    "operators error : " + operators.peek());
                        }
                    }
                    numbers.push(variate);
                    operators.push(LESS_EQUAL_VARIATE);
                    variate = Variate.build("");
                    break;
                case EQUAL:
                    variate = transform(lexical, variate);
                    while (!operators.isEmpty()) {
                        if (operators.peek().equals(LEFT_PARENTHESIS_VARIATE) || operators.peek().equals(COMMA_VARIATE)) {
                            break;
                        } else if (operators.peek().equals(GREATER_THAN_VARIATE)) {
                            operators.pop();
                            variate = lexical.gt(numbers.pop(), variate);
                        } else if (operators.peek().equals(GREATER_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.ge(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_THAN)) {
                            operators.pop();
                            variate = lexical.lt(numbers.pop(), variate);
                        } else if (operators.peek().equals(LESS_EQUAL_VARIATE)) {
                            operators.pop();
                            variate = lexical.le(numbers.pop(), variate);
                        } else if (operators.peek().equals(EQUAL)) {
                            operators.pop();
                            variate = lexical.eq(numbers.pop(), variate);
                        } else if (operators.peek().equals(PLUS)) {
                            operators.pop();
                            variate = lexical.plus(numbers.pop(), variate);
                        } else if (operators.peek().equals(MINUS)) {
                            operators.pop();
                            variate = lexical.minus(numbers.pop(), variate);
                        } else if (operators.peek().equals(TIMES)) {
                            operators.pop();
                            variate = lexical.times(numbers.pop(), variate);
                        } else if (operators.peek().equals(DIVISION)) {
                            operators.pop();
                            variate = lexical.division(numbers.pop(), variate);
                        } else {
                            throw new CompilerException(
                                    "operators error : " + operators.peek());
                        }
                    }
                    numbers.push(variate);
                    operators.push(EQUAL_VARIATE);
                    variate = Variate.build("");
                    break;
                case PLUS:
                    variate = transform(lexical, variate);
                    while (!operators.isEmpty()) {
                        if (operators.peek().equals(LEFT_PARENTHESIS_VARIATE) || operators.peek().equals(COMMA_VARIATE) ||
                                operators.peek().equals(GREATER_THAN_VARIATE) || operators.peek().equals(GREATER_EQUAL_VARIATE) ||
                                operators.peek().equals(LESS_THAN_VARIATE) || operators.peek().equals(LESS_EQUAL_VARIATE) ||
                                operators.peek().equals(EQUAL_VARIATE)) {
                            break;
                        } else if (operators.peek().equals(PLUS_VARIATE)) {
                            operators.pop();
                            variate = lexical.plus(numbers.pop(), variate);
                        } else if (operators.peek().equals(MINUS_VARIATE)) {
                            operators.pop();
                            variate = lexical.minus(numbers.pop(), variate);
                        } else if (operators.peek().equals(TIMES_VARIATE)) {
                            operators.pop();
                            variate = lexical.times(numbers.pop(), variate);
                        } else if (operators.peek().equals(DIVISION_VARIATE)) {
                            operators.pop();
                            variate = lexical.division(numbers.pop(), variate);
                        } else {
                            throw new CompilerException(
                                    "operators error : " + operators.peek().getValue());
                        }
                    }
                    numbers.push(variate);
                    operators.push(PLUS_VARIATE);
                    variate = Variate.build("");
                    break;
                case MINUS:
                    variate = transform(lexical, variate);
                    while (!operators.isEmpty()) {
                        if (operators.peek().equals(LEFT_PARENTHESIS_VARIATE) || operators.peek().equals(COMMA_VARIATE) ||
                                operators.peek().equals(GREATER_THAN_VARIATE) || operators.peek().equals(GREATER_EQUAL_VARIATE) ||
                                operators.peek().equals(LESS_THAN_VARIATE) || operators.peek().equals(LESS_EQUAL_VARIATE) ||
                                operators.peek().equals(EQUAL_VARIATE)) {
                            break;
                        } else if (operators.peek().equals(PLUS_VARIATE)) {
                            operators.pop();
                            variate = lexical.plus(numbers.pop(), variate);
                        } else if (operators.peek().equals(MINUS_VARIATE)) {
                            operators.pop();
                            variate = lexical.minus(numbers.pop(), variate);
                        } else if (operators.peek().equals(TIMES_VARIATE)) {
                            operators.pop();
                            variate = lexical.times(numbers.pop(), variate);
                        } else if (operators.peek().equals(DIVISION_VARIATE)) {
                            operators.pop();
                            variate = lexical.division(numbers.pop(), variate);
                        } else {
                            throw new CompilerException(
                                    "operators error : " + operators.peek().getValue());
                        }
                    }
                    numbers.push(variate);
                    operators.push(MINUS_VARIATE);
                    variate = Variate.build("");
                    break;
                case TIMES:
                    variate = transform(lexical, variate);
                    while (!operators.isEmpty()) {
                        if (operators.peek().equals(LEFT_PARENTHESIS_VARIATE) || operators.peek().equals(COMMA_VARIATE) ||
                                operators.peek().equals(GREATER_THAN_VARIATE) || operators.peek().equals(GREATER_EQUAL_VARIATE) ||
                                operators.peek().equals(LESS_THAN_VARIATE) || operators.peek().equals(LESS_EQUAL_VARIATE) ||
                                operators.peek().equals(EQUAL_VARIATE) || operators.peek().equals(PLUS_VARIATE) ||
                                operators.peek().equals(MINUS_VARIATE)) {
                            break;
                        } else if (operators.peek().equals(TIMES_VARIATE)) {
                            operators.pop();
                            variate = lexical.times(numbers.pop(), variate);
                        } else if (operators.peek().equals(DIVISION_VARIATE)) {
                            operators.pop();
                            variate = lexical.division(numbers.pop(), variate);
                        } else {
                            throw new CompilerException(
                                    "operators error : " + operators.peek().getValue());
                        }
                    }
                    numbers.push(variate);
                    operators.push(TIMES_VARIATE);
                    variate = Variate.build("");
                    break;
                case DIVISION:
                    variate = transform(lexical, variate);
                    while (!operators.isEmpty()) {
                        if (operators.peek().equals(LEFT_PARENTHESIS_VARIATE) || operators.peek().equals(COMMA_VARIATE) ||
                                operators.peek().equals(GREATER_THAN_VARIATE) || operators.peek().equals(GREATER_EQUAL_VARIATE) ||
                                operators.peek().equals(LESS_THAN_VARIATE) || operators.peek().equals(LESS_EQUAL_VARIATE) ||
                                operators.peek().equals(EQUAL_VARIATE) || operators.peek().equals(PLUS_VARIATE) ||
                                operators.peek().equals(MINUS_VARIATE)) {
                            break;
                        } else if (operators.peek().equals(TIMES_VARIATE)) {
                            operators.pop();
                            variate = lexical.times(numbers.pop(), variate);
                        } else if (operators.peek().equals(DIVISION_VARIATE)) {
                            operators.pop();
                            variate = lexical.division(numbers.pop(), variate);
                        } else {
                            throw new CompilerException(
                                    "operators error : " + operators.peek().getValue());
                        }
                    }
                    numbers.push(variate);
                    operators.push(DIVISION_VARIATE);
                    variate = Variate.build("");
                    break;
                case QUERY:
                    isQuery = !isQuery;
                    break;
                default:
                    if (isQuery) {
                        if (variate.isEmpty()) {
                            variate = Variate.build(ARRAY, baseQuery.getResponse(word));
                        } else {
                            throw new CompilerException("operators error.");
                        }
                    } else {
                        variate.expand(word);
                    }
            }
        }

        variate = transform(lexical, variate);

        while ( !operators.isEmpty() ) {
            if (operators.peek().equals(COMMA_VARIATE)) {
                operators.pop();
            } else if (operators.peek().equals(GREATER_THAN_VARIATE)) {
                operators.pop();
                variate = lexical.gt(numbers.pop(), variate);
            } else if (operators.peek().equals(GREATER_EQUAL_VARIATE)) {
                operators.pop();
                variate = lexical.ge(numbers.pop(), variate);
            } else if (operators.peek().equals(LESS_THAN_VARIATE)) {
                operators.pop();
                variate = lexical.lt(numbers.pop(), variate);
            } else if (operators.peek().equals(LESS_EQUAL_VARIATE)) {
                operators.pop();
                variate = lexical.lt(numbers.pop(), variate);
            } else if (operators.peek().equals(EQUAL_VARIATE)) {
                operators.pop();
                variate = lexical.eq(numbers.pop(), variate);
            } else if (operators.peek().equals(PLUS_VARIATE)) {
                operators.pop();
                variate = lexical.plus(numbers.pop(), variate);
            } else if (operators.peek().equals(MINUS_VARIATE)) {
                operators.pop();
                variate = lexical.minus(numbers.pop(), variate);
            } else if (operators.peek().equals(TIMES_VARIATE)) {
                operators.pop();
                variate = lexical.times(numbers.pop(), variate);
            } else if (operators.peek().equals(DIVISION_VARIATE)) {
                operators.pop();
                variate = lexical.division(numbers.pop(), variate);
            } else {
                throw new CompilerException(
                        "operators error : " + operators.peek().getValue());
            }
        }
        if (numbers.empty()) {
            return variate;
        }
        throw new CompilerException(
                "expr error : " + words);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容