1 (*===---------------------------------------------------------------------===
3 *===---------------------------------------------------------------------===*)
5 (* binop_precedence - This holds the precedence for each binary operator that is
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
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
28 * ::= identifier '(' argumentexpr ')' *)
29 | [< '
Token.Ident id
; stream
>] ->
30 let rec parse_args accumulator
= parser
31 | [< e
=parse_expr
; stream
>] ->
33 | [< '
Token.Kwd '
,'
; e
=parse_args (e
:: accumulator
) >] -> e
34 | [< >] -> e
:: accumulator
36 | [< >] -> accumulator
38 let rec parse_ident id
= parser
42 '
Token.Kwd '
)' ??
"expected ')'">] ->
43 Ast.Call
(id
, Array.of_list
(List.rev args
))
45 (* Simple variable ref. *)
46 | [< >] -> Ast.Variable id
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
>] ->
57 ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
59 '
Token.Ident id ??
"expected identifier after for";
60 '
Token.Kwd '
=' ??
"expected '=' after for";
65 '
Token.Kwd '
,' ??
"expected ',' after for";
70 | [< '
Token.Kwd '
,'
; step=parse_expr
>] -> Some
step
75 | [< '
Token.In
; body
=parse_expr
>] ->
76 Ast.For
(id
, start
, end_
, step, body
)
78 raise
(Stream.Error
"expected 'in' after for")
81 raise
(Stream.Error
"expected '=' after for")
85 * ::= 'var' identifier ('=' expression?
86 * (',' identifier ('=' expression)?)* 'in' expression *)
88 (* At least one variable name is required. *)
89 '
Token.Ident id ??
"expected identifier after var";
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'";
95 Ast.Var
(Array.of_list
(List.rev var_names
), body
)
97 | [< >] -> raise
(Stream.Error
"unknown token when expecting an expression.")
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
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
124 (* Parse the primary expression after the binary operator. *)
125 let rhs = parse_unary stream
in
127 (* Okay, we know this is a binop. *)
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
141 let lhs = Ast.Binary
(c
, lhs, rhs) in
142 parse_bin_rhs expr_prec
lhs stream
146 and parse_var_init
= parser
147 (* read in the optional initializer. *)
148 | [< '
Token.Kwd '
='
; e
=parse_expr
>] -> Some e
151 and parse_var_names accumulator
= parser
153 '
Token.Ident id ??
"expected identifier list after var";
155 e
=parse_var_names
((id
, init
) :: accumulator
) >] -> e
156 | [< >] -> accumulator
159 * ::= primary binoprhs *)
160 and parse_expr
= parser
161 | [< lhs=parse_unary
; stream
>] -> parse_bin_rhs
0 lhs stream
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
181 | [< '
Token.Ident id
;
182 '
Token.Kwd '
(' ??
"expected '(' in prototype";
184 '
Token.Kwd '
)' ??
"expected ')' in prototype" >] ->
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";
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")
202 Ast.Prototype
(name, args)
204 Ast.BinOpPrototype
(name, args, binary_precedence
)
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
>] ->
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