Few things
This commit is contained in:
		
							parent
							
								
									dae562047c
								
							
						
					
					
						commit
						6444f413ca
					
				
					 4 changed files with 47 additions and 32 deletions
				
			
		
							
								
								
									
										3
									
								
								ast.ml
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								ast.ml
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -19,6 +19,7 @@ type t =
 | 
			
		|||
  | Value of typ
 | 
			
		||||
  | Binop of t * binop * t
 | 
			
		||||
  | Set_binop_pre of binop * t
 | 
			
		||||
  | Get_binop_pre of binop
 | 
			
		||||
 | 
			
		||||
let value v = Value v
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,5 +46,7 @@ let print ast =
 | 
			
		|||
      pr "(set_pre %s " (binop_to_string op);
 | 
			
		||||
      aux pre;
 | 
			
		||||
      pr ")"
 | 
			
		||||
    | Get_binop_pre op ->
 | 
			
		||||
      pr "(get_pre %s)" (binop_to_string op)
 | 
			
		||||
  in
 | 
			
		||||
  aux ast; pr "\n"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								eval.ml
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								eval.ml
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,15 +1,15 @@
 | 
			
		|||
open Ast
 | 
			
		||||
 | 
			
		||||
let intop f a b =
 | 
			
		||||
let arith f a b =
 | 
			
		||||
  match a, b with
 | 
			
		||||
  | Int a, Int b -> Int (f a b)
 | 
			
		||||
  | _ -> failwith "typecheck failed"
 | 
			
		||||
 | 
			
		||||
let binop_to_func = function
 | 
			
		||||
  | Add -> intop Int.add
 | 
			
		||||
  | Sub -> intop Int.sub
 | 
			
		||||
  | Mul -> intop Int.mul
 | 
			
		||||
  | Div -> intop Int.div
 | 
			
		||||
  | Add -> arith Int.add
 | 
			
		||||
  | Sub -> arith Int.sub
 | 
			
		||||
  | Mul -> arith Int.mul
 | 
			
		||||
  | Div -> arith Int.div
 | 
			
		||||
 | 
			
		||||
let rec eval = function
 | 
			
		||||
  | Value v -> v
 | 
			
		||||
| 
						 | 
				
			
			@ -18,5 +18,7 @@ let rec eval = function
 | 
			
		|||
    f (eval l) (eval r)
 | 
			
		||||
  | Set_binop_pre (op, l) ->
 | 
			
		||||
    let l = match eval l with Int n -> n | _ -> failwith "not int" in 
 | 
			
		||||
    Hashtbl.replace Parser.precedence (Ast.binop_to_string op) l;
 | 
			
		||||
    Hashtbl.replace Parser.precedence op l;
 | 
			
		||||
    Unit
 | 
			
		||||
  | Get_binop_pre op ->
 | 
			
		||||
    Int (Hashtbl.find Parser.precedence op)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										18
									
								
								main.ml
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								main.ml
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -16,15 +16,15 @@ let rec repl () : unit =
 | 
			
		|||
  printf "> ";
 | 
			
		||||
  let line = read_line () in
 | 
			
		||||
  if line <> "quit" then begin
 | 
			
		||||
    try
 | 
			
		||||
      line
 | 
			
		||||
      |> Lex.tokenize
 | 
			
		||||
      |> Parser.parse
 | 
			
		||||
      |> Eval.eval
 | 
			
		||||
      |> Ast.typ_to_string
 | 
			
		||||
      |> printf "%s\n"
 | 
			
		||||
    with
 | 
			
		||||
    | e -> print_error e;
 | 
			
		||||
    (try
 | 
			
		||||
       line
 | 
			
		||||
       |> Lex.tokenize
 | 
			
		||||
       |> Parser.parse
 | 
			
		||||
       |> Eval.eval
 | 
			
		||||
       |> Ast.typ_to_string
 | 
			
		||||
       |> printf "%s\n"
 | 
			
		||||
     with
 | 
			
		||||
     | e -> print_error e);
 | 
			
		||||
    repl ()
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										44
									
								
								parser.ml
									
										
									
									
									
								
							
							
						
						
									
										44
									
								
								parser.ml
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
open Ast
 | 
			
		||||
 | 
			
		||||
