编译器

1. 构建 VariateType

public enum VariateType {
    /**
     * 

Variate type, include STRING, NUMERIC, * ARRAY, BOOLEAN, FUNCTION, * SYMBOL, SYMBOL and ORIGINAL.

*/ 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
     * 

Supported operators, sort operational character by priority level. ' is max level, * Note: = is not mutator method.

*/ 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}; /** *

check {@code op} is OPERATOR?

* * @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 spliteExpr(String expr) throws CompilerException { return spliteExpr(expr, new BaseQuery()); } public static List spliteExpr(final String expr, final BaseQuery baseQuery) throws CompilerException { List 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 0 && i 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()); } /** *

Lexical compiler triple: type is variate type, * name is variate name, value is variate value.

* * @date 2019/05/21 */ private VariateType type; private JsonElement value; private StringBuffer sb; /** *

Variate Constructor.

* * @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; } /** *

Variate Constructor.

* * @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; } /** *

build type variate

* * @param obj variate value. * @return Variate Variate type is type, 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); } /** *

build type variate

* * @param type datum type. * @param obj variate value. * @return Variate Variate type is type, 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()); } /** *

check {@code value} is empty?

* * @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); } /** *

expand value

* * @param ch the next of variate ch */ 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. "); } /** *

check {@code value} is empty?

* * @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; } /** *

transform {@code type}

* * @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}. "); } } /** *

transform {@code FUNCTION} type

* * @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); } /** *

transform {@code STRING} type

* * @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); } /** *

transform {@code FUNCTION} type

* * @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); } /** *

transform {@code NUMERIC} type

* * @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); } /** *

transform {@code BOOLEAN} type

* * @return void * * @see #transformType(VariateType) */ void toBOOLEAN() { type = BOOLEAN; } /** *

transform {@code STREAM} type

* * @return void * * @see #transformType(VariateType) */ void toSTREAM() { type = STREAM; } /** *

transform {@code ARRAY} type

* * @return void * * @see #transformType(VariateType) */ void toARRAY() { type = ARRAY; } /** *

transform {@code NUMERIC} type

* * @return void * * @see #transformType(VariateType) */ void toERROR() { type = ERROR; } /** *

check variate {@code type}

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

check variate {@code type}

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

check variate {@code type}

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

check variate {@code type}

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

check variate {@code type}

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

check variate {@code type}

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

check variate {@code type}

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

check variate {@code type}

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

check variate {@code type}

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

check variate {@code value}

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

check variate {@code value}

* * @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 {

    /**
     * 

function name

*/ 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); /** *

variate to values

*/ Map NAME_VARIATE = new HashMap<>(); /** *

gt sign

* * @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."); } /** *

lt sign

* * @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()eq sign

* * @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."); } /** *

eq sign

* * @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."); } /** *

eq sign

* * @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."); } /** *

plus sign

* * @param valueA valueA is numeric * @param valueB valueB is numeric * @return valueA+valueB * @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."); } /** *

minus sign

* * @param valueA valueA is numeric * @param valueB valueB is numeric * @return valueA-valueB * @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."); } /** *

times sign

* * @param valueA valueA is numeric * @param valueB valueB is numeric * @return valueA*valueB * @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."); } /** *

divide sign

* * @param valueA valueA is numeric * @param valueB valueB is numeric * @return valueA/valueB 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."); } /** *

execute function and

* * @param function function name * @param parameters parameters is variate_stream * @return execute result * @throws CompilerException if function is not def. */ default Variate execute(String function, List 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."); } /** *

execute function, and args is array

* * @param function function name * @param parameters function parameters * @return execute result */ default Variate execute(String function, Variate... parameters) throws CompilerException, MessageException { return execute(function, Stream.of(parameters).collect(Collectors.toList())); } /** *

check operator is a function?

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

store variate value function, return random variate

* * @param variate {@link #NAME_VARIATE} * @return variate name, 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())); } /** *

get variate value, by name

* * @param name variate name * @return variate * @throws CompilerException if variate is not exist */ default boolean isVariate(String name) throws CompilerException { return NAME_VARIATE.containsKey(name); } /** *

get variate value, by name

* * @param name variate name * @return variate * @throws CompilerException if variate 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;
    }

    /**
     * 

calculate expr value

* * @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 words = Variate.spliteExpr(expr, baseQuery); baseQuery.exeQuery(); return getExprValue(lexical, baseQuery, words); } /** *

calculate expr value

* * @param lexical lexical * @param baseQuery baseQuery * @param words words * @return Variate */ public static Variate getExprValue(final Lexical lexical, final BaseQuery baseQuery, final List words) throws CompilerException { boolean isQuery = false; Stack operators = new Stack<>(); Stack 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 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); } }

你可能感兴趣的:(编译器)