From 4efb65c5cd823c35bf93cf6ddcb69fa61ba6e0cf Mon Sep 17 00:00:00 2001 From: Hyeonung Baek Date: Tue, 18 Jan 2022 15:33:56 +0900 Subject: [PATCH] Add float --- ast.ml | 2 ++ eval.ml | 22 ++++++++++++++-------- lex.ml | 12 +++++++++--- parser.ml | 1 + token.ml | 4 +++- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/ast.ml b/ast.ml index 3ce2e25..2af8f17 100644 --- a/ast.ml +++ b/ast.ml @@ -1,9 +1,11 @@ type typ = | Int of int + | Float of float | Unit let typ_to_string = function | Int n -> Printf.sprintf "%d" n + | Float n -> Printf.sprintf "%f" n | Unit -> "()" type binop = diff --git a/eval.ml b/eval.ml index 5cb692c..baf2b2f 100644 --- a/eval.ml +++ b/eval.ml @@ -2,18 +2,24 @@ open Ast exception Invalid_type -let arith intf a b = +let arith intf floatf a b = match a, b with - | Int a, Int b -> Int (intf a b) + | Int a, Int b -> begin + try Int (intf a b) + with Exit -> Float (floatf (float a) (float b)) + end + | Float a, Int b -> Float (floatf a (float b)) + | Int a, Float b -> Float (floatf (float a) b) + | Float a, Float b -> Float (floatf a b) | _ -> raise Invalid_type let binop_to_func = function - | Add -> arith Int.add - | Sub -> arith Int.sub - | Mul -> arith Int.mul - | Div -> arith Int.div - | Mod -> arith Int.rem - | _ -> assert false + | Add -> arith Int.add Float.add + | Sub -> arith Int.sub Float.sub + | Mul -> arith Int.mul Float.mul + | Div -> arith Int.div Float.div + | Mod -> arith Int.rem Float.rem + | Exp -> arith (fun _ _ -> raise Exit) Float.pow let rec eval = function | Value v -> v diff --git a/lex.ml b/lex.ml index 9b54735..4afdf46 100644 --- a/lex.ml +++ b/lex.ml @@ -10,6 +10,7 @@ let is_digit c = let is_num = function | 'x' -> true + | '.' -> true | c -> is_digit c let is_whitespace = function @@ -46,9 +47,14 @@ let tokenize (str : string) : tokens = if is_whitespace x then aux s () (* skip whitespace *) else if is_digit x then - let n, s = partition_while is_num seq in - let n = int_of_string @@ String.of_seq n in - Seq.Cons (Int n, aux s) + let n, s = partition_while is_num s 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) else if is_ident_start x then let id, s = partition_while is_ident seq in let id = String.of_seq id in diff --git a/parser.ml b/parser.ml index 1714b9a..a68b223 100644 --- a/parser.ml +++ b/parser.ml @@ -80,6 +80,7 @@ let parse ts = | Seq.Nil -> assert false | Seq.Cons (x, seq) -> begin match x with | Token.Int n -> Value (Int n), seq + | Token.Float n -> Value (Float n), seq | LParen -> expr seq | _ -> unexpected_token x end diff --git a/token.ml b/token.ml index ac5394b..9a3e14c 100644 --- a/token.ml +++ b/token.ml @@ -1,5 +1,6 @@ type t = | Int of int + | Float of float | Ident of string | Plus | Minus @@ -37,7 +38,8 @@ let find_token seq = (fun (s, t) -> expect_token s t seq) let to_string = function - | Int n -> string_of_int n + | Int n -> Printf.sprintf "[int: %d]" n + | Float n -> Printf.sprintf "[float: %f]" n | Ident s -> s | t -> begin match List.find_opt (fun (_, tok) -> t = tok) !tokens with