/* Online calculator with sums and runtime stacks Syntax [sum(i=1,4) i*i] = 1*1 + 2*2 + 3*3 + 4*4 Requires calcsumgram.cup */ interface Exp // interface for visitees { public R accept(Expvisitor v); } interface Expvisitor // interface for visitors that return type T { public T visit(dlit d); public T visit(plusexp e); public T visit(minusexp e); public T visit(multexp e); public T visit(divexp e); public T visit(negexp e); public T visit(variable e); public T visit(summation s); } class variable implements Exp // class for simple double expressions { String name; public variable(String x) {name=x;} public R accept(Expvisitor v) { return v.visit(this); } } class summation implements Exp // [sum(i=0,n) i*i] { String var; // i Exp start, end; // 0,n Exp body; // i*i public summation(String i, Exp s, Exp e, Exp b) { var=i; start=s; end=e; body=b; } public R accept(Expvisitor v) { return v.visit(this); } }// summation class dlit implements Exp // class for simple double expressions { double value; public dlit(double x) {value=x;} public R accept(Expvisitor v) { return v.visit(this); } } class opexp // superclass for all binary operator expressions { Exp left, right; // left and right subtrees public opexp(Exp l, Exp r) {left=l; right=r;} } class plusexp extends opexp implements Exp { public plusexp(Exp l, Exp r) { super(l,r); } public R accept(Expvisitor v) { return v.visit(this); } } class minusexp extends opexp implements Exp { public minusexp(Exp l, Exp r) { super(l,r); } public R accept(Expvisitor v) { return v.visit(this); } } class multexp extends opexp implements Exp { public multexp(Exp l, Exp r) { super(l,r); } public R accept(Expvisitor v) { return v.visit(this); } } class divexp extends opexp implements Exp { public divexp(Exp l, Exp r) { super(l,r); } public R accept(Expvisitor v) { return v.visit(this); } } class negexp implements Exp // negative values { Exp sub; // subexpression public negexp(Exp s) { sub=s; } public R accept(Expvisitor v) { return v.visit(this); } } /* Stack structure must implement a stack of entries. In this case the size of each stack frame is 1 since there's always just one local variable in each summation expression. Otherwise, we will have to create a stack of more complex structures */ // a stack frame for one summation class scope { String var; // variable name Exp value; // value of variable scope next; // pointer to next scope down the stack public scope(String v, Exp e, scope n) {var=v; value=e; next=n;} public void update(String v, Exp nv) { if (var.equals(v)) value = nv; else if (next!=null) next.update(v,nv); else throw new Error("no such var: "+v); } } // scope class evaluator implements Expvisitor { // table is stack for local variables: scope table = null; // utility lookup function: looks up v in stack public Exp lookup(String v) { Exp E = null; scope current = table; while (current!=null && E==null) { if (current.var.equals(v)) E = current.value; current=current.next; } if (E==null) throw new Error("unbound variable: "+v); return E; }// lookup public Double visit(variable v) { return lookup(v.name).accept(this); } public Double visit(summation s) { // create new stack frame: table = new scope(s.var,s.start,table); Double i = s.start.accept(this); Double n = s.end.accept(this); Double sum = 0.0; while(i<=n) { table.update(s.var,new dlit(i)); sum = sum + s.body.accept(this); i++; }// while // delete stack frame: table = table.next; return sum; }//visit summation public Double visit(dlit d) { return d.value; } public Double visit(plusexp e) { return e.left.accept(this) + e.right.accept(this); } public Double visit(minusexp e) { return e.left.accept(this) - e.right.accept(this); } public Double visit(multexp e) { return e.left.accept(this) * e.right.accept(this); } public Double visit(divexp e) { return e.left.accept(this) / e.right.accept(this); } public Double visit(negexp e) { return -1 * e.sub.accept(this); } } // evaluation visitor ////////////////////////// // interface public class calcsum { public static void main(String[] args) throws Exception { parser P = new parser(); System.out.print("Enter expression: "); Exp E = (Exp)P.parse().value; double v = E.accept(new evaluator()); System.out.println("value is "+v); } } // calcsum