166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman(*===---------------------------------------------------------------------=== 266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * Parser 366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman *===---------------------------------------------------------------------===*) 466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman(* binop_precedence - This holds the precedence for each binary operator that is 666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * defined *) 766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanlet binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman(* precedence - Get the precedence of the pending binary operator token. *) 1066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanlet precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 1166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 1266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman(* primary 1366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * ::= identifier 1466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * ::= numberexpr 1566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * ::= parenexpr *) 1666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanlet rec parse_primary = parser 1766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* numberexpr ::= number *) 1866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< 'Token.Number n >] -> Ast.Number n 1966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 2066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* parenexpr ::= '(' expression ')' *) 2166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e 2266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 2366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* identifierexpr 2466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * ::= identifier 2566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * ::= identifier '(' argumentexpr ')' *) 2666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< 'Token.Ident id; stream >] -> 2766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman let rec parse_args accumulator = parser 2866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< e=parse_expr; stream >] -> 2966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman begin parser 3066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e 3166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< >] -> e :: accumulator 3266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman end stream 3366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< >] -> accumulator 3466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman in 3566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman let rec parse_ident id = parser 3666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* Call. *) 3766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< 'Token.Kwd '('; 3866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman args=parse_args []; 3966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 'Token.Kwd ')' ?? "expected ')'">] -> 4066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Ast.Call (id, Array.of_list (List.rev args)) 4166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* Simple variable ref. *) 4366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< >] -> Ast.Variable id 4466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman in 4566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman parse_ident id stream 4666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") 4866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman(* binoprhs 5066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * ::= ('+' primary)* *) 5166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanand parse_bin_rhs expr_prec lhs stream = 5266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman match Stream.peek stream with 5366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* If this is a binop, find its precedence. *) 5466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> 5566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman let token_prec = precedence c in 5666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 5766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* If this is a binop that binds at least as tightly as the current binop, 5866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * consume it, otherwise we are done. *) 5966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if token_prec < expr_prec then lhs else begin 6066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* Eat the binop. *) 6166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Stream.junk stream; 6266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 6366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* Parse the primary expression after the binary operator. *) 6466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman let rhs = parse_primary stream in 6566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 6666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* Okay, we know this is a binop. *) 6766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman let rhs = 6866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman match Stream.peek stream with 6966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | Some (Token.Kwd c2) -> 7066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* If BinOp binds less tightly with rhs than the operator after 7166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * rhs, let the pending operator take rhs as its lhs. *) 7266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman let next_prec = precedence c2 in 7366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if token_prec < next_prec 7466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman then parse_bin_rhs (token_prec + 1) rhs stream 7566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else rhs 7666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | _ -> rhs 7766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman in 7866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 7966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* Merge lhs/rhs. *) 8066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman let lhs = Ast.Binary (c, lhs, rhs) in 8166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman parse_bin_rhs expr_prec lhs stream 8266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman end 8366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | _ -> lhs 8466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 8566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman(* expression 8666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * ::= primary binoprhs *) 8766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanand parse_expr = parser 8866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream 8966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 9066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman(* prototype 9166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * ::= id '(' id* ')' *) 9266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanlet parse_prototype = 9366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman let rec parse_args accumulator = parser 9466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e 9566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< >] -> accumulator 9666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman in 9766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 9866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman parser 9966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< 'Token.Ident id; 10066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 'Token.Kwd '(' ?? "expected '(' in prototype"; 10166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman args=parse_args []; 10266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> 10366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* success. *) 10466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Ast.Prototype (id, Array.of_list (List.rev args)) 10566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 10666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< >] -> 10766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman raise (Stream.Error "expected function name in prototype") 10866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 10966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman(* definition ::= 'def' prototype expression *) 11066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanlet parse_definition = parser 11166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> 11266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Ast.Function (p, e) 11366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 11466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman(* toplevelexpr ::= expression *) 11566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanlet parse_toplevel = parser 11666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< e=parse_expr >] -> 11766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (* Make an anonymous proto. *) 11866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Ast.Function (Ast.Prototype ("", [||]), e) 11966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 12066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman(* external ::= 'extern' prototype *) 12166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanlet parse_extern = parser 12266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman | [< 'Token.Extern; e=parse_prototype >] -> e 123