Add float

This commit is contained in:
백현웅 2022-01-18 15:33:56 +09:00
parent 61b70f02f1
commit 4efb65c5cd
5 changed files with 29 additions and 12 deletions

2
ast.ml
View file

@ -1,9 +1,11 @@
type typ = type typ =
| Int of int | Int of int
| Float of float
| Unit | Unit
let typ_to_string = function let typ_to_string = function
| Int n -> Printf.sprintf "%d" n | Int n -> Printf.sprintf "%d" n
| Float n -> Printf.sprintf "%f" n
| Unit -> "()" | Unit -> "()"
type binop = type binop =

22
eval.ml
View file

@ -2,18 +2,24 @@ open Ast
exception Invalid_type exception Invalid_type
let arith intf a b = let arith intf floatf a b =
match a, b with 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 | _ -> raise Invalid_type
let binop_to_func = function let binop_to_func = function
| Add -> arith Int.add | Add -> arith Int.add Float.add
| Sub -> arith Int.sub | Sub -> arith Int.sub Float.sub
| Mul -> arith Int.mul | Mul -> arith Int.mul Float.mul
| Div -> arith Int.div | Div -> arith Int.div Float.div
| Mod -> arith Int.rem | Mod -> arith Int.rem Float.rem
| _ -> assert false | Exp -> arith (fun _ _ -> raise Exit) Float.pow
let rec eval = function let rec eval = function
| Value v -> v | Value v -> v

12
lex.ml
View file

@ -10,6 +10,7 @@ let is_digit c =
let is_num = function let is_num = function
| 'x' -> true | 'x' -> true
| '.' -> true
| c -> is_digit c | c -> is_digit c
let is_whitespace = function let is_whitespace = function
@ -46,9 +47,14 @@ let tokenize (str : string) : tokens =
if is_whitespace x then if is_whitespace x then
aux s () (* skip whitespace *) aux s () (* skip whitespace *)
else if is_digit x then else if is_digit x then
let n, s = partition_while is_num seq in let n, s = partition_while is_num s in
let n = int_of_string @@ String.of_seq n in let n = String.of_seq @@ Seq.cons x n in
Seq.Cons (Int n, aux s) 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 else if is_ident_start x then
let id, s = partition_while is_ident seq in let id, s = partition_while is_ident seq in
let id = String.of_seq id in let id = String.of_seq id in

View file

@ -80,6 +80,7 @@ let parse ts =
| Seq.Nil -> assert false | Seq.Nil -> assert false
| Seq.Cons (x, seq) -> begin match x with | Seq.Cons (x, seq) -> begin match x with
| Token.Int n -> Value (Int n), seq | Token.Int n -> Value (Int n), seq
| Token.Float n -> Value (Float n), seq
| LParen -> expr seq | LParen -> expr seq
| _ -> unexpected_token x | _ -> unexpected_token x
end end

View file

@ -1,5 +1,6 @@
type t = type t =
| Int of int | Int of int
| Float of float
| Ident of string | Ident of string
| Plus | Plus
| Minus | Minus
@ -37,7 +38,8 @@ let find_token seq =
(fun (s, t) -> expect_token s t seq) (fun (s, t) -> expect_token s t seq)
let to_string = function 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 | Ident s -> s
| t -> | t ->
begin match List.find_opt (fun (_, tok) -> t = tok) !tokens with begin match List.find_opt (fun (_, tok) -> t = tok) !tokens with