CS 635: Advanced Object-Oriented Design & Programming |
---|
Interpreter | slide # 2 |
...Structure | slide # 2 |
...Example - Boolean Expressions | slide # 3 |
......And | slide # 4 |
......Or | slide # 5 |
......Not | slide # 6 |
......Constant | slide # 7 |
......Variable | slide # 8 |
......Context | slide # 9 |
......Sample Use | slide # 10 |
...Consequences | slide # 11 |
...Implementation | slide # 11 |
Given a language defined by a simple grammar with rules like:
R ::= R1 R2 ... Rn
you create a class for each rule
The classes can be used to construct a tree that represents elements of the language
public interface BooleanExpression{ public boolean evaluate( Context values ); public BooleanExpression replace( String varName, BooleanExpression replacement ); public Object clone(); public String toString(); }
public class And implements BooleanExpression { private BooleanExpression leftOperand; private BooleanExpression rightOperand; public And( BooleanExpression leftOperand, BooleanExpression rightOperand) { this.leftOperand = leftOperand; this.rightOperand = rightOperand; } public boolean evaluate( Context values ) { return leftOperand.evaluate( values ) && rightOperand.evaluate( values ); } public BooleanExpression replace( String varName, BooleanExpression replacement ) { return new And( leftOperand.replace( varName, replacement), rightOperand.replace( varName, replacement) ); } public Object clone() { return new And( (BooleanExpression) leftOperand.clone( ), (BooleanExpression)rightOperand.clone( ) ); } public String toString(){ return "(" + leftOperand.toString() + " and " + rightOperand.toString() + ")"; } }
public class Or implements BooleanExpression { private BooleanExpression leftOperand; private BooleanExpression rightOperand; public Or( BooleanExpression leftOperand, BooleanExpression rightOperand) { this.leftOperand = leftOperand; this.rightOperand = rightOperand; } public boolean evaluate( Context values ) { return leftOperand.evaluate( values ) || rightOperand.evaluate( values ); } public BooleanExpression replace( String varName, BooleanExpression replacement ) { return new Or( leftOperand.replace( varName, replacement), rightOperand.replace( varName, replacement) ); } public Object clone() { return new Or( (BooleanExpression) leftOperand.clone( ), (BooleanExpression)rightOperand.clone( ) ); } public String toString() { return "(" + leftOperand.toString() + " or " + rightOperand.toString() + ")"; } }
public class Not implements BooleanExpression { private BooleanExpression operand; public Not( BooleanExpression operand) { this.operand = operand; } public boolean evaluate( Context values ) { return ! operand.evaluate( values ); } public BooleanExpression replace( String varName, BooleanExpression replacement ) { return new Not( operand.replace( varName, replacement) ); } public Object clone() { return new Not( (BooleanExpression) operand.clone( ) ); } public String toString() { return "( not " + operand.toString() + ")"; }
public class Constant implements BooleanExpression { private boolean value; private static Constant True = new Constant( true ); private static Constant False = new Constant( false ); public static Constant getTrue() { return True; } public static Constant getFalse(){ return False; } private Constant( boolean value) { this.value = value; } public boolean evaluate( Context values ) { return value; } public BooleanExpression replace( String varName, BooleanExpression replacement ) { return this; } public Object clone() { return this; } public String toString() { return String.valueOf( value ); } }
public class Variable implements BooleanExpression { private static Hashtable flyWeights = new Hashtable(); private String name; public static Variable get( String name ) { if ( ! flyWeights.contains( name )) flyWeights.put( name , new Variable( name )); return (Variable) flyWeights.get( name ); } private Variable( String name ) { this.name = name; } public boolean evaluate( Context values ) { return values.getValue( name ); } public BooleanExpression replace( String varName, BooleanExpression replacement ) { if ( varName.equals( name ) ) return (BooleanExpression) replacement.clone(); else return this; } public Object clone() { return this; } public String toString() { return name; } }
public class Context { Hashtable values = new Hashtable(); public boolean getValue( String variableName ) { Boolean wrappedValue = (Boolean) values.get( variableName ); return wrappedValue.booleanValue(); } public void setValue( String variableName, boolean value ) { values.put( variableName, new Boolean( value ) ); } }
public class Test { public static void main( String args[] ) throws Exception { BooleanExpression left = new Or( Constant.getTrue(), Variable.get( "x" ) ); BooleanExpression right = new And( Variable.get( "w" ), Variable.get( "x" ) ); BooleanExpression all = new And( left, right ); System.out.println( all ); Context values = new Context(); values.setValue( "x", true ); values.setValue( "w", false ); System.out.println( all.evaluate( values ) ); System.out.println( all.replace( "x", right ) ); } }Output ((true or x) and (w and x)) false ((true or (w and x)) and (w and (w and x)))
Implementing the grammar is easy
Complex grammars are hard to maintain
Adding new ways to interpret expressions
Flyweight