The Interpreter Pattern provides a way to evaluate the syntax or expressions of a language. It belongs to the behavioral pattern and implements an expression interface that interprets a specific context. The Interpreter Pattern is often used in SQL parsing, symbol processing engines, and more.
In software development, there are often repetitive problems with a certain similarity and regularity. If these problems can be generalized into a simple language, then the instances of these problems will be sentences of that language. This can be implemented using the interpreter pattern from compilation theory. The interpreter pattern defines a language for analyzing objects and represents the grammar of the language. It then designs a parser to interpret the sentences in the language, that is, to analyze instances in the application in the same way as in compiled languages. The concepts of grammar and sentences mentioned here are the same as those described in compilation theory. The grammar refers to the language's syntax rules, while the sentences are elements of the language.
- Abstract Expression
Expression
role: Declares an interface that all concrete expression roles need to implement. This interface mainly consists of aninterpret()
method, called the interpretation operation. - Terminal Expression
Terminal Expression
role: Implements the interface required by the abstract expression role, mainly aninterpret()
method. Each terminal in the grammar has a specific terminal expression corresponding to it. For example, in a simple formula likeR=R1+R2
,R1
andR2
are terminals, and their interpreters are terminal expressions. - Non-terminal Expression
Nonterminal Expression
role: Each rule in the grammar requires a specific non-terminal expression. Non-terminal expressions are generally operators or other keywords in the grammar. For example, in the formulaR=R1+R2
,+
is a non-terminal, and the interpreter for+
is a non-terminal expression. - Context
Context
role: The task of this role is generally to store the specific values corresponding to each terminal in the grammar. For example, inR=R1+R2
, we assign100
toR1
and200
toR2
. This information needs to be stored in the context role. In many cases, using aMap
as the context role is sufficient.
- Good extensibility: In the interpreter pattern, language grammar rules are represented using classes, so the grammar can be changed or extended through mechanisms such as inheritance.
- Easy implementation: Each expression node class in the syntax tree is similar, making it relatively easy to implement the grammar.
- Low execution efficiency: The interpreter pattern typically uses a large number of loops and recursive calls. When interpreting complex sentences, the execution speed is slow, and the debugging process is also cumbersome.
- Class proliferation: Each rule in the interpreter pattern requires at least one class definition. When there are many grammar rules, the number of classes will increase sharply, making the system difficult to manage and maintain.
- Limited application scenarios: There are very few instances in software development where language grammar needs to be defined, so this pattern is rarely used.
function Context() {
var sum = 0;
var list = [];
this.getSum = function() {
return sum;
}
this.setSum = function(_sum) {
sum = _sum;
}
this.add = function(eps) {
list.push(eps);
}
this.getList = function() {
return list;
}
}
function PlusExpression() {
this.interpret = function(context) {
var sum = context.getSum();
sum++;
context.setSum(sum);
}
}
function MinusExpression() {
this.interpret = function(context) {
var sum = context.getSum();
sum--;
context.setSum(sum);
}
}
(function() {
var context = new Context();
context.setSum(20);
// Run addition three times
context.add(new PlusExpression());
context.add(new PlusExpression());
context.add(new PlusExpression());
// Run subtraction twice
context.add(new MinusExpression());
context.add(new MinusExpression());
var list = context.getList();
for (var i = 0; i < list.length; i++) {
let expression = list[i];
expression.interpret(context);
}
console.log(context.getSum()); // 21
})();
https://github.com/WindrunnerMax/EveryDay
http://c.biancheng.net/view/1402.html
https://blog.csdn.net/itpinpai/article/details/51657199
https://www.runoob.com/design-pattern/interpreter-pattern.html