The Interpreter Pattern is a behavioral design pattern that defines a grammar for a language and provides an interpreter to evaluate expressions written in that language.

Each grammar rule is represented by a separate class, and complex expressions are formed by combining simpler expressions into a tree structure. Evaluating the expression involves recursively traversing this tree.

The pattern makes it easy to extend the language by introducing new expression classes without modifying existing ones.

The Interpreter Pattern is commonly used for expression evaluation, rule engines, query languages, calculators, and domain-specific languages (DSLs).

Structure

The Interpreter Pattern consists of the following participants.

1. The Expression defines the interface for interpreting expressions.
2. Terminal Expressions represent the basic elements of the language.
3. Non-Terminal Expressions combine other expressions to form more complex expressions.
4. The Context stores information required during interpretation.
5. The Client builds the expression tree and requests its evaluation.

Java Implementation

Suppose an application evaluates simple arithmetic expressions. Each number is represented by a terminal expression, while addition is represented by a non-terminal expression.

Create the expression interface.
public interface Expression {
    int interpret();
}
Create the terminal expression.
public class NumberExpression implements Expression {
    private final int value;

    public NumberExpression(int value) {
        this.value = value;
    }

    @Override
    public int interpret() {
        return value;
    }
}
Create the non-terminal expression.
public class AddExpression implements Expression {
    private final Expression left;
    private final Expression right;

    public AddExpression( Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret() {
        return left.interpret() + right.interpret();
    }
}
The client builds and evaluates the expression tree.
public class Main {
    public static void main(String[] args) {
        Expression expression = new AddExpression(new NumberExpression(10), new NumberExpression(20));
        System.out.println( expression.interpret());
    }
}
Output:
30

How It Works?

The client constructs an expression tree by combining simple expressions into more complex ones.

In this example, NumberExpression objects act as terminal expressions that return constant values, while AddExpression acts as a non-terminal expression that combines two child expressions.

When the client invokes interpret(), the request is propagated recursively through the expression tree. Each node evaluates itself and returns its result to its parent until the final value is produced.

This recursive evaluation allows complex expressions to be built from simple components while keeping each grammar rule isolated in its own class.

Advantages

1. It represents grammar rules as separate classes, making the language easy to extend.
2. Complex expressions can be built by combining simpler expressions.
3. The interpretation logic is separated from client code.
4. New grammar rules can be introduced without modifying existing expressions.

Disadvantages

1. The number of classes increases as the grammar grows.
2. Large or complex languages can produce deep expression trees that are difficult to maintain.
3. The pattern is generally unsuitable for implementing full programming languages.

JDK Examples

The Interpreter Pattern appears throughout the Java ecosystem.

1. The java.util.regex.Pattern class parses and interprets regular expression syntax to match input strings.

2. The javax.el.Expression API interprets Expression Language (EL) expressions used in Jakarta EE applications.

Summary

The Interpreter Pattern represents the grammar of a language using a hierarchy of expression classes and evaluates expressions by recursively traversing an expression tree.

By encapsulating each grammar rule in a separate class, the pattern makes simple languages easier to implement, extend, and maintain.
Nagesh Chauhan

Nagesh Chauhan

Principal Software Engineer • Java • Python • Distributed Systems • AI/ML

Principal Software Engineer with 14+ years of experience designing and delivering large-scale distributed systems, cloud-native applications, and AI-powered platforms.

Passionate about solving complex engineering problems using strong data structures and algorithms, along with expertise in Java, Spring Boot, Python, System Design, Microservices, Cloud, Kafka, Elasticsearch, and Generative AI.

Share this Article

💬 Comments

Join the Discussion