Add parser combinators

This commit is contained in:
백현웅 2022-01-13 00:31:26 +09:00
parent 6444f413ca
commit 1fd0b30b41

View file

@ -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";