1. Interrepeter Pattern
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
1.1 Interpreter Model - Core Ideas
Define a new language and specify how to parse it.
1.2 Interpreter Schema-Class Diagram
The parser has four roles:
- AbstractExpression: An Abstract parser that defines an abstract method. There is only one abstract method
- TerminalExpress: TerminalExpress: TerminalExpress. Usually there is only one TerminalExpress in an analytic schema.
- NonterminalExpression: Non-terminal expression.
- Context: Context, which contains global information beyond the parser.
1.3 Interpreter Patterns - Advantages and Disadvantages
- Advantages: Extension number, modification of grammar rules only needs to modify the corresponding non-terminal expression.
- Disadvantages:
- Parser patterns cause class expansion
- The parser mode uses recursive invocation, which is inefficient.
- perceptual difficulty
1.4 Interpreter Patterns - Applicable Scenarios
- A Simple Grammar Scenario to Explain
- Repeated problems can be applied to the interpreter model
1.5 Notes
- In project development, try not to apply interpreter model.
- If parser mode is needed in java development, you can refer to open source parsing toolkits such as Expression4J, Jep, MESP(Math Expression String Parser) and repeat wheels every time.
2. Parser pattern - application examples
The parser pattern is rarely used, so the author directly extracts an example of addition and subtraction from the book.
Class 2.1 Graphs
2.2 Abstract Expression
// Abstract expression class public abstract class Expression { // Analytical formulas and values, where the key value in var is the parameter in the formula and value is the specific value public abstract int interpreter(HashMap<String, Integer> var); }
2.3 Terminator expression - VarExpression
// variable resolver 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(key); } }
2.4 Symbol Expression
// Abstract symbol parser public abstract class SymbolExpression extends Expression { protected Expression left; protected Expression right; public SymbolExpression(Expression left, Expression right) { this.left = left; this.right = right; } }
2.5 AddExpression
// Additive parser public class AddExpression extends SymbolExpression { public AddExpression(Expression left, Expression right) { super(left, right); } @Override public int interpreter(HashMap<String, Integer> var) { return super.left.interpreter(var) + super.right.interpreter(var); } }
2.6 SubExpression
// Subtraction parser public class SubExpression extends SymbolExpression { public SubExpression(Expression left, Expression right) { super(left, right); } @Override public int interpreter(HashMap<String, Integer> var) { return super.left.interpreter(var) - super.right.interpreter(var); } }
2.7 Calculator
public class Calculator { // Expression private Expression expression; public Calculator(String expStr) { // Define a stack, arrange operators in order Stack<Expression> stack = new Stack<>(); // Expressions are split into character arrays char[] charArray = expStr.toCharArray(); // operation Expression left = null; Expression right = null; for (int i = 0; i < charArray.length; i++) { switch (charArray[i]) { case '+': // Addition results are put on the stack 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]))); } } // Throw out the calculation results. this.expression = stack.pop(); } // Start the operation public int run(HashMap<String, Integer> var) { return this.expression.interpreter(var); } }
2.8 Test
@Test public void test(){ // Expression String expStr = "a+b-c"; // Variable value HashMap<String, Integer> map = new HashMap<>(); map.put("a", 10); map.put("b", 5); map.put("c", 1); // Calculator Calculator calculator = new Calculator(expStr); // Calculation int result = calculator.run(map); System.out.println(expStr + "=" + result); }
2.9 Test Output
a+b-c=14