Sunday, July 23, 2017

Interpreter Pattern


Interpreter design pattern majorly used with languages and notations. This pattern can be useful to convert from one language to another. This pattern allows to write multiple rules or grammar for language to interpret and extend easily. Interpreter Pattern falls under behavioral pattern of GOF (Gang of Four) pattern.

When to use –


Interpreter Pattern is useful to interpret languages where rules/grammar are complex part which you can easily extend using this pattern. The pattern works on hierarchy of expression. The expression can be classified as Terminal or Non-Terminal. The terminal expression is standalone and can be Interpreted immediately. The non-terminal expression may contain one or more terminal or non-terminal expressions.  

Major components of Interpreter pattern –


Client – This client class responsible for build context, terminal and non-terminal expression objects. It also responsible to make call to interpret method of respective expression.
Context – This is context class used to store input/output data and other information required by expression.
Expression – This is an interface which defines Interpret method which will be implemented by sub classes.
TerminalExpression – This class will implement Expression interface and implements Interpret method.
NonTerminalExpression – This class will implement Expression interface and implements Interpret method similar to TerminalExpression class. This class may contain one or more terminal or non-terminal expressions and invoke Interpret method respectively.

There are many examples available for Interpreter design pattern. I would like to take simple example to understand the intent and implementation for Interpreter design pattern. In my example I would like interpret numbers to words. So I’ll provide number as input and that will be interpreted by pattern to words. Similarly, you can add multiple rules to interpret as per your requirement.

See below example of Interpreter pattern.

Code –
//Client class
class Program
{
    static void Main(string[] args)
    {
        Context ctx = new Context(5642);
        IExpression exp1 = new WordExpression();
        exp1.Interpret(ctx);

        Context ctx1 = new Context(397);
        SubExpression subExp = new SubExpression();
        subExp.Expression1 = new WordExpression();
        subExp.Interpret(ctx1);

        Console.ReadLine();
    }
}
//Context class
public class Context
{
    public int Input { get; set; }
    public Context(int inputValue)
    {
        Input = inputValue;
    }
}
//Expression Interface
public interface IExpression
{
    void Interpret(Context context);
}
//Terminal expression class
public class WordExpression : IExpression
{
    public Dictionary<int, string> numberWord = new Dictionary<int, string>() {
        { 1, "One" }, { 2, "Two" }, { 3, "Three" }, { 4, "Four" }, { 5, "Five" },
        { 6, "Six" }, { 7, "Seven" }, { 8, "Eight" }, { 9, "Nine" }, { 0, "Zero" } };
    public void Interpret(Context context)
    {
        Console.Write("Input Value {0} - ", context.Input);
        string value = context.Input.ToString();
        if (value.Length > 0)
        {
            foreach (char chr in value)
            {
                int number = (int)Char.GetNumericValue(chr);
                Console.Write("{0} ", numberWord[number]);
            }
            Console.WriteLine();
        }
    }
}
//Non-terminal expression class
public class SubExpression : IExpression
{
    public IExpression Expression1 { get; set; }
    public void Interpret(Context context)
    {
        Console.WriteLine("Running Sub Expression 1");
        Expression1.Interpret(context);
    }
}

Output –


As you can see in this example, user set context value to 5642 and Interpret it to words via calling WordExpression which is terminal expression. User also set value another context object ctx1 and set 397 value to Interpret to word via calling SubExpression which is non-terminal expression and contains reference of terminal expression. You can add multiple conversion rules and interpret methods via adding multiple expressions as per your requirement.

You can download full code from Gist.

I hope this article helps you to know more about Interpreter Design Pattern. Please leave your feedback in comments section below.

References –

See Also –