-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.ml
More file actions
326 lines (279 loc) · 13.1 KB
/
parser.ml
File metadata and controls
326 lines (279 loc) · 13.1 KB
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
open MicroCamlTypes
open Utils
open TokenTypes
(* Provided functions - DO NOT MODIFY *)
(* Matches the next token in the list, throwing an error if it doesn't match the given token *)
let match_token (toks: token list) (tok: token) =
match toks with
| [] -> raise (InvalidInputException(string_of_token tok))
| h::t when h = tok -> t
| h::_ -> raise (InvalidInputException(
Printf.sprintf "Expected %s from input %s, got %s"
(string_of_token tok)
(string_of_list string_of_token toks)
(string_of_token h)))
(* Matches a sequence of tokens given as the second list in the order in which they appear, throwing an error if they don't match *)
let match_many (toks: token list) (to_match: token list) =
List.fold_left match_token toks to_match
(* Return the next token in the token list as an option *)
let lookahead (toks: token list) =
match toks with
| [] -> None
| h::t -> Some h
(* Return the token at the nth index in the token list as an option*)
let rec lookahead_many (toks: token list) (n: int) =
match toks, n with
| h::_, 0 -> Some h
| _::t, n when n > 0 -> lookahead_many t (n-1)
| _ -> None
(* Part 2: Parsing expressions *)
(*
Expr -> LetExpr | IfExpr | FunctionExpr | OrExpr
LetExpr -> let Recursion Tok_ID = Expr in Expr
Recursion -> rec | ε
FunctionExpr -> fun Tok_ID -> Expr
IfExpr -> if Expr then Expr else Expr
OrExpr -> AndExpr || OrExpr | AndExpr
AndExpr -> EqualityExpr && AndExpr | EqualityExpr
EqualityExpr -> RelationalExpr EqualityOperator EqualityExpr | RelationalExpr
EqualityOperator -> = | <>
RelationalExpr -> AdditiveExpr RelationalOperator RelationalExpr | AdditiveExpr
RelationalOperator -> < | > | <= | >=
AdditiveExpr -> MultiplicativeExpr AdditiveOperator AdditiveExpr | MultiplicativeExpr
AdditiveOperator -> + | -
MultiplicativeExpr -> ConcatExpr MultiplicativeOperator MultiplicativeExpr | ConcatExpr
MultiplicativeOperator -> * | /
ConcatExpr -> UnaryExpr ^ ConcatExpr | UnaryExpr
UnaryExpr -> not UnaryExpr | FunctionCallExpr
FunctionCallExpr -> PrimaryExpr PrimaryExpr | PrimaryExpr
PrimaryExpr -> Tok_Int | Tok_Bool | Tok_String | Tok_ID | ( Expr ) *)
let get_id_string id =
match id with
| (Some (Tok_ID id_string)) -> id_string
| _ -> raise (InvalidInputException("bad news"))
;;
let rec parse_Expr toks =
let next_token = lookahead toks in
match next_token with
(* Expr -> LetExpr *)
| (Some Tok_Let) -> parse_LetExpr toks
(* Expr -> IfExpr *)
| (Some Tok_If) -> parse_IfExpr toks
(* Expr -> FunctionExpr *)
| (Some Tok_Fun) -> parse_FunctionExpr toks
(* Expr -> OrExpr EVERYTHING ELSE COMES OUT FROM HERE D: *)
| _ -> parse_OrExpr toks
and parse_LetExpr toks =
(* Pop off the let so that we can keep track of where we are *)
let toks_after_let = match_token toks Tok_Let in
match lookahead toks_after_let with
| Some Tok_Rec ->
let toks_after_rec = match_token toks_after_let Tok_Rec in
let id = lookahead toks_after_rec in
let id_string = get_id_string id in
let toks_after_id = match_token toks_after_rec (Tok_ID id_string) in
let toks_after_equal = match_token toks_after_id Tok_Equal in
let (toks_after_exp1, exp1) = parse_Expr toks_after_equal in
let toks_after_in = match_token toks_after_exp1 Tok_In in
let (toks_after_exp2, exp2) = parse_Expr toks_after_in in
(toks_after_exp2, Let (id_string, true, exp1, exp2))
| Some Tok_ID id ->
let toks_after_id = match_token toks_after_let (Tok_ID id) in
let toks_after_equal = match_token toks_after_id Tok_Equal in
let (toks_after_exp1, exp1) = parse_Expr toks_after_equal in
let toks_after_in = match_token toks_after_exp1 Tok_In in
let (toks_after_exp2, exp2) = parse_Expr toks_after_in in
(toks_after_exp2, Let (id, false, exp1, exp2))
| _ ->
raise (InvalidInputException("uh oh"))
(* let parse_FunctionExpr =;; *)
and parse_FunctionExpr toks =
let toks_after_fun = match_token toks Tok_Fun in
let id = lookahead toks_after_fun in
let id_string = get_id_string id in
let toks_after_id = match_token toks_after_fun (Tok_ID id_string) in
let toks_after_arrow = match_token toks_after_id Tok_Arrow in
let (toks_after_exp, exp) = parse_Expr toks_after_arrow in
(toks_after_exp, Fun(id_string, exp))
(* IfExpr -> if Expr then Expr else Expr *)
and parse_IfExpr toks =
let toks_after_if = match_token toks Tok_If in
let (toks_after_exp1, exp1) = parse_Expr toks_after_if in
let toks_after_then = match_token toks_after_exp1 Tok_Then in
let (toks_after_exp2, exp2) = parse_Expr toks_after_then in
let toks_after_else = match_token toks_after_exp2 Tok_Else in
let (toks_after_exp3, exp3) = parse_Expr toks_after_else in
(toks_after_exp3, If(exp1, exp2, exp3))
(* OrExpr -> AndExpr || OrExpr | AndExpr *)
(* Needs to be:
Or_Expr -> AndExpr L
L -> || OrExpr | epsilon *)
and parse_OrExpr toks =
(* Pop off the let so that we can keep track of where we are *)
let (toks_after_and, andexp) = parse_AndExpr toks in
match lookahead toks_after_and with
| Some Tok_Or ->
let toks_after_or_operator = match_token toks_after_and Tok_Or in
let (toks_after_or, orexp) = parse_OrExpr toks_after_or_operator in
(toks_after_or, Binop (Or, andexp, orexp))
| _ ->
(toks_after_and, andexp)
and parse_AndExpr toks =
let (toks_after_equalityexp, equalityexp) = parse_EqualityExpr toks in
match lookahead toks_after_equalityexp with
| Some Tok_And ->
let toks_after_and_operator = match_token toks_after_equalityexp Tok_And in
let (toks_after_and, andexp) = parse_AndExpr toks_after_and_operator in
(toks_after_and, Binop (And, equalityexp, andexp))
| _ ->
(toks_after_equalityexp, equalityexp)
and parse_EqualityExpr toks =
let (toks_after_relationalexp, relationalexp) = parse_RelationalExpr toks in
match lookahead toks_after_relationalexp with
| Some Tok_Equal ->
let toks_after_equality_operator = match_token toks_after_relationalexp Tok_Equal in
let (toks_after_equalityexp, equalityexp) = parse_EqualityExpr toks_after_equality_operator in
(toks_after_equalityexp, Binop (Equal, relationalexp, equalityexp))
| Some Tok_NotEqual ->
let toks_after_equality_operator = match_token toks_after_relationalexp Tok_NotEqual in
let (toks_after_equalityexp, equalityexp) = parse_EqualityExpr toks_after_equality_operator in
(toks_after_equalityexp, Binop (NotEqual, relationalexp, equalityexp))
| _ ->
(toks_after_relationalexp, relationalexp)
and parse_RelationalExpr toks =
let (toks_after_additiveexp, additiveexp) = parse_AdditiveExpr toks in
match lookahead toks_after_additiveexp with
| Some Tok_Less ->
let toks_after_relational_operator = match_token toks_after_additiveexp Tok_Less in
let (toks_after_relationalexp, relationalexp) = parse_RelationalExpr toks_after_relational_operator in
(toks_after_relationalexp, Binop (Less, additiveexp, relationalexp))
| Some Tok_LessEqual ->
let toks_after_relational_operator = match_token toks_after_additiveexp Tok_LessEqual in
let (toks_after_relationalexp, relationalexp) = parse_RelationalExpr toks_after_relational_operator in
(toks_after_relationalexp, Binop (LessEqual, additiveexp, relationalexp))
| Some Tok_Greater ->
let toks_after_relational_operator = match_token toks_after_additiveexp Tok_Greater in
let (toks_after_relationalexp, relationalexp) = parse_RelationalExpr toks_after_relational_operator in
(toks_after_relationalexp, Binop (Greater, additiveexp, relationalexp))
| Some Tok_GreaterEqual ->
let toks_after_relational_operator = match_token toks_after_additiveexp Tok_GreaterEqual in
let (toks_after_relationalexp, relationalexp) = parse_RelationalExpr toks_after_relational_operator in
(toks_after_relationalexp, Binop (GreaterEqual, additiveexp, relationalexp))
| _ ->
(toks_after_additiveexp, additiveexp)
and parse_AdditiveExpr toks =
let (toks_after_multiplicativeexp, multiplicativeexp) = parse_MultiplicativeExpr toks in
match lookahead toks_after_multiplicativeexp with
| Some Tok_Add ->
let toks_after_additive_operator = match_token toks_after_multiplicativeexp Tok_Add in
let (toks_after_additiveexp, additiveexp) = parse_AdditiveExpr toks_after_additive_operator in
(toks_after_additiveexp, Binop (Add, multiplicativeexp, additiveexp))
| Some Tok_Sub ->
let toks_after_additive_operator = match_token toks_after_multiplicativeexp Tok_Sub in
let (toks_after_additiveexp, additiveexp) = parse_AdditiveExpr toks_after_additive_operator in
(toks_after_additiveexp, Binop (Sub, multiplicativeexp, additiveexp))
| _ ->
(toks_after_multiplicativeexp, multiplicativeexp)
and parse_MultiplicativeExpr toks =
let (toks_after_concatexp, concatexp) = parse_ConcatExpr toks in
match lookahead toks_after_concatexp with
| Some Tok_Mult ->
let toks_after_multiplicative_operator = match_token toks_after_concatexp Tok_Mult in
let (toks_after_multiplicativeexp, multiplicativeexp) = parse_MultiplicativeExpr toks_after_multiplicative_operator in
(toks_after_multiplicativeexp, Binop (Mult, concatexp, multiplicativeexp))
| Some Tok_Div ->
let toks_after_multiplicative_operator = match_token toks_after_concatexp Tok_Div in
let (toks_after_multiplicativeexp, multiplicativeexp) = parse_MultiplicativeExpr toks_after_multiplicative_operator in
(toks_after_multiplicativeexp, Binop (Div, concatexp, multiplicativeexp))
| _ ->
(toks_after_concatexp, concatexp)
and parse_ConcatExpr toks =
let (toks_after_unaryexp, unaryexp) = parse_UnaryExpr toks in
match lookahead toks_after_unaryexp with
| Some Tok_Concat ->
let toks_after_concat = match_token toks_after_unaryexp Tok_Concat in
let (toks_after_concatexp, concatexp) = parse_ConcatExpr toks_after_concat in
(toks_after_concatexp, Binop (Concat, unaryexp, concatexp))
| _ ->
(toks_after_unaryexp, unaryexp)
and parse_UnaryExpr toks =
match lookahead toks with
| Some Tok_Not ->
let toks_after_not = match_token toks Tok_Not in
let (toks_after_unaryexp, unaryexp) = parse_UnaryExpr toks_after_not in
(toks_after_unaryexp, Not(unaryexp))
| _ ->
parse_FunctionCallExpr toks
and parse_FunctionCallExpr toks =
let (toks_after_exp1, exp1) = parse_PrimaryExpr toks in
match lookahead toks_after_exp1 with
| Some Tok_Int int ->
let (toks_after_exp2, exp2) = parse_PrimaryExpr toks_after_exp1 in
(toks_after_exp2, FunctionCall (exp1, exp2))
| Some Tok_Bool bool ->
let (toks_after_exp2, exp2) = parse_PrimaryExpr toks_after_exp1 in
(toks_after_exp2, FunctionCall (exp1, exp2))
| Some Tok_String string ->
let (toks_after_exp2, exp2) = parse_PrimaryExpr toks_after_exp1 in
(toks_after_exp2, FunctionCall (exp1, exp2))
| Some Tok_ID id ->
let (toks_after_exp2, exp2) = parse_PrimaryExpr toks_after_exp1 in
(toks_after_exp2, FunctionCall (exp1, exp2))
| Some Tok_LParen ->
let (toks_after_exp2, exp2) = parse_PrimaryExpr toks_after_exp1 in
(toks_after_exp2, FunctionCall (exp1, exp2))
| _ ->
(toks_after_exp1, exp1)
and parse_PrimaryExpr toks =
let next_token = lookahead toks in
match next_token with
(* PrimaryExpr -> Tok_Int *)
| Some Tok_Int int -> (match_token toks (Tok_Int int), Value(Int int))
(* PrimaryExpr -> Tok_Bool *)
| Some Tok_Bool bool -> (match_token toks (Tok_Bool bool), Value(Bool bool))
(* PrimaryExpr -> Tok_String *)
| Some Tok_String string -> (match_token toks (Tok_String string), Value(String string))
(* PrimaryExpr -> Tok_ID *)
| Some Tok_ID id -> (match_token toks (Tok_ID id), (ID id))
(* PrimaryExpr -> (Expr) *)
| Some Tok_LParen ->
let toks_after_lparen = match_token toks Tok_LParen in
let (toks_after_exp, exp) = parse_Expr toks_after_lparen in
let toks_after_rparen = match_token toks_after_exp Tok_RParen in
(toks_after_rparen, exp)
| _ -> raise (InvalidInputException(
Printf.sprintf "Expected %s from input %s, got %s"
(string_of_list string_of_token toks)
(string_of_list string_of_token toks)
(string_of_list string_of_token toks)))
;;
let rec parse_expr toks =
parse_Expr toks
;;
(* Part 3: Parsing mutop *)
let rec parse_mutop toks =
let next_token = lookahead toks in
match next_token with
(* Mutop -> DefMutop *)
| (Some Tok_Def) ->
parse_DefMutop toks
(* Mutop -> ;; *)
| (Some Tok_DoubleSemi) ->
let toks_after_double_semi = match_token toks Tok_DoubleSemi in
(toks_after_double_semi, NoOp)
(* Mutop -> ExprMutop *)
| _ ->
parse_ExprMutop toks
and parse_DefMutop toks =
let toks_after_def = match_token toks Tok_Def in
let id = lookahead toks_after_def in
let id_string = get_id_string id in
let toks_after_id = match_token toks_after_def (Tok_ID id_string) in
let toks_after_equal = match_token toks_after_id Tok_Equal in
let (toks_after_exp, exp) = parse_Expr toks_after_equal in
let toks_after_double_semi = match_token toks_after_exp Tok_DoubleSemi in
(toks_after_double_semi, (Def (id_string, exp)))
and parse_ExprMutop toks =
let (toks_after_exp, exp) = parse_Expr toks in
let toks_after_double_semi = match_token toks_after_exp Tok_DoubleSemi in
(toks_after_double_semi, Expr exp)