%{ // Code generated by yacc. DO NOT EDIT. package main import ( "math" "math/rand" "time" ) var reg = map[string]float64{ "pi": math.Pi, "e": math.E, } const last = "_" %} %union{ fval float64 sval string } %token NUMBER %token WORD %type exp %left '+' '-' %left '*' '/' '%' %left '^' %left UMINUS %% line : /* empty */ | exp { reg[last] = $1 yylex.(*yyLex).result = $1 yylex.(*yyLex).ok = true } | WORD '=' exp { reg[$1] = $3 } | error ; exp : NUMBER | WORD { $$ = reg[$1] } | '_' { $$ = reg[last] } | '!' { $$ = rand.Float64() } | exp '+' exp { $$ = $1 + $3 } | exp '-' exp { $$ = $1 - $3 } | exp '*' exp { $$ = $1 * $3 } | exp '/' exp { $$ = $1 / $3 } | exp '%' exp { $$ = math.Mod($1, $3) } | exp '^' exp { $$ = math.Pow($1, $3) } | '-' exp %prec UMINUS { $$ = -$2 } | '(' exp ')' { $$ = $2 } | '|' exp '|' { $$ = math.Abs($2) } ; %% func init() { rand.Seed(time.Now().UnixNano()) } func Parse(input string) (float64, bool, error) { l := lex(input) yyParse(l) return l.result, l.ok, l.err }