module S = Set.Make(String)
 | 
			
		||||
 | 
			
		||||
exception Expected of string
 | 
			
		||||
exception Unexpected_token of string
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -14,14 +16,14 @@ let unexpected_token t =
 | 
			
		|||
 * precedency, but infering precedence relation from the graph is hard
 | 
			
		||||
 * and the graph can be made to have loops, I just used plain table. *)
 | 
			
		||||
let precedence = [
 | 
			
		||||
  "+", 10;
 | 
			
		||||
  "-", 10;
 | 
			
		||||
  "*", 20;
 | 
			
		||||
  "/", 20;
 | 
			
		||||
  Add, 10;
 | 
			
		||||
  Sub, 10;
 | 
			
		||||
  Mul, 20;
 | 
			
		||||
  Div, 20;
 | 
			
		||||
] |> List.to_seq |> Hashtbl.of_seq
 | 
			
		||||
 | 
			
		||||
let precedence_of op =
 | 
			
		||||
  Hashtbl.find precedence (Ast.binop_to_string op)
 | 
			
		||||
  Hashtbl.find precedence op
 | 
			
		||||
 | 
			
		||||
let is_left_to_right = function
 | 
			
		||||
  | Add | Sub | Mul | Div -> true
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +54,7 @@ let parse ts =
 | 
			
		|||
        | Token.Plus | Minus | Asterisk | Slash as op ->
 | 
			
		||||
          let op = token_to_op op in
 | 
			
		||||
          let o = precedence_of op in 
 | 
			
		||||
          if o > pre then
 | 
			
		||||
          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
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +64,16 @@ let parse ts =
 | 
			
		|||
        | _ -> unexpected_token x
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
  and ident set seq =
 | 
			
		||||
    match seq () with
 | 
			
		||||
    | Seq.Nil ->
 | 
			
		||||
      let msg = "ident " ^ (S.elements set |> String.concat " or ") in
 | 
			
		||||
      expected msg
 | 
			
		||||
    | Seq.Cons (x, seq) -> begin match x with
 | 
			
		||||
        | Token.Ident id when S.mem id set -> id, seq
 | 
			
		||||
        | _ -> unexpected_token x
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
  and operator seq =
 | 
			
		||||
    match seq () with
 | 
			
		||||
    | Seq.Nil -> expected "operator"
 | 
			
		||||
| 
						 | 
				
			
			@ -69,22 +81,20 @@ let parse ts =
 | 
			
		|||
      try token_to_op x, seq with
 | 
			
		||||
      | _ -> expected "operator"
 | 
			
		||||
 | 
			
		||||
  and set_conf seq =
 | 
			
		||||
    match seq () with
 | 
			
		||||
    | Seq.Nil -> expected "ident"
 | 
			
		||||
    | Seq.Cons (x, seq) -> begin match x with
 | 
			
		||||
        | Token.Ident "level" ->
 | 
			
		||||
          let op, seq = operator seq in
 | 
			
		||||
          let v, seq = value seq in
 | 
			
		||||
          Set_binop_pre (op, v), seq
 | 
			
		||||
        | _ -> expected "argument"
 | 
			
		||||
      end
 | 
			
		||||
  and level seq =
 | 
			
		||||
    let id, seq = ident (S.of_list ["get"; "set"]) seq in
 | 
			
		||||
    let op, seq = operator seq in
 | 
			
		||||
    if id = "get" then
 | 
			
		||||
      Get_binop_pre op, seq
 | 
			
		||||
    else
 | 
			
		||||
      let v, seq = value seq in
 | 
			
		||||
      Set_binop_pre (op, v), seq
 | 
			
		||||
 | 
			
		||||
  and expr seq =
 | 
			
		||||
    match seq () with
 | 
			
		||||
    | Seq.Nil -> Value Unit, Seq.empty (* nop *)
 | 
			
		||||
    | Seq.Cons (x, s) -> begin match x with
 | 
			
		||||
        | Ident "set" -> set_conf s
 | 
			
		||||
        | Ident "level" -> level s
 | 
			
		||||
        | _ ->
 | 
			
		||||
          let left, seq = value seq in
 | 
			
		||||
          binop ~-1 left seq
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue