[InstCombine] Signed saturation tests. NFC
[llvm-core.git] / examples / OCaml-Kaleidoscope / Chapter7 / parser.ml
blobc0e7db8349a5aa7a1d1c1c64ff98e1069c43de2b
1 (*===---------------------------------------------------------------------===
2 * Parser
3 *===---------------------------------------------------------------------===*)
5 (* binop_precedence - This holds the precedence for each binary operator that is
6 * defined *)
7 let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
9 (* precedence - Get the precedence of the pending binary operator token. *)
10 let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
12 (* primary
13 * ::= identifier
14 * ::= numberexpr
15 * ::= parenexpr
16 * ::= ifexpr
17 * ::= forexpr
18 * ::= varexpr *)
19 let rec parse_primary = parser
20 (* numberexpr ::= number *)
21 | [< 'Token.Number n >] -> Ast.Number n
23 (* parenexpr ::= '(' expression ')' *)
24 | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
26 (* identifierexpr
27 * ::= identifier
28 * ::= identifier '(' argumentexpr ')' *)
29 | [< 'Token.Ident id; stream >] ->
30 let rec parse_args accumulator = parser
31 | [< e=parse_expr; stream >] ->
32 begin parser
33 | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
34 | [< >] -> e :: accumulator
35 end stream
36 | [< >] -> accumulator
38 let rec parse_ident id = parser
39 (* Call. *)
40 | [< 'Token.Kwd '(';
41 args=parse_args [];
42 'Token.Kwd ')' ?? "expected ')'">] ->
43 Ast.Call (id, Array.of_list (List.rev args))
45 (* Simple variable ref. *)
46 | [< >] -> Ast.Variable id
48 parse_ident id stream
50 (* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
51 | [< 'Token.If; c=parse_expr;
52 'Token.Then ?? "expected 'then'"; t=parse_expr;
53 'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
54 Ast.If (c, t, e)
56 (* forexpr
57 ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
58 | [< 'Token.For;
59 'Token.Ident id ?? "expected identifier after for";
60 'Token.Kwd '=' ?? "expected '=' after for";
61 stream >] ->
62 begin parser
63 | [<
64 start=parse_expr;
65 'Token.Kwd ',' ?? "expected ',' after for";
66 end_=parse_expr;
67 stream >] ->
68 let step =
69 begin parser
70 | [< 'Token.Kwd ','; step=parse_expr >] -> Some step
71 | [< >] -> None
72 end stream
74 begin parser
75 | [< 'Token.In; body=parse_expr >] ->
76 Ast.For (id, start, end_, step, body)
77 | [< >] ->
78 raise (Stream.Error "expected 'in' after for")
79 end stream
80 | [< >] ->
81 raise (Stream.Error "expected '=' after for")
82 end stream
84 (* varexpr
85 * ::= 'var' identifier ('=' expression?
86 * (',' identifier ('=' expression)?)* 'in' expression *)
87 | [< 'Token.Var;
88 (* At least one variable name is required. *)
89 'Token.Ident id ?? "expected identifier after var";
90 init=parse_var_init;
91 var_names=parse_var_names [(id, init)];
92 (* At this point, we have to have 'in'. *)
93 'Token.In ?? "expected 'in' keyword after 'var'";
94 body=parse_expr >] ->
95 Ast.Var (Array.of_list (List.rev var_names), body)
97 | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
99 (* unary
100 * ::= primary
101 * ::= '!' unary *)
102 and parse_unary = parser
103 (* If this is a unary operator, read it. *)
104 | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] ->
105 Ast.Unary (op, operand)
107 (* If the current token is not an operator, it must be a primary expr. *)
108 | [< stream >] -> parse_primary stream
110 (* binoprhs
111 * ::= ('+' primary)* *)
112 and parse_bin_rhs expr_prec lhs stream =
113 match Stream.peek stream with
114 (* If this is a binop, find its precedence. *)
115 | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
116 let token_prec = precedence c in
118 (* If this is a binop that binds at least as tightly as the current binop,
119 * consume it, otherwise we are done. *)
120 if token_prec < expr_prec then lhs else begin
121 (* Eat the binop. *)
122 Stream.junk stream;
124 (* Parse the primary expression after the binary operator. *)
125 let rhs = parse_unary stream in
127 (* Okay, we know this is a binop. *)
128 let rhs =
129 match Stream.peek stream with
130 | Some (Token.Kwd c2) ->
131 (* If BinOp binds less tightly with rhs than the operator after
132 * rhs, let the pending operator take rhs as its lhs. *)
133 let next_prec = precedence c2 in
134 if token_prec < next_prec
135 then parse_bin_rhs (token_prec + 1) rhs stream
136 else rhs
137 | _ -> rhs
140 (* Merge lhs/rhs. *)
141 let lhs = Ast.Binary (c, lhs, rhs) in
142 parse_bin_rhs expr_prec lhs stream
144 | _ -> lhs
146 and parse_var_init = parser
147 (* read in the optional initializer. *)
148 | [< 'Token.Kwd '='; e=parse_expr >] -> Some e
149 | [< >] -> None
151 and parse_var_names accumulator = parser
152 | [< 'Token.Kwd ',';
153 'Token.Ident id ?? "expected identifier list after var";
154 init=parse_var_init;
155 e=parse_var_names ((id, init) :: accumulator) >] -> e
156 | [< >] -> accumulator
158 (* expression
159 * ::= primary binoprhs *)
160 and parse_expr = parser
161 | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream
163 (* prototype
164 * ::= id '(' id* ')'
165 * ::= binary LETTER number? (id, id)
166 * ::= unary LETTER number? (id) *)
167 let parse_prototype =
168 let rec parse_args accumulator = parser
169 | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
170 | [< >] -> accumulator
172 let parse_operator = parser
173 | [< 'Token.Unary >] -> "unary", 1
174 | [< 'Token.Binary >] -> "binary", 2
176 let parse_binary_precedence = parser
177 | [< 'Token.Number n >] -> int_of_float n
178 | [< >] -> 30
180 parser
181 | [< 'Token.Ident id;
182 'Token.Kwd '(' ?? "expected '(' in prototype";
183 args=parse_args [];
184 'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
185 (* success. *)
186 Ast.Prototype (id, Array.of_list (List.rev args))
187 | [< (prefix, kind)=parse_operator;
188 'Token.Kwd op ?? "expected an operator";
189 (* Read the precedence if present. *)
190 binary_precedence=parse_binary_precedence;
191 'Token.Kwd '(' ?? "expected '(' in prototype";
192 args=parse_args [];
193 'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
194 let name = prefix ^ (String.make 1 op) in
195 let args = Array.of_list (List.rev args) in
197 (* Verify right number of arguments for operator. *)
198 if Array.length args != kind
199 then raise (Stream.Error "invalid number of operands for operator")
200 else
201 if kind == 1 then
202 Ast.Prototype (name, args)
203 else
204 Ast.BinOpPrototype (name, args, binary_precedence)
205 | [< >] ->
206 raise (Stream.Error "expected function name in prototype")
208 (* definition ::= 'def' prototype expression *)
209 let parse_definition = parser
210 | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
211 Ast.Function (p, e)
213 (* toplevelexpr ::= expression *)
214 let parse_toplevel = parser
215 | [< e=parse_expr >] ->
216 (* Make an anonymous proto. *)
217 Ast.Function (Ast.Prototype ("", [||]), e)
219 (* external ::= 'extern' prototype *)
220 let parse_extern = parser
221 | [< 'Token.Extern; e=parse_prototype >] -> e