Expression Evaluation: Expression BinaryVariableValue Never need an instance of Expression
Expression Evaluation: Abstract syntax definition: Expression = Variable | Value | Binary Variable = String id Value = int intValue | boolean boolValue Binary = Operator op; Expression term1, term2 Operator = BooleanOp | RelationalOp | ArithmeticOp Italics: type name; Non-italics: member name Review Section 2.3
Abstract Syntax Class Hierarchy Expression Variable Value Binary IntValue BoolValue UndefValue Instead of primitives
Abstract Syntax Class Hierarchy (2) Operator ArithmeticOp RelationalOp BooleanOp AddOp SubOp MultOp DivOp LessOp EqualOp GreaterOp... AndOp OrOp
Evaluation: M: Expression x ∑ Value M(Expression e, State σ) e.M(σ) = e (this) if e is a Value σ(e) if e is a Variable ApplyBinary(e.op, M(e.term1, σ), M(e.term2, σ)) if e is a Binary ApplyUnary(e.op, M(e.term1, σ)) if e is a Unary
What “state” means: By State we mean the set of all instance variable values. By σ(e) we mean the value of an Expression, e, given its current data state as σ. Example: e is the Expression x + 4 current value of x is 3 (σ(e)) current value of e is 7 M(e,σ(e)) Meaning of e
Expression.java public abstract class Expression { public abstract Value M(State sigma); } M (meaning) == evaluate
Command Pattern: Abstract (italics)
Motivation: GUI needs behaviour without knowing what kind. Command turns a request for behaviour into an object Concrete subclasses specify receiver-action pairs. Binary encapsulates a receiver (op) and an action (apply())
Variable.java public class Variable extends Expression { // Variable = String id String id; public boolean equals (Object obj) { String s = ((Variable) obj).id; return id.equalsIgnoreCase(s); // case-insensitive identifiers } public int hashCode ( ) { return id.hashCode( ); } public Value M(State sigma) { return (Value)(sigma.get(this)); }
Value.java (1) public class Value extends Expression { // Value = int intValue | boolean boolValue | Undefined static public Value create(int i ) { return new IntValue(i); } static public Value create(boolean b ) { return new BooleanValue(b); } static public Value create( ) { return new UndefValue(); } // only UndefValue class needs to override this public boolean isUndef() { return false; } public int intVal() { return -1; } // allows override public boolean boolVal() { return false; } // allows override public Value M(State sigma) { return this; }... }
Value.java (2) public class Value extends Expression { // Value = int intValue | boolean boolValue | Undefined... class IntValue extends Value { int intVal; public IntValue(int i) { intVal = i; } public int intVal() { return intVal; } } class BooleanValue extends Value { boolean boolVal; public BooleanValue(boolean b) { boolVal = b; } public boolean boolVal() { return boolVal; } } class UndefValue extends Value { public UndefValue() { } public boolean isUndef() { return true; } } In Chapter 3, Value had a Type instance variable. This is ad hoc polymorphism. Now we create the actual subclasses
Factory Pattern: Value is an example of a Factory Pattern. Factory patterns can be used in following cases: 1.When a class does not know which class of objects it must create. 2. A class specifies its sub-classes to specify which objects to create. 3. In programmer’s language (very raw form), you can use factory pattern where you have to create an object of any one of a number of sub-classes of some class depending on the data provided. NOTE: Patterns are archetypes of typical programming constructs.There is a whole study of what these archetypes are and how they should be used. eg:
Weird syntax: The book code for Value is “weird” and invalid. But this works strangely enough public Value extends Expression { public Value(int n) { return new IntValue(n);}... } public Value extends Expression { public Value Value(int n) {return new IntValue(n);}... } // client Value x = Value(3); // the actual type of x is IntValue
Binary.java public class Binary extends Expression { // Binary = Operator op; Expression term1, term2 Operator op; Expression term1, term2; public Binary(Operator o, Expression t1, Expression t2) { op = o; term1 = t1; term2 = t2; } public Value M(State sigma) { return op.apply(term1.M(sigma), term2.M(sigma)); } Only the Operator class needs be public
Operator.java public abstract class Operator { public abstract Value apply(Value v1, Value v2); } abstract class ArithmeticOp extends Operator { } abstract class RelationalOp extends Operator { } abstract class BooleanOp extends Operator { } NOTE: In a full implementation of Jay, we need to do type checking and the above three abstract classes help in this. For our purposes they don’t hurt so leave them there.
AddOp.java class AddOp extends ArithmeticOp { public Value apply(Value v1, Value v2) { if (v1.isUndef() || v2.isUndef()) return new Value(); return new Value(v1.intVal() + v2.intVal()); }
State.java // State.java import java.util.*; public class State { private Hashtable contents = null; public State () { contents = new Hashtable (); } public Enumeration keys() { return contents.keys(); } public Value get(Variable v) { return contents.get(v); } public State (Variable key, Value value) { if ( contents == null ) contents = new Hashtable (); contents.put(key,value); } public State onion( State t) { // union for ( Enumeration e = t.keys(); e.hasMoreElements(); ) { Variable v = e.nextElement(); contents.put(v, t.get(v)); } return this; }
State.java (2) Text implementation uses inheritance after complaining about Vector Stack Onion(): This is really just union. Any ideas? Hashtable.put(k,v) replaces any existing value if an attempt is made put a duplicate key.
Concordance: Roses are red Violets are blue Sugar is sweet So are you Are: 1, 2, 4 Blue: 2 Is: 3 Red: 1 Roses: 1 So: 4 Sugar: 3 Sweet: 3 Violets: 2 You: 4 Blue: 2 Red: 1 Roses: 1 So: 4 Sugar: 3 Sweet: 3 Violets: 2 You: 4 Without nonsense words
Concordance Uses: Searching large documents like Bible Variants include indexes, no nonsense concordance Cross-reference listing of program: what functions use what variables and call what other funtions
OOD Methodology(?): List all nouns (sounds like ER) found is problem description Concordance Words (String) Line numbers (int) Document Report
ULM Diagram:
Concordance.java public class Concordance { private Dictionary > dict = new Hashtable > (); private boolean allowDupl = true; public Concordance (boolean allowDupl ) { this.allowDupl = allowDupl; } public Concordance ( ) { this(true); } public void add (String word, Integer line) { Vector set = dict.get(word); if (set == null) // word not in Concordance { set = new Vector ( ); dict.put(word, set); } if (allowDupl || !set.contains(line)) set.addElement(line); } public Enumeration keys( ) { return dict.keys( ); } public Enumeration > elements (String word) { return (dict.get(word)).elements( ); } } Sets exist in Java but not ones that allow for duplicate entries.
Document.java public class Document { public Document (BufferedReader input, boolean sensitive, Concordance dict) throws IOExecption { String line; for (int number = 1; (line = input.readLine())!=null; number++) { if (!sensitive) line = line.toLowerCase( ); Enumeration e = new StringTokenizer(line, " \t\n.,!?;:()[]{}"); while (e.hasMoreElements( )) dict.add(e.nextElement( ), new Integer(number)); }
Report.java public class Report { public Report (Concordance dict, PrintStream out) { Enumeration e = dict.keys( ); while (e.hasMoreElements( )) { String word = e.nextElement( ); out.print(word + ":"); Enumeration > f = dict.elements(word); while (f.hasMoreElements( )) out.print(" " + f.nextElement( )); out.println( ); } Exercise: Add code to the above so that an HTML document is produced.
Things learned: A good library is a good thing. Enumerators have numerable uses