Newer
Older
zweic / sources / zweic / Printer.scala
/*  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
  }
}