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:

  1. 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.
  2. 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.
  3. 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