// Copyright (c) 2010 Gavin Harrison
// See LICENSE for GPLv3 Terms
import java.util.*;
interface Expr { int run(HashMap<String,Integer> hm); }
interface Condition { boolean test(HashMap<String,Integer> hm); }
interface Statement { void run(HashMap<String,Integer> hm); }
class Num implements Expr
{
Integer val;
public Num(Integer i)
{
val = i;
}
public int run(HashMap<String,Integer> hm)
{
return val;
}
}
class ID implements Expr
{
String name;
public ID(String s)
{
name = s;
}
public int run(HashMap<String,Integer> hm)
{
return (hm.get(name));
}
}
class DivExpr implements Expr
{
Expr left,right;
public DivExpr(Expr l,Expr r)
{
left = l;
right = r;
}
public int run(HashMap<String,Integer> hm)
{
int rval = right.run(hm);
if (rval == 0)
{
System.out.println("Error: division by zero");
System.exit(1);
}
return (left.run(hm) / rval);
}
}
class MultExpr implements Expr
{
Expr left,right;
public MultExpr(Expr l,Expr r)
{
left = l;
right = r;
}
public int run(HashMap<String,Integer> hm)
{
return (left.run(hm) * right.run(hm));
}
}
class MinusExpr implements Expr
{
Expr left,right;
public MinusExpr(Expr l,Expr r)
{
left = l;
right = r;
}
public int run(HashMap<String,Integer> hm)
{
return (left.run(hm) - right.run(hm));
}
}
class PlusExpr implements Expr
{
Expr left,right;
public PlusExpr(Expr l,Expr r)
{
left = l;
right = r;
}
public int run(HashMap<String,Integer> hm)
{
return (left.run(hm) + right.run(hm));
}
}
class InvExpr implements Expr
{
Expr expr;
public InvExpr(Expr e)
{
expr = e;
}
public int run(HashMap<String,Integer> hm)
{
return (-1 * expr.run(hm));
}
}
class GteCond implements Condition
{
Expr left,right;
public GteCond(Expr l,Expr r)
{
left = l;
right = r;
}
public boolean test(HashMap<String,Integer> hm)
{
return (left.run(hm) >= right.run(hm));
}
}
class GtCond implements Condition
{
Expr left,right;
public GtCond(Expr l,Expr r)
{
left = l;
right = r;
}
public boolean test(HashMap<String,Integer> hm)
{
return (left.run(hm) > right.run(hm));
}
}
class LteCond implements Condition
{
Expr left,right;
public LteCond(Expr l,Expr r)
{
left = l;
right = r;
}
public boolean test(HashMap<String,Integer> hm)
{
return (left.run(hm) <= right.run(hm));
}
}
class LtCond implements Condition
{
Expr left,right;
public LtCond(Expr l,Expr r)
{
left = l;
right = r;
}
public boolean test(HashMap<String,Integer> hm)
{
return (left.run(hm) < right.run(hm));
}
}
class NeqCond implements Condition
{
Expr left,right;
public NeqCond(Expr l,Expr r)
{
left = l;
right = r;
}
public boolean test(HashMap<String,Integer> hm)
{
return (left.run(hm) != right.run(hm));
}
}
class EqCond implements Condition
{
Expr left,right;
public EqCond(Expr l,Expr r)
{
left = l;
right = r;
}
public boolean test(HashMap<String,Integer> hm)
{
return (left.run(hm) == right.run(hm));
}
}
class OddCond implements Condition
{
Expr expr;
public OddCond(Expr e)
{
expr = e;
}
public boolean test(HashMap<String,Integer> hm)
{
return (expr.run(hm) % 2 == 1);
}
}
class PrintStmt implements Statement
{
Expr expr;
public PrintStmt(Expr e)
{
expr = e;
}
public void run(HashMap<String,Integer> hm)
{
System.out.println(expr.run(hm));
}
}
class WhileStmt implements Statement
{
Condition cond;
Statement stmt;
public WhileStmt(Condition c, Statement s)
{
cond = c;
stmt = s;
}
public void run(HashMap<String,Integer> hm)
{
while (cond.test(hm))
stmt.run(hm);
}
}
class IfStmt implements Statement
{
Condition cond;
Statement stmt;
public IfStmt(Condition c, Statement s)
{
cond = c;
stmt = s;
}
public void run(HashMap<String,Integer> hm)
{
if (cond.test(hm))
stmt.run(hm);
}
}
class BeginStmt implements Statement
{
StmtLst stmts;
public BeginStmt(StmtLst sl)
{
stmts = sl;
}
public void run(HashMap<String,Integer> hm)
{
stmts.run(hm);
}
}
class AssignStmt implements Statement
{
String name;
Expr val;
public AssignStmt(String i, Expr e)
{
name = i;
val = e;
}
public void run(HashMap<String,Integer> hm)
{
if (hm.containsKey(name))
hm.put(name,val.run(hm));
else
{
System.out.println("Error: variable "+name+" undeclared");
System.exit(1);
}
}
}
class StmtLst
{
ArrayList<Statement> stmts;
public StmtLst(Statement s)
{
stmts = new ArrayList<Statement>();
stmts.add(s);
}
public void add(Statement s)
{
stmts.add(s);
}
public void run(HashMap<String,Integer> hm)
{
for(int i=0;i<stmts.size();i++)
stmts.get(i).run(hm);
}
}
class VarLst
{
HashMap<String,Integer> lst;
public VarLst(String id)
{
lst = new HashMap<String,Integer>();
lst.put(id,0);
}
public void add(String id)
{
lst.put(id,0);
}
public HashMap<String,Integer> hm() { return lst; }
}
class Block
{
HashMap<String,Integer> vars;
Statement stmt;
public Block(VarLst vl, Statement s)
{
vars = vl.hm();
stmt = s;
}
public void run()
{
stmt.run(vars);
}
}
class Program
{
Block body;
public Program(Block b)
{
body = b;
}
public void exec()
{
body.run();
}
}