From 20e324f4c28c3d42f6a21f40138b22f32824f1af Mon Sep 17 00:00:00 2001 From: Hyeonung Baek Date: Tue, 18 Jan 2022 15:36:09 +0900 Subject: [PATCH] Improve operator lexing --- lex.ml | 15 +++++++++++++++ parser.ml | 20 ++++++++++++-------- token.ml | 15 --------------- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/lex.ml b/lex.ml index 4afdf46..48a6ad4 100644 --- a/lex.ml +++ b/lex.ml @@ -26,6 +26,21 @@ let is_ident_start = let is_ident = either is_ident_start is_digit +let expect_token str tok seq = + let rec aux ts seq = + match ts (), seq () with + | Seq.Nil, _ -> Some seq + | Seq.Cons _, Seq.Nil -> None + | Seq.Cons (a, ts), Seq.Cons (b, seq) -> + if a = b then aux ts seq else None + in + let str = String.to_seq str in + aux str seq |> Option.map (fun s -> tok, s) + +let find_token seq = + !Token.tokens |> List.find_map + (fun (s, t) -> expect_token s t seq) + (* same as take_while f seq, drop_while f seq *) let rec partition_while f seq : 'a Seq.t * 'a Seq.t = match seq () with diff --git a/parser.ml b/parser.ml index a68b223..c0a2552 100644 --- a/parser.ml +++ b/parser.ml @@ -31,14 +31,18 @@ let is_left_to_right = function | Add | Sub | Mul | Div -> true | _ -> assert false -let token_to_op = function - | Token.Plus -> Add - | Minus -> Sub - | Asterisk -> Mul - | Slash -> Div - | Carret -> Exp - | Percent -> Mod - | _ -> failwith "Parser.token_to_op" +let operators = [ + Token.Plus, Add; + Minus, Sub; + Asterisk, Mul; + Slash, Div; + Carret, Exp; + Percent, Mod; +] |> List.to_seq |> Hashtbl.of_seq + +let token_to_op tok = + try Hashtbl.find operators tok + with _ -> failwith "Parser.token_to_op" (* common parsers *) diff --git a/token.ml b/token.ml index 9a3e14c..1e83fc8 100644 --- a/token.ml +++ b/token.ml @@ -22,21 +22,6 @@ let tokens = ref [ ")", RParen; ] -let expect_token str tok seq = - let rec aux ts seq = - match ts (), seq () with - | Seq.Nil, _ -> Some seq - | Seq.Cons _, Seq.Nil -> None - | Seq.Cons (a, ts), Seq.Cons (b, seq) -> - if a = b then aux ts seq else None - in - let str = String.to_seq str in - aux str seq |> Option.map (fun s -> tok, s) - -let find_token seq = - !tokens |> List.find_map - (fun (s, t) -> expect_token s t seq) - let to_string = function | Int n -> Printf.sprintf "[int: %d]" n | Float n -> Printf.sprintf "[float: %f]" n