15. Interpreter mode

Given a language, define a representation of its grammar, and define an interpreter that uses that representation to interpret sentences in the language.

Class Diagram

Code example

1.	class Context {}  
2.	abstract class Expression {  
3.	    public abstract Object interpreter(Context ctx);  
4.	}  
5.	class TerminalExpression extends Expression {  
6.	    public Object interpreter(Context ctx){  
7.	        return null;  
8.	    }  
9.	}  
10.	class NonterminalExpression extends Expression {  
11.	    public NonterminalExpression(Expression...expressions){  
12.	          
13.	    }  
14.	    public Object interpreter(Context ctx){  
15.	        return null;  
16.	    }  
17.	}  
18.	public class Client {  
19.	    public static void main(String[] args){  
20.	        String expression = "";  
21.	        char[] charArray = expression.toCharArray();  
22.	        Context ctx = new Context();  
23.	        Stack<Expression> stack = new Stack<Expression>();  
24.	        for(int i=0;i<charArray.length;i++){  
25.	            //进行语法判断,递归调用  
26.	        }  
27.	        Expression exp = stack.pop();  
28.	        exp.interpreter(ctx);  
29.	    }  
30.	}  

The code part of grammatical recursion needs to be implemented according to the specific situation, so it is not reflected in the code. Abstract expressions are the key to generating grammar sets. Each non-terminal symbol expression interprets a minimum grammatical unit, and then recursively combines these grammatical units into a complete grammar. This is the interpreter mode.

Parser mode structure

  1. Abstract interpreter: Declare an abstract interface (or abstract class) that all concrete expressions must implement. The interface is mainly an interpret() method, which is called an interpretation operation. The specific interpretation task is completed by its various implementation classes, and the specific interpreters are respectively completed by the terminal interpreter TerminalExpression and the non-terminal interpreter NonterminalExpression.
  2. Terminal expression: realize the interpretation operation associated with the elements in the grammar. Usually, there is only one terminal expression in an interpreter mode, but there are multiple instances, corresponding to different terminal symbols. The terminal symbol is half of the operation unit in the grammar. For example, there is a simple formula R=R1+R2, in which R1 and R2 are terminal symbols, and the corresponding interpreter that parses R1 and R2 is terminal expression.                                
  3. Non-terminal symbol expression: each rule in the grammar corresponds to a non-terminal symbol expression. Non-terminal symbol expressions are generally operators or other keywords in the grammar. For example, in the formula R=R1+R2, + is not Terminal symbol, the interpreter that parses + is a non-terminal symbol expression. Non-terminal symbol expressions increase according to the complexity of the logic. In principle, each grammar rule corresponds to a non-terminal symbol expression.
  4. Environmental role: The task of this role is generally to store the specific value corresponding to each terminal symbol in the grammar, such as R=R1+R2, we assign 100 to R1 and 200 to R2. This information needs to be stored in the environmental role. In many cases, it is sufficient to use Map to act as the environmental role.

Advantages and disadvantages of interpreter mode

The interpreter is a simple grammatical analysis tool. Its most significant advantage is its extensibility. To modify the grammar rules, you only need to modify the corresponding non-terminal symbols. If you expand the grammar, you only need to add non-terminal symbols.

However, the interpreter mode will cause the expansion of classes. Each grammar needs to produce a non-terminal symbol expression. When the grammar rules are more complicated, a large number of class files may be generated, which brings a lot of trouble to maintenance. At the same time, due to the recursive call method, each non-terminal expression only cares about the expressions related to itself, and each expression needs to know the final result, which must be recursive, whether it is an object-oriented language or a process-oriented language , Recursion is not recommended. Due to the use of a large number of loops and recursion, efficiency is an issue that cannot be ignored. Especially when used to explain a complex and lengthy grammar, the efficiency is unbearable.

Interpreter mode usage scenarios

Interpreter mode can be used in the following situations:

  1. There is a simple grammatical rule, such as a sql statement. If we need to perform rm conversion based on the sql statement, we can use the interpreter mode to interpret the statement.
  2. Some recurring problems, such as the four arithmetic operations of addition, subtraction, multiplication and division, but the formula is different every time, sometimes it is a+bc*d, sometimes a*b+cd, etc., etc., the formula is ever-changing, but it is always added Subtract, multiply and divide the four non-terminals to connect, then we can use the interpreter mode.

 

Guess you like

Origin blog.csdn.net/sinat_37138973/article/details/88636537