Behavioral

Interpreter

Interpreter turns a sentence in a small language - say, the expression x + 5 - 2 - into a tree of objects, one class per rule (number, variable, addition, subtraction). Getting the answer is just calling one method on the root: each object works out its own piece by asking its children for theirs, so the tree evaluates itself.

Complexity
Popularity

Problem

Imagine building a small calculator that evaluates arithmetic expressions typed in as text, like x + 5 - 2, where x is a variable that can hold any number. The rules are tiny - numbers, variables, addition, subtraction - but they combine in endless ways: x + 5, (x + 5) - 2, 2 - (x + 5), and so on.

A quick fix is one big function that scans the string and handles each case with a pile of if/else. It works for a couple of examples, then falls apart as soon as expressions nest deeper or a new operator shows up, because parsing and evaluating are tangled together in one place with no reusable pieces.

What's missing is a way to treat "a number", "a variable", "a sum", and "a difference" as separate, composable building blocks - instead of special cases buried inside one big block of code.

Solution

Interpreter turns each grammar rule into its own class, all sharing one interpret method that produces a result when called. Simple pieces of the expression - a number, a variable - become terminal expression classes that know their value directly. Compound pieces - a sum, a difference - become nonterminal expression classes that hold their sub-expressions and combine whatever those return.

The expression x + 5 - 2 is built once into a small tree: a subtraction node holding an addition node (variable x and number 5) and a number node (2). Evaluating the whole expression is just calling interpret on the root - the recursion works its way down the tree and combines the results back up. Adding a new operator, like multiplication, means adding one new nonterminal class - the rest of the tree, and the rest of the grammar, doesn't change.

When to Use

  • Reach for Interpreter when the language you need to evaluate is genuinely small and its sentences map cleanly onto a tree of a handful of rule types.
  • It pays off when the grammar is expected to stay stable; a rapidly growing rule set is a sign to switch to a parser generator instead.
  • It's a reasonable choice when raw evaluation speed matters less than having a clear, testable, one-rule-per-class model of the language.

Real-World Examples

  • Regex engines - a compiled pattern becomes a tree of matcher nodes (literal, concatenation, alternation, repetition) that walk an input string and report a match.
  • ORM query builders - libraries like SQLAlchemy or Django's ORM build a tree of filter and predicate objects from chained method calls, then interpret that tree into SQL at execution time.
  • Spreadsheet formula engines - an expression like =A1 + B2 * 2 is parsed into a tree of cell references and operators that the spreadsheet interprets to produce the cell's displayed value.