diff --git a/ast.ml b/ast.ml index ae18fa3..9f3905c 100644 --- a/ast.ml +++ b/ast.ml @@ -30,14 +30,9 @@ module Value = struct let to_string = function | Int n -> string_of_int n | Float n -> string_of_float n - | String s -> s + | String s -> "\"" ^ s ^ "\"" | Nop -> "nop" - let of_token = function - | Token.Int n -> Int n - | Float n -> Float n - | _ -> invalid_arg "Value.of_token" - let typeof = function | Int _ -> Type.Int | Float _ -> Type.Float diff --git a/lex.ml b/lex.ml index 48a6ad4..93afc86 100644 --- a/lex.ml +++ b/lex.ml @@ -1,6 +1,9 @@ +open Ast.Value + type tokens = Token.t Seq.t exception Token_not_found +exception Unclosed_quote let either f g c = f c || g c @@ -58,24 +61,37 @@ let tokenize (str : string) : tokens = let open Token in match seq () with | Seq.Nil -> Seq.Nil - | Seq.Cons (x, s) -> + | Seq.Cons (x, seq) -> if is_whitespace x then - aux s () (* skip whitespace *) + aux seq () (* skip whitespace *) + + else if x = '"' then + let str, seq = partition_while ((<>) '"') seq in + let str = String (String.of_seq str) in + begin match seq () with + | Seq.Nil -> raise Unclosed_quote + | Seq.Cons (x, seq) -> + if x = '"' then Seq.Cons (Value str, aux seq) + else raise Unclosed_quote + end + else if is_digit x then - let n, s = partition_while is_num s in + let n, seq = partition_while is_num seq in let n = String.of_seq @@ Seq.cons x n in let n = if String.contains n '.' (* float *) then Float (float_of_string n) else Int (int_of_string n) in - Seq.Cons (n, aux s) + Seq.Cons (Value n, aux seq) + else if is_ident_start x then - let id, s = partition_while is_ident seq in - let id = String.of_seq id in - Seq.Cons (Ident id, aux s) + let id, seq = partition_while is_ident seq in + let id = String.of_seq @@ Seq.cons x id in + Seq.Cons (Ident id, aux seq) + else - match find_token seq with + match find_token @@ Seq.cons x seq with | None -> raise Token_not_found | Some (t, s) -> Seq.Cons (t, aux s) in diff --git a/main.ml b/main.ml index 8bdcad8..f5ede32 100644 --- a/main.ml +++ b/main.ml @@ -7,6 +7,7 @@ let version = "%%VERSION%%" let error_to_string e = try raise e with | Lex.Token_not_found -> sprintf "invalid token" + | Lex.Unclosed_quote -> sprintf "string not closed" | Parser.Expected t -> sprintf "expected %s" t | Parser.Unexpected_token t -> sprintf "unexpected token \"%s\"" t | Ast.Invalid_type t -> sprintf "invalid type %s" (Ast.Type.to_string t) diff --git a/parser.ml b/parser.ml index 1492822..9f412f0 100644 --- a/parser.ml +++ b/parser.ml @@ -173,8 +173,7 @@ and value seq = match seq () with | Seq.Nil -> raise End_of_tokens | Seq.Cons (x, seq) -> begin match x with - | Token.Int n -> Value (Int n), seq - | Float n -> Value (Float n), seq + | Token.Value x -> Value x, seq | Ident id -> Var id, seq | LParen -> let e, seq = expr min_int seq in diff --git a/token.ml b/token.ml index 3647f3c..6c28600 100644 --- a/token.ml +++ b/token.ml @@ -1,6 +1,5 @@ type t = - | Int of int - | Float of float + | Value of Ast.Value.t | Ident of string | Plus | Minus @@ -25,8 +24,7 @@ let tokens = ref [ ] let to_string = function - | Int n -> Printf.sprintf "[int: %d]" n - | Float n -> Printf.sprintf "[float: %f]" n + | Value v -> Ast.Value.to_string v | Ident s -> s | t -> begin match List.find_opt (fun (_, tok) -> t = tok) !tokens with