type t = | Int of int | Ident of string | Plus | Minus | Asterisk | Slash | Carret | Percent | LParen | RParen let tokens = ref [ "+", Plus; "-", Minus; "*", Asterisk; "/", Slash; "^", Carret; "%", Percent; "(", LParen; ")", 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 -> string_of_int n | Ident s -> s | t -> begin match List.find_opt (fun (_, tok) -> t = tok) !tokens with | None -> failwith "Token.to_string" | Some (s, _) -> s end