How to Work with the Interpreter Design Template

0


Design patterns are proven solutions to common software design problems. They provide the correct and tested solution for what is often encountered when designing software applications. The interpreter model is such a solution.

The performer design template set

The Interpreter design pattern allows you to define the business rules for your application as classes. You can take advantage of this design pattern to create domain-specific languages. The Interpreter design model is a behavioral model, specifying how instances of classes should communicate; Behavioral design models deal with collaboration between objects and the delegation of responsibilities between objects.

The Interpreter design template is similar to the Composite design template. The composite design model functions as an interpreter design model when the resulting hierarchical structure represents grammar: you have an interpreter who accepts a set of rules and interprets them. Essentially, this model assesses the grammar and expressions of the language.

Typical use cases of the Interpreter design pattern

The Interpreter design model is not as popular as other models, and it is often overlooked due to its complexity. However, it is a powerful design pattern with distinct use cases. A typical use case of the Interpreter design model is to represent a simple grammar as an abstract syntax tree structure. Another use case is to produce different types of data output from your application; that is, generate reports, possibly in different formats. You can also take advantage of the Interpreter design pattern to implement SQL parsers and symbol processing engines.

Participants in the Performer design model

The participants in a typical implementation of the interpreter design model are:

  • Context: This is the class which contains the information available to the interpreter.
  • AbstractExpression: It is generally an interface which defines an operation.
  • TerminalExpression: This acts as the main interpreter and implements an operation associated with terminal symbols as defined in the grammar.
  • NonTerminalExpression: This is typically used to implement logical operators (AND, OR, etc.) between terminal and non-terminal expressions
  • Client: it is the consumer who builds a syntax tree or who is provided with a syntax tree which represents a sentence in the language defined by the grammar. The client usually initiates interpretation operations.

Interpreter design model implementation

To implement a structural representation of the Interpreter design model in C #, consider the following abstract class named ExpressionBase. Note that this is only a structural implementation of the Interpreter design pattern.

public abstract class ExpressionBase
    {
        public abstract void Interpret(Context context);
    }

The TerminalExpression class extends the abstract base class ExpressionBase and implements the Interpret method:

public class TerminalExpression : ExpressionBase
    {
        public override void Interpret(Context context)
        {
            Console.WriteLine("TerminalExpression for {0}.", context.Output);
        }
    }

The Interpret method accepts an instance of Context class as a parameter.

public class Context
    {
        public string Output { get; set; }
        public Context(string output)
        {
            Output = output;
        }
    }

Here is the Client class which instantiates the Context and the TerminalExpression classes and invokes the Interpret method on the TerminalExpression class by passing the instance of the Context to classify.

public class Client
    {
        public void Interpret()
        {
            Context context = new Context("IDG Context");
            TerminalExpression terminalExpressionObj = new TerminalExpression();          
            terminalExpressionObj.Interpret(context);
        }
    }

Here is the full code:

public class Context
    {
        public string Output { get; set; }
        public Context(string output)
        {
            Output = output;
        }
    }
    public abstract class ExpressionBase
    {
        public abstract void Interpret(Context context);
    }
    public class TerminalExpression : ExpressionBase
    {
        public override void Interpret(Context context)
        {
            Console.WriteLine("TerminalExpression for {0}.", context.Output);
        }
    }
    public class Client
    {
        public void Interpret()
        {
            Context context = new Context("IDG Context");
            TerminalExpression terminalExpressionObj = new TerminalExpression();          
            terminalExpressionObj.Interpret(context);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Client client = new Client();
            client.Interpret();
            Console.Read();
        }
    }

Potential disadvantages of the Interpreter design pattern

A potential drawback of using this model is its complexity of implementation. Thus, you must have implemented extensive error checks before launching the application in production.

Also, as grammar gets more complicated over time (possibly due to language updates), maintaining the code base can become difficult. Plan accordingly!

Copyright © 2018 IDG Communications, Inc.


Share.

Leave A Reply