Add mod (working) and exp (not eval'ed yet)
This commit is contained in:
parent
0ec304cfdf
commit
dd2a1e160e
5 changed files with 35 additions and 6 deletions
6
ast.ml
6
ast.ml
|
@ -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
12
eval.ml
|
@ -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 ->
|
||||||
|
|
1
main.ml
1
main.ml
|
@ -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
|
||||||
|
|
16
parser.ml
16
parser.ml
|
@ -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
|
||||||
|
|
6
token.ml
6
token.ml
|
@ -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 -> ")"
|
||||||
|
|
Loading…
Add table
Reference in a new issue