/** AST class definitions */ /** The AST type which support a visitor interface */ /** * Interface for abstract syntax trees (ASTs). */ interface AST { /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(ASTVisitor v); } /** * Interface for a visitor to an AST. */ interface ASTVisitor { /** * Case for BoolConstants. * @param b host * @return visitor-specific return value */ RtnType forBoolConstant(BoolConstant b); /** * Case for IntConstants. * @param i host * @return visitor-specific return value */ RtnType forIntConstant(IntConstant i); /** * Case for NullConstants. * @param n host * @return visitor-specific return value */ RtnType forNullConstant(NullConstant n); /** * Case for Variables. * @param v host * @return visitor-specific return value */ RtnType forVariable(Variable v); /** * Case for PrimFuns. * @param f host * @return visitor-specific return value */ RtnType forPrimFun(PrimFun f); /** * Case for UnOpApps. * @param u host * @return visitor-specific return value */ RtnType forUnOpApp(UnOpApp u); /** * Case for BinOpApps. * @param b host * @return visitor-specific return value */ RtnType forBinOpApp(BinOpApp b); /** * Case for Apps. * @param a host * @return visitor-specific return value */ RtnType forApp(App a); /** * Case for Maps. * @param m host * @return visitor-specific return value */ RtnType forMap(Map m); /** * Case for Ifs. * @param i host * @return visitor-specific return value */ RtnType forIf(If i); /** * Case for Lets. * @param l host * @return visitor-specific return value */ RtnType forLet(Let l); } /** * AST visitor in which all cases delegate to an abstract default case. */ abstract class ADefaultASTVisitor implements ASTVisitor { /** * Default case. * @param a host * @return visitor-specific return value */ public abstract RtnType forDefault(AST a); /** * Case for BoolConstants. * * @param b host * * @return visitor-specific return value */ public RtnType forBoolConstant(BoolConstant b) { return forDefault(b); } /** * Case for IntConstants. * * @param i host * * @return visitor-specific return value */ public RtnType forIntConstant(IntConstant i) { return forDefault(i); } /** * Case for NullConstants. * * @param n host * * @return visitor-specific return value */ public RtnType forNullConstant(NullConstant n) { return forDefault(n); } /** * Case for Variables. * * @param v host * * @return visitor-specific return value */ public RtnType forVariable(Variable v) { return forDefault(v); } /** * Case for PrimFuns. * * @param f host * * @return visitor-specific return value */ public RtnType forPrimFun(PrimFun f) { return forDefault(f); } /** * Case for UnOpApps. * * @param u host * * @return visitor-specific return value */ public RtnType forUnOpApp(UnOpApp u) { return forDefault(u); } /** * Case for BinOpApps. * * @param b host * * @return visitor-specific return value */ public RtnType forBinOpApp(BinOpApp b) { return forDefault(b); } /** * Case for Apps. * * @param a host * * @return visitor-specific return value */ public RtnType forApp(App a) { return forDefault(a); } /** * Case for Maps. * * @param m host * * @return visitor-specific return value */ public RtnType forMap(Map m) { return forDefault(m); } /** * Case for Ifs. * * @param i host * * @return visitor-specific return value */ public RtnType forIf(If i) { return forDefault(i); } /** * Case for Lets. * * @param l host * * @return visitor-specific return value */ public RtnType forLet(Let l) { return forDefault(l); } } /** * The interface supported by Jam "atomic" expressions (Constant, PrimFun, Variable). */ interface Term extends AST { } /** * The interface supported by Jam tokens that denote constants. */ interface Constant extends Term { } /** * Abstract class for unary operators. */ abstract class UnOp { /** * Name of the operator. */ String name; /** * Constructor for a unary operator. * @param s name of the operator */ public UnOp(String s) { name = s; } /** * Returns the string representation of this unary operator. * @return string representation */ public String toString() { return name; } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public abstract RtnType accept(UnOpVisitor v); } /** * Interface for a visitor to a unary operator. */ interface UnOpVisitor { /** * Case for unary plus. * @param op host * @return visitor-specific return value */ RtnType forUnOpPlus(UnOpPlus op); /** * Case for unary minus. * @param op host * @return visitor-specific return value */ RtnType forUnOpMinus(UnOpMinus op); /** * Case for not. * @param op host * @return visitor-specific return value */ RtnType forOpTilde(OpTilde op); // RtnType forOpBang(OpBang op); // RtnType forOpRef(OpRef op); } /** * Abstract class for binary operators. */ abstract class BinOp { /** * Name of the operator. */ String name; /** * Constructor for a binary operator. * @param s name of the operator */ public BinOp(String s) { name = s; } /** * Returns the string representation of this unary operator. * @return string representation */ public String toString() { return name; } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public abstract RtnType accept(BinOpVisitor v); } /** * Interface for a visitor to a binary operator. */ interface BinOpVisitor { /** * Case for binary plus. * @param op host * @return visitor-specific return value */ RtnType forBinOpPlus(BinOpPlus op); /** * Case for binary minus. * @param op host * @return visitor-specific return value */ RtnType forBinOpMinus(BinOpMinus op); /** * Case for times. * @param op host * @return visitor-specific return value */ RtnType forOpTimes(OpTimes op); /** * Case for divide. * @param op host * @return visitor-specific return value */ RtnType forOpDivide(OpDivide op); /** * Case for equals. * @param op host * @return visitor-specific return value */ RtnType forOpEquals(OpEquals op); /** * Case for not equals. * @param op host * @return visitor-specific return value */ RtnType forOpNotEquals(OpNotEquals op); /** * Case for less than. * @param op host * @return visitor-specific return value */ RtnType forOpLessThan(OpLessThan op); /** * Case for greater than. * @param op host * @return visitor-specific return value */ RtnType forOpGreaterThan(OpGreaterThan op); /** * Case for less than or equals. * @param op host * @return visitor-specific return value */ RtnType forOpLessThanEquals(OpLessThanEquals op); /** * Case for greater than or equals. * @param op host * @return visitor-specific return value */ RtnType forOpGreaterThanEquals(OpGreaterThanEquals op); /** * Case for and. * @param op host * @return visitor-specific return value */ RtnType forOpAnd(OpAnd op); /** * Case for or. * @param op host * @return visitor-specific return value */ RtnType forOpOr(OpOr op); // RtnType forOpGets(OpGets op); } /** * Unary plus operator. */ class UnOpPlus extends UnOp { /** * Singleton instance. */ public static final UnOpPlus ONLY = new UnOpPlus(); /** * Singleton constructor. */ private UnOpPlus() { super("+"); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(UnOpVisitor v) { return v.forUnOpPlus(this); } } /** * Unary minus operator. */ class UnOpMinus extends UnOp { /** * Singleton instance. */ public static final UnOpMinus ONLY = new UnOpMinus(); /** * Singleton constructor. */ private UnOpMinus() { super("-"); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(UnOpVisitor v) { return v.forUnOpMinus(this); } } /** * Not operator. */ class OpTilde extends UnOp { /** * Singleton instance. */ public static final OpTilde ONLY = new OpTilde(); /** * Singleton constructor. */ private OpTilde() { super("~"); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(UnOpVisitor v) { return v.forOpTilde(this); } } //class OpBang extends UnOp { // public static final OpBang ONLY = new OpBang(); // private OpBang() { super("!"); } // public RtnType accept(UnOpVisitor v) { // return v.forOpBang(this); // } //} // //class OpRef extends UnOp { // public static final OpRef ONLY = new OpRef(); // private OpRef() { super("ref"); } // public RtnType accept(UnOpVisitor v) { // return v.forOpRef(this); // } //} /** * Binary plus operator. */ class BinOpPlus extends BinOp { /** * Singleton instance. */ public static final BinOpPlus ONLY = new BinOpPlus(); /** * Singleton constructor. */ private BinOpPlus() { super("+"); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forBinOpPlus(this); } } /** * Binary minus operator. */ class BinOpMinus extends BinOp { /** * Singleton instance. */ public static final BinOpMinus ONLY = new BinOpMinus(); /** * Singleton constructor. */ private BinOpMinus() { super("-"); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forBinOpMinus(this); } } /** * Times operator. */ class OpTimes extends BinOp { /** * Singleton instance. */ public static final OpTimes ONLY = new OpTimes(); /** * Singleton constructor. */ private OpTimes() { super("*"); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forOpTimes(this); } } /** * Divide operator. */ class OpDivide extends BinOp { /** * Singleton instance. */ public static final OpDivide ONLY = new OpDivide(); /** * Singleton constructor. */ private OpDivide() { super("/"); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forOpDivide(this); } } /** * Equals operator. */ class OpEquals extends BinOp { /** * Singleton instance. */ public static final OpEquals ONLY = new OpEquals(); /** * Singleton constructor. */ private OpEquals() { super("="); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forOpEquals(this); } } /** * Not equals operator. */ class OpNotEquals extends BinOp { /** * Singleton instance. */ public static final OpNotEquals ONLY = new OpNotEquals(); /** * Singleton constructor. */ private OpNotEquals() { super("!="); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forOpNotEquals(this); } } /** * Less than operator. */ class OpLessThan extends BinOp { /** * Singleton instance. */ public static final OpLessThan ONLY = new OpLessThan(); /** * Singleton constructor. */ private OpLessThan() { super("<"); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forOpLessThan(this); } } /** * Greater than operator. */ class OpGreaterThan extends BinOp { /** * Singleton instance. */ public static final OpGreaterThan ONLY = new OpGreaterThan(); /** * Singleton constructor. */ private OpGreaterThan() { super(">"); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forOpGreaterThan(this); } } /** * Less than or equals operator. */ class OpLessThanEquals extends BinOp { /** * Singleton instance. */ public static final OpLessThanEquals ONLY = new OpLessThanEquals(); /** * Singleton constructor. */ private OpLessThanEquals() { super("<="); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forOpLessThanEquals(this); } } /** * Greater than or equals operator. */ class OpGreaterThanEquals extends BinOp { /** * Singleton instance. */ public static final OpGreaterThanEquals ONLY = new OpGreaterThanEquals(); /** * Singleton constructor. */ private OpGreaterThanEquals() { super(">="); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forOpGreaterThanEquals(this); } } /** * And operator. */ class OpAnd extends BinOp { /** * Singleton instance. */ public static final OpAnd ONLY = new OpAnd(); /** * Singleton constructor. */ private OpAnd() { super("&"); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forOpAnd(this); } } /** * Or operator. */ class OpOr extends BinOp { /** * Singleton instance. */ public static final OpOr ONLY = new OpOr(); /** * Singleton constructor. */ private OpOr() { super("|"); } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(BinOpVisitor v) { return v.forOpOr(this); } } //class OpGets extends BinOp { // public static final OpGets ONLY = new OpGets(); // private OpGets() { super("<-"); } // public RtnType accept(BinOpVisitor v) { // return v.forOpGets(this); // } //} /** * AST node for applications of unary operators. */ class UnOpApp implements AST { /** * Unary operator. */ private UnOp rator; /** * Operand. */ private AST arg; /** * Constructor for a unary operator application. * @param r operator * @param a operand */ UnOpApp(UnOp r, AST a) { rator = r; arg = a; } /** * Accessor for the operator. * @return operator */ public UnOp rator() { return rator; } /** * Accessor for the operand. * @return operand */ public AST arg() { return arg; } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(ASTVisitor v) { return v.forUnOpApp(this); } /** * Return the string representation of the node. * @return string representation */ public String toString() { return rator + " " + arg; } } /** * AST node for applications of binary operators. */ class BinOpApp implements AST { /** * Binary operator. */ private BinOp rator; /** * Operands. */ private AST arg1, arg2; /** * Constructor for a unary operator application. * @param r operator * @param a1 first operand * @param a2 second operand */ BinOpApp(BinOp r, AST a1, AST a2) { rator = r; arg1 = a1; arg2 = a2; } /** * Accessor for the operator. * @return operator */ public BinOp rator() { return rator; } /** * Accessor for the first operand. * @return first operand */ public AST arg1() { return arg1; } /** * Accessor for the second operand. * @return second operand */ public AST arg2() { return arg2; } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(ASTVisitor v) { return v.forBinOpApp(this); } /** * Return the string representation of the node. * @return string representation */ public String toString() { return "(" + arg1 + " " + rator + " " + arg2 + ")"; } } /** * AST node for Maps. */ class Map implements AST { /** * Array of variables. */ private Variable[] vars; /** * Body of the map. */ private AST body; /** * Constructor for a Map. * @param v array of variables * @param b body */ Map(Variable[] v, AST b) { vars = v; body = b; } /** * Accessor for the array of variables. * @return array of variables */ public Variable[] vars() { return vars; } /** * Accessor for the body. * @return body */ public AST body() { return body; } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(ASTVisitor v) { return v.forMap(this); } /** * Return the string representation of the node. * @return string representation */ public String toString() { return "map " + ToString.toString(vars, ",") + " to " + body; } } /** * AST node for function applications. */ class App implements AST { /** * Operator. */ private AST rator; /** * Array of arguments. */ private AST[] args; /** * Constructor for a function application. * @param r operator * @param a array of arguments */ App(AST r, AST[] a) { rator = r; args = a; } /** * Accessor for the operator. * @return operator */ public AST rator() { return rator; } /** * Accessor for the array of arguments. * @return array of arguments */ public AST[] args() { return args; } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(ASTVisitor v) { return v.forApp(this); } /** * Return the string representation of the node. * @return string representation */ public String toString() { return rator.accept(new ADefaultASTVisitor() { public String forDefault(AST a) { return "(" + rator + ")(" + ToString.toString(args, ", ") + ")"; } public String forPrimFun(PrimFun f) { return rator + "(" + ToString.toString(args, ", ") + ")"; } public String forVariable(Variable v) { return rator + "(" + ToString.toString(args, ", ") + ")"; } }); } } /** * AST node for an If. */ class If implements AST { /** * ASTs for the test, consequence, and alternative expressions. */ private AST test, conseq, alt; /** * Constructor for an If. * @param t test expression * @param c consequence expression * @param a alternative expression */ If(AST t, AST c, AST a) { test = t; conseq = c; alt = a; } /** * Accessor for the test expression. * @return test expression */ public AST test() { return test; } /** * Accessor for the consequence expression. * @return consequence expression */ public AST conseq() { return conseq; } /** * Accessor for the alternative expression. * @return alternative expression */ public AST alt() { return alt; } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(ASTVisitor v) { return v.forIf(this); } /** * Return the string representation of the node. * @return string representation */ public String toString() { return "if " + test + " then " + conseq + " else " + alt; } } /** * AST node for a Let. */ class Let implements AST { /** * Array of definitions. */ private Def[] defs; /** * Body of the let statement. */ private AST body; /** * Constructor for a Let. * @param d array of definitions * @param b body */ Let(Def[] d, AST b) { defs = d; body = b; } /** * Visitor hook. * @param v visitor to execute * @return visitor-specific return value */ public RtnType accept(ASTVisitor v) { return v.forLet(this); } /** * Accessor for the array of definitions. * @return array of definitions */ public Def[] defs() { return defs; } /** * Accessor for the body. * @return body */ public AST body() { return body; } /** * Accessor for the variables in the definitions, i.e. the left-hand sides. * @return array of variables. */ public Variable[] vars() { int n = defs.length; Variable[] vars = new Variable[n]; for(int i = 0; i < n; i++) { vars[i] = defs[i].lhs(); } return vars; } /** * Accessor for the expressions in the definitions, i.e. the right-hand sides. * @return array of expressions. */ public AST[] exps() { int n = defs.length; AST[] exps = new AST[n]; for(int i = 0; i < n; i++) { exps[i] = defs[i].rhs(); } return exps; } /** * Return the string representation of the node. * @return string representation */ public String toString() { return "let " + ToString.toString(defs, " ") + " in " + body; } } /** * Class for a definition. */ class Def { /** * Left-hand side of the definition. */ private Variable lhs; /** * Right-hand side of the definition. */ private AST rhs; /** * Constructor for a definition * @param l left-hand side * @param r right-hand side */ Def(Variable l, AST r) { lhs = l; rhs = r; } /** * Accessor for the left-hand side. * @return left-hand side */ public Variable lhs() { return lhs; } /** * Accessor for the right-hand side. * @return right-hand side */ public AST rhs() { return rhs; } /** * Return the string representation of the definition. * @return string representation */ public String toString() { return lhs + " := " + rhs + ";"; } } /** * Helper class to create string representations. */ class ToString { /** * Helper method to create a string representation of an array. If an array element is an array itself, * it will recusrively invoke this method for that element. * @param a array * @param s separator * @return string representation of an array */ public static String toString(Object[] a, String s) { StringBuffer result = new StringBuffer(); for(int i = 0; i < a.length; i++) { if (i > 0) { result.append(s); } Object elt = a[i]; String eltString = (elt instanceof Object[]) ? toString((Object[])elt, s) : elt.toString(); result.append(eltString); } return result.toString(); } }