-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathParser.mly
343 lines (306 loc) · 10.8 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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
%{
open NicePrint
open Core.Std
open Ast
let (>>|) = Option.(>>|)
exception UnexpectedType
let construct_binary_assign typ arg1 arg2 =
match typ with
| T_assign -> E_assign (arg1,arg2)
| T_mul_assign -> E_mul_assign(arg1,arg2)
| T_div_assign -> E_div_assign(arg1,arg2)
| T_mod_assign -> E_mod_assign(arg1,arg2)
| T_plu_assign -> E_plu_assign(arg1,arg2)
| T_min_assign -> E_min_assign(arg1,arg2)
| _ -> raise UnexpectedType
let construct_unary_assign typ arg ~before =
match typ,before with
| T_incr,true -> E_incr_bef arg
| T_incr,false -> E_incr_aft arg
| T_dcr,true -> E_decr_bef arg
| T_dcr,false -> E_decr_aft arg
| _ -> raise UnexpectedType
let construct_type typ arg =
match typ with
| T_int -> Ty_int arg
| T_bool -> Ty_bool arg
| T_char -> Ty_char arg
| T_double -> Ty_double arg
| T_void when arg=0 -> Ty_void
| _ -> raise UnexpectedType
let construct_unary_operation typ arg =
match typ with
| T_addr -> E_addr arg
| T_times -> E_deref arg
| T_plus -> printf "found unary minus\n"; E_uplus arg
| T_minus -> printf "found unary minus\n" ; E_uminus arg
| T_negate -> E_negate arg
| _ -> raise UnexpectedType
let construct_binary_operation typ arg1 arg2 =
match typ with
| T_times -> E_mult(arg1,arg2)
| T_div -> E_div (arg1,arg2)
| T_mod -> E_mod (arg1,arg2)
| T_plus -> E_plus(arg1,arg2)
| T_minus -> E_minus (arg1,arg2)
| T_lt -> E_lt(arg1,arg2)
| T_gt -> E_gt (arg1,arg2)
| T_lteq -> E_lteq(arg1,arg2)
| T_gteq -> E_gteq(arg1,arg2)
| T_eq -> E_eq (arg1,arg2)
| T_neq -> E_neq(arg1,arg2)
| T_and -> E_and(arg1,arg2)
| T_or -> E_or (arg1,arg2)
| T_comma -> E_comma (arg1,arg2)
| _ -> raise UnexpectedType;;
let get_size_of_param_list paramlist =
match paramlist with
| Some lst -> string_of_int @@ List.length lst
| None -> "0";;
%}
%token <Ast.ast_decl list> T_include
%token <string>T_id
(*---------------Types---------------*)
%token T_double T_bool T_char T_int
(*------------Literals---------------*)
%token <string> T_string
%token <string> T_double_const
%token <string> T_int_const
%token <char> T_char_const
%token T_true T_false
(*-----------------------------------*)
%token T_null
%token T_plu_assign T_min_assign T_mul_assign T_div_assign T_mod_assign
%token T_assign /* "=" */
%token T_incr T_dcr /* "++" "--" */
%token T_lteq T_gteq T_gt T_lt T_neq T_eq /* "<=", ">=" ">" "<" "!=" "==" */
%token T_lbrace T_rbrace /* "{" "}" */
%token T_lbrack T_rbrack /* "[" "]" */
%token T_lparen T_rparen /* "(" ")" */
%token T_colon T_semicolon T_comma
%token T_qmark /* '?' */
%token T_and
%token T_or
%token T_negate /* '!' */
%token T_plus
%token T_minus
%token T_times
%token T_addr /* pointer '*' */
%token T_break T_byref T_continue T_new T_delete T_else
%token T_return T_void
%token T_eof
%token T_for T_if
%token T_mod T_div
%left LOWEST
%left T_comma
%left COMMAND
%right T_assign T_plu_assign T_min_assign T_mul_assign T_div_assign T_mod_assign
%nonassoc TERNARY T_qmark
%left T_or
%left T_and
%left T_eq T_neq
%left T_lteq T_lt T_gt T_gteq
%left T_plus T_minus
%left T_times T_div T_mod
%left UNARY
%right T_incr T_dcr CAST
%nonassoc T_else
%nonassoc T_lbrack
%start program
%type <Ast.ast_decl list> program
%type <ast_decl> declaration
%type <ast_type> ctype
%type <int> pointer_asterisk_e
%type <ast_param list> parameter_list
%type <ast_stmt> statement
%type <ast_expr> expression
%type <ast_expr list> expression_list
%%
program:
includes declaration+ T_eof
{
List.rev_append (List.rev $1) $2
};
includes:
| { [] }
| T_include includes { List.rev_append (List.rev $1) $2 }
declaration_list:
| declaration declaration_list { $1::$2 }
| declaration { $1::[] }
;
declaration:
| vd = variable_declaration; { vd }
| fd = function_declaration; { fd }
| fd = function_definition; { fd }
;
%inline variable_declaration:
| ct = ctype; md = more_declarators; T_semicolon { D_var_decl (ct,md) }
;
more_declarators:
| declarator { $1::[]}
| declarator T_comma more_declarators { $1::$3}
ctype:
basic_type pointer_asterisk_e { construct_type $1 $2 }
;
pointer_asterisk_e:
| %prec LOWEST { 0 }
| T_times pointer_asterisk_e { 1+$2}
;
basic_type:
| T_int { T_int }
| T_bool { T_bool }
| T_char { T_char }
| T_double { T_double }
;
declarator:
T_id T_lbrack constant_expression T_rbrack {($1,Some $3)}
| T_id {($1,None)}
;
%inline function_declaration:
rt = result_type; id = T_id; T_lparen; par=parameter_list?; T_rparen; T_semicolon;
{
let total_parameters = get_size_of_param_list par
in D_func_decl (rt,id ^ "_" ^ total_parameters , par >>| List.rev )
}
;
%inline result_type:
ct = ctype; { ct }
| T_void { Ty_void }
;
parameter_list:
parameter_list T_comma parameter { $3::$1 }
| parameter { $1::[] }
;
parameter:
T_byref ctype T_id { P_byref ($2,$3)}
| ctype T_id { P_byval ($1,$2)}
;
%inline function_definition:
rt = result_type; id = T_id; T_lparen; par=parameter_list?; T_rparen; T_lbrace;
derlst =declaration_list?; st = statement*; T_rbrace;
{
let total_parameters = get_size_of_param_list par in
D_func_def (rt,id ^ "_" ^ total_parameters, par >>| List.rev ,derlst,st)
};
statement:
T_semicolon { S_None}
| expression T_semicolon { S_expr $1 }
(*-------------------- Block Statement --------------------*)
| T_lbrace statement* T_rbrace { S_braces $2 }
(*-------------------- If Statement -----------------------*)
| T_if T_lparen expression T_rparen statement else_part_e
{ S_if ($3,$5,$6)}
(*-------------------- For Statement ----------------------*)
| label_e T_for T_lparen expression? T_semicolon expression? T_semicolon
expression? T_rparen statement { S_for ($1,$4,$6,$8,$10)}
(*-------------------- Other Keywords *--------------------*)
| T_continue T_id? T_semicolon { S_continue $2}
| T_break T_id? T_semicolon { S_break $2}
| T_return expression? T_semicolon { S_return $2}
;
else_part_e:
%prec LOWEST { None}
| T_else statement { Some $2}
;
label_e:
{ None }
| T_id T_colon { Some $1}
;
expression:
T_id { E_id $1 }
(*-------------------- (x+y) * 3 ------ ------------------------*)
| T_lparen expression T_rparen { $2 }
(*---------------------------------------------------------------*)
| T_true { E_bool true }
| T_false { E_bool false }
| T_null { E_null }
| T_int_const { E_int $1 }
| T_char_const { E_char $1 }
| T_double_const { E_double $1 }
| T_string { E_string $1 }
(*------------------------- f(x+2,y,..z) -----------------------*)
| name = T_id ; T_lparen ; params = expression_list? ; T_rparen
(* TODO: Refactor function calls to have an actual expression list without extra code *)
(* This will make the design better, but special attention should be given to priority against common commas*)
{ let params = (match params with
| None -> None
| Some (hd::tl) ->
let rec flatten_commas acc expr =
match expr with
| E_comma (x,y) -> flatten_commas (y::acc) x
| _ -> expr::acc
in Some (flatten_commas [] hd)
| _ -> printf "This should not happen!\n"; None )
in
let params_num = match params with
| None -> "0"
| Some lst -> string_of_int (List.length lst)
in
E_function_call (name ^ "_" ^ params_num,params) }
(*----------------------------- x[z] -------------------------*)
| expression T_lbrack expression T_rbrack { E_array_access ($1,$3)}
(*------------------- &x,-x,*x,!x,+x -------------------------*)
| op = unary_operator ; e = expression %prec UNARY
{ construct_unary_operation op e }
(*--------------------------- x OP y -------------------------*)
| e1 = expression ; op = binary_operator; e2 = expression
{ construct_binary_operation op e1 e2 }
(*------------------------- ++ -- ----------------------------*)
| unary_assignment expression %prec T_dcr
{ construct_unary_assign $1 $2 ~before:true }
| expression unary_assignment
{ construct_unary_assign $2 $1 ~before:false }
(*--------------------- %=, *=, +=, /=, .. --------------------*)
| expression binary_assignment expression %prec T_assign
{ construct_binary_assign $2 $1 $3 }
(*----------------------- Type Casting --------------------------*)
| T_lparen ctype T_rparen expression %prec CAST
{ E_cast ($2,$4) }
(*--------------------------- X?Y:Z -----------------------------*)
| expression T_qmark expression T_colon expression %prec TERNARY
{ E_ternary_op ($1,$3,$5) }
(*---------------------------------------------------------------*)
| T_new ctype %prec LOWEST { E_new ($2,None)}
| T_new ctype T_lbrack expression T_rbrack { E_new ($2,Some $4)}
| T_delete expression %prec COMMAND { E_delete $2}
;
expression_list:
rest = expression_list ; T_comma ; new_expr = expression { new_expr::rest }
| expression %prec LOWEST { $1::[]}
;
constant_expression: expression { $1 };
unary_operator:
T_addr { T_addr }
| T_times { T_times }
| T_plus { T_plus }
| T_minus { T_minus }
| T_negate { T_negate }
;
%inline binary_operator:
T_times { T_times }
| T_div { T_div }
| T_mod { T_mod }
| T_plus { T_plus }
| T_minus { T_minus }
| T_lt { T_lt }
| T_gt { T_gt }
| T_lteq { T_lteq }
| T_gteq { T_gteq }
| T_eq { T_eq }
| T_neq { T_neq }
| T_and { T_and }
| T_or { T_or }
| T_comma { T_comma }
;
unary_assignment:
T_incr { T_incr }
| T_dcr { T_dcr }
;
binary_assignment:
T_assign { T_assign }
| T_mul_assign { T_mul_assign }
| T_div_assign { T_div_assign }
| T_mod_assign { T_mod_assign }
| T_plu_assign { T_plu_assign }
| T_min_assign { T_min_assign }
;