17abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao(*===---------------------------------------------------------------------=== 27abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * Parser 37abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao *===---------------------------------------------------------------------===*) 47abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 57abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao(* binop_precedence - This holds the precedence for each binary operator that is 67abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * defined *) 77abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaolet binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 87abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 97abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao(* precedence - Get the precedence of the pending binary operator token. *) 107abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaolet precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 117abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 127abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao(* primary 137abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= identifier 147abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= numberexpr 157abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= parenexpr 167abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= ifexpr 177abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= forexpr 187abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= varexpr *) 197abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaolet rec parse_primary = parser 207abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* numberexpr ::= number *) 217abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Number n >] -> Ast.Number n 227abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 237abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* parenexpr ::= '(' expression ')' *) 247abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e 257abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 267abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* identifierexpr 277abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= identifier 287abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= identifier '(' argumentexpr ')' *) 297abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Ident id; stream >] -> 307abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let rec parse_args accumulator = parser 317abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< e=parse_expr; stream >] -> 327abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao begin parser 337abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e 347abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> e :: accumulator 357abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao end stream 367abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> accumulator 377abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao in 387abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let rec parse_ident id = parser 397abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* Call. *) 407abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Kwd '('; 417abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao args=parse_args []; 427abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Kwd ')' ?? "expected ')'">] -> 437abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao Ast.Call (id, Array.of_list (List.rev args)) 447abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 457abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* Simple variable ref. *) 467abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> Ast.Variable id 477abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao in 487abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao parse_ident id stream 497abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 507abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) 517abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.If; c=parse_expr; 527abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Then ?? "expected 'then'"; t=parse_expr; 537abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> 547abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao Ast.If (c, t, e) 557abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 567abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* forexpr 577abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *) 587abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.For; 597abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Ident id ?? "expected identifier after for"; 607abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Kwd '=' ?? "expected '=' after for"; 617abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao stream >] -> 627abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao begin parser 637abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 647abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao start=parse_expr; 657abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Kwd ',' ?? "expected ',' after for"; 667abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao end_=parse_expr; 677abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao stream >] -> 687abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let step = 697abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao begin parser 707abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Kwd ','; step=parse_expr >] -> Some step 717abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> None 727abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao end stream 737abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao in 747abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao begin parser 757abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.In; body=parse_expr >] -> 767abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao Ast.For (id, start, end_, step, body) 777abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> 787abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao raise (Stream.Error "expected 'in' after for") 797abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao end stream 807abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> 817abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao raise (Stream.Error "expected '=' after for") 827abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao end stream 837abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 847abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* varexpr 857abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= 'var' identifier ('=' expression? 867abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * (',' identifier ('=' expression)?)* 'in' expression *) 877abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Var; 887abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* At least one variable name is required. *) 897abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Ident id ?? "expected identifier after var"; 907abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao init=parse_var_init; 917abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao var_names=parse_var_names [(id, init)]; 927abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* At this point, we have to have 'in'. *) 937abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.In ?? "expected 'in' keyword after 'var'"; 947abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao body=parse_expr >] -> 957abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao Ast.Var (Array.of_list (List.rev var_names), body) 967abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 977abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") 987abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 997abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao(* unary 1007abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= primary 1017abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= '!' unary *) 1027abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaoand parse_unary = parser 1037abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* If this is a unary operator, read it. *) 1047abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] -> 1057abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao Ast.Unary (op, operand) 1067abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 1077abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* If the current token is not an operator, it must be a primary expr. *) 1087abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< stream >] -> parse_primary stream 1097abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 1107abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao(* binoprhs 1117abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= ('+' primary)* *) 1127abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaoand parse_bin_rhs expr_prec lhs stream = 1137abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao match Stream.peek stream with 1147abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* If this is a binop, find its precedence. *) 1157abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> 1167abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let token_prec = precedence c in 1177abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 1187abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* If this is a binop that binds at least as tightly as the current binop, 1197abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * consume it, otherwise we are done. *) 1207abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao if token_prec < expr_prec then lhs else begin 1217abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* Eat the binop. *) 1227abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao Stream.junk stream; 1237abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 1247abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* Parse the primary expression after the binary operator. *) 1257abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let rhs = parse_unary stream in 1267abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 1277abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* Okay, we know this is a binop. *) 1287abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let rhs = 1297abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao match Stream.peek stream with 1307abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | Some (Token.Kwd c2) -> 1317abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* If BinOp binds less tightly with rhs than the operator after 1327abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * rhs, let the pending operator take rhs as its lhs. *) 1337abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let next_prec = precedence c2 in 1347abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao if token_prec < next_prec 1357abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao then parse_bin_rhs (token_prec + 1) rhs stream 1367abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao else rhs 1377abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | _ -> rhs 1387abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao in 1397abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 1407abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* Merge lhs/rhs. *) 1417abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let lhs = Ast.Binary (c, lhs, rhs) in 1427abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao parse_bin_rhs expr_prec lhs stream 1437abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao end 1447abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | _ -> lhs 1457abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 1467abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaoand parse_var_init = parser 1477abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* read in the optional initializer. *) 1487abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Kwd '='; e=parse_expr >] -> Some e 1497abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> None 1507abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 1517abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaoand parse_var_names accumulator = parser 1527abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Kwd ','; 1537abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Ident id ?? "expected identifier list after var"; 1547abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao init=parse_var_init; 1557abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao e=parse_var_names ((id, init) :: accumulator) >] -> e 1567abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> accumulator 1577abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 1587abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao(* expression 1597abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= primary binoprhs *) 1607abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaoand parse_expr = parser 1617abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream 1627abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 1637abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao(* prototype 1647abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= id '(' id* ')' 1657abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= binary LETTER number? (id, id) 1667abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao * ::= unary LETTER number? (id) *) 1677abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaolet parse_prototype = 1687abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let rec parse_args accumulator = parser 1697abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e 1707abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> accumulator 1717abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao in 1727abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let parse_operator = parser 1737abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Unary >] -> "unary", 1 1747abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Binary >] -> "binary", 2 1757abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao in 1767abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let parse_binary_precedence = parser 1777abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Number n >] -> int_of_float n 1787abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> 30 1797abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao in 1807abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao parser 1817abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Ident id; 1827abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Kwd '(' ?? "expected '(' in prototype"; 1837abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao args=parse_args []; 1847abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> 1857abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* success. *) 1867abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao Ast.Prototype (id, Array.of_list (List.rev args)) 1877abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< (prefix, kind)=parse_operator; 1887abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Kwd op ?? "expected an operator"; 1897abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* Read the precedence if present. *) 1907abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao binary_precedence=parse_binary_precedence; 1917abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Kwd '(' ?? "expected '(' in prototype"; 1927abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao args=parse_args []; 1937abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> 1947abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let name = prefix ^ (String.make 1 op) in 1957abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao let args = Array.of_list (List.rev args) in 1967abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 1977abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* Verify right number of arguments for operator. *) 1987abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao if Array.length args != kind 1997abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao then raise (Stream.Error "invalid number of operands for operator") 2007abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao else 2017abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao if kind == 1 then 2027abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao Ast.Prototype (name, args) 2037abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao else 2047abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao Ast.BinOpPrototype (name, args, binary_precedence) 2057abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< >] -> 2067abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao raise (Stream.Error "expected function name in prototype") 2077abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 2087abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao(* definition ::= 'def' prototype expression *) 2097abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaolet parse_definition = parser 2107abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> 2117abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao Ast.Function (p, e) 2127abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 2137abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao(* toplevelexpr ::= expression *) 2147abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaolet parse_toplevel = parser 2157abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< e=parse_expr >] -> 2167abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao (* Make an anonymous proto. *) 2177abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao Ast.Function (Ast.Prototype ("", [||]), e) 2187abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao 2197abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao(* external ::= 'extern' prototype *) 2207abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaolet parse_extern = parser 2217abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao | [< 'Token.Extern; e=parse_prototype >] -> e 222