-
Notifications
You must be signed in to change notification settings - Fork 1
/
parser.mly
147 lines (129 loc) · 3 KB
/
parser.mly
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
%{
open Syntax
%}
/* Lexemes */
%token BLANKLINE
%token <string> STRING
%token <float> NUM
%token <string> VARIABLE
%token TRUE
%token FALSE
%token UNDEFINED
%token NULL
%token TAKE
%token TAKING
%token RETURN
%token CONTINUE
%token BREAK
%token WHILE
%token UNTIL
%token IF
%token ELSE
%token IS
%token ISNOT
%token LISTEN
%token TO
%token PRINT
%token PUT
%token INTO
%token BUILD
%token UP
%token KNOCK
%token DOWN
%token GT
%token GE
%token LT
%token LE
%token PLUS
%token MINUS
%token TIMES
%token DIVIDE
%token COMMA
%token AND
%token OR
%token EOF
/* Precedence and associativity */
%left PLUS MINUS
%left TIMES DIVIDE
/* Top level rule */
%start prog
%type <(Syntax.segment list)> prog
%%
/* Grammar */
prog:
| blankline s=seg blankline p=prog { s::p }
| blankline s=seg blankline EOF { [s] }
;
seg:
| f=VARIABLE TAKE arg=arguments b=block BLANKLINE { Func (f,arg,b) }
| b=block { Block (b) }
;
blankline:
| { Stm([Nop]) }
| blanklines { Stm([Nop]) }
blanklines:
| BLANKLINE blanklines { Stm([Nop]) }
| BLANKLINE { Stm([Nop]) }
;
condition:
| e1=expression IS e2=expression { Eq (e1,e2) }
| e1=expression ISNOT e2=expression { Ne (e1,e2) }
| e1=expression GT e2=expression { Gt (e1,e2) }
| e1=expression GE e2=expression { Ge (e1,e2) }
| e1=expression LT e2=expression { Lt (e1,e2) }
| e1=expression LE e2=expression { Le (e1,e2) }
| c1=condition AND c2=condition { And (c1,c2) }
| c1=condition OR c2=condition { Or (c1,c2) }
;
arguments:
| x=VARIABLE AND arg=arguments { x::arg }
| x=VARIABLE { [x] }
;
parameters:
| e=expression COMMA param=parameters { e::param }
| e=expression { [e] }
;
statements:
| s1=statement s2=statements { s1::s2 }
| s=statement { [s] }
;
statement:
| x=VARIABLE IS v=value { Definition (x,v) }
| e=expression { Expression e }
| PUT e=expression INTO x=VARIABLE { Assign (x,e) }
| LISTEN TO x=VARIABLE { Scan x }
| PRINT e=expression { Print e }
| BREAK { Break }
| CONTINUE { Continue }
| RETURN e=expression { Return e }
| KNOCK x=VARIABLE DOWN { Dec x }
| BUILD x=VARIABLE UP { Inc x }
;
block:
| b=block_content { [b] }
| b1=block_content b2=block { b1::b2 }
;
block_content:
| IF cond=condition b=block BLANKLINE { If (cond,b,[Stm([Nop])]) }
| IF cond=condition b1=block BLANKLINE ELSE b2=block BLANKLINE { If (cond,b1,b2) }
| WHILE cond=condition b=block BLANKLINE { While (cond,b) }
| UNTIL cond=condition b=block BLANKLINE { Until (cond,b) }
| s=statements { Stm(s) }
;
value:
| TRUE { Boolean True }
| FALSE { Boolean False }
| UNDEFINED { Undefined }
| NULL { Null }
| s = STRING { String s }
| n = NUM { Number n }
;
expression:
| f=VARIABLE TAKING p=parameters { Call(f,p) }
| x = VARIABLE { Variable x }
| v = value { Value v }
| e1 = expression TIMES e2 = expression { Times (e1, e2) }
| e1 = expression PLUS e2 = expression { Plus (e1, e2) }
| e1 = expression MINUS e2 = expression { Minus (e1, e2) }
| e1 = expression DIVIDE e2 = expression { Divide (e1, e2) }
;