Behavioral Pattern: Interpreter
Download
1 / 10

Behavioral Pattern: Interpreter - PowerPoint PPT Presentation


  • 127 Views
  • Uploaded on

Behavioral Pattern: Interpreter. Chapter 5 – Page 149. Some programs benefit from having a language to describe operations that they can perform. The Interpreter Pattern generally describes defining a grammar for that language and using that grammar to interpret statements in that language.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' Behavioral Pattern: Interpreter' - kris


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

Behavioral Pattern: Interpreter

Chapter 5 – Page 149

Some programs benefit from having a language to describe operations that they can perform.

The Interpreter Pattern generally describes defining a grammar for that language and using that grammar to interpret statements in that language.


The Interpreter Pattern

Chapter 5 – Page 150

The AbstractExpression defines an interface for executing an operation.

The TerminalExpression implements an Interpret operation associated with terminal symbols in the grammar.

  • The Context contains information that is global to the interpreter.

  • The Client invokes the interpret operation and builds (or is given) an abstract syntax tree, assembled from CompoundExpressions and TerminalExpressions) representing a particular sentence in the language that the grammar defines.

  • One CompoundExpression class is required for every rule in the grammar, each one implementing an Interpret operation for nonterminal symbols in the grammar.


Example: Boolean Expressions

Chapter 5 – Page 151

A BooleanExpression is either a terminal expression (a Constant) or a compound expression (an AND, OR, or NOT Expression).

A BooleanExpression is interpreted (or “interpreted) in the context of its variable names and values.

For instance, the BooleanExpression (X AND NOT Y) OR Z in the context of (X,Y,Z) = (true, false, false) evaluates to eval(X AND NOT Y) OR eval(Z), which is (eval(X) AND eval(NOT Y)) OR false, which evaluates to (true AND NOT eval(Y)), which is NOT(false), resulting in an evaluation of true.


Example: Roman Numerals

Chapter 5 – Page 152

Reading left to right, a Roman Numeral can be interpreted via four “sub-interpreters”.

First, the thousands characters (the leading “M” characters) are read. This is followed by the hundreds characters (either a nine-sequence “CM”, a four-sequence “CD”, or an optional five-sequence “D” followed by zero to three one-sequences “C”). The tens and ones characters are handled similarly.

Notice that all of the derived “expressions” are terminal.


Roman Numeral Code in C++

Chapter 5 – Page 153

#include <iostream>

#include <string>

using namespace std;

class Thousand;

class Hundred;

class Ten;

class One;

classRomanNumeralInterpreter

{

public:

RomanNumeralInterpreter(); // Creator for client

RomanNumeralInterpreter(int){} // Creator for subclasses, avoids infinite loop

int interpret(string); // interpret() for client

virtual void interpret(string &input, int &total) // interpret() for derived classes

{

int index = 0;

if (input.substr(0, 2) == nine())

{

total += 9 * multiplier();

index += 2;

}

else if (input.substr(0, 2) == four())

{

total += 4 * multiplier();

index += 2;

}


Chapter 5 – Page 154

else

{

if (input[0] == five()[0])

{

total += 5 * multiplier();

index = 1;

}

else

index = 0;

int count = 1;

while ( (input[index] == one()[0]) && (count <= 3) )

{

total += 1 * multiplier();

index++;

count++;

}

}

// remove leading characters processed

input = input.substr(index, input.length() - index);

}

protected:

// cannot be pure virtual because client asks for instance

virtual string one() { return""; }

virtual string four() { return""; }

virtual string five() { return""; }

virtual string nine() { return""; }

virtual intmultiplier() { return 0; }

private:

RomanNumeralInterpreter *thousands;

RomanNumeralInterpreter *hundreds;

RomanNumeralInterpreter *tens;

RomanNumeralInterpreter *ones;

};


class Thousand: publicRomanNumeralInterpreter

{

public:

// provide 1-argument creator to avoid infinite loop in base class creator

Thousand(int): RomanNumeralInterpreter(1) {}

protected:

string one() { return"M"; }

string four() { return""; }

string five() { return""; }

string nine() { return""; }

int multiplier() { return 1000; }

};

class Hundred: publicRomanNumeralInterpreter

{

public:

Hundred(int): RomanNumeralInterpreter(1) {}

protected:

string one() { return"C"; }

string four() { return"CD"; }

string five() { return"D"; }

string nine() { return"CM"; }

int multiplier() { return 100; }

};

class Ten: publicRomanNumeralInterpreter

{

public:

Ten(int): RomanNumeralInterpreter(1) {}

protected:

string one() { return"X"; }

string four() { return"XL"; }

string five() { return"L"; }

string nine() { return"XC"; }

int multiplier() { return 10; }

};

Chapter 5 – Page 155


Chapter 5 – Page 156

class One: publicRomanNumeralInterpreter

{

public:

One(int): RomanNumeralInterpreter(1) {}

protected:

string one() { return"I"; }

string four() { return"IV"; }

string five() { return"V"; }

string nine() { return"IX"; }

int multiplier() { return 1; }

};

RomanNumeralInterpreter::RomanNumeralInterpreter()

{

// use 1-argument creator to avoid infinite loop

thousands = new Thousand(1);

hundreds = new Hundred(1);

tens = new Ten(1);

ones = new One(1);

}

intRomanNumeralInterpreter::interpret(string input)

{

int total;

total = 0;

thousands->interpret(input, total);

hundreds->interpret(input, total);

tens->interpret(input, total);

ones->interpret(input, total);

if (input != "") // Input was invalid

return 0;

return total;

}


Chapter 5 – Page 157

void main()

{

RomanNumeralInterpreter interpreter;

string input;

cout << "Enter Roman Numeral: ";

cin >> input;

while (input != "quit")

{

cout << " interpretation is " << interpreter.interpret(input) << endl;

cout << "Enter Roman Numeral: ";

cin >> input;

}

}


Interpreter Pattern Advantages

Chapter 5 – Page 158

  • When a program presents a number of different, but somewhat similar, cases with which it must contend, it can be advantageous to use a simple language to describe these cases and then have the program interpret that language.

  • Recognizing cases where the Interpreter Pattern can be helpful can be problematic, and programmers who lack training in formal languages or compilers often overlook this option.

  • One fairly obvious place where languages are applicable is when the program must parse algebraic strings in order to carry out operations based on the computation of user-entered equations.

  • A far more useful situation that uses the Interpreter Pattern is when the program produces varying kinds of output (e.g., generating reports based on a database without having to resort to elaborate SQL queries).


ad