Change get/set precedence/associativity to external function
This commit is contained in:
parent
34eeff4a01
commit
8c40e99241
4 changed files with 43 additions and 62 deletions
16
ast.ml
16
ast.ml
|
@ -15,11 +15,6 @@ type t =
|
|||
| Binop of t * operator * t
|
||||
| If of t * t * t (* cond then else *)
|
||||
| Apply of t * t list (* function application *)
|
||||
(* these will be seperated into external functions. *)
|
||||
| Set_binop_pre of operator * t
|
||||
| Get_binop_pre of operator
|
||||
| Set_binop_aso of operator * string
|
||||
| Get_binop_aso of operator
|
||||
|
||||
and operator =
|
||||
| Add | Sub | Mul | Div (* arithmetics *)
|
||||
|
@ -89,16 +84,5 @@ let print ast =
|
|||
pr "(if"; f co; f th; f el; pr ")"
|
||||
| Apply (f, args) ->
|
||||
pr "("; aux f; List.iter (fun a -> pr " "; aux a) args; pr ")"
|
||||
|
||||
| Set_binop_pre (op, pre) ->
|
||||
pr "(set_pre %s " (op_to_string op);
|
||||
aux pre;
|
||||
pr ")"
|
||||
| Get_binop_pre op ->
|
||||
pr "(get_pre %s)" (op_to_string op)
|
||||
| Set_binop_aso (op, aso) ->
|
||||
pr "(set_assoc %s %s)" (op_to_string op) aso
|
||||
| Get_binop_aso op ->
|
||||
pr "(get_pre %s)" (op_to_string op)
|
||||
in
|
||||
aux ast; pr "\n"
|
||||
|
|
57
eval.ml
57
eval.ml
|
@ -168,6 +168,42 @@ module External = struct
|
|||
| [v] -> raise @@ Type.Invalid (Value.typeof v)
|
||||
| _ -> invalid_arg "External.floatfun"
|
||||
|
||||
let symbol_to_op op =
|
||||
op
|
||||
|> String.to_seqi
|
||||
|> Lex.find_token
|
||||
|> Option.get
|
||||
|> fst
|
||||
|> Parser.token_to_op
|
||||
|
||||
let set_op_pre = function
|
||||
| [Symbol op; Int l] ->
|
||||
let op = symbol_to_op op in
|
||||
Hashtbl.replace Parser.precedence op l;
|
||||
Nop
|
||||
| _ -> failwith "set_op_pre"
|
||||
|
||||
let get_op_pre = function
|
||||
| [Symbol op] ->
|
||||
let op = symbol_to_op op in
|
||||
Int (Hashtbl.find Parser.precedence op)
|
||||
| _ -> failwith "get_op_pre"
|
||||
|
||||
let set_op_assoc = function
|
||||
| [Symbol op; String a] ->
|
||||
let op = symbol_to_op op in
|
||||
Hashtbl.replace Parser.oper_assoc op @@ Parser.assoc_of_string a;
|
||||
Nop
|
||||
| _ -> failwith "set_op_assoc"
|
||||
|
||||
let get_op_assoc = function
|
||||
| [Symbol op] ->
|
||||
let op = symbol_to_op op in
|
||||
Hashtbl.find_opt Parser.oper_assoc op
|
||||
|> Option.value ~default: Parser.Left_to_right
|
||||
|> (fun a -> String (Parser.assoc_to_string a))
|
||||
| _ -> failwith "get_op_assoc"
|
||||
|
||||
let apply f args =
|
||||
let f = match f with
|
||||
| "sin" -> floatfun Float.sin
|
||||
|
@ -175,6 +211,10 @@ module External = struct
|
|||
| "tan" -> floatfun Float.tan
|
||||
| "deg" -> floatfun deg
|
||||
| "rad" -> floatfun rad
|
||||
| "set_op_pre" -> set_op_pre
|
||||
| "get_op_pre" -> get_op_pre
|
||||
| "set_op_assoc" -> set_op_assoc
|
||||
| "get_op_assoc" -> get_op_assoc
|
||||
| _ -> raise @@ Invalid f
|
||||
in
|
||||
f args
|
||||
|
@ -250,23 +290,6 @@ let rec eval env ast =
|
|||
end
|
||||
| Apply (v, args) -> apply v args env
|
||||
|
||||
| Set_binop_pre (op, l) ->
|
||||
let l =
|
||||
match aux l with
|
||||
| Int n -> n
|
||||
| v -> raise @@ Type.Invalid (Value.typeof v)
|
||||
in
|
||||
Hashtbl.replace Parser.precedence op l;
|
||||
Nop
|
||||
| Get_binop_pre op ->
|
||||
Int (Hashtbl.find Parser.precedence op)
|
||||
| Set_binop_aso (op, a) ->
|
||||
Hashtbl.replace Parser.oper_assoc op @@ Parser.assoc_of_string a;
|
||||
Nop
|
||||
| Get_binop_aso op ->
|
||||
(match Hashtbl.find_opt Parser.oper_assoc op with
|
||||
| None -> String "left"
|
||||
| Some a -> String (Parser.assoc_to_string a))
|
||||
| _ -> failwith "Eval.eval"
|
||||
|
||||
(* apply args to result of expr *)
|
||||
|
|
2
main.ml
2
main.ml
|
@ -27,6 +27,8 @@ let print_error e =
|
|||
let stdlib = [
|
||||
"sin"; "cos"; "tan";
|
||||
"deg"; "rad";
|
||||
"get_op_pre"; "set_op_pre";
|
||||
"get_op_assoc"; "set_op_assoc";
|
||||
]
|
||||
|> List.to_seq
|
||||
|> Seq.map (fun v -> v, External v)
|
||||
|
|
30
parser.ml
30
parser.ml
|
@ -191,11 +191,9 @@ and expr pre seq =
|
|||
seq |> oneof [
|
||||
ifexpr;
|
||||
let_value;
|
||||
oneof [apply; unary; value] @> binop pre;
|
||||
level;
|
||||
assoc;
|
||||
lambda;
|
||||
extern_value;
|
||||
oneof [apply; unary; value] @> binop pre;
|
||||
(* TODO: place error routine here *)
|
||||
]
|
||||
|
||||
|
@ -209,32 +207,6 @@ and let_value seq =
|
|||
let f, seq = mustbe (expr min_int) seq in
|
||||
Letin (id, e, f), seq
|
||||
|
||||
(* level := "level" {"get" | "set"} [op] *)
|
||||
and level seq =
|
||||
let _, seq = ident "level" seq in
|
||||
let id, seq = idents (S.of_list ["get"; "set"]) seq in
|
||||
let op, seq = operator seq in
|
||||
if id = "get" then
|
||||
Get_binop_pre op, seq
|
||||
else if id = "set" then
|
||||
let v, seq = value seq in
|
||||
Set_binop_pre (op, v), seq
|
||||
else
|
||||
failwith "Parser.level"
|
||||
|
||||
(* assoc := "assoc" {"get" | "set"} [op] *)
|
||||
and assoc seq =
|
||||
let _, seq = ident "assoc" seq in
|
||||
let id, seq = idents (S.of_list ["get"; "set"]) seq in
|
||||
let op, seq = operator seq in
|
||||
if id = "get" then
|
||||
Get_binop_aso op, seq
|
||||
else if id = "set" then
|
||||
let a, seq = idents (S.of_list ["left"; "right"]) seq in
|
||||
Set_binop_aso (op, a), seq
|
||||
else
|
||||
failwith "Parser.assoc"
|
||||
|
||||
(* lambda := "fun" [ident]+ "->" expr *)
|
||||
and lambda seq =
|
||||
let _, seq = ident "fun" seq in
|
||||
|
|
Loading…
Add table
Reference in a new issue