Applied Design Patterns with Java
Behavioral :: Interpreter (243) {C ch 18}
Implementation
The Interpreter and Composite
(163) patterns share many implementation issues.
The following issues are specific to Interpreter:
- Creating the abstract syntax tree. The Interpreter pattern doesn't explain how to create an abstract syntax tree. It doesn't address
parsing. The abstract syntax tree can be created by a table-driven parser, by a hand-crafted (usually recursive
descent) parser, or directly by the client.
- Defining the Interpret operation. It's not necessary to define the Interpret operation in the expression classes.
If it's common to create a new Interpreter,
then it's better to use the Visitor (331) pattern to put Interpret in a separate "visitor" object.
A grammar
for a programming language will have many operations on abstract syntax trees, such as as type-checking, optimization,
code generation, and so on. It will be more likely to use a Visitor to avoid defining these operations on every grammar class.
- Sharing terminal symbols with the Flyweight
pattern. Grammars whose sentences contain many occurrences
of a terminal symbol might benefit from sharing a single copy of that symbol. Grammars for computer programs are
good examples—each program variable will appear in many places throughout the code. Terminal
nodes generally don't store information about their position in the abstract syntax tree. Parent nodes pass them
whatever context they need during interpretation. There is a distinction between shared (intrinsic) state and passed-in
(extrinsic) state, and the Flyweight (195) pattern applies. Each instance
of LiteralExpression for dog receives a context containing the substring matched so far. Every LiteralExpression
does the same thing in its Interpret operation—it checks whether the next part of the input contains a dog—no matter
where the instance appears in the tree.
Related Patterns
Composite (163): The abstract syntax tree is an instance of the Composite pattern.
Flyweight (195) shows how to share terminal symbols within the abstract syntax tree.
Iterator (257): The Interpreter can use an Iterator to traverse the structure.
Visitor (331) can be used to maintain the behavior in each node in the abstract syntax tree in one class.
Catalog Behavioral Prev Next