anchor.diff:  	| keyMAXDATE LPAREN RPAREN			{retval = new DateLiteral(DateLiteral.Type.MAXDATE);}
   	| keyDATE LPAREN s1=stringValue COMMA s2=stringValue RPAREN
   							{retval = new DateExpr($s1.retval, $s2.retval);}
  -	| keyYEAR LPAREN n=numberValue RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.YEAR, $n.retval);}
  -	| keyWEEK LPAREN n=numberValue RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.WEEK, $n.retval);}
  -	| keyDAY LPAREN n=numberValue RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.DAY, $n.retval);}
  -	| keyHOUR LPAREN n=numberValue RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.HOUR, $n.retval);}
  -	| keyMINUTE LPAREN n=numberValue RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.MINUTE, $n.retval);}
  -	| keySECOND LPAREN n=numberValue RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.SECOND, $n.retval);}
  -	| keyMILLI LPAREN n=numberValue RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.MILLI, $n.retval);}
  +	| keyYEAR LPAREN n=addExpr RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.YEAR, $n.retval);}
  +	| keyWEEK LPAREN n=addExpr RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.WEEK, $n.retval);}
  +	| keyDAY LPAREN n=addExpr RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.DAY, $n.retval);}
  +	| keyHOUR LPAREN n=addExpr RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.HOUR, $n.retval);}
  +	| keyMINUTE LPAREN n=addExpr RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.MINUTE, $n.retval);}
  +	| keySECOND LPAREN n=addExpr RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.SECOND, $n.retval);}
  +	| keyMILLI LPAREN n=addExpr RPAREN		{retval = new IntervalExpr(IntervalExpr.IntervalType.MILLI, $n.retval);}
   	;
   
   funcReturningString returns [StringValue retval]
   	: keyCONCAT LPAREN s1=stringValue COMMA s2=stringValue RPAREN
   							{retval = new StringFunction(FunctionType.CONCAT, $s1.retval, $s2.retval);}
  -	| keySUBSTRING LPAREN s=stringValue COMMA n1=numberValue COMMA n2=numberValue RPAREN
  +	| keySUBSTRING LPAREN s=stringValue COMMA n1=addExpr COMMA n2=addExpr RPAREN
   							{retval = new Substring($s.retval, $n1.retval, $n2.retval);}
   	| keyTRIM LPAREN s=stringValue RPAREN		{retval = new StringFunction(FunctionType.TRIM, $s.retval);}
   	| keyLOWER LPAREN s=stringValue RPAREN		{retval = new StringFunction(FunctionType.LOWER, $s.retval);} 
  
positive.code: options {backtrack=true;}	
  	: d=dateValue					{retval = $d.retval;}
  	| s=stringValue					{retval = $s.retval;}
  	| n=numberValue					{retval = $n.retval;}
  	| b=valueAtom					{retval = $b.retval;}
  	;
  
  
negative.code: 	;
  	
  // Value Atom
  valueAtom returns [ValueExpr retval]
  options {backtrack=true;}	
  	: b=booleanLiteral				{retval = $b.retval;}
  	| s=stringLiteral				{retval = $s.retval;}
  	| i=integerLiteral				{retval = $i.retval;}
  	| v=varRef					{retval = this.getValueExpr($v.text);}
  	| p=paramRef
  	;
  
  // Literals		
  stringLiteral returns [StringValue retval]
  	: v=QUOTED 					{retval = new StringLiteral($v.text);};
  	
  integerLiteral returns [NumberValue retval]
  	: v=INT						{retval = new IntegerLiteral(Integer.valueOf($v.text));};	
  
  booleanLiteral returns [BooleanValue retval]
  	: t=keyTRUE					{retval = new BooleanLiteral($t.text);}
  	| f=keyFALSE					{retval = new BooleanLiteral($f.text);}
  	;
  		
  // Numeric calculations
  addExpr returns [ValueExpr retval] 
  @init {List<NumberValue> exprList = Lists.newArrayList(); List<Operator> opList = Lists.newArrayList(); }
  	: m=multExpr {exprList.add($m.retval);} (op=plusMinus n=multExpr {opList.add($op.retval); exprList.add($n.retval);})*	
  							{retval = getLeftAssociativeNumberValues(exprList, opList);};
  	
  multExpr returns [ValueExpr retval]
  @init {List<NumberValue> exprList = Lists.newArrayList(); List<Operator> opList = Lists.newArrayList(); }
  	: m=signedExpr {exprList.add($m.retval);} (op=multDiv n=signedExpr {opList.add($op.retval); exprList.add($n.retval);})*	
  							{retval = getLeftAssociativeNumberValues(exprList, opList);};
  	
  signedExpr returns [ValueExpr retval]
  	: (s=plusMinus)? n=parenExpr 			{$signedExpr.retval = ($s.retval == Operator.MINUS) ? new NumberCalcExpr($n.retval, Operator.NEGATIVE, null) :  $n.retval;};
  
  parenExpr returns [ValueExpr retval]
  	: n=condExpr					{retval = $n.retval;}
  	| LPAREN s=addExpr RPAREN			{retval = $s.retval;}
  	;
  	   						 
  condExpr returns [ValueExpr retval]
  	: l=numberVal					{retval = $l.retval;} 
  	| keyIF e=orExpr keyTHEN n1=addExpr keyELSE n2=addExpr keyEND 	
  							{retval = new NumberTernary($e.retval, $n1.retval, $n2.retval);}
  	;
  
  