tutorial, no_image, designpatterns,

Designpatterns - no_image

Upendra Upendra Follow Jan 23, 2025 · 3 mins read
Designpatterns - no_image
Share this

Interpreter pattern

Interpreter design pattern specifies how to evaluate sentences in a language. The basic idea is to have a class for each symbol (terminal or nonterminal) in a specialized computer language. The syntax tree of a sentence in the language is an instance of the composite pattern and is used to evaluate (interpret) the sentence for a client.

The interpreter pattern solves problems like:

  • A grammar for a simple language should be defined
  • so that sentences in the language can be interpreted.

The interpreter pattern describes how to solve such problems:

  • Define a grammar for a simple language by defining an Expression class hierarchy and implementing an interpret() operation.
  • Represent a sentence in the language by an abstract syntax tree (AST) made up of Expression instances.
  • Interpret a sentence by calling interpret() on the AST.

Example

Let’s create Expression interface:

public interface Expression {
    boolean interpret(String context);
}

and few implementation of it AndExpression, OrExpression, TerminalExpression:

public final class TerminalExpression implements Expression {

    private final String data;

    public TerminalExpression(String data) {
        this.data = data;
    }

    @Override
    public boolean interpret(String context) {
        return context.contains(data);
    }
}
public final class OrExpression implements Expression {

    private final Expression firstExpression;
    private final Expression secondExpression;

    public OrExpression(Expression firstExpression, Expression secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }

    @Override
    public boolean interpret(String context) {
        return firstExpression.interpret(context) || secondExpression.interpret(context);
    }
}
public final class AndExpression implements Expression {

    private final Expression firstExpression;
    private final Expression secondExpression;

    public AndExpression(Expression firstExpression, Expression secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }

    @Override
    public boolean interpret(String context) {
        return firstExpression.interpret(context) && secondExpression.interpret(context);
    }
}

example of usage interpreter pattern:

public final class InterpreterExample {

    public void example() {
        Expression expression1 = new TerminalExpression("One");
        Expression expression2 = new TerminalExpression("1");

        Expression expression3 = new TerminalExpression("Two");
        Expression expression4 = new TerminalExpression("2");

        System.out.println("Is Two equals One = " + expression1.interpret("Two"));
        System.out.println("Is 2 equals 2 = " + expression4.interpret("2"));

        Expression andExpression = new AndExpression(expression1, expression2);
        String correctAndString = "One 1";
        String wrongAndString = "One 2";

        System.out.println("Check correct and string = " + andExpression.interpret(correctAndString));
        System.out.println("Check wrong and string = " + andExpression.interpret(wrongAndString));

        Expression orExpression = new OrExpression(expression3, expression4);
        String correctOrString = "2";
        String wrongOrString = "1 One";

        System.out.println("Check correct or string = " + orExpression.interpret(correctOrString));
        System.out.println("Check wrong or string = " + orExpression.interpret(wrongOrString));
    }
}

Output:

Is Two equals One = false
Is 2 equals 2 = true
Check correct AND string = true
Check wrong AND string = false
Check correct OR string = true
Check wrong OR string = false

Conclusion

Advantages:

  • It’s easy to change and extend the grammar. Because the pattern uses classes to represent grammar rules, you can use inheritance to change or extend the grammar. Existing expressions can be modified incrementally, and new expressions can be defined as variations on old ones.
  • Implementing the grammar is easy, too. Classes defining nodes in the abstract syntax tree have similar implementations. These classes are easy to write, and often their generation can be automated with a compiler or parser generator.

Disadvantages:

  • Complex grammars are hard to maintain. The Interpreter pattern defines at least one class for every rule in the grammar. Hence grammars containing many rules can be hard to manage and maintain.

Links

https://en.wikipedia.org/wiki/Interpreter_pattern
https://www.geeksforgeeks.org/interpreter-design-pattern/
https://www.tutorialspoint.com/design_pattern/interpreter_pattern.htm

credit goes to @swayangjit
Join Newsletter
Get the latest news right in your inbox. We never spam!
Upendra
Written by Upendra Follow
Hi, I am Upendra, the author in Human and machine languages,I don't know to how 3 liner bio works so just Connect with me on social sites you will get to know me better.