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
|
/* description: Parses end executes mathematical expressions. */
/* lexical grammar */
%lex
%%
\s+ /* skip whitespace */
[0-9]+("."[0-9]+)?\b return 'NUMBER'
"n" return 'n'
"||" return '||'
"&&" return '&&'
"?" return '?'
":" return ':'
"<=" return '<='
">=" return '>='
"<" return '<'
">" return '>'
"!=" return '!='
"==" return '=='
"%" return '%'
"(" return '('
")" return ')'
<<EOF>> return 'EOF'
. return 'INVALID'
/lex
/* operator associations and precedence */
%right <code> '?' ':'
%left '||'
%left '&&'
%left '<=' '>=' '<' '>' '!=' '=='
%left '%'
%start expressions
%% /* language grammar */
expressions
: e EOF
{ return { type : 'GROUP', expr: $1 }; }
;
e
: e '?' e ':' e
{$$ = { type: 'TERNARY', expr: $1, truthy : $3, falsey: $5 }; }
| e '||' e
{$$ = { type: "OR", left: $1, right: $3 };}
| e '&&' e
{$$ = { type: "AND", left: $1, right: $3 };}
| e '<' e
{$$ = { type: 'LT', left: $1, right: $3 }; }
| e '<=' e
{$$ = { type: 'LTE', left: $1, right: $3 };}
| e '>' e
{$$ = { type: 'GT', left: $1, right: $3 };}
| e '>=' e
{$$ = { type: 'GTE', left: $1, right: $3 };}
| e '!=' e
{$$ = { type: 'NEQ', left: $1, right: $3 };}
| e '==' e
{$$ = { type: 'EQ', left: $1, right: $3 };}
| e '%' e
{$$ = { type: 'MOD', left: $1, right: $3 };}
| '(' e ')'
{$$ = { type: 'GROUP', expr: $2 }; }
| 'n'
{$$ = { type: 'VAR' }; }
| NUMBER
{$$ = { type: 'NUM', val: Number(yytext) }; }
;
|