symbolic mathematics engine in OCaml with differentiation, integration, simplification, and numerical methods
17

Configure Feed

Select the types of activity you want to include in your feed.

leibniz / lib / parser.ml
2.7 kB 111 lines
1open Lexer 2open Expr 3 4type parse_state = { tokens : token list; mutable pos : int } 5 6let peek state = 7 if state.pos < List.length state.tokens then 8 List.nth state.tokens state.pos 9 else EOF 10 11let advance state = 12 state.pos <- state.pos + 1 13 14let expect state tok = 15 if peek state = tok then advance state 16 else failwith (Printf.sprintf "expected token") 17 18let rec parse_expr state = 19 parse_additive state 20 21and parse_additive state = 22 let left = ref (parse_multiplicative state) in 23 while peek state = Plus || peek state = Minus do 24 let op = peek state in 25 advance state; 26 let right = parse_multiplicative state in 27 left := if op = Plus then Add (!left, right) else Sub (!left, right) 28 done; 29 !left 30 31and parse_multiplicative state = 32 let left = ref (parse_power state) in 33 while peek state = Star || peek state = Slash do 34 let op = peek state in 35 advance state; 36 let right = parse_power state in 37 left := if op = Star then Mul (!left, right) else Div (!left, right) 38 done; 39 !left 40 41and parse_power state = 42 let left = parse_unary state in 43 if peek state = Caret then begin 44 advance state; 45 let right = parse_power state in 46 match left with 47 | Var "e" -> Exp right 48 | _ -> Pow (left, right) 49 end else left 50 51and parse_unary state = 52 match peek state with 53 | Minus -> 54 advance state; 55 Neg (parse_unary state) 56 | _ -> parse_primary state 57 58and parse_primary state = 59 match peek state with 60 | Num n -> 61 advance state; 62 Const n 63 | Var v -> 64 advance state; 65 Var v 66 | Ident "sin" -> 67 advance state; 68 expect state LParen; 69 let arg = parse_expr state in 70 expect state RParen; 71 Sin arg 72 | Ident "cos" -> 73 advance state; 74 expect state LParen; 75 let arg = parse_expr state in 76 expect state RParen; 77 Cos arg 78 | Ident "tan" -> 79 advance state; 80 expect state LParen; 81 let arg = parse_expr state in 82 expect state RParen; 83 Tan arg 84 | Ident "exp" -> 85 advance state; 86 expect state LParen; 87 let arg = parse_expr state in 88 expect state RParen; 89 Exp arg 90 | Ident "ln" -> 91 advance state; 92 expect state LParen; 93 let arg = parse_expr state in 94 expect state RParen; 95 Ln arg 96 | Ident "e" -> 97 advance state; 98 Const (exp 1.0) 99 | LParen -> 100 advance state; 101 let expr = parse_expr state in 102 expect state RParen; 103 expr 104 | _ -> failwith "unexpected token in primary" 105 106let parse str = 107 let tokens = tokenize str in 108 let state = { tokens; pos = 0 } in 109 let expr = parse_expr state in 110 if peek state = EOF then expr 111 else failwith "unexpected tokens after expression"