概要
Interpreterパターンは、
特定の文法ルールを持つ言語(または式)を、構造として解釈し、実行・評価できる仕組みを構築するパターンである。
本パターンは、DSL(ドメイン固有言語)や構文木の構築、
ミニスクリプト、ルールエンジンの実装など、「言語のような構造」を定義する際に非常に有効である。
1. なぜInterpreterが必要か?
❌ if/elif/else で全てを解析・評価
if expr == "a + b":
return a + b
elif expr == "a - b":
return a - b
→ 条件分岐の羅列でロジックが硬直化し、拡張不能・再利用不能
✅ 「構文ルール」「構文木」「解釈」を構造として分離
Expression = Add(Variable("a"), Variable("b"))
context = {"a": 3, "b": 5}
result = Expression.interpret(context) # 8
→ ルールベースで柔軟に解釈可能な言語構造が完成
2. 基本構成
✅ 抽象構文(Expressionインタフェース)
class Expression:
def interpret(self, context):
raise NotImplementedError
✅ 具体的構文ノード
class Number(Expression):
def __init__(self, value):
self.value = value
def interpret(self, context):
return self.value
class Variable(Expression):
def __init__(self, name):
self.name = name
def interpret(self, context):
return context[self.name]
class Add(Expression):
def __init__(self, left, right):
self.left = left
self.right = right
def interpret(self, context):
return self.left.interpret(context) + self.right.interpret(context)
class Subtract(Expression):
def __init__(self, left, right):
self.left = left
self.right = right
def interpret(self, context):
return self.left.interpret(context) - self.right.interpret(context)
✅ 実行例:式の構築と評価
# 式: (a + 5) - b
expr = Subtract(
Add(Variable("a"), Number(5)),
Variable("b")
)
context = {"a": 10, "b": 3}
print(expr.interpret(context)) # → 12
3. Python的応用:再帰構文評価と構造の自動生成
✅ 再帰評価により、入れ子の式にも対応可能
expr = Add(
Add(Number(1), Number(2)),
Subtract(Number(10), Number(4))
)
print(expr.interpret({})) # → 1+2+(10-4) = 9
✅ 構文ツリーの自動構築(例:簡易パーサー)
def parse(tokens):
stack = []
for token in tokens:
if token.isdigit():
stack.append(Number(int(token)))
elif token in ["+", "-"]:
right = stack.pop()
left = stack.pop()
if token == "+":
stack.append(Add(left, right))
else:
stack.append(Subtract(left, right))
return stack[0]
expr = parse(["3", "4", "+", "2", "-"])
print(expr.interpret({})) # → 3 + 4 - 2 = 5
4. 実務ユースケース
✅ DSL(ドメイン固有言語)の構文解釈
- ワークフロー定義、UI条件記述、データ変換DSLの解析器に応用可能
✅ ルールベースのフィルタ・スクリプト実行
expr = And(Equals(Variable("type"), Number(1)), GreaterThan(Variable("score"), Number(80)))
→ 組織内評価ロジックや検閲フィルターの柔軟定義が可能
✅ SQL風構文の解釈・トランスパイル基盤
→ SELECTやWHERE節のような構文をクラス構造として再現・評価
5. よくある誤用と対策
❌ 構文ノードに解釈以外の責務が混在
→ ✅ interpret()
のみに責務を集中し、出力や副作用は他に委譲
❌ ノード数が膨大になりメンテ困難
→ ✅ 共通演算を Mixin などで抽象化し、構文木設計をモジュール化
❌ 表現力を追い求めすぎて本末転倒
→ ✅ Interpreterパターンはあくまで「小さな言語」向き
→ 巨大な構文は パーサジェネレータやAST解析ツールの方が適切
結語
Interpreterパターンとは、「ロジックをコードではなく構文として記述する」ための設計哲学である。
- DSLの実行基盤や構文木の定義が容易に
- 柔軟かつテスト可能な評価機構の構築
- 複雑なロジックも、「構文」としての操作対象に抽象化可能
Pythonicとは、“振る舞いを操作可能な構造に変える”ことであり、
Interpreterパターンはその構造設計において、柔らかくも強靭な言語的解釈力を与える。