Interpreter Mode
Definition: The interpreter pattern is the behavior pattern of the class. Given a language, the interpreter pattern can define a representation of its grammar and provide an interpreter at the same time. The client can use this interpreter to interpret the sentences in the language.
Structure of the Interpreter pattern
The following is an example of a schematic system that discusses the structure of the interpreter pattern. The structure diagram of the system is as follows:
The roles involved in the pattern are as follows:
(1) Abstract expression role: declares an abstract interface that all specific expression roles need to implement. This interface is primarily a interpret () method, which is called an interpretation operation.
(2) The Terminator expression (Terminal expression) role: Implements the interface required by the abstract expression role, mainly a interpret () method; each terminator in the grammar has a specific end expression corresponding to it. For example, there is a simple formula R=R1+R2, in which R1 and R2 are terminator, corresponding parsing R1 and R2 of the interpreter is the Terminator expression.
(3) Non-terminator expressions (nonterminal expression) role: Each rule in the grammar requires a specific non-terminator expression, the non-terminator expression is generally the syntax of the operator or other keywords, such as the formula R=R1+R2, "+" is not Terminator, The interpreter that parses "+" is a non-terminator expression.
(4) environment (context) role: The task of this role is generally used to store the grammar of the individual terminator corresponding to the specific values, such as R=R1+R2, we give the R1 value of 100, to R2 assigned value 200. This information needs to be stored in the environment role, and in many cases it is sufficient for us to use map to act as an environment role.
Specific cases
Context Environment role Public
class context {
private map<variable,integer> ValueMap = new hashmap<variable, Integer> ();
public void AddValue (Variable x, int y)
{
valuemap.put (x, y);
}
public int LookupValue (Variable x)
{
int i = valuemap.get (x);
return i;
}
}
Abstract expression role, or you can use an interface to implement public
abstract class Expression {public
abstract int interpret (Context con);
}
Terminator expression role Public
class Constant extends expression {
private int i;
Public Constant (int i) {
this.i = i;
}
public int interpret (Context con) {
return i;
}
}
public class Variable extends expression{public
int interpret (Context con)
{
// This is the variable object that calls the interpret method
return con. LookupValue (this);
}
}
Non-terminator expression role public
class Add extends expression {
Private expression left, right;
Public Add (expression left, expression right)
{
this.left = left;
This.right = right;
}
public int interpret (Context con)
{
return Left.interpret (Con) + Right.interpret (con);
}
}
public class Subtract extends expression {
Private expression left, right;
Public Subtract (expression left, expression right)
{
this.left = left;
This.right = right;
}
public int interpret (Context con)
{
return Left.interpret (Con)-right.interpret (con);
}
}
public class Multiply extends expression {
Private expression left, right;
Public Multiply (expression left, expression right)
{
this.left = left;
This.right = right;
}
public int interpret (Context con)
{
return Left.interpret (Con) * Right.interpret (con);
}
}
Public Class division extends expression{
private Expression left, right;
Public division (expression left, expression right)
{
this.left = left;
This.right = right;
}
public int interpret (Context con)
{
try {
return Left.interpret (Con)/Right.interpret (con);
} catch (ArithmeticException ae)
{
System.out.println ("The divisor is 0. ");
return-11111;}}}
Test procedure, calculation (A*B)/(a-b+2) Public
class Test {
private static Expression EX,EXA,EXS,EXM;
private static Context con;
public static void Main (string[] args)
{
con = new Context ();
Set variable, constant
Variable a = new Variable ();
Variable B = new Variable ();
Constant C = new Constant (2);
Assign a value to
a variable con.addvalue (a, ten);
Con.addvalue (b, 8);
operation, the structure of the sentence is analyzed by ourselves, constructing
exs=new Subtract (A, b);
Exa=new Add (Exs, c);
Exm=new Multiply (A, b);
ex = new Division (EXM, Exa);
SYSTEM.OUT.PRINTLN ("The result of the operation is:" + Ex.interpret (Con));}
}
Advantages and Disadvantages
The interpreter pattern provides an easy way to execute the syntax, and it is easy to modify or extend the syntax. Many classes in a general system use similar syntax, and an interpreter can be used instead of implementing an interpreter for each rule. and the different rules in the interpreter are implemented by different classes, which makes it easier to add a new syntax rule.
But the interpreter pattern is difficult to maintain for complex grammars. As you can imagine, each of these rules is supposed to correspond to a processing class, and these classes also have to recursively invoke abstract expression roles, and it's a horrible thing to be intertwined with mess classes.