From 1fd0b30b414336aceab5469e663c4d42169388ce Mon Sep 17 00:00:00 2001 From: Hyeonung Baek Date: Thu, 13 Jan 2022 00:31:26 +0900 Subject: [PATCH] Add parser combinators --- parser.ml | 69 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/parser.ml b/parser.ml index 2716329..de2caf1 100644 --- a/parser.ml +++ b/parser.ml @@ -35,6 +35,39 @@ let token_to_op = function | Slash -> Div | _ -> failwith "Parser.token_to_op" +(* common parsers *) + +let idents set seq = + match seq () with + | Seq.Nil -> + let msg = "ident " ^ (S.elements set |> String.concat " or ") in + expected msg + | Seq.Cons (x, seq) -> begin + match x with + | Token.Ident id when S.mem id set -> id, seq + | _ -> unexpected_token x + end + +let ident str seq = + idents (S.singleton str) seq + +let operator seq = + match seq () with + | Seq.Nil -> expected "operator" + | Seq.Cons (x, seq) -> + try token_to_op x, seq with + | _ -> expected "operator" + +(* parser combinators *) + +let either f g seq = + try f seq with _ -> g seq + +let (@>) f g seq = + let a, seq = f seq in + g a seq + +(* parse tokens *) let parse ts = (* value := int | ( expr ) *) let rec value seq = @@ -64,41 +97,21 @@ let parse ts = | _ -> unexpected_token x end - and ident set seq = - match seq () with - | Seq.Nil -> - let msg = "ident " ^ (S.elements set |> String.concat " or ") in - expected msg - | Seq.Cons (x, seq) -> begin match x with - | Token.Ident id when S.mem id set -> id, seq - | _ -> unexpected_token x - end - - and operator seq = - match seq () with - | Seq.Nil -> expected "operator" - | Seq.Cons (x, seq) -> - try token_to_op x, seq with - | _ -> expected "operator" - - and level seq = - let id, seq = ident (S.of_list ["get"; "set"]) seq in + and level _ seq = + let id, seq = idents (S.of_list ["get"; "set"]) seq in let op, seq = operator seq in if id = "get" then Get_binop_pre op, seq - else + else if id = "set" then let v, seq = value seq in Set_binop_pre (op, v), seq + else + failwith "Parser.level" and expr seq = - match seq () with - | Seq.Nil -> Value Unit, Seq.empty (* nop *) - | Seq.Cons (x, s) -> begin match x with - | Ident "level" -> level s - | _ -> - let left, seq = value seq in - binop ~-1 left seq - end + seq |> either + (ident "level" @> level) + (value @> binop ~-1) in let ast, rest = expr ts in if rest () <> Seq.Nil then failwith "Parser.parse";