Pythonで実現するInterpreterパターン：独自言語・DSLの構文解析と評価

# 

## 概要

**Interpreterパターン**は、  
特定の文法ルールを持つ言語（または式）を、構造として解釈し、**実行・評価できる仕組みを構築するパターン**である。

本パターンは、DSL（ドメイン固有言語）や構文木の構築、  
ミニスクリプト、ルールエンジンの実装など、**「言語のような構造」を定義する際に非常に有効**である。

---

## 1. なぜInterpreterが必要か？

### ❌ if/elif/else で全てを解析・評価

```python
if expr == "a + b":
    return a + b
elif expr == "a - b":
    return a - b
```

→ 条件分岐の羅列でロジックが硬直化し、**拡張不能・再利用不能**

---

### ✅ 「構文ルール」「構文木」「解釈」を構造として分離

```python
Expression = Add(Variable("a"), Variable("b"))
context = {"a": 3, "b": 5}
result = Expression.interpret(context)  # 8
```

→ **ルールベースで柔軟に解釈可能な言語構造が完成**

---

## 2. 基本構成

### ✅ 抽象構文（Expressionインタフェース）

```python
class Expression:
    def interpret(self, context):
        raise NotImplementedError
```

---

### ✅ 具体的構文ノード

```python
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)
```

---

### ✅ 実行例：式の構築と評価

```python
# 式: (a + 5) - b
expr = Subtract(
    Add(Variable("a"), Number(5)),
    Variable("b")
)

context = {"a": 10, "b": 3}
print(expr.interpret(context))  # → 12
```

---

## 3. Python的応用：再帰構文評価と構造の自動生成

### ✅ 再帰評価により、入れ子の式にも対応可能

```python
expr = Add(
    Add(Number(1), Number(2)),
    Subtract(Number(10), Number(4))
)
print(expr.interpret({}))  # → 1+2+(10-4) = 9
```

---

### ✅ 構文ツリーの自動構築（例：簡易パーサー）

```python
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]
```

```python
expr = parse(["3", "4", "+", "2", "-"])
print(expr.interpret({}))  # → 3 + 4 - 2 = 5
```

---

## 4. 実務ユースケース

### ✅ DSL（ドメイン固有言語）の構文解釈  
- ワークフロー定義、UI条件記述、データ変換DSLの解析器に応用可能

---

### ✅ ルールベースのフィルタ・スクリプト実行

```python
expr = And(Equals(Variable("type"), Number(1)), GreaterThan(Variable("score"), Number(80)))
```

→ 組織内評価ロジックや検閲フィルターの柔軟定義が可能

---

### ✅ SQL風構文の解釈・トランスパイル基盤

→ SELECTやWHERE節のような構文を**クラス構造として再現・評価**

---

## 5. よくある誤用と対策

### ❌ 構文ノードに解釈以外の責務が混在

→ ✅ `interpret()` のみに責務を集中し、出力や副作用は他に委譲

---

### ❌ ノード数が膨大になりメンテ困難

→ ✅ 共通演算を Mixin などで抽象化し、**構文木設計をモジュール化**

---

### ❌ 表現力を追い求めすぎて本末転倒

→ ✅ Interpreterパターンはあくまで「小さな言語」向き  
→ 巨大な構文は **パーサジェネレータやAST解析ツール**の方が適切

---

## 結語

Interpreterパターンとは、**「ロジックをコードではなく構文として記述する」ための設計哲学**である。

- DSLの実行基盤や構文木の定義が容易に
- 柔軟かつテスト可能な評価機構の構築
- 複雑なロジックも、「構文」としての操作対象に抽象化可能

**Pythonicとは、“振る舞いを操作可能な構造に変える”ことであり、  
Interpreterパターンはその構造設計において、柔らかくも強靭な言語的解釈力を与える。**