import AST.*;
import java.util.*;

public class Test2 {

  public static void main(String[] args) {
    Prog p = createAST(5);
    String tree = p.printTree();
    System.out.println("Tree: " + tree);
  }

  public static Prog createAST(int level) {
    return new Prog(
      new AST.List().add(
        new CompUnit(
          "comp",
          new AST.List().add(
            new ClassDecl("Object", new TypeName("Object"), 
              new AST.List()
              .add(new FieldDecl(parseDots("comp.Object"), "f", parseDots("comp.Object." + levelToStr(level) + ".f")))
              .add(parseInnerClass(levelToStr(level)))
            )
          )
        ) 
      )
    );
  }

  private static String levelToStr(int level) {
    StringBuffer buf = new StringBuffer();
    for (int i = 1; i <= level; i++) {
      buf.append("Inner" + i);
      if (i + 1 <= level) {
        buf.append(".");
      }
    }
    return buf.toString();
  }

  private static MemberClassDecl parseInnerClass(String nestedName) {
    Stack<MemberClassDecl> stack = new Stack<MemberClassDecl>();
    StringTokenizer tok = new StringTokenizer(nestedName, ".");
    while (tok.hasMoreTokens()) {
      stack.push(new MemberClassDecl(new ClassDecl(tok.nextToken(), new TypeName("Object"), new AST.List())));
    }
    MemberClassDecl innerMost = stack.peek();
    innerMost.getClassDeclNoTransform().getBodyDeclListNoTransform()
        .add(new FieldDecl(parseDots("comp.Object"), "f", parseDots("comp.Object.f")));
    while (stack.size() > 1) { 
      MemberClassDecl child = stack.pop();
      MemberClassDecl parent = stack.pop();
      parent.getClassDeclNoTransform().getBodyDeclListNoTransform().add(child);
      stack.push(parent);
    }
    return stack.pop();
  }

  private static Name parseDots(String list) {
    Stack<Name> stack = new Stack<Name>();
    StringTokenizer tok = new StringTokenizer(list, ".");
    while (tok.hasMoreTokens()) {
      stack.push(new ParseName(tok.nextToken()));
    }
    while (stack.size() > 1) { 
      Name right = stack.pop();
      Name left = stack.pop();
      stack.push(new Dot("dot", left, right));
    }
    return stack.pop();
  }

}
