symbolic mathematics engine in OCaml with differentiation, integration, simplification, and numerical methods
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"