/* zweic -- a compiler for Zwei * * Stephane Micheloud & LAMP * * $Id$ */ package zweic; import java.io.PrintWriter; /** * This class implements a pretty printer for abstract syntax * trees in Zwei. */ class Printer(out: PrintWriter) { import Operators._; /** * Indentation string. */ private val step = " "; /** * indentation level. */ private var level = 0; def joinprint(args:List[Tree], sep: => Printer):Printer = args match { case h :: Nil => print(h); case h :: t => print(h); sep; joinprint(t, sep); case Nil => print(""); } def joinprint(args:List[Tree], sep:String):Printer = { joinprint(args, print(sep)); } /** * Prints a tree node. */ def print(tree: Tree): Printer = { if (tree.isInstanceOf[Expr] && tree.asInstanceOf[Expr].brackets) print("("); tree match { case Program(decls, main) => joinprint(decls, println).println; print(main).println; // // Tree nodes for definitions // case ClassDef(name, extend, members) => print("class ").print(name); extend match { case Some(e) => print(" extends ").print(e); case _ => null; } print(" {").indent.println; joinprint(members, println.println); undent.println.print("}").println; case FieldDecl(formal) => print(formal).print(";"); case MethodDef(name, args, returntype, expression) => print(returntype).print(" ").print(name); print(" (").joinprint(args, ", ").print(") "); print(expression); case Formal(name, typ) => print(typ).print(" ").print(name); // // Tree nodes for types // case IntType() => print("Int"); case NullType() => print("Null"); case ClassType(name) => print(name); // // Tree nodes for statements // case While(cond, stats) => print("while (").print(cond).print(") {"); indent.println.joinprint(stats, println).undent.println.print("}"); case Var(varname, vartype, init) => print(vartype).print(" ").print(varname).print(" = "). print(init).print(";"); case Set(name, expr) => print(name).print(" = ").print(expr).print(";"); case Do(expr) => print(expr).print(";"); case PrintInt(expr) => print("printInt(").print(expr).print(")").print(";"); case PrintChar(expr) => print("printChar(").print(expr).print(")").print(";"); // // Tree nodes for expressions // case Ident(name) => print(name); case New(name, args) => print("new ").print(name).print("("); joinprint(args, ", "); print(")"); case Select(prefix, selector) => print(prefix).print(".").print(selector); case Call(obj, funcname, args) => print(obj).print(".").print(funcname).print("("); joinprint(args, ", ") print(")"); case NullLit() => print("null"); case IntLit(value) => print(value.toString()); case Unop(op, expr) => print(op.toString()).print(expr); case Binop(op, left, right) => print(left).print(" "); print(op.toString()); print(" ").print(right); case ReadInt() => print("readInt"); case ReadChar() => print("readChar"); case If(cond, stata, statb) => print("if (").print(cond).print(") "); indent.print(stata).undent.println; print("else ").indent; print(statb).undent; case Block(stats, expression) => print("{").indent.println; for (val s <- stats) { print(s).println; } print("return ").print(expression); undent.println.print("}"); case x => error("unexpected error in tree"); }; if (tree.isInstanceOf[Expr] && tree.asInstanceOf[Expr].brackets) print(")"); print(""); } /** * Print abstract syntax trees separated by commas. */ private def print(trees: List[Tree]): Printer = trees match { case _ => this } /** * Print a string. */ private def print(value: String): Printer = { out.print(value); this } private def print(name: Name): Printer = print(name.name); private def print(formal: Pair[Name, TypeTree]): Printer = print(formal._2).print(" ").print(formal._1); /** * Print an end-of-line character and indent the following * line appropriately. */ private def println = { out.println(); for (val i <- List.range(0, level)) out.print(step); this } /** * Increment the indentation level. */ private def indent = { level = level + 1; this } /** * Decrement the indentation level. */ private def undent = { level = level - 1; this } }