0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで実装するInterpreterパターン:文法をコードに変換するミニ言語設計

Posted at

概要

Interpreter(インタプリタ)パターンは、
文法ルール(構文)をクラス階層として表現し、式やコマンドを構文木として解釈・評価する設計パターンである。

SQL、正規表現、DSL(ドメイン固有言語)など、構造化された文法を扱うシステムで活用される


1. なぜInterpreterが必要か?

❌ 条件やルールを文字列ベースで処理すると保守性が低い

if expression == "A AND B":
    ...

文字列分解が煩雑になり、構文が拡張しづらい


✅ 文法をオブジェクトとして構成し、解釈・評価の責務を明確化

expr = And(Variable("A"), Variable("B"))
context = {"A": True, "B": False}
result = expr.interpret(context)

構文の拡張・再利用が容易になり、ミニ言語としても運用可能


2. 基本構造

✅ 抽象式インターフェース

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

✅ 終端式(TerminalExpression)

class Variable(Expression):
    def __init__(self, name):
        self.name = name

    def interpret(self, context):
        return context.get(self.name, False)

✅ 非終端式(NonTerminalExpression)

class And(Expression):
    def __init__(self, left: Expression, right: Expression):
        self.left = left
        self.right = right

    def interpret(self, context):
        return self.left.interpret(context) and self.right.interpret(context)

class Or(Expression):
    def __init__(self, left: Expression, right: Expression):
        self.left = left
        self.right = right

    def interpret(self, context):
        return self.left.interpret(context) or self.right.interpret(context)

✅ 使用例

expr = Or(Variable("A"), And(Variable("B"), Variable("C")))
context = {"A": False, "B": True, "C": True}

print(expr.interpret(context))  # True

3. Python的応用:ミニDSL構築のための柔軟なパターン

class Equal(Expression):
    def __init__(self, var, value):
        self.var = var
        self.value = value

    def interpret(self, context):
        return context.get(self.var) == self.value
rule = And(Equal("type", "admin"), Equal("status", "active"))
ctx = {"type": "admin", "status": "active"}
print(rule.interpret(ctx))  # True

複雑な条件を文法としてモデル化し、再利用可能なロジックへ


4. 実務ユースケース

✅ フォームバリデーション・入力チェックのDSL

IF age > 18 AND country == "JP" のようなルールを式として解釈


✅ 検索条件構築(例:ElasticSearch DSLやクエリビルダ)

→ ユーザ入力を構文木に変換し、柔軟な検索条件を構築


✅ ビジネスルールエンジン(ルールの柔軟な定義と評価)

price > 1000 AND category == "book" などのルールを解釈可能に


✅ 教育・演習目的のミニ言語開発(自作インタプリタ)

→ 電卓、ロジック言語、構文木ベースの評価エンジン


5. よくある誤用と対策

❌ 構文が複雑すぎてクラス数が肥大化

→ ✅ 複雑な構文はVisitorやパーサージェネレータに移行検討


❌ 解釈と構文構築の責務が混在する

→ ✅ 構文解析(パース)と評価(インタプリタ)を明確に分離


❌ 再帰評価によるパフォーマンス低下

→ ✅ 中間コードへの変換(AST → Bytecode)やキャッシュ導入を検討


結語

Interpreterパターンとは、“文法をコードに映し、構造化された解釈を可能にする設計”である。

  • 表現を式として定義することで、柔軟かつ安全に条件やロジックを操作可能に
  • 解釈・評価の責務を分離することで、可読性・保守性を高めた設計が可能に
  • Pythonでは抽象クラスと辞書によって、明快かつ直感的に実装可能

Pythonicとは、“式をコードとして扱い、構文を抽象すること”。
Interpreterパターンはその抽象性を、評価の知性として昇華する技法である。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?