package rebelsky.compiler.parser;

import java.util.Hashtable;	// Used for storing attributes
import java.util.Vector;	// Used for storing children
import rebelsky.compiler.misc.Symbol;

/**
 * A simple node for a parse tree.
 *
 * @author Samuel A. Rebelsky
 * @version 1.2 of April 2004.
 */
public class Node
{
  // +--------+------------------------------------------------------------
  // | Fields |
  // +--------+

  /**
   * The symbol stored in the current node.  The legal values
   * should probably be stored in a separate class.
   */
  Symbol symbol;

  /**
   * The children of the current node.  They must be other nodes.
   */
  Vector children;

  /**
   * The attributes of the current node.  You can have as many as
   * you want.  Each has a name.  You should be able to change
   * these attributes.
   */
  Hashtable attributes;


  // +--------------+------------------------------------------------------
  // | Constructors |
  // +--------------+

  /**
   * Create a new node with a particular set of children.  The vector
   * must be null or include only other nodes.
   */
  public Node(Symbol symbol, Vector children) {
    this.initialize(symbol, children);
  } // Node(int, Vector)

  /**
   * Create a new node with no children.
   */
  public Node(Symbol symbol) {
    this.initialize(symbol, null);
  } // Node(Symbol)

  /**
   * Create a new node with exactly one child.
   */
  public Node(Symbol symbol, Node child) {
    Vector children = new Vector();
    children.add(child);
    this.initialize(symbol, children);
  } // Node(Symbol, Node)

  private void initialize(Symbol symbol, Vector children)
  {
    this.symbol = symbol;
    this.children = children;
    this.attributes = new Hashtable();
  } // initialize(Symbol, Vector)

  // +-----------+---------------------------------------------------------
  // | Observers |
  // +-----------+

  /**
   * Get the symbol associated with this node.
   */
  public Symbol getSymbol() {
    return this.symbol;
  } // getSymbol()


  /**
   * Determine how many children this node has.
   */
  public int numChildren() {
    if (children == null)
      return 0;
    else
      return children.size();
  } // numChildren(void)

  /**
   * Get one of the children.
   * 
   * @exception Exception
   *   If the node does not contain the specified child.
   */
  public Node getChild(int childNum) {
    return (Node) children.get(childNum);
  } // getChild

  /**
   * Get one of the attributes.
   */
  public Object getAttribute(String attribute) {
    return attributes.get(attribute);
  } // getAttribute(String)


  // +-----------+---------------------------------------------------------
  // | Modifiers |
  // +-----------+

  /**
   * Set one of the attributes.
   */
  public void setAttribute(String attribute, Object value) {
    attributes.put(attribute, value);
  } // setAttribute(String,Object)

  /**
   * Replace the child of a node.  The node must already have
   * a child with that number.
   */
  public void replaceChild(int childnum, Node newchild) {
    this.children.set(childnum, newchild);
  } // replaceChild(int, Node)

} // class Node

