Chapter 23: interpreter mode
First, the four arithmetic problem
Four operations implemented by the interpreter mode, computing the value of a + bc, specific requirements
First enter form of an expression, such as a + b + c-d + e, the expression to the letters can not be repeated
In the input values a, b, c, d, e of
Finally, the results obtained: Figure
Second, the traditional solution to the problem of the four operations analysis
Write a method of receiving an expression of the form, and then resolved according to the value input by the user, the result obtained
Analysis: If you add new operators, such as * / (and so on, is not conducive to expansion, in addition to make a way to parse the program structure will cause confusion, not clear enough.
Solution: Consider using an interpreter modes , namely: Expression -> Interpreter (there can be multiple) -> results
Third, the mode explains the basics
basic introduction
Compiling principles, an arithmetic expression formed by the lexical analyzer lexical unit, and then re-build these lexical units by parser parse tree, forming an abstract syntax parse tree. Here lexical analyzer and parser can be seen as an interpreter
Interpreter pattern (Interpreter Pattern): refers to a given language (expression) , the definition of a grammar which represent and define an interpreter , using the interpreter to interpret the language sentences (expression )
- Scenarios
- Applications may be a need to explain the execution of the sentence in the language is expressed as an abstract syntax tree
- Some recurring problem can be expressed in a simple language
- A simple explanation of the syntax required scene
Such examples include, such as compilers, computing arithmetic expressions, regular expressions, robotics
Fourth, the mode explains the principle of FIG class
To explain the principles of the class diagram - that (roles and responsibilities interpreter mode)
Context: the role of environmental, global contain information beyond the interpreter.
AbstractExpression: abstract expression, declare an abstract interpretation of the operation, this method is an abstract syntax tree shared by all nodes
TerminalExpression: terminator expression is achieved in the grammar associated with the terminator explaining the operation
NonTermialExpression: non-terminator expression achieved in explaining the operation of the grammar nonterminals.
Description: Enter the Context he TerminalExpression information can be input by the Client
Fifth, the interpreter model to achieve four
- Examples of application requirements
Interpretation mode is achieved by the four arithmetic operations, such as calculating the value of a + bc
- Ideas and analysis scheme (FIG class)
- Code
Computing abstract class
package com.gjxaiou.interpreter;
import java.util.HashMap;
import java.util.Stack;
public class Calculator {
// 定义表达式
private Expression expression;
// 构造函数传参,并解析
public Calculator(String expStr) { // expStr = a+b
// 安排运算先后顺序
Stack<Expression> stack = new Stack<>();
// 表达式拆分成字符数组
char[] charArray = expStr.toCharArray();// [a, +, b]
Expression left = null;
Expression right = null;
//遍历我们的字符数组, 即遍历 [a, +, b]
//针对不同的情况,做处理
for (int i = 0; i < charArray.length; i++) {
switch (charArray[i]) {
case '+': //
left = stack.pop();// 从stack取出left => "a"
right = new VarExpression(String.valueOf(charArray[++i]));// 取出右表达式 "b"
stack.push(new AddExpression(left, right));// 然后根据得到left 和 right 构建 AddExpresson加入stack
break;
case '-': //
left = stack.pop();
right = new VarExpression(String.valueOf(charArray[++i]));
stack.push(new SubExpression(left, right));
break;
default:
//如果是一个 Var 就创建要给 VarExpression 对象,并push到 stack
stack.push(new VarExpression(String.valueOf(charArray[i])));
break;
}
}
//当遍历完整个 charArray 数组后,stack 就得到最后Expression
this.expression = stack.pop();
}
public int run(HashMap<String, Integer> var) {
//最后将表达式a+b和 var = {a=10,b=20}
//然后传递给expression的interpreter进行解释执行
return this.expression.interpreter(var);
}
}
Expression abstract class
package com.gjxaiou.interpreter;
import java.util.HashMap;
/**
* 抽象类表达式,通过HashMap 键值对, 可以获取到变量的值
*/
public abstract class Expression {
// a + b - c
// 解释公式和数值, key 就是公式(表达式) 参数[a,b,c], value就是就是具体值
// HashMap {a=10, b=20}
public abstract int interpreter(HashMap<String, Integer> var);
}
Variable interpreter
package com.gjxaiou.interpreter;
import java.util.HashMap;
/**
* 变量的解释器
* @author Administrator
*
*/
public class VarExpression extends Expression {
private String key; // key=a,key=b,key=c
public VarExpression(String key) {
this.key = key;
}
// var 就是{a=10, b=20}
// interpreter 根据 变量名称,返回对应值
@Override
public int interpreter(HashMap<String, Integer> var) {
return var.get(this.key);
}
}
Abstract operational sign interpreter
package com.gjxaiou.interpreter;
import java.util.HashMap;
/**
* 抽象运算符号解析器 这里,每个运算符号,都只和自己左右两个数字有关系,
* 但左右两个数字有可能也是一个解析的结果,无论何种类型,都是Expression类的实现类
*
* @author Administrator
*
*/
public class SymbolExpression extends Expression {
protected Expression left;
protected Expression right;
public SymbolExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
//因为 SymbolExpression 是让其子类来实现,因此 interpreter 是一个默认实现
@Override
public int interpreter(HashMap<String, Integer> var) {
return 0;
}
}
Specific symbol interpreter
package com.gjxaiou.interpreter;
import java.util.HashMap;
/**
* 加法解释器
* @author Administrator
*
*/
public class AddExpression extends SymbolExpression {
public AddExpression(Expression left, Expression right) {
super(left, right);
}
//处理相加
//var 仍然是 {a=10,b=20}..
//一会我们debug 源码,就ok
@Override
public int interpreter(HashMap<String, Integer> var) {
//super.left.interpreter(var) : 返回 left 表达式对应的值 a = 10
//super.right.interpreter(var): 返回right 表达式对应值 b = 20
return super.left.interpreter(var) + super.right.interpreter(var);
}
}
//--------------------------------------------------------------------
package com.gjxaiou.interpreter;
import java.util.HashMap;
public class SubExpression extends SymbolExpression {
public SubExpression(Expression left, Expression right) {
super(left, right);
}
//求出left 和 right 表达式相减后的结果
@Override
public int interpreter(HashMap<String, Integer> var) {
return super.left.interpreter(var) - super.right.interpreter(var);
}
}
Use an abstract class
package com.gjxaiou.interpreter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
public class ClientTest {
public static void main(String[] args) throws IOException {
String expStr = getExpStr(); // a+b
HashMap<String, Integer> var = getValue(expStr);// var {a=10, b=20}
Calculator calculator = new Calculator(expStr);
System.out.println("运算结果:" + expStr + "=" + calculator.run(var));
}
// 获得表达式
public static String getExpStr() throws IOException {
System.out.print("请输入表达式:");
return (new BufferedReader(new InputStreamReader(System.in))).readLine();
}
// 获得值映射
public 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.print("请输入" + String.valueOf(ch) + "的值:");
String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
map.put(String.valueOf(ch), Integer.valueOf(in));
}
}
}
return map;
}
}
Six to explain the mode in the source application framework Spring Analysis
Spring Framework SpelExpressionParser used to explain the mode to
+ Debug source code analysis
- Explanation
VII Notes and details of the mode of interpretation
When there is a need to explain the implementation of the language, the language can be expressed in a sentence as an abstract syntax tree, you can consider using an interpreter mode, so that the program has good scalability
Scenario: compiler, arithmetic expression evaluation, regular expressions, robots
The use of an interpreter may bring: Interpreter pattern can cause swelling class to explain the mode using a recursive call method will result in a very complex debugging, efficiency may be reduced.