// Expr.java

/** A primitave regular expression. It could be as simple as a single
 *  letter, or an empty string, to as complex as an expression involving
 *  Unions, Concatenations, and Kleene Star
 *  @author <a href="mailto:bergmann@rowan.edu"> Seth Bergmann </a>
 *  @author <a href="mailto:gspyo@jersey.net"> Greg Safko </a>
 */
 
public abstract class Expr
{  

   /** Private variables for an expression.
    *  @param left The left operand of the concatenation.
    *  @param right The right operand of the concatenation.
    *  @param star The entire expression formatted for a * operation
    *  @param prim The character variable that holds primitive data
    *  @param epsChar The character variable that holds characters used to represent epsilon (the empty string)
    *  @param nullChar The character variable that holds characters used to represent the empty set (the null set)
    */
   
   private Expr left, right, star;
   private Character prim;
   private Character epsChar = new Character('e');
   private Character nullChar = new Character('N');
  
  
   public Expr (Character p)
   {
   		prim = p;   	
   }
   
   /** Constructor for an Expr
    *  Return the expression in the form of a string which
    *  is ready for the star operation.
    */  
    
   public Expr (Expr s)
   {	
   		star = s;   	 
   }
   
   /**  Constructor for an Expr with left and right operands
    *  Stores the expression in a left Expr and right Expr format
    */ 
    
   public Expr (Expr l, Expr r)
   {	
   		left = l;
   		right = r;  
   		left = left.reduce();
   		right = right.reduce();	 
   }
   

	// Methods used to return the left, right, and star parameters 
   	public Expr getLeft()
   	{
   		return left;
   	}
   
   	public Expr getRight()
   	{
   		return right;
   	}
   	
   	public Expr getStar()
   	{
   		return star;
   	}
   
    public Character getValue()
   	{
   		return prim;
   	}
   
    public boolean equals(Expr e)
    {
    if (this instanceof Union)
    	if (e instanceof Union)
    		return (this.getLeft().equals(e.getLeft())
    				&& this.getRight().equals(e.getRight()))
    				|| 
    				(this.getLeft().equals(e.getRight())
    				&& this.getRight().equals(e.getLeft()));	
    	else
    		return false;	
    	
    if (this instanceof Star)
    	if (e instanceof Star)
    		return (this.getStar().equals(e.getStar()));
    	else
    		return false;
    		
    if (this instanceof Alpha)
    	if (e instanceof Alpha)
    		return (this.getValue().equals(e.getValue()));
    	else
    		return false;

   	// If the code reaches here, assume for now that 
   	// a comparison cannot be made
   	return false;   	
    }
    
   	public boolean isEpsilon()
   	{
   	if (epsChar == prim)
   		return true;
   	else
   		return false;
   	}

  	public boolean isNull()
   	{
   	if (nullChar == prim)
   		return true;
   	else
   		return false;
   	}
   	
   	public Expr reduce()
	{
		return this;
	}
	
	void setRight( Expr r)
	{
		right = r;
	}
}

