Add mod (working) and exp (not eval'ed yet)

This commit is contained in:
백현웅 2022-01-13 01:13:41 +09:00
parent 0ec304cfdf
commit dd2a1e160e
5 changed files with 35 additions and 6 deletions

6
ast.ml
View file

@ -7,13 +7,17 @@ let typ_to_string = function
| Unit -> "()" | Unit -> "()"
type binop = type binop =
| Add | Sub | Mul | Div | Add | Sub | Mul | Div (* arithmetics *)
| Mod (* modular operation *)
| Exp (* exponentation *)
let binop_to_string = function let binop_to_string = function
| Add -> "+" | Add -> "+"
| Sub -> "-" | Sub -> "-"
| Mul -> "*" | Mul -> "*"
| Div -> "/" | Div -> "/"
| Mod -> "%"
| Exp -> "^"
type t = type t =
| Value of typ | Value of typ

12
eval.ml
View file

@ -1,15 +1,19 @@
open Ast open Ast
let arith f a b = exception Invalid_type
let arith intf a b =
match a, b with match a, b with
| Int a, Int b -> Int (f a b) | Int a, Int b -> Int (intf a b)
| _ -> failwith "typecheck failed" | _ -> raise Invalid_type
let binop_to_func = function let binop_to_func = function
| Add -> arith Int.add | Add -> arith Int.add
| Sub -> arith Int.sub | Sub -> arith Int.sub
| Mul -> arith Int.mul | Mul -> arith Int.mul
| Div -> arith Int.div | Div -> arith Int.div
| Mod -> arith Int.rem
| _ -> assert false
let rec eval = function let rec eval = function
| Value v -> v | Value v -> v
@ -17,7 +21,7 @@ let rec eval = function
let f = binop_to_func op in let f = binop_to_func op in
f (eval l) (eval r) f (eval l) (eval r)
| Set_binop_pre (op, l) -> | Set_binop_pre (op, l) ->
let l = match eval l with Int n -> n | _ -> failwith "not int" in let l = match eval l with Int n -> n | _ -> raise Invalid_type in
Hashtbl.replace Parser.precedence op l; Hashtbl.replace Parser.precedence op l;
Unit Unit
| Get_binop_pre op -> | Get_binop_pre op ->

View file

@ -8,6 +8,7 @@ let error_to_string e =
try raise e with try raise e with
| Parser.Expected t -> sprintf "expected %s" t | Parser.Expected t -> sprintf "expected %s" t
| Parser.Unexpected_token t -> sprintf "unexpected token \"%s\"" t | Parser.Unexpected_token t -> sprintf "unexpected token \"%s\"" t
| Eval.Invalid_type -> "invalid type"
| Failure f -> sprintf "error on %s" f | Failure f -> sprintf "error on %s" f
| Division_by_zero -> "cannot divide by zero" | Division_by_zero -> "cannot divide by zero"
| _ -> raise e | _ -> raise e

View file

@ -20,6 +20,8 @@ let precedence = [
Sub, 10; Sub, 10;
Mul, 20; Mul, 20;
Div, 20; Div, 20;
Mod, 30;
Exp, 30;
] |> List.to_seq |> Hashtbl.of_seq ] |> List.to_seq |> Hashtbl.of_seq
let precedence_of op = let precedence_of op =
@ -27,12 +29,15 @@ let precedence_of op =
let is_left_to_right = function let is_left_to_right = function
| Add | Sub | Mul | Div -> true | Add | Sub | Mul | Div -> true
| _ -> assert false
let token_to_op = function let token_to_op = function
| Token.Plus -> Add | Token.Plus -> Add
| Minus -> Sub | Minus -> Sub
| Asterisk -> Mul | Asterisk -> Mul
| Slash -> Div | Slash -> Div
| Carret -> Exp
| Percent -> Mod
| _ -> failwith "Parser.token_to_op" | _ -> failwith "Parser.token_to_op"
(* common parsers *) (* common parsers *)
@ -84,7 +89,7 @@ let parse ts =
match seq () with match seq () with
| Seq.Nil -> left, Seq.empty | Seq.Nil -> left, Seq.empty
| Seq.Cons (x, seq) -> begin match x with | Seq.Cons (x, seq) -> begin match x with
| Token.Plus | Minus | Asterisk | Slash as op -> | Token.Plus | Minus | Asterisk | Slash | Percent as op ->
let op = token_to_op op in let op = token_to_op op in
let o = precedence_of op in let o = precedence_of op in
if o > pre then (* op has to be calculated first *) if o > pre then (* op has to be calculated first *)
@ -93,6 +98,15 @@ let parse ts =
binop pre (Ast.binop left op right) seq binop pre (Ast.binop left op right) seq
else else
left, Seq.cons x seq left, Seq.cons x seq
| Carret as op ->
let op = token_to_op op in
let o = precedence_of op in
if o >= pre then (* op has to be calculated first *)
let v, seq = value seq in
let right, seq = binop o v seq in
binop pre (Ast.binop left op right) seq
else
left, Seq.cons x seq
| RParen -> left, seq | RParen -> left, seq
| _ -> unexpected_token x | _ -> unexpected_token x
end end

View file

@ -5,6 +5,8 @@ type t =
| Minus | Minus
| Asterisk | Asterisk
| Slash | Slash
| Carret
| Percent
| LParen | LParen
| RParen | RParen
@ -13,6 +15,8 @@ let of_char = function
| '-' -> Minus | '-' -> Minus
| '*' -> Asterisk | '*' -> Asterisk
| '/' -> Slash | '/' -> Slash
| '^' -> Carret
| '%' -> Percent
| '(' -> LParen | '(' -> LParen
| ')' -> RParen | ')' -> RParen
| _ -> invalid_arg "Token.of_char" | _ -> invalid_arg "Token.of_char"
@ -33,5 +37,7 @@ let to_string = function
| Minus -> "-" | Minus -> "-"
| Asterisk -> "*" | Asterisk -> "*"
| Slash -> "/" | Slash -> "/"
| Carret -> "^"
| Percent -> "%"
| LParen -> "(" | LParen -> "("
| RParen -> ")" | RParen -> ")"