1use ast::predictive::convert;
2use cst::predictive::parse;
3use mathml::to_mathml;
4use tracing::debug;
5use transformations::transform;
6
7use crate::tokens::tokenize;
8
9pub mod ast;
10pub mod cst;
11pub mod mathml;
12pub mod transformations;
13pub mod tokens;
14
15pub fn to_math_ml(content: &str) -> String {
16 let tokens = tokenize(content);
17 debug!("Tokens: {tokens:#?}");
18 let cst = parse(&tokens);
19 debug!("CST: {cst:#?}");
20 let ast = convert(&cst);
21 debug!("AST: {ast:#?}");
22 let t_ast = transform(ast);
23 debug!("AST after transformation: {t_ast:#?}");
24
25 to_mathml(&t_ast)
26}
27
28#[cfg(test)]
29mod test {
30 use crate::to_math_ml;
32
33 macro_rules! test_parse {
34 ($name:ident, $input:expr, $expected:expr) => {
35 #[test]
36 fn $name() {
37 let mathml = to_math_ml($input);
39 assert_eq!(mathml, $expected);
40 }
41 };
42 }
43
44 test_parse!(
45 test_parse1,
46 "sum_b^a",
47 "<math display=\"block\"><munderover><mo>∑</mo><mi>b</mi><mi>a</mi></munderover></math>"
48 );
49
50 test_parse!(
51 test_frac,
52 "(a+b)/6",
53 "<math display=\"block\"><mfrac><mrow><mi>a</mi><mo>+</mo><mi>b</mi></mrow><mn>6</mn></mfrac></math>"
54 );
55
56 test_parse!(
57 test_vector,
58 "[[1,2], [2, 23]]",
59 "<math display=\"block\"><mrow><mo>[</mo><mtable columnlines=\"none\"><mtr><mtd><mn>1</mn></mtd><mtd><mn>2</mn></mtd></mtr><mtr><mtd><mn>2</mn></mtd><mtd><mn>23</mn></mtd></mtr></mtable><mo>]</mo></mrow></math>"
60 );
61
62 test_parse!(
63 test_vector_sum,
64 "[[1],[sum_1^2a]]",
65 "<math display=\"block\"><mrow><mo>[</mo><mtable columnlines=\"\"><mtr><mtd><mn>1</mn></mtd></mtr><mtr><mtd><munderover><mo>∑</mo><mn>1</mn><mn>2</mn></munderover><mi>a</mi></mtd></mtr></mtable><mo>]</mo></mrow></math>"
66 );
67
68 test_parse!(
69 test_sum,
70 "sum_1^2a",
71 "<math display=\"block\"><munderover><mo>∑</mo><mn>1</mn><mn>2</mn></munderover><mi>a</mi></math>"
72 );
73
74 test_parse!(
75 test_recusrsive_matrices,
76 "[[[[1],[2]]], [[[a], [b]]]]",
77 "<math display=\"block\"><mrow><mo>[</mo><mtable columnlines=\"\"><mtr><mtd><mrow><mo>[</mo><mtable columnlines=\"\"><mtr><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mn>2</mn></mtd></mtr></mtable><mo>]</mo></mrow></mtd></mtr><mtr><mtd><mrow><mo>[</mo><mtable columnlines=\"\"><mtr><mtd><mi>a</mi></mtd></mtr><mtr><mtd><mi>b</mi></mtd></mtr></mtable><mo>]</mo></mrow></mtd></mtr></mtable><mo>]</mo></mrow></math>"
78 );
79
80 test_parse!(
81 test_table_bar,
82 "[[1, |, 2], [a, b, c]]",
83 "<math display=\"block\"><mrow><mo>[</mo><mtable columnlines=\"solid none\"><mtr><mtd><mn>1</mn></mtd><mtd><mn>2</mn></mtd><mtd></mtd></mtr><mtr><mtd><mi>a</mi></mtd><mtd><mi>b</mi></mtd><mtd><mi>c</mi></mtd></mtr></mtable><mo>]</mo></mrow></math>"
84 );
85
86 test_parse!(
87 test_table_complex,
88 "{:[log_2 16 = 4,], [(2*5-3)/6, ]}",
89 "<math display=\"block\"><mrow><mtable columnlines=\"none\"><mtr><mtd><msub><mi>log</mi><mn>2</mn></msub><mn>16</mn><mo>=</mo><mn>4</mn></mtd><mtd></mtd></mtr><mtr><mtd><mfrac><mrow><mn>2</mn><mo>⋅</mo><mn>5</mn><mo>-</mo><mn>3</mn></mrow><mn>6</mn></mfrac></mtd><mtd></mtd></mtr></mtable><mo>}</mo></mrow></math>"
90 );
91
92 test_parse!(
93 test_text,
94 "\"b la \"",
95 "<math display=\"block\"><mtext>b la </mtext></math>"
96 );
97
98 test_parse!(
99 test_operations,
100 "a=2",
101 "<math display=\"block\"><mi>a</mi><mo>=</mo><mn>2</mn></math>"
102 );
103
104 test_parse!(
105 test_parse_group,
106 "(s)",
107 "<math display=\"block\"><mrow><mo>(</mo><mi>s</mi><mo>)</mo></mrow></math>"
108 );
109
110 test_parse!(
111 test_function,
112 "log_2 16 = 4",
113 "<math display=\"block\"><msub><mi>log</mi><mn>2</mn></msub><mn>16</mn><mo>=</mo><mn>4</mn></math>"
114 );
115
116 test_parse!(
117 test_fuzz_1,
118 "ȳ?",
119 "<math display=\"block\"><mi>ȳ</mi><mi>?</mi></math>"
120 );
121
122 test_parse!(
123 test_fuzz_2,
124 "{Ц\"2",
125 "<math display=\"block\"><mi>{</mi><mi>Ц</mi><mi>\"</mi><mn>2</mn></math>"
126 );
127
128 test_parse!(
129 test_fuzz_3,
130 "{]!(",
131 "<math display=\"block\"><mrow><mo>{</mo><mo>]</mo></mrow><mi>!</mi><mi>(</mi></math>"
132 );
133
134 test_parse!(
135 test_fuzz_4,
136 r#"Y{]
137 ]{:}]]]"#,
138 "<math display=\"block\"><mi>Y</mi><mrow><mo>{</mo><mo>]</mo></mrow><mi>\n</mi><mi>]</mi><mrow><mo>}</mo></mrow><mi>]</mi><mi>]</mi><mi>]</mi></math>"
139 );
140
141 test_parse!(
142 test_ubrace_with_nested_group,
143 "ubrace({(2x,+,17y,=,23),(x,-,y,=,5):})_(\"equation system\")",
144 "<math display=\"block\"><munder><munder><munder><mrow><mrow><mo>{</mo><mtable columnlines=\"none none none none\"><mtr><mtd><mn>2</mn><mi>x</mi></mtd><mtd><mo>+</mo></mtd><mtd><mn>17</mn><mi>y</mi></mtd><mtd><mo>=</mo></mtd><mtd><mn>23</mn></mtd></mtr><mtr><mtd><mi>x</mi></mtd><mtd><mo>-</mo></mtd><mtd><mi>y</mi></mtd><mtd><mo>=</mo></mtd><mtd><mn>5</mn></mtd></mtr></mtable></mrow></mrow><mo>⏟</mo></munder></munder><mrow><mtext>equation system</mtext></mrow></munder></math>"
145 );
146
147 test_parse!(
148 test_ubrace_with_appended_expression,
149 "obrace(ubrace(t)_(a))^ba",
150 "<math display=\"block\"><mover><mover><mover><mrow><munder><munder><munder><mrow><mi>t</mi></mrow><mo>⏟</mo></munder></munder><mrow><mi>a</mi></mrow></munder></mrow><mo>⏞</mo></mover></mover><mi>b</mi></mover><mi>a</mi></math>"
151 );
152
153 test_parse!(
154 test_div_symbol,
155 "-:",
156 "<math display=\"block\"><mo>÷</mo></math>"
157 );
158
159 test_parse!(
160 test_root,
161 "root (abc)(d) ",
162 "<math display=\"block\"><mroot><mrow><mi>d</mi></mrow><mrow><mi>a</mi><mi>b</mi><mi>c</mi></mrow></mroot></math>"
163 );
164}