aboutsummaryrefslogtreecommitdiff
path: root/calc.y
blob: 9f81d6c9251a48f964e44d1784cad83b20cf9de1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
%{
// 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 <fval> NUMBER
%token <sval> WORD

%type <fval> exp

%left '+' '-'
%left '*' '/' '%'
%left '^'
%left UMINUS

%%

line
	:			/* empty */
	| exp			{
				  reg[last] = $1
				  yylex.(*yyLex).result = $1
				}
	| 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, error) {
	l := lex(input)
	yyParse(l)
	return l.result, l.err
}