content: package java_cup.runtime;
  
  import javax.xml.stream.XMLStreamException;
  import javax.xml.stream.XMLStreamWriter;
  
  /**
   * Default Implementation for SymbolFactory, creates
   * plain old Symbols
   *
   * @version last updated 27-03-2006
   * @author Michael Petter
   */
  
  /* *************************************************
    class DefaultSymbolFactory
    interface for creating new symbols  
   ***************************************************/
  public class ComplexSymbolFactory implements SymbolFactory{
      public static class Location {
          private String unit="unknown";
          private int line, column, offset=-1;
          /**
           * Copy Constructor for other ComplexSymbolFactory based Locations
           * @param other
           */
          public Location(Location other){
          	this(other.unit,other.line,other.column,other.offset);
          }
  	/**
  	 * Location Object
  	 * stores compilation unit, line, column and offset to the file start
  	 * @param unit      compilation unit, e.g. file name
  	 * @param line      line number
  	 * @param column    column number
  	 * @param offset    offset from file start
  	 */
      public Location(String unit, int line, int column, int offset){
  	   this(unit,line,column);
  	   this.offset=offset;
  	}
  	/**
  	 * Location Object
  	 * stores compilation unit, line and column
  	 * @param unit      compilation unit, e.g. file name
  	 * @param line      line number
  	 * @param column    column number
  	 */
          public Location(String unit, int line, int column){
              this.unit=unit;
              this.line=line;
              this.column=column;
          }
  	/**
  	 * Location Object
  	 * stores line, column and offset to the file start
  	 * @param line      line number
  	 * @param column    column number
  	 * @param offset    offset from file start
  	 */
          public Location(int line, int column, int offset){
  	    this(line,column);
  	    this.offset=offset;
  	}
  	/**
  	 * Location Object
  	 * stores line and column 
  	 * @param line      line number
  	 * @param column    column number
  	 */
          public Location(int line, int column){
              this.line=line;
              this.column=column;
          }
  	/**
  	 * getColumn
  	 * @returns column if known, else -1
  	 */
          public int getColumn(){
              return column;
          }
  	/**
  	 * getLine
  	 * @returns line if known, else -1
  	 */
          public int getLine(){
              return line;
          }
          /**
           * move moves this Location by the given differences. 
           * @param linediff
           * @param coldiff
           * @param offsetdiff
           */
          public void move(int linediff, int coldiff, int offsetdiff){
      		if (this.line >= 0)
      			this.line += linediff;
      		if (this.column >= 0)
      			this.column += coldiff;
      		if (this.offset >= 0)
      			this.offset += offsetdiff;
          }
          /**
           * Cloning factory method
           * @param other
           * @return new cloned Location
           */
          public static Location clone(Location other){
          	return new Location(other);
          }
  	/**
  	 * getUnit
  	 * @returns compilation unit if known, else 'unknown'
  	 */
          public String getUnit(){
              return unit;
          }
  	/**
  	 * getLine
  	 * @returns line if known, else -1
  	 */
          public String toString(){
              return getUnit()+":"+getLine()+"/"+getColumn()+"("+offset+")";
          }
          /**
           * Writes the location information directly into an XML document
           * @param writer the destination XML Document
           * @param orientation adds details about the orientation of this location as an attribute; often used with the strings "left" or "right"
           * @throws XMLStreamException
           */
          public void toXML(XMLStreamWriter writer,String orientation) throws XMLStreamException {
          	writer.writeStartElement("location");
          	writer.writeAttribute("compilationunit", unit);
          	writer.writeAttribute("orientation", orientation);
          	writer.writeAttribute("linenumber", line+"");
          	writer.writeAttribute("columnnumber", column+"");
          	writer.writeAttribute("offset", offset+"");
          	writer.writeEndElement();
          }
  	/**
  	 * getOffset
  	 * @returns offset to start if known, else -1
  	 */
          public int getOffset(){
              return offset;
          }
      }
      /**
       * ComplexSymbol with detailed Location Informations and a Name
       */
      public static class ComplexSymbol extends Symbol {
          protected String name;
          public Location xleft,xright;
          public ComplexSymbol(String name, int id) {
              super(id);
              this.name=name;
          }
          public ComplexSymbol(String name, int id, Object value) {
              super(id,value);
              this.name=name;
          }
          public String toString(){
              if (xleft==null || xright==null) return "Symbol: "+name;
              return "Symbol: "+name+" ("+xleft+" - "+xright+")";
          }
          public String getName(){
          	return name;
          }
          public ComplexSymbol(String name, int id, int state) {
              super(id,state);
              this.name=name;
          }
          public ComplexSymbol(String name, int id, Symbol left, Symbol right) {
              super(id,left,right);
              this.name=name;
              if (left!=null)  this.xleft = ((ComplexSymbol)left).xleft;
              if (right!=null) this.xright= ((ComplexSymbol)right).xright;
          }
          public ComplexSymbol(String name, int id, Location left, Location right) {
              super(id,left.offset,right.offset);
              this.name=name;
              this.xleft=left;
              this.xright=right;
          }
          public ComplexSymbol(String name, int id, Symbol left, Symbol right, Object value) {
              super(id,left.left,right.right,value);
              this.name=name;
              if (left!=null)  this.xleft = ((ComplexSymbol)left).xleft;
              if (right!=null) this.xright= ((ComplexSymbol)right).xright;
          }
          public ComplexSymbol(String name, int id, Symbol left, Object value) {
              super(id,left.right,left.right,value);
              this.name=name;
              if (left!=null) { 
              	this.xleft = ((ComplexSymbol)left).xright;
              	this.xright= ((ComplexSymbol)left).xright;
              }
          }
          public ComplexSymbol(String name, int id, Location left, Location right, Object value) {
              super(id,left.offset,right.offset,value);
              this.name=name;
              this.xleft=left;
              this.xright=right;
          }
          public Location getLeft(){
              return xleft;
          }
          public Location getRight(){
              return xright;
          }
      }
  
  
      // Factory methods
      /**
       * newSymbol
       * creates a complex symbol with Location objects for left and right boundaries;
       * this is used for terminals with values!
       */
      public Symbol newSymbol(String name, int id, Location left, Location right, Object value){
          return new ComplexSymbol(name,id,left,right,value);
      }
      /**
       * newSymbol
       * creates a complex symbol with Location objects for left and right boundaries;
       * this is used for terminals without values!
       */
      public Symbol newSymbol(String name, int id, Location left, Location right){
          return new ComplexSymbol(name,id,left,right);
      }
  	public Symbol newSymbol(String name, int id, Symbol left, Object value) {
  		return new ComplexSymbol(name,id,left,value);
  	}
      public Symbol newSymbol(String name, int id, Symbol left, Symbol right, Object value){
          return new ComplexSymbol(name,id,left,right,value);
      }
      public Symbol newSymbol(String name, int id, Symbol left, Symbol right){
          return new ComplexSymbol(name,id,left,right);
      }
      public Symbol newSymbol(String name, int id){
          return new ComplexSymbol(name,id);
      }
      public Symbol newSymbol(String name, int id, Object value){
          return new ComplexSymbol(name,id,value);
      }
      public Symbol startSymbol(String name, int id, int state){
          return new ComplexSymbol(name,id,state);
      }
  }
  