The Interpreter Pattern: A Comprehensive Guide

Ovevriew

The Interpreter pattern is a behavioral design pattern that defines a grammatical representation for a language and provides an interpreter to handle this grammar. It's particularly useful when you need to evaluate sentences or expressions in a specific language.

When to Use

The Interpreter pattern is most effective in the following situations:

  1. When you have a language that needs to be interpreted and executed
  2. When you can represent sentences in the language as an abstract syntax tree
  3. When the grammar is relatively simple - complex grammars can lead to unwieldy class hierarchies
  4. When performance is not a critical concern, as the most efficient interpreters typically don't parse syntax trees directly

Structure

The Interpreter pattern consists of the following key components:

  • Abstract Expression: Declares an interface for interpreting expressions
  • Terminal Expression: Implements the interpretation for terminal symbols in the grammar
  • Nonterminal Expression: Implements the interpretation for nonterminal symbols in the grammar
  • Context: Contains information that's global to the interpreter
  • Client: Builds or uses the abstract syntax tree to interpret specific sentences

Implementation Example

Abstract Expression Interface


/**
 * Defines the interface for all expression nodes in the AST
 */
public interface IExpression
{
    void Interpret(IContext context);
}

Contextt Class


/**
 * Contains global information used by the interpreter
 */
public class Context
{
    private string input;
    public string Input 
    {
        get { return input; }
        set { input = value; }
    }
    
    private string output;
    public string Output 
    {
        get { return output; }
        set { output = value; }
    }
}

Terminal Expression


/**
 * Implements interpretation for terminal symbols in the grammar
 */
public class TerminalExpression : IExpression
{
    public void Interpret(IContext context)
    {
        Console.WriteLine("Terminal interpreter executed");
    }
}

Nonterminal Expression


/**
 * Implements interpretation for nonterminal symbols in the grammar
 */
public class NonterminalExpression : IExpression
{
    public void Interpret(IContext context)
    {
        Console.WriteLine("Nonterminal interpreter executed");
    }
}

Client Code


/**
 * Demonstrates the usage of the Interpreter pattern
 */
public static void TestInterpreter()
{
    IContext context = new Context();
    List<iexpression> expressions = new List<iexpression>();
    expressions.Add(new TerminalExpression());
    expressions.Add(new NonterminalExpression());
    expressions.Add(new NonterminalExpression());
    expressions.Add(new TerminalExpression());

    foreach(IExpression exp in expressions)
    {
        exp.Interpret(context);
    }
}
</iexpression></iexpression>

Practical Example: Roman Numeral Converter

A practical application of the Interpreter pattern is converting Roman numerals to Arabic numbers. Here's how this can be implemented:

Abstract Expression Base Class


/**
 * Base class for all Roman numeral expressions
 */
public abstract class RomanNumeralExpression
{
    protected Dictionary<string int=""> numeralMap = new Dictionary<string int="">
    {
        {"I", 1}, {"V", 5}, {"X", 10}, {"L", 50}, 
        {"C", 100}, {"D", 500}, {"M", 1000}
    };
    
    public RomanNumeralExpression()
    {
        // Initialize the numeral mapping
    }
    
    /**
     * All concrete expressions must implement this method
     */
    public virtual void Interpret(RomanContext context)
    {
        if (context.input.Length == 0)
            return;
            
        foreach (var pair in numeralMap)
        {
            if (context.input.EndsWith(pair.Key))
            {
                context.result += pair.Value;
                context.input = context.input.Substring(0, context.input.Length - 1);
                break;
            }
        }
    }
}
</string></string>

Terminal Expression


/**
 * Handles direct numeric conversion
 */
public class NumericExpression : RomanNumeralExpression
{
    public override void Interpret(RomanContext context)
    {
        int value;
        if (int.TryParse(context.input, out value))
        {
            context.result = value;
            context.input = "";
        }
    }
}

Nonterminal Expressions


/**
 * Handles subtraction cases like IV (4), IX (9), etc.
 */
public class SubtractiveExpression : RomanNumeralExpression
{
    public override void Interpret(RomanContext context)
    {
        var subtractivePairs = new Dictionary<string int="">
        {
            {"IV", 4}, {"IX", 9}, {"XL", 40}, {"XC", 90},
            {"CD", 400}, {"CM", 900}
        };
        
        foreach (var pair in subtractivePairs)
        {
            if (context.input.EndsWith(pair.Key))
            {
                context.result += pair.Value;
                context.input = context.input.Substring(0, context.input.Length - 2);
                break;
            }
        }
    }
}

/**
 * Handles additive cases like III (3), VI (6), etc.
 */
public class AdditiveExpression : RomanNumeralExpression
{
    public override void Interpret(RomanContext context)
    {
        base.Interpret(context);
    }
}
</string>

Context Class


/**
 * Context for Roman numeral interpretation
 */
public class RomanContext
{
    public string input { get; set; }
    public int result { get; set; }
    
    public RomanContext(string input)
    {
        this.input = input;
        this.result = 0;
    }
}

Client Implementation


/**
 * Tests the Roman numeral interpreter
 */
public static void TestRomanNumeralInterpreter()
{
    string romanNumeral = "XIV"; // 14
    RomanContext context = new RomanContext(romanNumeral);
    
    List<romannumeralexpression> expressions = new List<romannumeralexpression>();
    expressions.Add(new NumericExpression());
    expressions.Add(new SubtractiveExpression());
    expressions.Add(new AdditiveExpression());
    
    while (!string.IsNullOrEmpty(context.input))
    {
        foreach (var exp in expressions)
        {
            exp.Interpret(context);
        }
    }
    
    Console.WriteLine("{0} = {1}", romanNumeral, context.result);
}
</romannumeralexpression></romannumeralexpression>

Applications

The Interpreter pattern is commonly used in:

  • Regular expression engines
  • Programming language compilers and interpreters
  • Natural language processing systems
  • Rule engines and business rule processors
  • Mathematical expression evaluators

Tags: interpreter pattern Design Patterns Behavioral Patterns syntax tree grammar evaluation

Posted on Mon, 18 May 2026 23:48:50 +0000 by pythian