Interpreter Pattern


In real life, an interpreter is one who translates one language into another. On similar lines, the interpreter pattern is useful when we have data in another language - perhaps an XML/JSON or some incoming data or just a regular expression - that we have to use in our code. Here, we need to convert a complex text or byte sequence into useful logic.

The interpreter pattern is very rarely used - because most interpreters are already implemented. But it is worthwhile understanding it in detail.

Any language is state based. A new piece of incoming data is meaningful in the context of what had come before it. And we cannot conclude we have understood it until we have absorbed the whole of it - since potentially, the last chunk can negate all that we got before it.

Thus, the interpreter has a Context that is built up by the incoming Expressions and this is built until it encounters the Terminal Expression that announces that there is no more data to be consumed.

The Interpreter pattern is used exhaustively to define grammars, tokenize input and store it. It can be used in rules engines. We can also use the Interpreter pattern to add functionality to the composite pattern.

Participants


The Interpreter pattern has 5 players:

  • AbstractExpression - Declares an abstract Interpret operation that is common to all nodes
  • in the abstract syntax tree.
  • TerminalExpression - Implements an Interpret operation associated with terminal symbols
  • in the grammar. An instance is required for every terminal symbol in a sentence.
  • NonterminalExpression - (AlternationExpression, RepetitionExpression, SequenceExpressions) - One such class is required for every rule R ::= R1 R2 ... Rn in the grammar. Maintains instance variables of type AbstractExpression - for each of the symbols R1 through Rn. Implements an Interpret operation for nonterminal symbols in the grammar. Interpret typically calls itself recursively on the variables representing R1 through Rn.
  • Context - Contains information that's global to the interpreter.
  • Client - Builds (or is given) an abstract syntax tree representing a particular sentence in the language that the grammar defines. The abstract syntax tree is assembled from instances of the NonterminalExpression and TerminalExpression classes. Invokes the Interpret operation.