import java.util.StringTokenizer; class Node { public String tag() { return getClass().getName(); } } /* ========================================================================= */ class NodeList extends Node { public Listable first; // First child. public void append(Listable newChild) { if (first == null) first = newChild; // It's our first child. else { Listable last = first; // Not really the last child, but will be. while (last.next != null) last = last.next; // Find last child. last.next = newChild; // Now it's the last, so we append to it. } } public String toString() { String result = "(" + tag() + ","; for (Listable c = first; c != null; c = c.next) result += c + ","; result += "null)"; return result; } } /* ========================================================================= */ class MethodDecls extends NodeList { } class FormalParams extends NodeList { } class ActualParams extends NodeList { } class Statements extends NodeList { } /* ========================================================================= */ class Listable extends Node { public Listable next; } /* ========================================================================= */ /* High-level program structures. */ /* ========================================================================= */ class ClassDecl extends Node // Class tree. { public Id name; // Name of class. public MethodDecls methods; // List of method declarations. public ClassDecl(Id n, MethodDecls ms) { name = n; methods = ms; } public String toString() { return "(" + tag() + "," + name + "," + methods + ")"; } } /* ------------------------------------------------------------------------- */ class MethodDecl extends Listable // Single method declaration (and definition too!). { public Id typeName; public Id name; public FormalParams params; public Block body; public MethodDecl(Id tn, Id n, FormalParams ps, Block b) { name = n; typeName = tn; params = ps; body = b; } public String toString() { return "(" + tag() + "," + typeName + "," + name + "," + params + "," + body + ")"; } } /* ------------------------------------------------------------------------- */ class FormalParam extends Listable // Single formal parameter. { public Id typeName; public Id name; public FormalParam(Id tn, Id n) { typeName = tn; name = n; } public String toString() { return "(" + tag() + "," + typeName + "," + name + ")"; } } /* ========================================================================= */ /* Expressions. */ /* ========================================================================= */ // Because actual parameter lists consist of lists of expressions, Expression needs to be listable. class Expression extends Listable { } /* ------------------------------------------------------------------------- */ class Id extends Expression // Identifier node { public String spelling; public Id(String s) { spelling = s; } public String toString() { return tag() + " \"" + spelling + "\""; } } /* ------------------------------------------------------------------------- */ class Num extends Expression // Integer literal. { public String spelling; public Num(String s) { spelling = s; } public String toString() { return tag() + " \"" + spelling + "\""; } } /* ------------------------------------------------------------------------- */ class Bool extends Expression // Boolean literal. Note that the spelling { // of the boolean literel is "true or "false" public String spelling; public Bool(String s) { spelling = s; } public String toString() { return tag() + " \"" + spelling + "\""; } } /* ------------------------------------------------------------------------- */ // Why don't we insist that the left and right operands of an ArithmeticExpr // be numbers or identifiers? Because then a type error in the source text // would lead to a runtime error in the compiler during parsing. We want to // do that during the checking phase. class ArithmeticExpr extends Expression { public int op; // We use Token's enumerations. public Expression left; public Expression right; public ArithmeticExpr(int o, Expression lt, Expression rt) { op = o; left = lt; right = rt;} public String toString() { return "(" + tag() + "," + Token.spellingOf(op) + "," + left + "," + right + ")"; } } /* ------------------------------------------------------------------------- */ // The left and right operands should be boolean -- that is, EqualityExpr. See comment // above for ArithmeticExpr for reason why we don't insist on this. class ConditionalExpr extends Expression { public int op; // We use Token's enumerations. public Expression left; public Expression right; public ConditionalExpr(int o, Expression lt, Expression rt) { op = o; left = lt; right = rt;} public String toString() { return "(" + tag() + "," + Token.spellingOf(op) + "," + left + "," + right + ")"; } } /* ------------------------------------------------------------------------- */ // Here the left and right must be the same type, but could be any kind of expression. class EqualityExpr extends Expression { public int op; // We use Token's enumerations. public Expression left; public Expression right; public EqualityExpr(int o, Expression lt, Expression rt) { op = o; left = lt; right = rt;} public String toString() { return "(" + tag() + "," + Token.spellingOf(op) + "," + left + "," + right + ")"; } } /* ------------------------------------------------------------------------- */ class CallExpr extends Expression { public Id name; public ActualParams params; public CallExpr(Id n, ActualParams ps) { name = n; params = ps; } public String toString() { return "(" + tag() + "," + name + "," + params + ")"; } } /* ========================================================================= */ /* Statements. */ /* ========================================================================= */ class Statement extends Listable { } /* ------------------------------------------------------------------------- */ class Block extends Statement { public Statements statements; public Block(Statements ss) { statements = ss; } public String toString() { return "(" + tag() + "," + statements + ")"; } } /* ------------------------------------------------------------------------- */ // Note that this has the same exact form as FormalParam. class LocalVarDecl extends Statement { public Id typeName; public Id name; public LocalVarDecl(Id tn, Id n) { typeName = tn; name = n; } public String toString() { return "(" + tag() + "," + typeName + "," + "," + name + ")"; } } /* ------------------------------------------------------------------------- */ class AssignStmt extends Statement { public Id destination; public Expression source; public AssignStmt(Id d, Expression s) { destination = d; source = s; } public String toString() { return "(" + tag() + "," + destination + "," + source + ")"; } } /* ------------------------------------------------------------------------- */ class IfStmt extends Statement { public Expression premise; public Statement conclusion; public Statement alternative; public IfStmt(Expression p, Statement c, Statement a) { premise = p; conclusion = c; alternative = a; } public String toString() { String as = (alternative == null ? "null" : alternative.toString()); return "(" + tag() + "," + premise + "," + conclusion + "," + as + ")"; } } /* ------------------------------------------------------------------------- */ class WhileStmt extends Statement { public Expression requirement; public Statement body; public WhileStmt(Expression req, Statement b) { requirement = req; body = b; } public String toString() { return "(" + tag() + "," + requirement + "," + body + ")"; } } /* ------------------------------------------------------------------------- */ class ReturnStmt extends Statement { public Expression value; public ReturnStmt(Expression v) { value = v; } public String toString() { return "(" + tag() + "," + value + ")"; } } /* ========================================================================= */ class Indenter { public static void print(String list) { StringTokenizer st = new StringTokenizer(list, ",", false); int indent = 0; while (st.hasMoreTokens()) { String s = st.nextToken(); int openTree = 0, closeTree = 0; for (int i = 0; i < indent; i++) System.out.print("| "); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '(') openTree++; else if (c == ')') closeTree++; else System.out.print(c); } System.out.println(); indent += openTree - closeTree; } } }