Use when you need to interpret sentences in a simple language — defining a grammar as a class hierarchy where each rule is a class and interpreting an expression is traversing that hierarchy.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add jeffreytse/grimoire-core --skill apply-interpreter-pattern --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Apply Interpreter Pattern?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jeffreytse-apply-interpreter-pattern)More formats (shields.io, HTML) on the badges page.
---
name: apply-interpreter-pattern
description: Use when you need to interpret sentences in a simple language — defining a grammar as a class hierarchy where each rule is a class and interpreting an expression is traversing that hierarchy.
source: "Gamma, Helm, Johnson, Vlissides, \"Design Patterns: Elements of Reusable Object-Oriented Software\" (1994) pp. 243–255; Python ast module; SQL query parsers; regular expression engines; Excel formula evaluation"
tags: [design-patterns, behavioral, interpreter, oop, developer, language-processing, expression-evaluation]
related: [apply-composite-pattern, apply-visitor-pattern, apply-solid-principles]
---
# Apply Interpreter Pattern
Define a grammar for a language and represent each grammar rule as a class, using composition to interpret expressions.
## Why This Is Best Practice
**Adopted by:** Python's `ast` module (every Python expression is an AST node that
interprets itself — the foundation of all Python compilers, linters, and tools), Java's
`javax.script` (script interpreter architecture), SQL database engines (query expressions
are parsed into an AST where each node knows how to evaluate itself), and Excel (cell
formula evaluation traverses an expression tree).
**Impact:** GoF documents that Interpreter makes grammar rules independently changeable
and combinable. Python's `ast` module design enables the entire ecosystem of static
analysis tools (Flake8, mypy, Bandit) — each tool visits the same expression tree
without modifying the parser.
**Why best:** The alternative — a large `if/elif` parser — puts all rules in one method.
Adding a new grammar rule requires modifying that method. Interpreter makes each rule
an independent class — adding a rule means adding a class, not editing existing code.
Sources: Gamma et al. (1994) pp. 243–255; Python `ast` module documentation;
ANTLR4 documentation (widely-used parser generator that embodies the Interpreter pattern)
## Steps
### Step 1: Define the grammar (small and simple — this pattern suits narrow DSLs)
```
<expression> ::= <number>
| <expression> '+' <expression>
| <expression> '*' <expression>
```
### Step 2: Define the abstract expression interface
```python
from abc import ABC, abstractmethod
class Expression(ABC):
@abstractmethod
def interpret(self, context: dict) -> int: ...
```
### Step 3: Implement terminal expressions (leaves — no sub-expressions)
```python
class NumberExpression(Expression):
def __init__(self, value: int):
self._value = value
def interpret(self, context: dict) -> int:
return self._value
class VariableExpression(Expression):
def __init__(self, name: str):
self._name = name
def interpret(self, context: dict) -> int:
return context[self._name]
```
### Step 4: Implement non-terminal expressions (composites — have sub-expressions)
```python
class AddExpression(Expression):
def __init__(self, left: Expression, right: Expression):
self._left = left
self._right = right
def interpret(self, context: dict) -> int:
return self._left.interpret(context) + self._right.interpret(context)
class MultiplyExpression(Expression):
def __init__(self, left: Expression, right: Expression):
self._left = left
self._right = right
def interpret(self, context: dict) -> int:
return self._left.interpret(context) * self._right.interpret(context)
```
### Step 5: Build and interpret an expression tree
```python
# Represents: (x + 3) * 2
context = {"x": 5}
expr = MultiplyExpression(
AddExpression(VariableExpression("x"), NumberExpression(3)),
NumberExpression(2)
)
print(expr.interpret(context)) # (5 + 3) * 2 = 16
```
Note: expression trees are typically built by a parser, not manually. Interpreter
defines the evaluation step; parsing is a separate concern.
## When NOT to Use
- **Complex grammars** — GoF explicitly warns against using Interpreter for complex languages. Use a real parser generator (ANTLR, PLY, lark-parser) instead.
- **Performance-critical expression evaluation** — recursive tree traversal is slow for large expressions. Compiled languages parse to bytecode for a reason.
- **When an existing library covers the domain** — regular expressions (`re`), SQL (`sqlparse`), and math expressions (`sympy`) have mature parsers. Don't reimplement them.
## Common Mistakes
**Using Interpreter for a complex language.** If the grammar has more than 10 rules or requires backtracking, use a parser generator. Interpreter doesn't scale to real languages.
**Mixing parsing and interpretation.** The Interpreter pattern covers evaluation of an already-parsed expression tree. Building the tree (parsing) is a separate step and should be separate code.
**Not handling context errors.** If `context["x"]` is missing, `VariableExpression.interpret()` raises `KeyError`. Validate context before interpretation or catch and wrap errors.Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!