/**
 *
 */
package ca.uwaterloo.joos.ast.decl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import ca.uwaterloo.joos.ast.AST.ASTConstructException;
import ca.uwaterloo.joos.ast.ASTNode;
import ca.uwaterloo.joos.ast.Modifiers;
import ca.uwaterloo.joos.ast.descriptor.ChildDescriptor;
import ca.uwaterloo.joos.ast.type.ArrayType;
import ca.uwaterloo.joos.ast.type.PrimitiveType;
import ca.uwaterloo.joos.ast.type.ReferenceType;
import ca.uwaterloo.joos.ast.type.Type;
import ca.uwaterloo.joos.parser.ParseTree.LeafNode;
import ca.uwaterloo.joos.parser.ParseTree.Node;
import ca.uwaterloo.joos.parser.ParseTree.TreeNode;

/**
 * @author Greg Wang
 *
 */
public abstract class BodyDeclaration extends ASTNode {

	protected static final ChildDescriptor MODIFIERS = new ChildDescriptor(Modifiers.class);
	protected static final ChildDescriptor TYPE = new ChildDescriptor(Type.class);

	public BodyDeclaration(Node node, ASTNode parent) throws Exception {
		super(node, parent);
	}

	public Modifiers getModifiers() throws ChildTypeUnmatchException {
		return (Modifiers) this.getChildByDescriptor(BodyDeclaration.MODIFIERS);
	}

	public Type getType() throws ChildTypeUnmatchException {
		return (Type) this.getChildByDescriptor(BodyDeclaration.TYPE);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * ca.uwaterloo.joos.parser.ParseTreeTraverse.Traverser#processTreeNode(
	 * ca.uwaterloo.joos.parser.ParseTree.TreeNode)
	 */
	@Override
	public List<Node> processTreeNode(TreeNode treeNode) throws Exception {
		List<Node> offers = new ArrayList<Node>();
		if (treeNode.productionRule.getLefthand().equals("modifiers")) {
			Modifiers modifiers = new Modifiers(treeNode, this);
			addChild(MODIFIERS, modifiers);
		} else if (treeNode.productionRule.getLefthand().equals("primitivetype")) {
			Type type = new PrimitiveType(treeNode, this);
			addChild(TYPE, type);
		} else if (treeNode.productionRule.getLefthand().equals("referencetype")) {
			Type type = null;
			List<String> rhs = Arrays.asList(treeNode.productionRule.getRighthand());
			if(rhs.contains("arraytype")) {
				type = new ArrayType(treeNode.children.get(0), this);
			}
			else if(rhs.contains("name")) {
				type = new ReferenceType(treeNode.children.get(0), this);
			}
			else {
				throw new ASTConstructException("Unknown referencetype" + rhs);
			}
			addChild(TYPE, type);
		} else {
			offers.addAll(treeNode.children);
		}
		return offers;
	}


	/* (non-Javadoc)
	 * @see ca.uwaterloo.joos.parser.ParseTreeTraverse.Traverser#processLeafNode(ca.uwaterloo.joos.parser.ParseTree.LeafNode)
	 */
	@Override
	public void processLeafNode(LeafNode leafNode) throws Exception {
		if (leafNode.token.getKind().equals("ID")) {
			setIdentifier(leafNode.token.getLexeme());
		}
	}
}

@@ -309,16 +309,102 @@
 riptor;%0A
+import ca.uwaterloo.joos.ast.name.Name;%0Aimport ca.uwaterloo.joos.ast.name.SimpleName;%0A
 import c
@@ -436,24 +436,24 @@
 .ArrayType;%0A
-
 import ca.uw
@@ -820,16 +820,96 @@
 Node %7B%0A%0A
+%09protected static final ChildDescriptor NAME = new ChildDescriptor(Name.class);%0A
 %09protect
@@ -1141,16 +1141,16 @@
 ption %7B%0A
-
 %09%09super(
@@ -1164,16 +1164,317 @@
 arent);%0A
+%09%09Name name = this.getName();%0A%09%09if (name == null) %7B%0A%09%09%09throw new ASTConstructException(%22BodyDeclaration always expecting a name%22);%0A%09%09%7D%0A%09%09this.setIdentifier(name.getName());%0A%09%7D%0A%09%0A%09public Name getName() throws ChildTypeUnmatchException %7B%0A%09%09return (Name) this.getChildByDescriptor(BodyDeclaration.NAME);%0A
 %09%7D%0A%0A%09pub
@@ -3182,48 +3182,95 @@
 %0A%09%09%09
-setIdentifier(leafNode.token.getLexeme()
+Name name = new SimpleName(leafNode, this);%0A%09%09%09this.addChild(BodyDeclaration.NAME, name
 );%0A%09

Add Name to BodyDecl