Design patterns: Interpreter

Mauto 2 min

The Interpreter Pattern is a behavioral design pattern used to define the grammar of a simple language and interpret its expressions. It is used when you want to process a domain-specific language (DSL) or perform complex operations through predefined expressions and syntax rules. This pattern breaks complex expressions down into simpler sub-expressions and evaluates them recursively.

Strengths

  1. Easy to Add New Rules: It lets you add new interpretation rules easily, keeping the code organized and simple to extend.
  2. Modeling Custom Languages: Ideal for building interpreters for custom or domain-specific languages (DSLs), providing a clear structure for defining syntax rules.
  3. Decomposition and Recursion: It splits complex expressions into simpler sub-expressions that can be evaluated recursively, making it easier to interpret complex languages.
  4. Flexibility: Expressions can be represented flexibly as a tree structure, making it possible to handle compound or nested expressions.
  5. Maintainability: The pattern cleanly separates grammar and syntax rules, making the code more maintainable and easier to understand.

Use Case

Suppose we want to interpret a simple mathematical expression (for example, addition and subtraction) and evaluate its result.

PHP Code

// Interface for all expressions
interface Expression {
    public function interpret(array $context);
}

// Expression for numbers
class Number implements Expression {
    private $number;

    public function __construct($number) {
        $this->number = $number;
    }

    public function interpret(array $context) {
        return $this->number;
    }
}

// Expression for addition
class Add implements Expression {
    private $leftExpression;
    private $rightExpression;

    public function __construct(Expression $leftExpression, Expression $rightExpression) {
        $this->leftExpression = $leftExpression;
        $this->rightExpression = $rightExpression;
    }

    public function interpret(array $context) {
        return $this->leftExpression->interpret($context) + $this->rightExpression->interpret($context);
    }
}

// Expression for subtraction
class Subtract implements Expression {
    private $leftExpression;
    private $rightExpression;

    public function __construct(Expression $leftExpression, Expression $rightExpression) {
        $this->leftExpression = $leftExpression;
        $this->rightExpression = $rightExpression;
    }

    public function interpret(array $context) {
        return $this->leftExpression->interpret($context) - $this->rightExpression->interpret($context);
    }
}

// Usage
$expression = new Add(
    new Number(5),
    new Subtract(new Number(10), new Number(3))
);

$result = $expression->interpret([]);
echo "Result: $result\n";  // Output: Result: 12

Explanation

  • Expression is the common interface for all expressions (numbers, addition, subtraction).
  • Number represents a simple number (a terminal expression).
  • Add and Subtract are nonterminal expressions that implement addition and subtraction respectively.
  • interpret() is used to evaluate the expression, recursively calling the interpret methods on the child expressions.

In this example, the compound expression 5 + (10 - 3) is built and evaluated using the Interpreter pattern.

Conclusion

The Interpreter Pattern is useful when you need to implement interpreters for domain-specific languages or evaluate complex expressions. This pattern lets you represent and evaluate grammar rules in a structured and flexible way.

BACK TO THE GUIDE

Copiato