/* 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:String):Printer = args match { case h :: Nil => print(h); case h :: t => print(h).print(sep); joinprint(t, sep); case Nil => print("---"); } /** * Prints a tree node. */ def print(tree: Tree): Printer = tree match { case Program(decls, main) => for (val d <- decls) { print(d).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; for (val m <- members) { print(m).println; } undent; print("}").println; case FieldDecl(formal) => print(formal); case MethodDef(name, args, returntype, expression) => print(returntype).print(" ").print(name).print(" ("); joinprint(args, ", "); print(") {").println; indent; print(expression).println; undent; print("}") 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; for (val s <- stats) { print(s).println; } undent; println; print("}"); case Var(varname, vartype, init) => print(vartype).print(" ").print(varname).print(" = ").print(init); case Set(name, expr) => print(name).print(" = ").print(expr); case Do(expr) => print(expr); case PrintInt(expr) => print("PrintInt(").print(expr).print(")"); case PrintChar(expr) => print("PrintChar(").print(expr).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(op.toString()).print(right); case ReadInt() => print("ReadInt"); case ReadChar() => print("ReadChar"); case If(cond, stata, statb) => print("if (").print(cond).print(") {"); indent; println; print(stata) undent; println; print("} else {") indent; println; print(statb) undent; println; print("}").println; case Block(stats, expression) => print("{") indent; println; for(val s <- stats) { print(s).println; } print("return ").print(expression) undent; println; print("}").println; case x => this } /** * 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 abstract syntax trees separated by commas. */ private def printFormals(formals: List[Pair[Name, TypeTree]]): Printer = formals match { // ... à compléter ... case _ => this } /** * 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 } }