Tag: Key pack code express separates specific Lex value type
Tenth chapter, Interpreter mode
The interpreter pattern is a less-than-used behavioral pattern. It provides a way to interpret a language's syntax or expression.
But its use is very widespread, just because we very rarely go back to construct a language grammar, so use less.
1. Definition
Given a language, define a representation of its grammar and define an interpreter that uses that representation to interpret sentences in the language.
(The language is the object we need to explain, grammar is the law of the language, the interpreter is the translator.) Language is translated by grammar. )
2. Usage Scenarios
1. Consider using the interpreter pattern when a simple language needs to be interpreted to run and be able to represent the statements in that language as an abstract syntax tree.
2. In the case of recurrent problems in certain areas, it is possible to translate the problems in this area into statements under a grammatical rule. Then build the interpreter to interpret the statement.
3. Simple implementation
We use the interpreter pattern to interpret the expression "m+n+p", so that the M, N, and p representing the numbers can be regarded as the terminating symbol, and the "+" operation symbol can be used as a non-terminating symbol.
terminalexpression: Terminator expression that implements the interpretation of Terminator in grammar.
Each terminator in the grammar has a detailed end expression corresponding to it.
nonterminalexpression : Non-terminator expression, which implements the interpretation of non-terminator in grammar. Non-terminator expressions are added based on the complexity of the logic. In principle, each grammar rule corresponds to a non-terminator expression.
An abstract arithmetic operator interpreter
publicabstractclass ArithemticExpression { /** * 抽象的解析方法 * 详细的解析逻辑由详细的子类实现 * * @return 解析得到详细的值 */ publicabstractintinterpreter();}
Digital Interpreter
publicclass NumExpression extends ArithemticExpression{ privateint num; publicNumExpression(int num){ this.num = num; } @Override publicintinterpreter() { return num; }}
operator symbol Interpreter
publicabstractclass OperatorExpression extends ArithemticExpression{ protected ArithemticExpression exp1, exp2; publicOperatorExpression(ArithemticExpression exp1, ArithemticExpression exp2){ this.exp1 = exp1; this.exp2 = exp2; }}
Detailed addition operator interpreter
publicclass AdditionExpression extends OperatorExpression{ publicAdditionExpression(ArithemticExpression exp1, ArithemticExpression exp2) { super(exp1, exp2); } @Override publicintinterpreter() { return exp1.interpreter() + exp2.interpreter(); }}
Processing interpreter
Public class Calculator { //Declare a stack stack to store and manipulate all relevant interpreters PrivateStack<arithemticexpression> Mexpstack =NewStack<arithemticexpression> (); Public Calculator(String expression) {//Declare two temporary variables of type arithemticexpression, store operator's left and right digital interpreterArithemticexpression EXP1,EXP2;//Based on space Cut expression string (1 + 2 + 3 + 4, for example)string[] elements = Expression.split (" ");/ * * Iterate through an array of expression elements * / for(inti =0; i < elements.length; i++) {/ * Infer operation symbol * / Switch(Elements[i].charat (0)) { Case ' + '://Assuming a plus, the interpreter in the stack pops up as the interpreter to the left of the operator symbolEXP1 = Mexpstack.pop ();//At the same time constructs the next element of the array of operation symbols as a digital interpreterEXP2 =NewNumexpression (Integer.parseint (elements[++i));//Construct addition operation interpreter through the above two number interpreterMexpstack.push (NewAdditionexpression (EXP1, EXP2)); Break;default:/ * * Assuming a number, construct the digital interpreter directly and press it into the stack */Mexpstack.push (NewNumexpression (integer.valueof (elements[i))); Break; } } }/** * Calculation results * * @return finally calculated results */ Public int Calculate(){returnMexpstack.pop (). Interpreter (); }}
Call
publicclass Client { publicstaticvoidmain(String[] args) { new Calculator("22 + 553 + 83 + 5"); System.out.println("计算结果:"+c.calculate()); }}
Results:
计算结果:663
Assuming the addition of operations such as subtraction, add the appropriate inference in calculator to:
publicclass SubtractionExpression extends OperatorExpression{ publicSubtractionExpression(ArithemticExpression exp1, ArithemticExpression exp2) { super(exp1, exp2); } @Override publicintinterpreter() { return exp1.interpreter() - exp2.interpreter(); }}
Added in calculator:
case‘-‘: exp1 = mExpStack.pop(); new NumExpression(Integer.parseInt(elements[++i])); mExpStack.push(new SubtractionExpression(exp1, exp2)); break;
From above we can see that the interpreter mode is very flexible, he can simplify the complex problems, modularization, separation, implementation, interpretation of the operation.
4.Android pattern Implementation in source code 1.PackageParser
Packageparser is to read the Androidmanifest.xml configuration file, the detailed principle of reference: Analysis Androidmanifest principle
5. Summary 1. Strengths
The greatest strength makes it flexible to extend when we want to extend the grammar rules. Just add the corresponding non-terminator interpreter, and when building the abstract syntax tree. It is convenient to use the new interpreter object for a detailed explanation.
2. Disadvantages
1. Each grammar produces a non-terminator expression, and the grammatical rules are more complex. It is possible to generate a large number of class files, which poses a lot of trouble for maintenance.
2. The interpreter mode is due to the use of a large number of loops and recursion. Efficiency is a problem, especially when it comes to parsing complex, lengthy grammars, and efficiency is unbearable.
6. References
References Link: Interpreter mode detailed explanation
"Android source code design mode analysis and actual combat" reading notes (10)