import pascal.PascalNonterminals;

import rebelsky.compiler.misc.Checker;
import rebelsky.compiler.misc.Symbol;
import rebelsky.compiler.misc.Traverser;
import rebelsky.compiler.parser.Node;

/**
 * A traverser that prints every declared identifier with its type.
 * (For types that are not just identifiers, just prints the root
 * symbol.)
 *
 * @author Samuel A. Rebelsky
 * @version 1.0 of April 2004
 */
public class VariableTyper
  extends Traverser
{
  String indent = "";

  public VariableTyper()
  {
    this.setChecker(PascalNonterminals.VARIABLE_DECLARATION, new Checker() {
      public void check(Traverser t, Node n) 
        throws Exception
      {
        // Count the number of variables declared.
        int numvars = n.numChildren() - 1;
        // Visit all the children, just in case.
        for (int i = 0; i <= numvars; i++)
          t.traverse(n.getChild(i));
        // Get the type
        Symbol type = n.getChild(numvars).getSymbol();
        if (type == PascalNonterminals.TYPE_IDENTIFIER)
          type = n.getChild(numvars).getChild(0).getSymbol();
        // Print the types
        for (int i = 0; i < numvars; i++) {
          System.out.print(indent);
          System.out.println(n.getChild(i).getSymbol() + " has type " + type);
        } // for
      } // check(Traverser)
    });
    this.setChecker(PascalNonterminals.PROCEDURE_DECLARATION, new Checker() {
      public void check(Traverser t, Node n)
        throws Exception
      {
        indent = indent + "  ";
        System.out.println(indent + "Entering new scope");
        int numchildren = n.numChildren();
        for (int i = 0; i < numchildren; i++)
          t.traverse(n.getChild(i));
        System.out.println(indent + "Leaving new scope");
        indent = indent.substring(2);
      } // check(Traverser, Node)
    });
  } // VariableTyper()
} // class VariableTyper

