Interpreter mode of design mode

Posted by benji2010 on Fri, 17 Sep 2021 11:54:08 +0200

Four arithmetic problems

Four operations are realized through the interpreter mode, such as calculating the value of a+b-c. specific requirements:

  1. First enter the form of the expression, such as a+b+c-d+e, which requires that the letters of the expression cannot be repeated.
  2. Then enter the values of a, b, c, d and e respectively.
  3. Finally, the operation result is output.

Interpreter mode

Basic introduction
  1. In the compilation principle, an arithmetic expression forms lexical units through the lexical analyzer, and then these lexical units build a parsing tree through the parser, and finally form an abstract parsing tree. The lexical analyzer and parser here can be regarded as interpreters.
  2. Interpreter mode: it refers to a given language (expression), defining a representation of its grammar, and defining an interpreter, which is used to interpret sentences (expressions) in the language.
Interpreter mode solves four arithmetic problems

In order to achieve convenience and simplify the problem. We only introduce addition and subtraction.

  1. UML class diagram
  2. code implementation
    Expression class:
    import java.util.HashMap;
    
    public abstract class Expression {
        public abstract int interpreter(HashMap<String, Integer> var);
    }
    
    Variable interpreter VarExpression class:
    import java.util.HashMap;
    
    /**
     * Variable interpreter
     */
    public class VarExpression extends Expression {
    
        private String key;
    
        public VarExpression(String key) {
            this.key = key;
        }
    
        @Override
        public int interpreter(HashMap<String, Integer> var) {
            return var.get(this.key);
        }
    }
    
    Symbolic expression class:
    import java.util.HashMap;
    
    public class SymbolExpression extends Expression{
    
        protected Expression left;
        protected Expression right;
    
        public SymbolExpression(Expression left, Expression right) {
            this.left = left;
            this.right = right;
        }
    
        @Override
        public int interpreter(HashMap<String, Integer> var) {
            return 0;
        }
    }
    
    Addition symbol addressexpression class:
    import java.util.HashMap;
    
    public class AddExpression extends SymbolExpression {
    
        public AddExpression(Expression left, Expression right) {
            super(left, right);
        }
    
        public int interpreter(HashMap<String, Integer> var) {
            return super.left.interpreter(var) + super.right.interpreter(var);
        }
    }
    
    Subtracter SubExpression class:
    import java.util.HashMap;
    
    public class SubExpression extends SymbolExpression {
    
        public SubExpression(Expression left, Expression right) {
            super(left, right);
        }
    
        public int interpreter(HashMap<String, Integer> var) {
            return super.left.interpreter(var) - super.right.interpreter(var);
        }
    }
    
    Calculator calculator class:
    import java.util.HashMap;
    import java.util.Stack;
    
    public class Calculator {
    
        private Expression expression;
    
        public Calculator(String expStr) {
            Stack<Expression> stack = new Stack<>();
    
            char[] charArray = expStr.toCharArray();
    
            Expression left = null;
            Expression right = null;
    
            for (int i = 0; i < charArray.length; ++i) {
                switch (charArray[i]) {
                    case '+':
                        left = stack.pop();
                        right = new VarExpression(String.valueOf(charArray[++i]));
                        stack.push(new AddExpression(left, right));
                        break;
                    case '-':
                        left = stack.pop();
                        right = new VarExpression(String.valueOf(charArray[++i]));
                        stack.push(new SubExpression(left, right));
                        break;
                    default:
                        stack.push(new VarExpression(String.valueOf(charArray[i])));
                        break;
                }
            }
            this.expression = stack.pop();
        }
    
        public int run(HashMap<String, Integer> var) {
            return this.expression.interpreter(var);
        }
    }
    
    Client class:
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.HashMap;
    
    public class Client {
    
        public static void main(String[] args) throws IOException {
    
            String expStr = getExpStr();
            HashMap<String, Integer> var = getValue(expStr);
    
            Calculator calculator = new Calculator(expStr);
            System.out.println("Operation result:" + expStr + "=" + calculator.run(var));
        }
    
        private static HashMap<String, Integer> getValue(String expStr) throws IOException {
    
            HashMap<String, Integer> map = new HashMap<>();
    
            for (char ch: expStr.toCharArray()) {
                if (ch != '+' && ch != '-') {
                    if (!map.containsKey(String.valueOf(ch))) {
                        System.out.println("Please enter" + String.valueOf(ch) + "Straight:");
                        String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
                        map.put(String.valueOf(ch), Integer.valueOf(in));
                    }
                }
            }
            return map;
        }
    
        private static String getExpStr() throws IOException {
            System.out.println("Please enter an expression:");
            return (new BufferedReader(new InputStreamReader(System.in))).readLine();
        }
    }
    

Application of Interpreter pattern in Spring framework

For example:

public class Main {
    public static void main(String[] args) {
        SpelExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression("10 * (2 + 1) * 1 + 66");
        int result = (Integer) expression.getValue();
        System.out.println(result);
    }
}
  1. UML class diagram
  2. summary
    1. Expression is an expression interface. There are different implementation classes below, such as SpelExpression.
    2. When using, different Expression objects are returned according to different ExpressionParser objects created (such as InternalSpelExpressionParser or SpelExpressionParser).
    3. The getValue() method is an interpreter method. Different expressioins call the getValue method to interpret the expression and get the result.

Notes and details of interpreter mode

  1. When a language needs interpretation and execution, the sentences in the language can be expressed as an abstract syntax tree, and the interpreter mode can be considered to make the program have good scalability.
  2. Application scenarios: compiler, operation expression calculation, regular expression, robot, etc.
  3. Possible problems caused by using the interpreter: the interpreter mode will cause class expansion, and the recursive call method used in the interpreter mode may lead to mode crash and low execution efficiency.

Topics: Design Pattern