应用场景
这个在编译器的语义分析过程中常用的一种模式, 即分析虚拟语法树 (AST), 但它并不能解决如何生成语法树的问题.
在实际的工作中, 有时也会遇到一些类似的工作, 比如我们会使用 DSL 来解决一些复杂的业务问题, 这时候就需要我们来定义一些简单的语法来实现. 再比如
比如前段时间需要开发一个 maven 的插件, 需要对一些依赖的版本大小限制 (比如 guava>18.0), 以及一些依赖之间互斥 (A|B), 这些规则可以自定义 (以方便扩展); 所以我开发的插件的工作是解析配置文件, 然后判断项目的依赖是否满足规则, 如果不满足则退出编译.
- context
- @AllArgsConstructor
- public class Context {
- private Map<String, Expression> variables;
- public int getValue(String key) {
- if (variables.containsKey(key)) {
- return variables.get(key).interpreter(this);
- }
- return 0;
- }
- }
- expression
- public interface Expression {
- public int interpreter(Context context);
- }
- TerminalExpression
- @AllArgsConstructor
- public class Number implements Expression {
- private int number;
- public int interpreter(Context context) {
- return number;
- }
- }
- /**
- * TerminalExpression
- */
- @AllArgsConstructor
- public class VariableExpression implements Expression {
- private String variable;
- public int interpreter(Context context) {
- return context.getValue(variable);
- }
- }
- NonterminalExpression
- @AllArgsConstructor
- public class MinusExpression implements Expression {
- // 左操作数
- private Expression left;
- // 右操作数
- private Expression right;
- public int interpreter(Context context) {
- return left.interpreter(context) - right.interpreter(context);
- }
- }
- @AllArgsConstructor
- public class MinusExpression implements Expression {
- // 左操作数
- private Expression left;
- // 右操作数
- private Expression right;
- public int interpreter(Context context) {
- return left.interpreter(context) - right.interpreter(context);
- }
- }
- client
- /**
- *
- * 这个严格来说并不能算是解释器的一部分, 因为它还完成了 token 解析, 可以当成一个 client 来操作
- */
- @AllArgsConstructor
- public class Evaluator implements Expression {
- private Expression syntaxTree;
- public Evaluator(String expression) {
- Stack<Expression> expressionStack = new Stack<Expression>();
- for (String token : expression.split(" ")) {
- if (token.equals("+")) {
- Expression subExpression = new PlusExpression(expressionStack.pop(), expressionStack.pop());
- expressionStack.push(subExpression);
- } else if (token.equals("-")) {
- // it's necessary remove first the right operand from the stack
- Expression right = expressionStack.pop();
- // ..and after the left one
- Expression left = expressionStack.pop();
- Expression subExpression = new MinusExpression(left, right);
- expressionStack.push(subExpression);
- } else
- expressionStack.push(new VariableExpression(token));
- }
- syntaxTree = expressionStack.pop();
- }
- public int interpreter(Context context) {
- return syntaxTree.interpreter(context);
- }
- public static void main(String[] args) {
- String expression = "w x z - +";
- Evaluator sentence = new Evaluator(expression);
- Map<String,Expression> variables = new HashMap<String,Expression>();
- variables.put("w", new Number(5));
- variables.put("x", new Number(10));
- variables.put("z", new Number(42));
- int result = sentence.interpreter(new Context(variables));
- System.out.println(result);
- }
- }
来源: https://juejin.im/post/5ad84374f265da502b5f52d6