class NumRu::Units

  token INT ERR SHIFT SPACE MULTIPLY DIVIDE EXPONENT REAL NAME DATE TIME ZONE
  options no_result_var

rule

unit_spec:
	/* { yyaccept; }  */  /* <-- to acccept empty unit_spec */
	| origin_exp { val[0] }
	| error { yyerrok }
	;

origin_exp:	 
	unit_exp
	| unit_exp SHIFT value_exp { val[0].shift(val[2]) }
	| unit_exp SHIFT timestamp { val[0].shift(val[2]) }
	;

unit_exp: 
	power_exp
	| number_exp
	| unit_exp power_exp		{ val[0].mul(val[1]) }
	| unit_exp MULTIPLY power_exp	{ val[0].mul(val[2]) }
	| unit_exp DIVIDE power_exp	{ val[0].divide(val[2]) }
	| unit_exp MULTIPLY number_exp	{ val[0].mul(val[2]) }
	| unit_exp DIVIDE number_exp	{ val[0].divide(val[2]) }
	;

power_exp:
	NAME { NameNode.new(val[0]) }
	| power_exp number_exp { val[0].pow(val[1]) }
	| power_exp EXPONENT value_exp { val[0].pow(val[2]) }
	| '(' origin_exp ')' { val[1] }
	;

value_exp:
	number_exp
	| '(' value_exp ')' { val[1] }
	;

number_exp:	 
	INT { NumberNode.new(val[0]) }
	| REAL { NumberNode.new(val[0]) }
	;

timestamp:	 
	time_exp
	| '(' timestamp ')' { val[1] }
	;

time_exp:
	DATE { TimeNode.new(val[0], 0.0, 0) }
	| DATE TIME { TimeNode.new(val[0], val[1], 0) }
	| DATE TIME ZONE { TimeNode.new(val[0], val[1], val[2]) }
	;

end

---- header

require 'date'

---- inner

