TechWayFit
● Design Patterns in Practice

Interpreter Pattern – Building Expression Evaluators and DSLs

Tech Buddy July 7, 2025 8 min read
Interpreter Pattern – Building Expression Evaluators and DSLs

Interpreter Pattern

The Interpreter Pattern provides a way to evaluate language grammar or expressions. It is used to define a representation of grammar along with an interpreter that uses the representation to interpret sentences in the language.

🧩 What is the Interpreter Pattern?

The Interpreter Pattern is a behavioral design pattern that specifies how to evaluate sentences in a language. It defines a grammar for a simple language and uses an interpreter to process statements of that language.

🎯 Real-World Analogy

Think of a calculator parsing a mathematical expression like "2 + 3 - 1". Each number and operation has meaning, and the system understands how to compute it by interpreting each token based on grammar rules.

📊 UML Diagram

                      classDiagram
                          class AbstractExpression {
                            <<interface>>
                            + interpret(context)
                          }
                          class TerminalExpression {
                            + interpret(context)
                          }
                          class NonTerminalExpression {
                            + interpret(context)
                          }
                          class Context {
                            + input
                            + output
                          }
                      
                          AbstractExpression <|-- TerminalExpression
                          AbstractExpression <|-- NonTerminalExpression
                        

🏗️ Structure and Participants

  • Context: Holds the information that is global to the interpreter. This typically includes the input string or data to be parsed and any output or state needed during interpretation.
  • AbstractExpression: Defines the common interface (usually an interpret(context) method) for all concrete expression classes. Every grammar rule or symbol will implement this interface.
  • TerminalExpression: Implements the interpretation for grammar elements that do not contain other expressions (i.e., leaf nodes in the grammar tree). For example, numbers or variables in a mathematical expression.
  • NonTerminalExpression: Implements grammar rules that involve other expressions (i.e., composite nodes). These classes combine terminal and/or non-terminal expressions to represent more complex grammar constructs, such as addition or subtraction in an arithmetic language.

💡 Use Cases

  • Simple language interpreters (arithmetic, boolean)
  • Rule engines or DSLs (Domain-Specific Languages)
  • Command parsing in chatbots or command-line interfaces
  • Validation engines for expressions or conditions

👨‍💻 Example Code


                      // Abstract Expression
                      interface IExpression {
                          int Interpret();
                      }
                      
                      // Terminal
                      class Number : IExpression {
                          private int _value;
                          public Number(int value) => _value = value;
                          public int Interpret() => _value;
                      }
                      
                      // Non-Terminal
                      class Add : IExpression {
                          private IExpression _left, _right;
                          public Add(IExpression left, IExpression right) {
                              _left = left;
                              _right = right;
                          }
                          public int Interpret() => _left.Interpret() + _right.Interpret();
                      }
                      
                      // Usage
                      var expression = new Add(new Number(5), new Number(3));
                      Console.WriteLine(expression.Interpret()); // Output: 8
                            

                      from abc import ABC, abstractmethod
                      
                      class Expression(ABC):
                          @abstractmethod
                          def interpret(self):
                              pass
                      
                      class Number(Expression):
                          def __init__(self, value):
                              self.value = value
                          def interpret(self):
                              return self.value
                      
                      class Add(Expression):
                          def __init__(self, left, right):
                              self.left = left
                              self.right = right
                          def interpret(self):
                              return self.left.interpret() + self.right.interpret()
                      
                      # Usage
                      expr = Add(Number(5), Number(3))
                      print(expr.interpret())  # Output: 8
                            

⚖️ Pros and Cons

Pros Cons
Good for simple grammar parsing and expression evaluation Can become complex and hard to maintain for large or evolving grammars
Extensible—easy to add new grammar rules or expressions by introducing new classes Poor performance for complex expressions due to recursive interpretation and object creation
Improves readability and separation of concerns by encapsulating grammar logic Class explosion: each grammar rule or symbol often requires a new class, leading to many small classes
Useful for implementing DSLs, rule engines, and interpreters for custom languages Not suitable for parsing complex languages—better tools exist (e.g., parser generators, ANTLR)
Promotes reusability and testability of grammar components Can be difficult to debug and optimize as the grammar grows

📌 When to Use

  • You have a simple grammar to interpret.
  • You want to implement a small language, query, or expression evaluator.
  • You want a highly extensible solution where new rules are frequently added.

🧠 Quiz Time

📝 Summary

The Interpreter Pattern is powerful when used in the right scenarios, such as custom language parsers and expression evaluation engines. However, for complex grammars, it’s often better to use tools like ANTLR or parser generators.

Next Up: Series Complete – Congrats! 🎉
Explore more on system design, security, and architecture at TechWayFit.

Comments

Loading comments…

Leave a comment