ce/parser.ml

91 lines
2.2 KiB
OCaml
Raw Normal View History

2022-01-10 01:31:47 +09:00
open Ast
exception Expected of string
exception Unexpected_token of string
let expected t =
raise (Expected t)
let unexpected_token t =
raise @@ Unexpected_token (Token.to_string t)
let precedence = [
"+", 10;
"-", 10;
"*", 20;
"/", 20;
] |> List.to_seq |> Hashtbl.of_seq
let precedence_of op =
Hashtbl.find precedence (Ast.binop_to_string op)
let token_to_op = function
| Token.Plus -> Add
| Minus -> Sub
| Asterisk -> Mul
| Slash -> Div
| _ -> failwith "Parser.token_to_op"
let parse : type a. Token.t Seq.t -> a Ast.t = fun ts ->
(* value := int | ( expr ) *)
let rec value seq =
match seq () with
| Seq.Nil -> assert false
| Seq.Cons (x, seq) -> begin match x with
| Token.Int n -> Value (Int n), seq
| LParen -> expr seq
| _ -> unexpected_token x
end
(* binop := binop op binop *)
and binop pre left seq =
match seq () with
| Seq.Nil -> left, Seq.empty
| Seq.Cons (x, seq) -> begin match x with
| Token.Plus | Minus | Asterisk | Slash as op ->
let op = token_to_op op in
let o = precedence_of op in
if o > pre then
let v, seq = value seq in
let right, seq = binop o v seq in
binop pre (Ast.binop left op right) seq
else
left, Seq.cons x seq
| RParen -> left, 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 set_conf seq =
match seq () with
| Seq.Nil -> expected "ident"
| Seq.Cons (x, seq) -> begin match x with
| Token.Ident "level" ->
let op, seq = operator seq in
let v, seq = value seq in
Set_binop_pre (op, v), seq
| _ -> expected "argument"
end
and expr seq =
match seq () with
| Seq.Nil -> Value Unit (* nop *)
| Seq.Cons (x, s) -> begin match x with
| Ident "set" -> set_conf s
| _ ->
let left, seq = value seq in
binop ~-1 left seq
end
in
let ast, _ = expr ts in
(*
if rest () <> Seq.Nil then failwith "Parser.parse";
*)
ast