The interpreter pattern is specific implementation of the composite pattern generally used for language parsing. In the interpreter pattern a class is produced for each symbol in the language. A statement can then be broken down into a syntax tree of these classes which can in turn be used to interpret the statement.
You should use Interpreter when there is a language that you need to interpret and when the statements of the language can be represented as abstract syntax trees. It works best when:
- the grammar of the language is simple. Otherwise, the class hierarchy for the grammar becomes large and complex.
- the grammar is stable and known when developing the class structure. The interpreter pattern could not be used if the grammar is user definable, for example.
- efficiency is not essential.
This class defines the interpret() operation which is implemented by all nodes in the abstract syntax tree.
This class implements the interpret() operation. A separate class or subclass is needed for each terminal symbol.
This class also implements the interpret() operation which typically calls itself recursively for all parts the nonterminal is composed of. A separate class or subclass of this is required for each rule in the grammar.
This class contains information that's global to the interpreter.
This class builds the abstract syntax tree (from Terminals and Nonterminals) for one statement in the language defined by the grammar. It then goes on to invoke the interpret() operation.
- Interpreter makes it easy to change and extend the grammar using inheritance.
- Implementing the grammar is easy because the nodes in the abstract syntax tree have similar interpretations and are usually easy to write. Often, writing these classes can be automated using a compiler or parser generator.
- It is hard to maintain complex grammar using Interpreter because it defines at least one class for every rule in the grammar. This can soon lead to a huge number of classes.
- It is easy to add new ways to interpret an expression.
- Composite: The abstract syntax tree uses a Composite pattern.
- Flyweight: This pattern can be used to share the terminal symbols.
- Iterator: This pattern can be used to traverse the Interpreter structure.
- Visitor: This pattern can be used to collect the behavior for all abstract syntax tree nodes in one class.
Creational: Abstract Factory | Builder | Factory Method | Prototype | Singleton