CHAPTER 24

image

Interpreter Patterns

GoF Definition: Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

Concept

Here, in general, we define a grammatical representation for a language and provide an interpreter to deal with that grammar (e.g., in our example we have interpreted a string input as binary data). In simple words, this pattern says how to evaluate sentences in a language.

Real–Life Example

A language translator who translates a language for us provides a classic example for this pattern. Or, we can also consider music notes as our grammar and musicians as our interpreters.

Computer World Example

A Java compiler interprets the source code into byte code. This byte code is understandable by JVM (Java virtual machine). In C# also, our source code is converted to MSIL (Microsoft intermediate language) code, which is interpreted by CLR (common language runtime). Upon execution, this MSIL (intermediate code) is converted to native code (binary executable code) by a JIT (Just In time) compiler.

Illustration

Here we need to create an interpreter context engine for our interpretation work. Then we need to create an expression implementation (ideally we should have more implementations—e.g., here we may also be interested in converting the data to hexadecimal or any other format) that will consume the functionality provided by the interpreter context. At last we have created the client who will accept the user input to generate the required output. The client here will also decide which expression to use if we have more than one expression. Go through the example now. Here we have two choices: we can interpret an input string (basically a decimal number) as binary data or we can simply interpret it and print the digits in the input into their equivalent English words.

UML Class Diagram

9781484218013_unFig24-01.jpg

Package Explorer view

High-level structure of the parts of the program is as follows:

9781484218013_unFig24-02.jpg

Implementation

package interpreter.pattern.demo;

import java.util.Scanner;

/*Context class: interpretation is carried out based on our implementation.*/
class Context
{
        public String input;
        public Context(String input)
        {
                this.input=input;
        }
        public void getBinaryForm(String input)
        {
                int i = Integer.parseInt(input);
                //integer to its equivalent binary string representation
                String binaryString = Integer.toBinaryString(i);
                System.out.println("Binary equivalent of "+input+ " is "+ binaryString);
        }
        public void printInWords(String input)
        {
                this.input = input;
                System.out.println("Printing the input in words:");
                char c[]=input.toCharArray();
                for(int i=0;i<c.length;i++)
                {
                        switch (c[i])
                        {
                        case ’1’:
                                System.out.print("One ");
                                break;
                        case ’2’:
                                System.out.print("Two ");
                                break;
                        case ’3’:
                                System.out.print("Three ");
                                break;
                        case ’4’:
                                System.out.print("Four ");
                                break;
                        case ’5’:
                                System.out.print("Five ");
                                break;
                        case ’6’:
                                System.out.print("Six ");
                                break;
                        case ’7’:
                                System.out.print("Seven ");
                                break;
                        case ’8’:
                                System.out.print("Eight ");
                                break;
                        case ’9’:
                                System.out.print("Nine ");
                                break;
                        case ’0’:
                                System.out.print("Zero ");
                                break;
                        default:
                                System.out.print("* ");
                                break;
                        }
                }
        }
}

interface IExpression
{
        void interpret(Context ic);
}
class StringToBinayExp implements IExpression
{
        private String str;
        public StringToBinaryExp(String s)
        {
                str = s;
        }

        @Override
        public void interpret(Context ic)
        {
                ic.getBinaryForm(str);
        }
}
class IntToWords implements IExpression
{
        private String str;
        public IntToWords(String str)
        {
                this.str = str;
        }
        @Override
        public void interpret(Context ic)
        {
                ic.printInWords(str);
        }
}
class InterpreterPatternEx
{
        public Context clientContext=null;
        public IExpression exp=null;
        public InterpreterPatternEx(Context c)
        {
                clientContext = c;
        }
        public void interpret(String str)
        {
                //We’ll test 2 consecutive inputs at a time
                for(int i=0;i<2;i++){
                        System.out.println(" Enter ur choice(1 or 2)");
                        Scanner in = new Scanner(System.in);
                        String c = in.nextLine();
                        if (c.equals("1"))
                        {
                                exp = new IntToWords(str);
                                exp.interpret(clientContext);
                        }
                        else
                        {
                                exp = new StringToBinaryExp(str);
                                exp.interpret(clientContext);
                        }
                }
        }

        public static void main(String[] args)
        {
                System.out.println(" ***Interpreter Pattern Demo*** ");
                System.out.println("Enter a number :");
                Scanner in = new Scanner(System.in);
                String input = in.nextLine();
                                Context context=new Context(input);
                InterpreterPatternEx client = new InterpreterPatternEx(context);
                client.interpret(input);
        }
}

Output

9781484218013_unFig24-03.jpg

Note

  1. This pattern is widely used to interpret the statements in a language as abstract syntax trees. It performs best when the grammar is easy to understand and simple.
  2. We can represent, modify, or implement a grammar easily.
  3. We can evaluate an expression in our preferred ways. It is up to us how we’ll interpret those expressions.
  4. If the grammar is complex (e.g., it may have many constraints/rules), implementing this pattern becomes hard. For each rule, we may need to implement a new class, and obviously it is a cumbersome process.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.255.140