2011年4月19日 星期二

GoF Behavioral - Interpretor


  • Intent


to define a representation of the grammar of a given language, along with an interpreter that use this representation to interpret sentences in the language.




  • Benefits




  1. It's easier to change and extend the grammar.

  2. Implementing the grammar is straightforward.




  • 適用情境




  1. The grammar of the language is not complicated.

  2. Efficiency is not a priority.




  • Class Diagram




[caption id="attachment_239" align="alignnone" width="548" caption="Interpreter pattern"]Interpreter pattern[/caption]


  • Sample Code


這個範例大概是最近看來比較辛苦的,居然出現了直譯器這個詞,想當初compiler課程我可是將近直接放棄XD,雖然老師上課很偉大都給openbook exam,但還是很多人直接退選了,因為真的有難度!!

下面是一個 Reverse Polish notation,這個表示式真實的呈現了直譯器模式的核心意涵。

grammar expression as below

expression ::= plus | minus | ariable | number

plus ::= expression expression '+'

minus ::= expression expression '-'

variable ::= 'a' | 'b' | 'c' | ... | 'z'

digit = '0'| '1'| ... '9'

number ::= digit | digit number

以下是要展示的語法輸入內涵,將透過範例程式做更明確的實質內容呈現( interprete it )

a b +     // i.e a+b

a b c + -   // i.e  a+b-c

a b + c a - -    /// i.e  a+b-c-a
package interpreter;

import java.util.HashMap;
import java.util.Stack;

interface Expression {

public int interpret(HashMap<String, Expression> variables);
}

class Number implements Expression {
private int number;

public Number(int number) {
this.number = number;
}

@Override
public int interpret(HashMap<String, Expression> variables) {
// TODO Auto-generated method stub
return number;
}
}

class Plus implements Expression {
Expression leftOperand;
Expression rightOperand;

public Plus(Expression left, Expression right) {
this.leftOperand = left;
this.rightOperand = right;
}

public int interpret(HashMap<String, Expression> variables) {
return this.leftOperand.interpret(variables) + this.rightOperand.interpret(variables);
}
}

class Minus implements Expression {
Expression leftOperand;
Expression rightOperand;

public int interpret(HashMap<String, Expression> variables) {
return this.leftOperand.interpret(variables) - this.rightOperand.interpret(variables);
}

public Minus(Expression left, Expression right) {
this.leftOperand = left;
this.rightOperand = right;
}
}

class Variable implements Expression {
private String name;

public Variable(String name) {
this.name = name;
}

public int interpret(HashMap<String, Expression> variables) {
if (null == variables.get(name))
return 0;
return variables.get(name).interpret(variables);
}
}

class Evaluator implements Expression {
private Expression syntaxTree;

public Evaluator(String expression) {
Stack<Expression> expressionStack = new Stack<Expression>();
for (String token : expression.split(" ")) {
if (token.equals("+")) {
Expression subExpression = new Plus(expressionStack.pop(), expressionStack.pop());
expressionStack.push(subExpression);
} else if (token.equals("-")) {
// it's necessary remove first the right operand from the stack
Expression right = expressionStack.pop();
// ..and after the left one
Expression left = expressionStack.pop();
Expression subExpression = new Minus(left, right);
expressionStack.push(subExpression);
} else
expressionStack.push(new Variable(token));
}
syntaxTree = expressionStack.pop();
}

public int interpret(HashMap<String, Expression> context) {
return syntaxTree.interpret(context);
}
}

public class InterpreterPattern {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String expression = "w x z - +";
Evaluator sentence = new Evaluator(expression);
HashMap<String, Expression> variables = new HashMap<String, Expression>();
variables.put("w", new Number(5));
variables.put("x", new Number(10));
variables.put("z", new Number(42));
int result = sentence.interpret(variables);
System.out.println(result);

}

}

沒有留言: