Skip to content

Interpreter Pattern

Category: Behavioral Pattern

Overview

Define a representation for a grammar along with an interpreter that uses the representation to interpret sentences in the language. This pattern is used to evaluate sentences by representing grammar rules as classes and interpreting expressions recursively.

Usage Guidelines

Use when:

  • Grammar is simple and well-defined
  • Efficiency is not a primary concern
  • Need to evaluate expressions in a language
  • Implementing simple business rule engines

Avoid when:

  • Grammar is complex (use parser generators instead)
  • Performance is critical as interpretation adds overhead
  • Compilation to bytecode would be more efficient
  • Standard parsing libraries suffice

Implementation

class Expression:
    """Base class for interpreting expressions in a given context."""

    def interpret(self, context: str) -> bool:
        """Interpret the given context.

        Args:
            context: The input context to interpret.

        Returns:
            bool: The result of the interpretation.
        """
        pass

class TerminalExpression(Expression):
    """Terminal expression that checks for a literal value."""

    def __init__(self, literal: str) -> None:
        self.literal = literal

    def interpret(self, context: str) -> bool:
        """Check if the context contains the literal."""
        return self.literal in context

class OrExpression(Expression):
    """Non-terminal expression for logical OR."""

    def __init__(self, expr1: Expression, expr2: Expression) -> None:
        self.expr1 = expr1
        self.expr2 = expr2

    def interpret(self, context: str) -> bool:
        """Return true if either expression is true."""
        return self.expr1.interpret(context) or self.expr2.interpret(context)

class AndExpression(Expression):
    """Non-terminal expression for logical AND."""

    def __init__(self, expr1: Expression, expr2: Expression) -> None:
        self.expr1 = expr1
        self.expr2 = expr2

    def interpret(self, context: str) -> bool:
        """Return true if both expressions are true."""
        return self.expr1.interpret(context) and self.expr2.interpret(context)

Usage

# Build expression: "John" AND "Doe"
john = TerminalExpression("John")
doe = TerminalExpression("Doe")
is_john_doe = AndExpression(john, doe)

print(is_john_doe.interpret("John Doe"))  # True
print(is_john_doe.interpret("John Smith"))  # False

# Build expression: "Manager" OR "Director"
manager = TerminalExpression("Manager")
director = TerminalExpression("Director")
is_leadership = OrExpression(manager, director)

print(is_leadership.interpret("Senior Manager"))  # True
print(is_leadership.interpret("Software Engineer"))  # False

Trade-offs

Benefits:

  1. Easy to add new grammar rules through extensibility
  2. Grammar and interpretation are separate concerns
  3. Grammar can be modified by composing expressions
  4. Expression objects can be reused

Drawbacks:

  1. Many classes for complex grammars causing class proliferation
  2. Interpretation is slower than compiled alternatives
  3. Complex grammars lead to complex class hierarchies
  4. Large grammars are hard to maintain

Real-World Examples

  • SQL interpreters parsing and executing queries
  • Regular expressions for pattern matching
  • Mathematical expressions evaluation
  • Business rule engines
  • Composite
  • Flyweight
  • Iterator
  • Visitor

API Reference

design_patterns.behavioral.interpreter

AndExpression

Bases: Expression

Non-terminal expression for logical AND.

Source code in src/design_patterns/behavioral/interpreter.py
class AndExpression(Expression):
    """Non-terminal expression for logical AND."""

    def __init__(self, expr1: Expression, expr2: Expression) -> None:
        self.expr1 = expr1
        self.expr2 = expr2

    def interpret(self, context: str) -> bool:
        """Return true if both expressions are true."""
        return self.expr1.interpret(context) and self.expr2.interpret(context)

interpret(context)

Return true if both expressions are true.

Source code in src/design_patterns/behavioral/interpreter.py
def interpret(self, context: str) -> bool:
    """Return true if both expressions are true."""
    return self.expr1.interpret(context) and self.expr2.interpret(context)

Expression

Base class for interpreting expressions in a given context.

Source code in src/design_patterns/behavioral/interpreter.py
class Expression:
    """Base class for interpreting expressions in a given context."""

    def interpret(self, context: str) -> bool:
        """
        Interpret the given context.

        Args:
            context (str): The input context to interpret.

        Returns:
            bool: The result of the interpretation.
        """
        pass

interpret(context)

Interpret the given context.

Parameters:

Name Type Description Default
context str

The input context to interpret.

required

Returns:

Name Type Description
bool bool

The result of the interpretation.

Source code in src/design_patterns/behavioral/interpreter.py
def interpret(self, context: str) -> bool:
    """
    Interpret the given context.

    Args:
        context (str): The input context to interpret.

    Returns:
        bool: The result of the interpretation.
    """
    pass

OrExpression

Bases: Expression

Non-terminal expression for logical OR.

Source code in src/design_patterns/behavioral/interpreter.py
class OrExpression(Expression):
    """Non-terminal expression for logical OR."""

    def __init__(self, expr1: Expression, expr2: Expression) -> None:
        self.expr1 = expr1
        self.expr2 = expr2

    def interpret(self, context: str) -> bool:
        """Return true if either expression is true."""
        return self.expr1.interpret(context) or self.expr2.interpret(context)

interpret(context)

Return true if either expression is true.

Source code in src/design_patterns/behavioral/interpreter.py
def interpret(self, context: str) -> bool:
    """Return true if either expression is true."""
    return self.expr1.interpret(context) or self.expr2.interpret(context)

TerminalExpression

Bases: Expression

Terminal expression that checks for a literal value.

Source code in src/design_patterns/behavioral/interpreter.py
class TerminalExpression(Expression):
    """Terminal expression that checks for a literal value."""

    def __init__(self, literal: str) -> None:
        self.literal = literal

    def interpret(self, context: str) -> bool:
        """Check if the context contains the literal."""
        return self.literal in context

interpret(context)

Check if the context contains the literal.

Source code in src/design_patterns/behavioral/interpreter.py
def interpret(self, context: str) -> bool:
    """Check if the context contains the literal."""
    return self.literal in context