-
Notifications
You must be signed in to change notification settings - Fork 2
/
calculator.y
115 lines (94 loc) · 1.76 KB
/
calculator.y
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
%{
var result
%}
/* operator associations and precedence */
%token tE tEND tNUMBER tPI tL tR
%left '+' '-'
%left '*' '/'
%left '^'
%left tUMINUS
%start expressions
%% /* language grammar */
expressions
: e tEND
{result = $1;}
;
e
: e '+' e
{$$ = $1 + $3;}
| e '-' e
{$$ = $1 - $3;}
| e '*' e
{$$ = $1 * $3;}
| e '/' e
{$$ = $1 / $3;}
| e '^' e
{$$ = Math.pow($1, $3);}
| '-' e %prec tUMINUS
{$$ = -$2;}
| '(' e ')'
{$$ = $2;}
| tNUMBER
{$$ = Number(yyval);}
| tE
{$$ = Math.E;}
| tPI
{$$ = Math.PI;}
;
%%
var T = YYParser.TOKENS
var Lexer = (function(){
function Lexer (tokens)
{
this.tokens = tokens
}
Lexer.prototype =
{
yylex: function ()
{
if (this.tokens.length == 0)
return 0;
var token = this.tokens.shift();
// the value of the token
this.yylval = token[1];
return token[0];
},
yyerror: function (location, message)
{
console.log('at ' + location, message)
}
}
return Lexer
})();
var
tPLUS = 43, // '+'.charCodeAt(0)
tMINUS = 45, // '-'.charCodeAt(0)
tMULT = 42, // '*'.charCodeAt(0)
tDIV = 47, // '/'.charCodeAt(0)
tPOW = 94, // '^'.charCodeAt(0)
tL = 40, // '('.charCodeAt(0)
tR = 41; // ')'.charCodeAt(0)
// (-(2+2*2)/1)*-7
var lexer = new Lexer
([
[tL, '('],
[tMINUS, '-'],
[tL, '('],
[tNUMBER, '2'],
[tPLUS, '+'],
[tNUMBER, '2'],
[tMULT, '*'],
[tNUMBER, '2'],
[tR, ')'],
[tDIV, '/'],
[tNUMBER, '1'],
[tR, ')'],
[tMULT, '*'],
[tMINUS, '-'],
[tNUMBER, '7'],
[tEND, '']
])
var parser = new YYParser(lexer);
parser.yydebug = 2;
console.log(parser.parse() ? 'Parsed OK.' : 'Parsed with errors.')
console.log('Answer is ' + result);