From grimoire
Implements the Interpreter design pattern for small languages: define a grammar as a class hierarchy where each rule is a class and interpretation traverses that hierarchy.
How this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:apply-interpreter-patternThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Define a grammar for a language and represent each grammar rule as a class, using composition to interpret expressions.
Define a grammar for a language and represent each grammar rule as a class, using composition to interpret expressions.
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)
<expression> ::= <number>
| <expression> '+' <expression>
| <expression> '*' <expression>
from abc import ABC, abstractmethod
class Expression(ABC):
@abstractmethod
def interpret(self, context: dict) -> int: ...
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]
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)
# 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.
re), SQL (sqlparse), and math expressions (sympy) have mature parsers. Don't reimplement them.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.
npx claudepluginhub jeffreytse/grimoire --plugin grimoireTeaches Pythonic idioms, PEP 8 style, type hints, and best practices for writing readable, maintainable Python code. Useful when writing or reviewing Python code and designing packages.
DEPRECATED: No longer provides meaningful uplift over base model regex capabilities. Retained for reference only.
Guides adding a grammar handler for domain-specific file formats (e.g., GitHub Actions, Docker Compose) by inheriting from YamlGrammarBase, implementing content validation, metadata extraction, tests, and registration.