@pie-framework/math-validation 1.4.2 → 2.0.0-next.20261110063142
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +233 -0
- package/README.md +41 -110
- package/dist/conversion/ast-to-mathjs.d.ts +3 -0
- package/dist/conversion/error.d.ts +4 -0
- package/dist/conversion/flatten.d.ts +1 -0
- package/{lib → dist}/conversion/latex-to-ast.d.ts +14 -13
- package/{lib → dist}/conversion/lexer.d.ts +7 -7
- package/dist/difference.d.ts +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1594 -0
- package/dist/latex-equal.d.ts +2 -0
- package/dist/literal/index.d.ts +3 -0
- package/dist/log.d.ts +1 -0
- package/dist/mathjs.d.ts +11 -0
- package/{lib → dist}/node-sort.d.ts +1 -1
- package/dist/options.d.ts +13 -0
- package/{lib → dist}/symbolic/compare-compound-inequations.d.ts +4 -4
- package/{lib → dist}/symbolic/compare-equations.d.ts +1 -1
- package/dist/symbolic/index.d.ts +1 -0
- package/dist/symbolic/simplify.d.ts +2 -0
- package/{lib → dist}/symbolic/utils.d.ts +8 -4
- package/dist/value.d.ts +6 -0
- package/package.json +32 -53
- package/lib/conversion/ast-to-mathjs.d.ts +0 -12
- package/lib/conversion/ast-to-mathjs.js +0 -329
- package/lib/conversion/ast-to-mathjs.js.map +0 -1
- package/lib/conversion/error.d.ts +0 -5
- package/lib/conversion/error.js +0 -13
- package/lib/conversion/error.js.map +0 -1
- package/lib/conversion/flatten.d.ts +0 -12
- package/lib/conversion/flatten.js +0 -103
- package/lib/conversion/flatten.js.map +0 -1
- package/lib/conversion/latex-to-ast.js +0 -1479
- package/lib/conversion/latex-to-ast.js.map +0 -1
- package/lib/conversion/lexer.js +0 -135
- package/lib/conversion/lexer.js.map +0 -1
- package/lib/conversion/util.d.ts +0 -3
- package/lib/conversion/util.js +0 -36
- package/lib/conversion/util.js.map +0 -1
- package/lib/demo.d.ts +0 -4
- package/lib/demo.js +0 -173
- package/lib/demo.js.map +0 -1
- package/lib/difference.d.ts +0 -2
- package/lib/difference.js +0 -24
- package/lib/difference.js.map +0 -1
- package/lib/index.d.ts +0 -5
- package/lib/index.js +0 -9
- package/lib/index.js.map +0 -1
- package/lib/latex-equal.d.ts +0 -10
- package/lib/latex-equal.js +0 -41
- package/lib/latex-equal.js.map +0 -1
- package/lib/literal/index.d.ts +0 -10
- package/lib/literal/index.js +0 -22
- package/lib/literal/index.js.map +0 -1
- package/lib/log.d.ts +0 -1
- package/lib/log.js +0 -14
- package/lib/log.js.map +0 -1
- package/lib/mathjs.d.ts +0 -3
- package/lib/mathjs.js +0 -9
- package/lib/mathjs.js.map +0 -1
- package/lib/node-sort.js +0 -236
- package/lib/node-sort.js.map +0 -1
- package/lib/symbolic/compare-compound-inequations.js +0 -68
- package/lib/symbolic/compare-compound-inequations.js.map +0 -1
- package/lib/symbolic/compare-equations.js +0 -108
- package/lib/symbolic/compare-equations.js.map +0 -1
- package/lib/symbolic/index.d.ts +0 -4
- package/lib/symbolic/index.js +0 -215
- package/lib/symbolic/index.js.map +0 -1
- package/lib/symbolic/utils.js +0 -207
- package/lib/symbolic/utils.js.map +0 -1
|
@@ -1,1479 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.LatexToAst = exports.DEFAULT_OPTS = exports.latex_rules = exports.whitespace_rule = void 0;
|
|
7
|
-
const error_1 = require("./error");
|
|
8
|
-
const lexer_1 = __importDefault(require("./lexer"));
|
|
9
|
-
const flatten_1 = require("./flatten");
|
|
10
|
-
const log_1 = require("../log");
|
|
11
|
-
const log = log_1.logger("mv:latex-to-ast");
|
|
12
|
-
// UPDATETHIS: Delete or change to new license & package name
|
|
13
|
-
/*
|
|
14
|
-
* recursive descent parser for math expressions
|
|
15
|
-
*
|
|
16
|
-
* Copyright 2014-2017 by
|
|
17
|
-
* Jim Fowler <kisonecat@gmail.com>
|
|
18
|
-
* Duane Nykamp <nykamp@umn.edu>
|
|
19
|
-
*
|
|
20
|
-
* This file is part of a math-expressions library
|
|
21
|
-
*
|
|
22
|
-
* math-expressions is free software: you can redistribute
|
|
23
|
-
* it and/or modify it under the terms of the GNU General Public
|
|
24
|
-
* License as published by the Free Software Foundation, either
|
|
25
|
-
* version 3 of the License, or at your option any later version.
|
|
26
|
-
*
|
|
27
|
-
* math-expressions is distributed in the hope that it
|
|
28
|
-
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
29
|
-
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
30
|
-
* See the GNU General Public License for more details.
|
|
31
|
-
*
|
|
32
|
-
*/
|
|
33
|
-
// UPDATETHIS: Is this grammar still correct?
|
|
34
|
-
/* Grammar:
|
|
35
|
-
|
|
36
|
-
statement_list =
|
|
37
|
-
statement_list ',' statement |
|
|
38
|
-
statement
|
|
39
|
-
|
|
40
|
-
statement =
|
|
41
|
-
'\\dots' |
|
|
42
|
-
statement_a '|' statement_a |
|
|
43
|
-
statement_a 'MID' statement_a |
|
|
44
|
-
statement_a ':' statement_a
|
|
45
|
-
**** statement_a '|' statement_a
|
|
46
|
-
used with turning off '|' statement '|' in baseFactor
|
|
47
|
-
tried only after parse error encountered
|
|
48
|
-
|
|
49
|
-
statement_a =
|
|
50
|
-
statement_a 'OR' statement_b |
|
|
51
|
-
statement_b
|
|
52
|
-
|
|
53
|
-
statement_b =
|
|
54
|
-
statement_b 'AND' relation |
|
|
55
|
-
relation
|
|
56
|
-
|
|
57
|
-
relation =
|
|
58
|
-
'NOT' relation |
|
|
59
|
-
relation '=' expression |
|
|
60
|
-
relation 'NE' expression |
|
|
61
|
-
relation '<' expression |
|
|
62
|
-
relation '>' expression |
|
|
63
|
-
relation 'LE' expression |
|
|
64
|
-
relation 'GE' expression |
|
|
65
|
-
relation 'IN' expression |
|
|
66
|
-
relation 'NOTIN' expression |
|
|
67
|
-
relation 'NI' expression |
|
|
68
|
-
relation 'NOTNI' expression |
|
|
69
|
-
relation 'SUBSET' expression |
|
|
70
|
-
relation 'NOTSUBSET' expression |
|
|
71
|
-
relation 'SUPERSET' expression |
|
|
72
|
-
relation 'NOTSUPERSET' expression |
|
|
73
|
-
expression
|
|
74
|
-
|
|
75
|
-
expression =
|
|
76
|
-
expression '+' term |
|
|
77
|
-
expression '-' term |
|
|
78
|
-
expression 'UNION' term |
|
|
79
|
-
expression 'INTERSECT' term |
|
|
80
|
-
'+' term |
|
|
81
|
-
term
|
|
82
|
-
|
|
83
|
-
term =
|
|
84
|
-
term '*' factor |
|
|
85
|
-
term nonMinusFactor |
|
|
86
|
-
term '/' factor |
|
|
87
|
-
factor
|
|
88
|
-
|
|
89
|
-
baseFactor =
|
|
90
|
-
'(' statement_list ')' |
|
|
91
|
-
'[' statement_list ']' |
|
|
92
|
-
'{' statement_list '}' |
|
|
93
|
-
'LBRACE' statement_list 'RBRACE' |
|
|
94
|
-
'(' statement ',' statement ']' |
|
|
95
|
-
'[' statement ',' statement ')' |
|
|
96
|
-
'|' statement '|' |
|
|
97
|
-
\frac{statement}{statement} |
|
|
98
|
-
number |
|
|
99
|
-
variable |
|
|
100
|
-
modified_function '(' statement_list ')' |
|
|
101
|
-
modified_applied_function '(' statement_list ')' |
|
|
102
|
-
modified_function '{' statement_list '}' |
|
|
103
|
-
modified_applied_function '{' statement_list '}' |
|
|
104
|
-
modified_function |
|
|
105
|
-
modified_applied_function factor |
|
|
106
|
-
sqrt '[' statement ']' '{' statement '}' |
|
|
107
|
-
baseFactor '_' baseFactor |
|
|
108
|
-
*** modified_applied_function factor
|
|
109
|
-
allowed only if allowSimplifiedFunctionApplication==true
|
|
110
|
-
*** '|' statement '|'
|
|
111
|
-
allowed only at beginning of factor or if not currently in absolute value
|
|
112
|
-
|
|
113
|
-
modified_function =
|
|
114
|
-
function |
|
|
115
|
-
function '_' baseFactor |
|
|
116
|
-
function '_' baseFactor '^' factor |
|
|
117
|
-
function '^' factor
|
|
118
|
-
function "'"
|
|
119
|
-
function '_' baseFactor "'"
|
|
120
|
-
function '_' baseFactor "'" '^' factor
|
|
121
|
-
function "'" '^' factor
|
|
122
|
-
*** where the "'" after the functions can be repeated
|
|
123
|
-
|
|
124
|
-
modified_applied_function =
|
|
125
|
-
applied_function |
|
|
126
|
-
applied_function '_' baseFactor |
|
|
127
|
-
applied_function '_' baseFactor '^' factor |
|
|
128
|
-
applied_function '^' factor
|
|
129
|
-
applied_function "'"
|
|
130
|
-
applied_function '_' baseFactor "'"
|
|
131
|
-
applied_function '_' baseFactor "'" '^' factor
|
|
132
|
-
applied_function "'" '^' factor
|
|
133
|
-
*** where the "'" after the applied_functions can be repeated
|
|
134
|
-
|
|
135
|
-
nonMinusFactor =
|
|
136
|
-
baseFactor |
|
|
137
|
-
baseFactor '^' factor |
|
|
138
|
-
baseFactor '!' and/or "'" |
|
|
139
|
-
baseFactor '!' and/or "'" '^' factor|
|
|
140
|
-
*** where '!' and/or "'" indicates arbitrary sequence of "!" and/or "'"
|
|
141
|
-
|
|
142
|
-
factor =
|
|
143
|
-
'-' factor |
|
|
144
|
-
nonMinusFactor
|
|
145
|
-
|
|
146
|
-
*/
|
|
147
|
-
// Some of the latex commands that lead to spacing
|
|
148
|
-
exports.whitespace_rule = "\\s|\\\\,|\\\\!|\\\\ |\\\\>|\\\\;|\\\\:|\\\\quad\\b|\\\\qquad\\b";
|
|
149
|
-
// in order to parse as scientific notation, e.g., 3.2E-12 or .7E+3,
|
|
150
|
-
// it must be at the end or followed a comma, &, |, \|, ), }, \}, ], \\, or \end
|
|
151
|
-
const sci_notat_exp_regex = "(E[+\\-]?[0-9]+\\s*($|(?=\\,|&|\\||\\\\\\||\\)|\\}|\\\\}|\\]|\\\\\\\\|\\\\end)))?";
|
|
152
|
-
// TO-DO: ADD all mathjs built-in units?
|
|
153
|
-
const lengthUnit = "(mm|cm|km|ft|yd|mi|mmi|li|rd|angstrom|mil";
|
|
154
|
-
const volumeUnit = "|mL|ml|L|m3|in3|ft3|pt|qt|gal|bbl)";
|
|
155
|
-
const measurmentUnit = lengthUnit + volumeUnit + "{1}";
|
|
156
|
-
const numberWithCommasAsThousandsSeparator = "[0-9]{1,3}(\\,[0-9]{3})+(\\.[0-9]+)*";
|
|
157
|
-
// const latex_rules = [["\\\\neq(?![a-zA-Z])", "NE"]];
|
|
158
|
-
exports.latex_rules = [
|
|
159
|
-
[measurmentUnit, "UNIT"],
|
|
160
|
-
["\\$", "TEXT"],
|
|
161
|
-
["\\\\" + "\\$", "TEXT"],
|
|
162
|
-
["\\\\text{[a-zA-Z0-9\\s\\\\,\\\\.]+?}", "TEXT"],
|
|
163
|
-
["[0-9]+\\s*\\\\frac(?![a-zA-Z])", "MIXED_NUMBER"],
|
|
164
|
-
[numberWithCommasAsThousandsSeparator + sci_notat_exp_regex, "NUMBER"],
|
|
165
|
-
["[0-9]+(\\.[0-9]*)?" + sci_notat_exp_regex, "NUMBER"],
|
|
166
|
-
["\\.[0-9]+" + sci_notat_exp_regex, "NUMBER"],
|
|
167
|
-
[",", ","],
|
|
168
|
-
["\\*", "*"],
|
|
169
|
-
["\\×", "*"],
|
|
170
|
-
["\\•", "*"],
|
|
171
|
-
["\\·", "*"],
|
|
172
|
-
["\\/", "/"],
|
|
173
|
-
["\\÷", "/"],
|
|
174
|
-
["%", "PERCENT"],
|
|
175
|
-
["\\\\%", "PERCENT"],
|
|
176
|
-
["−", "-"],
|
|
177
|
-
["-", "-"],
|
|
178
|
-
["\\+", "+"],
|
|
179
|
-
["\\^", "^"],
|
|
180
|
-
["\\(", "("],
|
|
181
|
-
["\\\\left\\s*\\(", "("],
|
|
182
|
-
["\\\\bigl\\s*\\(", "("],
|
|
183
|
-
["\\\\Bigl\\s*\\(", "("],
|
|
184
|
-
["\\\\biggl\\s*\\(", "("],
|
|
185
|
-
["\\\\Biggl\\s*\\(", "("],
|
|
186
|
-
["\\)", ")"],
|
|
187
|
-
["\\\\right\\s*\\)", ")"],
|
|
188
|
-
["\\\\bigr\\s*\\)", ")"],
|
|
189
|
-
["\\\\Bigr\\s*\\)", ")"],
|
|
190
|
-
["\\\\biggr\\s*\\)", ")"],
|
|
191
|
-
["\\\\Biggr\\s*\\)", ")"],
|
|
192
|
-
["\\[", "["],
|
|
193
|
-
["\\\\left\\s*\\[", "["],
|
|
194
|
-
["\\\\bigl\\s*\\[", "["],
|
|
195
|
-
["\\\\Bigl\\s*\\[", "["],
|
|
196
|
-
["\\\\biggl\\s*\\[", "["],
|
|
197
|
-
["\\\\Biggl\\s*\\[", "["],
|
|
198
|
-
["\\]", "]"],
|
|
199
|
-
["\\\\right\\s*\\]", "]"],
|
|
200
|
-
["\\\\bigr\\s*\\]", "]"],
|
|
201
|
-
["\\\\Bigr\\s*\\]", "]"],
|
|
202
|
-
["\\\\biggr\\s*\\]", "]"],
|
|
203
|
-
["\\\\Biggr\\s*\\]", "]"],
|
|
204
|
-
["\\|", "|"],
|
|
205
|
-
["\\\\left\\s*\\|", "|L"],
|
|
206
|
-
["\\\\bigl\\s*\\|", "|L"],
|
|
207
|
-
["\\\\Bigl\\s*\\|", "|L"],
|
|
208
|
-
["\\\\biggl\\s*\\|", "|L"],
|
|
209
|
-
["\\\\Biggl\\s*\\|", "|L"],
|
|
210
|
-
["\\\\right\\s*\\|", "|"],
|
|
211
|
-
["\\\\bigr\\s*\\|", "|"],
|
|
212
|
-
["\\\\Bigr\\s*\\|", "|"],
|
|
213
|
-
["\\\\biggr\\s*\\|", "|"],
|
|
214
|
-
["\\\\Biggr\\s*\\|", "|"],
|
|
215
|
-
["\\\\big\\s*\\|", "|"],
|
|
216
|
-
["\\\\Big\\s*\\|", "|"],
|
|
217
|
-
["\\\\bigg\\s*\\|", "|"],
|
|
218
|
-
["\\\\Bigg\\s*\\|", "|"],
|
|
219
|
-
["{", "{"],
|
|
220
|
-
["}", "}"],
|
|
221
|
-
["\\\\{", "LBRACE"],
|
|
222
|
-
["\\\\left\\s*\\\\{", "LBRACE"],
|
|
223
|
-
["\\\\bigl\\s*\\\\{", "LBRACE"],
|
|
224
|
-
["\\\\Bigl\\s*\\\\{", "LBRACE"],
|
|
225
|
-
["\\\\biggl\\s*\\\\{", "LBRACE"],
|
|
226
|
-
["\\\\Biggl\\s*\\\\{", "LBRACE"],
|
|
227
|
-
["\\\\}", "RBRACE"],
|
|
228
|
-
["\\\\right\\s*\\\\}", "RBRACE"],
|
|
229
|
-
["\\\\bigr\\s*\\\\}", "RBRACE"],
|
|
230
|
-
["\\\\Bigr\\s*\\\\}", "RBRACE"],
|
|
231
|
-
["\\\\biggr\\s*\\\\}", "RBRACE"],
|
|
232
|
-
["\\\\Biggr\\s*\\\\}", "RBRACE"],
|
|
233
|
-
["\\\\cdot(?![a-zA-Z])", "*"],
|
|
234
|
-
["\\\\div(?![a-zA-Z])", "/"],
|
|
235
|
-
["\\\\times(?![a-zA-Z])", "*"],
|
|
236
|
-
["\\\\frac(?![a-zA-Z])", "FRAC"],
|
|
237
|
-
["°", "deg"],
|
|
238
|
-
["°", "deg"],
|
|
239
|
-
["\\\\degree", "deg"],
|
|
240
|
-
["\\\\deg", "deg"],
|
|
241
|
-
["\\\\grade", "grad"],
|
|
242
|
-
["\\\\gon", "grad"],
|
|
243
|
-
["\\\\grad", "grad"],
|
|
244
|
-
[":", ":"],
|
|
245
|
-
["\\\\mid", "MID"],
|
|
246
|
-
["\\\\vartheta(?![a-zA-Z])", "LATEXCOMMAND", "\\theta"],
|
|
247
|
-
["\\\\π", "LATEXCOMMAND", "\\pi"],
|
|
248
|
-
["\\\\varepsilon(?![a-zA-Z])", "LATEXCOMMAND", "\\epsilon"],
|
|
249
|
-
["\\\\varrho(?![a-zA-Z])", "LATEXCOMMAND", "\\rho"],
|
|
250
|
-
["\\\\varphi(?![a-zA-Z])", "LATEXCOMMAND", "\\phi"],
|
|
251
|
-
["\\\\infty(?![a-zA-Z])", "INFINITY"],
|
|
252
|
-
["\\\\Infinity(?![a-zA-Z])", "INFINITY"],
|
|
253
|
-
["\\\\sqrt(?![a-zA-Z])", "SQRT"],
|
|
254
|
-
["\\\\log(?![a-zA-Z])", "LOG"],
|
|
255
|
-
["\\\\ln(?![a-zA-Z])", "LN"],
|
|
256
|
-
["\\\\cosec", "LATEXCOMMAND", "\\csc"],
|
|
257
|
-
// inverse trigonometric functions
|
|
258
|
-
["\\\\sin\\^\\{-1}(?![a-zA-Z])", "LATEXCOMMAND", "\\asin"],
|
|
259
|
-
["\\\\cos\\^\\{-1}(?![a-zA-Z])", "LATEXCOMMAND", "\\acos"],
|
|
260
|
-
["\\\\tan\\^\\{-1}(?![a-zA-Z])", "LATEXCOMMAND", "\\atan"],
|
|
261
|
-
["\\\\cot\\^\\{-1}(?![a-zA-Z])", "LATEXCOMMAND", "\\acot"],
|
|
262
|
-
["\\\\sec\\^\\{-1}(?![a-zA-Z])", "LATEXCOMMAND", "\\asec"],
|
|
263
|
-
["\\\\csc\\^\\{-1}(?![a-zA-Z])", "LATEXCOMMAND", "\\acsc"],
|
|
264
|
-
["\\\\arsin(?![a-zA-Z])", "LATEXCOMMAND", "\\asin"],
|
|
265
|
-
["\\\\arcsin(?![a-zA-Z])", "LATEXCOMMAND", "\\asin"],
|
|
266
|
-
["\\\\arcos(?![a-zA-Z])", "LATEXCOMMAND", "\\acos"],
|
|
267
|
-
["\\\\arccos(?![a-zA-Z])", "LATEXCOMMAND", "\\acos"],
|
|
268
|
-
["\\\\artan(?![a-zA-Z])", "LATEXCOMMAND", "\\atan"],
|
|
269
|
-
["\\\\arctan(?![a-zA-Z])", "LATEXCOMMAND", "\\atan"],
|
|
270
|
-
["\\\\arcot(?![a-zA-Z])", "LATEXCOMMAND", "\\acot"],
|
|
271
|
-
["\\\\arccot(?![a-zA-Z])", "LATEXCOMMAND", "\\acot"],
|
|
272
|
-
["\\\\arsec(?![a-zA-Z])", "LATEXCOMMAND", "\\asec"],
|
|
273
|
-
["\\\\arcsec(?![a-zA-Z])", "LATEXCOMMAND", "\\asec"],
|
|
274
|
-
["\\\\arcsc(?![a-zA-Z])", "LATEXCOMMAND", "\\acsc"],
|
|
275
|
-
["\\\\arccsc(?![a-zA-Z])", "LATEXCOMMAND", "\\acsc"],
|
|
276
|
-
["\\\\land(?![a-zA-Z])", "AND"],
|
|
277
|
-
["\\\\wedge(?![a-zA-Z])", "AND"],
|
|
278
|
-
["\\\\lor(?![a-zA-Z])", "OR"],
|
|
279
|
-
["\\\\vee(?![a-zA-Z])", "OR"],
|
|
280
|
-
["\\\\lnot(?![a-zA-Z])", "NOT"],
|
|
281
|
-
["=", "="],
|
|
282
|
-
["≠", "NE"],
|
|
283
|
-
["\\\\neq(?![a-zA-Z])", "NE"],
|
|
284
|
-
["\\\\ne(?![a-zA-Z])", "NE"],
|
|
285
|
-
["\\\\not\\s*=", "NE"],
|
|
286
|
-
["\\\\leq(?![a-zA-Z])", "LE"],
|
|
287
|
-
["\\\\le(?![a-zA-Z])", "LE"],
|
|
288
|
-
["\\\\geq(?![a-zA-Z])", "GE"],
|
|
289
|
-
["\\\\ge(?![a-zA-Z])", "GE"],
|
|
290
|
-
["<", "<"],
|
|
291
|
-
["≤", "LE"],
|
|
292
|
-
["\\\\lt(?![a-zA-Z])", "<"],
|
|
293
|
-
[">", ">"],
|
|
294
|
-
["≥", "GE"],
|
|
295
|
-
["\\\\gt(?![a-zA-Z])", ">"],
|
|
296
|
-
// is approximately
|
|
297
|
-
["\\\\approx", "≈"],
|
|
298
|
-
["≈", "≈"],
|
|
299
|
-
// not almost equal to
|
|
300
|
-
["\\\\napprox", "≉"],
|
|
301
|
-
["≉", "≉"],
|
|
302
|
-
// is similar or equal to
|
|
303
|
-
["\\\\simeq", "≃"],
|
|
304
|
-
["≃", "≃"],
|
|
305
|
-
// is similar to
|
|
306
|
-
["\\\\sim", "~"],
|
|
307
|
-
["~", "~"],
|
|
308
|
-
// is not similar to
|
|
309
|
-
["\\\\nsim", "≁"],
|
|
310
|
-
["≁", "≁"],
|
|
311
|
-
// is congruent to
|
|
312
|
-
["\\\\cong", "≅"],
|
|
313
|
-
["≅", "≅"],
|
|
314
|
-
// is not congurent to
|
|
315
|
-
["\\\\ncong", "≆"],
|
|
316
|
-
["≆", "≆"],
|
|
317
|
-
// inverse f and g functions are treated as text
|
|
318
|
-
["f\\^\\{-1}", "TEXT"],
|
|
319
|
-
["g\\^\\{-1}", "TEXT"],
|
|
320
|
-
["\\\\in(?![a-zA-Z])", "IN"],
|
|
321
|
-
["\\\\notin(?![a-zA-Z])", "NOTIN"],
|
|
322
|
-
["\\\\not\\s*\\\\in(?![a-zA-Z])", "NOTIN"],
|
|
323
|
-
["\\\\ni(?![a-zA-Z])", "NI"],
|
|
324
|
-
["\\\\not\\s*\\\\ni(?![a-zA-Z])", "NOTNI"],
|
|
325
|
-
["\\\\subset(?![a-zA-Z])", "SUBSET"],
|
|
326
|
-
["\\\\not\\s*\\\\subset(?![a-zA-Z])", "NOTSUBSET"],
|
|
327
|
-
["\\\\supset(?![a-zA-Z])", "SUPERSET"],
|
|
328
|
-
["\\\\not\\s*\\\\supset(?![a-zA-Z])", "NOTSUPERSET"],
|
|
329
|
-
["\\\\cup(?![a-zA-Z])", "UNION"],
|
|
330
|
-
["\\\\cap(?![a-zA-Z])", "INTERSECT"],
|
|
331
|
-
["!", "!"],
|
|
332
|
-
["'", "'"],
|
|
333
|
-
["_", "_"],
|
|
334
|
-
["&", "&"],
|
|
335
|
-
["\\\\ldots", "LDOTS"],
|
|
336
|
-
["\\\\\\\\", "LINEBREAK"],
|
|
337
|
-
["\\\\begin\\s*{\\s*[a-zA-Z0-9]+\\s*}", "BEGINENVIRONMENT"],
|
|
338
|
-
["\\\\end\\s*{\\s*[a-zA-Z0-9]+\\s*}", "ENDENVIRONMENT"],
|
|
339
|
-
["\\\\var\\s*{\\s*[a-zA-Z0-9]+\\s*}", "VARMULTICHAR"],
|
|
340
|
-
["\\\\[a-zA-Z]+(?![a-zA-Z])", "LATEXCOMMAND"],
|
|
341
|
-
["[a-zA-Z]", "VAR"],
|
|
342
|
-
];
|
|
343
|
-
// defaults for parsers if not overridden by context
|
|
344
|
-
// if true, allowed applied functions to omit parentheses around argument
|
|
345
|
-
// if false, omitting parentheses will lead to a Parse Error
|
|
346
|
-
const allowSimplifiedFunctionApplicationDefault = true;
|
|
347
|
-
// allowed multicharacter latex symbols
|
|
348
|
-
// in addition to the below applied function symbols
|
|
349
|
-
const allowedLatexSymbolsDefault = [
|
|
350
|
-
"alpha",
|
|
351
|
-
"beta",
|
|
352
|
-
"gamma",
|
|
353
|
-
"Gamma",
|
|
354
|
-
"delta",
|
|
355
|
-
"Delta",
|
|
356
|
-
"epsilon",
|
|
357
|
-
"zeta",
|
|
358
|
-
"eta",
|
|
359
|
-
"theta",
|
|
360
|
-
"Theta",
|
|
361
|
-
"iota",
|
|
362
|
-
"kappa",
|
|
363
|
-
"lambda",
|
|
364
|
-
"Lambda",
|
|
365
|
-
"mu",
|
|
366
|
-
"nu",
|
|
367
|
-
"xi",
|
|
368
|
-
"Xi",
|
|
369
|
-
"pi",
|
|
370
|
-
"Pi",
|
|
371
|
-
"rho",
|
|
372
|
-
"sigma",
|
|
373
|
-
"Sigma",
|
|
374
|
-
"tau",
|
|
375
|
-
"Tau",
|
|
376
|
-
"upsilon",
|
|
377
|
-
"Upsilon",
|
|
378
|
-
"phi",
|
|
379
|
-
"Phi",
|
|
380
|
-
"chi",
|
|
381
|
-
"psi",
|
|
382
|
-
"Psi",
|
|
383
|
-
"omega",
|
|
384
|
-
"Omega",
|
|
385
|
-
"partial",
|
|
386
|
-
];
|
|
387
|
-
// Applied functions must be given an argument so that
|
|
388
|
-
// they are applied to the argument
|
|
389
|
-
const appliedFunctionSymbolsDefault = [
|
|
390
|
-
"abs",
|
|
391
|
-
"exp",
|
|
392
|
-
"log",
|
|
393
|
-
"ln",
|
|
394
|
-
"log10",
|
|
395
|
-
"sign",
|
|
396
|
-
"sqrt",
|
|
397
|
-
"erf",
|
|
398
|
-
"acos",
|
|
399
|
-
"acosh",
|
|
400
|
-
"acot",
|
|
401
|
-
"acoth",
|
|
402
|
-
"acsc",
|
|
403
|
-
"acsch",
|
|
404
|
-
"asec",
|
|
405
|
-
"asech",
|
|
406
|
-
"asin",
|
|
407
|
-
"asinh",
|
|
408
|
-
"atan",
|
|
409
|
-
"atanh",
|
|
410
|
-
"cos",
|
|
411
|
-
"cosh",
|
|
412
|
-
"cot",
|
|
413
|
-
"coth",
|
|
414
|
-
"csc",
|
|
415
|
-
"csch",
|
|
416
|
-
"sec",
|
|
417
|
-
"sech",
|
|
418
|
-
"sin",
|
|
419
|
-
"sinh",
|
|
420
|
-
"tan",
|
|
421
|
-
"tanh",
|
|
422
|
-
"arg",
|
|
423
|
-
];
|
|
424
|
-
const missingFactorDefaultBehavior = function (token, e) {
|
|
425
|
-
throw e;
|
|
426
|
-
};
|
|
427
|
-
exports.DEFAULT_OPTS = {
|
|
428
|
-
allowSimplifiedFunctionApplication: allowSimplifiedFunctionApplicationDefault,
|
|
429
|
-
allowedLatexSymbols: allowedLatexSymbolsDefault,
|
|
430
|
-
appliedFunctionSymbols: appliedFunctionSymbolsDefault,
|
|
431
|
-
/**
|
|
432
|
-
* Functions could have an argument, in which case they are applied
|
|
433
|
-
* or, if they don't have an argument in parentheses, then they are treated
|
|
434
|
-
* like a variable, except that trailing ^ and ' have higher precedence
|
|
435
|
-
*/
|
|
436
|
-
functionSymbols: ["f", "g"],
|
|
437
|
-
parseLeibnizNotation: true,
|
|
438
|
-
missingFactor: missingFactorDefaultBehavior,
|
|
439
|
-
unknownCommandBehavior: "error",
|
|
440
|
-
};
|
|
441
|
-
class LatexToAst {
|
|
442
|
-
constructor(opts) {
|
|
443
|
-
this.opts = Object.assign(Object.assign({}, exports.DEFAULT_OPTS), opts);
|
|
444
|
-
if (this.opts.unknownCommandBehavior !== "error" &&
|
|
445
|
-
this.opts.unknownCommandBehavior !== "passthrough") {
|
|
446
|
-
throw new Error("Unknown behavior for unknown command: " +
|
|
447
|
-
this.opts.unknownCommandBehavior);
|
|
448
|
-
}
|
|
449
|
-
this.lexer = new lexer_1.default(exports.latex_rules, exports.whitespace_rule);
|
|
450
|
-
}
|
|
451
|
-
advance(params) {
|
|
452
|
-
this.token = this.lexer.advance(params);
|
|
453
|
-
if (this.token.token_type === "INVALID") {
|
|
454
|
-
throw new error_1.ParseError("Invalid symbol '" + this.token.original_text + "'", this.lexer.location);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
return_state() {
|
|
458
|
-
return {
|
|
459
|
-
lexer_state: this.lexer.return_state(),
|
|
460
|
-
token: Object.assign({}, this.token),
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
set_state(state) {
|
|
464
|
-
this.lexer.set_state(state.lexer_state);
|
|
465
|
-
this.token = Object.assign({}, state.token);
|
|
466
|
-
}
|
|
467
|
-
convert(input, pars) {
|
|
468
|
-
this.lexer.set_input(input);
|
|
469
|
-
this.advance();
|
|
470
|
-
var result = this.statement_list(pars);
|
|
471
|
-
if (this.token.token_type !== "EOF") {
|
|
472
|
-
throw new error_1.ParseError("Invalid location of '" + this.token.original_text + "'", this.lexer.location);
|
|
473
|
-
}
|
|
474
|
-
return flatten_1.flatten(result);
|
|
475
|
-
}
|
|
476
|
-
statement_list(pars) {
|
|
477
|
-
var list = [this.statement(pars)];
|
|
478
|
-
while (this.token.token_type === ",") {
|
|
479
|
-
this.advance();
|
|
480
|
-
list.push(this.statement(pars));
|
|
481
|
-
}
|
|
482
|
-
if (list.length > 1)
|
|
483
|
-
list = ["list"].concat(list);
|
|
484
|
-
else
|
|
485
|
-
list = list[0];
|
|
486
|
-
return list;
|
|
487
|
-
}
|
|
488
|
-
statement(opts = {}) {
|
|
489
|
-
const { inside_absolute_value = 0, unknownCommands = "error" } = opts;
|
|
490
|
-
// \ldots can be a statement by itself
|
|
491
|
-
if (this.token.token_type === "LDOTS") {
|
|
492
|
-
this.advance();
|
|
493
|
-
return ["ldots"];
|
|
494
|
-
}
|
|
495
|
-
var original_state;
|
|
496
|
-
try {
|
|
497
|
-
original_state = this.return_state();
|
|
498
|
-
let lhs = this.statement_a({
|
|
499
|
-
inside_absolute_value: inside_absolute_value,
|
|
500
|
-
unknownCommands: unknownCommands,
|
|
501
|
-
});
|
|
502
|
-
//console.log("lhs:", lhs);
|
|
503
|
-
if (this.token.token_type !== ":" && this.token.token_type !== "MID")
|
|
504
|
-
return lhs;
|
|
505
|
-
let operator = this.token.token_type === ":" ? ":" : "|";
|
|
506
|
-
this.advance();
|
|
507
|
-
let rhs = this.statement_a({ unknownCommands: unknownCommands });
|
|
508
|
-
return [operator, lhs, rhs];
|
|
509
|
-
}
|
|
510
|
-
catch (e) {
|
|
511
|
-
try {
|
|
512
|
-
// if ran into problem parsing statement
|
|
513
|
-
// then try again with ignoring absolute value
|
|
514
|
-
// and then interpreting bar as a binary operator
|
|
515
|
-
// return state to what it was before attempting to parse statement
|
|
516
|
-
this.set_state(original_state);
|
|
517
|
-
let lhs = this.statement_a({ parse_absolute_value: false });
|
|
518
|
-
//console.log("lhs:", lhs);
|
|
519
|
-
if (this.token.token_type[0] !== "|") {
|
|
520
|
-
throw e;
|
|
521
|
-
}
|
|
522
|
-
this.advance();
|
|
523
|
-
let rhs = this.statement_a({ parse_absolute_value: false });
|
|
524
|
-
return ["|", lhs, rhs];
|
|
525
|
-
}
|
|
526
|
-
catch (e2) {
|
|
527
|
-
throw e; // throw original error
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
statement_a(opts = {}) {
|
|
532
|
-
const { inside_absolute_value = 0, parse_absolute_value = true, unknownCommands, } = opts;
|
|
533
|
-
var lhs = this.statement_b({
|
|
534
|
-
inside_absolute_value: inside_absolute_value,
|
|
535
|
-
parse_absolute_value: parse_absolute_value,
|
|
536
|
-
unknownCommands: unknownCommands,
|
|
537
|
-
});
|
|
538
|
-
while (this.token.token_type === "OR") {
|
|
539
|
-
let operation = this.token.token_type.toLowerCase();
|
|
540
|
-
this.advance();
|
|
541
|
-
let rhs = this.statement_b({
|
|
542
|
-
inside_absolute_value: inside_absolute_value,
|
|
543
|
-
parse_absolute_value: parse_absolute_value,
|
|
544
|
-
unknownCommands: unknownCommands,
|
|
545
|
-
});
|
|
546
|
-
lhs = [operation, lhs, rhs];
|
|
547
|
-
}
|
|
548
|
-
return lhs;
|
|
549
|
-
}
|
|
550
|
-
statement_b(params) {
|
|
551
|
-
// split AND into second statement to give higher precedence than OR
|
|
552
|
-
var lhs = this.relation(params);
|
|
553
|
-
while (this.token.token_type === "AND") {
|
|
554
|
-
let operation = this.token.token_type.toLowerCase();
|
|
555
|
-
this.advance();
|
|
556
|
-
let rhs = this.relation(params);
|
|
557
|
-
lhs = [operation, lhs, rhs];
|
|
558
|
-
}
|
|
559
|
-
return lhs;
|
|
560
|
-
}
|
|
561
|
-
relation(params) {
|
|
562
|
-
if (this.token.token_type === "NOT" || this.token.token_type === "!") {
|
|
563
|
-
this.advance();
|
|
564
|
-
return ["not", this.relation(params)];
|
|
565
|
-
}
|
|
566
|
-
var lhs = this.expression(params);
|
|
567
|
-
let relationalToken = (token) => token === "<" ||
|
|
568
|
-
token === "LE" ||
|
|
569
|
-
token === ">" ||
|
|
570
|
-
token === "GE" ||
|
|
571
|
-
token === "NE";
|
|
572
|
-
while (this.token.token_type === "=" ||
|
|
573
|
-
this.token.token_type === "NE" ||
|
|
574
|
-
this.token.token_type === "<" ||
|
|
575
|
-
this.token.token_type === ">" ||
|
|
576
|
-
this.token.token_type === "LE" ||
|
|
577
|
-
this.token.token_type === "GE" ||
|
|
578
|
-
this.token.token_type === "IN" ||
|
|
579
|
-
this.token.token_type === "NOTIN" ||
|
|
580
|
-
this.token.token_type === "NI" ||
|
|
581
|
-
this.token.token_type === "NOTNI" ||
|
|
582
|
-
this.token.token_type === "SUBSET" ||
|
|
583
|
-
this.token.token_type === "NOTSUBSET" ||
|
|
584
|
-
this.token.token_type === "SUPERSET" ||
|
|
585
|
-
this.token.token_type === "NOTSUPERSET" ||
|
|
586
|
-
this.token.token_type === "≈" ||
|
|
587
|
-
this.token.token_type === "≉" ||
|
|
588
|
-
this.token.token_type === "~" ||
|
|
589
|
-
this.token.token_type === "≃" ||
|
|
590
|
-
this.token.token_type === "≁" ||
|
|
591
|
-
this.token.token_type === "≅" ||
|
|
592
|
-
this.token.token_type === "≆") {
|
|
593
|
-
let operation = this.token.token_type.toLowerCase();
|
|
594
|
-
let inequality_sequence = relationalToken(this.token.token_type);
|
|
595
|
-
this.advance();
|
|
596
|
-
let rhs = this.expression(params);
|
|
597
|
-
const relationalOperator = (operatorSign) => {
|
|
598
|
-
switch (operatorSign) {
|
|
599
|
-
case "<":
|
|
600
|
-
return "smaller";
|
|
601
|
-
case "LE":
|
|
602
|
-
case "le":
|
|
603
|
-
return "smallerEq";
|
|
604
|
-
case ">":
|
|
605
|
-
return "larger";
|
|
606
|
-
case "GE":
|
|
607
|
-
case "ge":
|
|
608
|
-
return "largerEq";
|
|
609
|
-
case "NE":
|
|
610
|
-
case "ne":
|
|
611
|
-
return "unequal";
|
|
612
|
-
}
|
|
613
|
-
};
|
|
614
|
-
if (inequality_sequence && relationalToken(this.token.token_type)) {
|
|
615
|
-
let strict = ["tuple"];
|
|
616
|
-
strict.push(relationalOperator(operation));
|
|
617
|
-
let args = ["tuple", lhs, rhs];
|
|
618
|
-
while (relationalToken(this.token.token_type)) {
|
|
619
|
-
strict.push(relationalOperator(this.token.token_type));
|
|
620
|
-
this.advance();
|
|
621
|
-
args.push(this.expression(params));
|
|
622
|
-
}
|
|
623
|
-
lhs = ["relational", args, strict];
|
|
624
|
-
}
|
|
625
|
-
else if (operation === "=") {
|
|
626
|
-
lhs = [operation, lhs, rhs];
|
|
627
|
-
// check for sequence of multiple =
|
|
628
|
-
while (this.token.token_type === "=") {
|
|
629
|
-
this.advance();
|
|
630
|
-
lhs.push(this.expression(params));
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
else {
|
|
634
|
-
lhs = [operation, lhs, rhs];
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
return lhs;
|
|
638
|
-
}
|
|
639
|
-
expression(params) {
|
|
640
|
-
if (this.token.token_type === "+")
|
|
641
|
-
this.advance();
|
|
642
|
-
let negative_begin = false;
|
|
643
|
-
if (this.token.token_type === "-") {
|
|
644
|
-
negative_begin = true;
|
|
645
|
-
this.advance();
|
|
646
|
-
}
|
|
647
|
-
var lhs = this.term(params);
|
|
648
|
-
if (negative_begin) {
|
|
649
|
-
lhs = ["-", lhs];
|
|
650
|
-
}
|
|
651
|
-
while (this.token.token_type === "+" ||
|
|
652
|
-
this.token.token_type === "-" ||
|
|
653
|
-
this.token.token_type === "UNION" ||
|
|
654
|
-
this.token.token_type === "INTERSECT") {
|
|
655
|
-
let operation = this.token.token_type.toLowerCase();
|
|
656
|
-
let negative = false;
|
|
657
|
-
if (this.token.token_type === "-") {
|
|
658
|
-
operation = "+";
|
|
659
|
-
negative = true;
|
|
660
|
-
this.advance();
|
|
661
|
-
}
|
|
662
|
-
else {
|
|
663
|
-
this.advance();
|
|
664
|
-
// @ts-ignore
|
|
665
|
-
if (operation === "+" && this.token.token_type === "-") {
|
|
666
|
-
negative = true;
|
|
667
|
-
this.advance();
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
let rhs = this.term(params);
|
|
671
|
-
if (negative) {
|
|
672
|
-
rhs = ["-", rhs];
|
|
673
|
-
}
|
|
674
|
-
lhs = [operation, lhs, rhs];
|
|
675
|
-
}
|
|
676
|
-
return lhs;
|
|
677
|
-
}
|
|
678
|
-
term(params) {
|
|
679
|
-
var lhs;
|
|
680
|
-
try {
|
|
681
|
-
lhs = this.factor(params);
|
|
682
|
-
}
|
|
683
|
-
catch (e) {
|
|
684
|
-
lhs = this.opts.missingFactor(this.token, e);
|
|
685
|
-
lhs = Number.isFinite(lhs) ? lhs : 0;
|
|
686
|
-
}
|
|
687
|
-
var keepGoing = false;
|
|
688
|
-
do {
|
|
689
|
-
keepGoing = false;
|
|
690
|
-
if (this.token.token_type === "PERCENT") {
|
|
691
|
-
this.advance();
|
|
692
|
-
lhs = ["%", lhs];
|
|
693
|
-
keepGoing = true;
|
|
694
|
-
}
|
|
695
|
-
else if (this.token.token_type === "*") {
|
|
696
|
-
this.advance();
|
|
697
|
-
lhs = ["*", lhs, this.factor(params)];
|
|
698
|
-
keepGoing = true;
|
|
699
|
-
}
|
|
700
|
-
else if (this.token.token_type === "/") {
|
|
701
|
-
this.advance();
|
|
702
|
-
lhs = ["/", lhs, this.factor(params)];
|
|
703
|
-
keepGoing = true;
|
|
704
|
-
}
|
|
705
|
-
else {
|
|
706
|
-
// this is the one case where a | could indicate a closing absolute value
|
|
707
|
-
let params2 = Object.assign({}, params);
|
|
708
|
-
params2.allow_absolute_value_closing = true;
|
|
709
|
-
let rhs = this.nonMinusFactor(params2);
|
|
710
|
-
if (rhs !== false) {
|
|
711
|
-
lhs = ["*", lhs, rhs];
|
|
712
|
-
keepGoing = true;
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
} while (keepGoing);
|
|
716
|
-
return lhs;
|
|
717
|
-
}
|
|
718
|
-
factor(params) {
|
|
719
|
-
// console.log("factor:", this.token);
|
|
720
|
-
// console.log("before: lexer state:", this.lexer.return_state());
|
|
721
|
-
if (this.token.token_type === "-") {
|
|
722
|
-
this.advance();
|
|
723
|
-
return ["-", this.factor(params)];
|
|
724
|
-
}
|
|
725
|
-
var result = this.nonMinusFactor(params);
|
|
726
|
-
// console.log("result", result);
|
|
727
|
-
if (result === false) {
|
|
728
|
-
if (this.token.token_type === "EOF") {
|
|
729
|
-
throw new error_1.ParseError("Unexpected end of input", this.lexer.location);
|
|
730
|
-
}
|
|
731
|
-
else {
|
|
732
|
-
//console.log("lexer state:", this.lexer.return_state());
|
|
733
|
-
throw new error_1.ParseError("Invalid location of '" + this.token.original_text + "'", this.lexer.location);
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
else {
|
|
737
|
-
return result;
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
nonMinusFactor(params) {
|
|
741
|
-
let result = this.baseFactor(params);
|
|
742
|
-
// allow arbitrary sequence of factorials
|
|
743
|
-
if (this.token.token_type === "!" || this.token.token_type === "'") {
|
|
744
|
-
if (result === false)
|
|
745
|
-
throw new error_1.ParseError("Invalid location of " + this.token.token_type, this.lexer.location);
|
|
746
|
-
while (this.token.token_type === "!" || this.token.token_type === "'") {
|
|
747
|
-
if (this.token.token_type === "!")
|
|
748
|
-
result = ["apply", "factorial", result];
|
|
749
|
-
else
|
|
750
|
-
result = ["prime", result];
|
|
751
|
-
this.advance();
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
if (this.token.token_type === "^") {
|
|
755
|
-
if (result === false) {
|
|
756
|
-
throw new error_1.ParseError("Invalid location of ^", this.lexer.location);
|
|
757
|
-
}
|
|
758
|
-
this.advance();
|
|
759
|
-
// do not allow absolute value closing here
|
|
760
|
-
let params2 = Object.assign({}, params);
|
|
761
|
-
delete params2.allow_absolute_value_closing;
|
|
762
|
-
delete params2.inside_absolute_value;
|
|
763
|
-
return ["^", result, this.factor(params2)];
|
|
764
|
-
}
|
|
765
|
-
return result;
|
|
766
|
-
}
|
|
767
|
-
fraction({ inside_absolute_value = 0, parse_absolute_value = true, allow_absolute_value_closing = false, unknownCommands = "error", }) {
|
|
768
|
-
this.advance();
|
|
769
|
-
if (this.token.token_type !== "{") {
|
|
770
|
-
throw new error_1.ParseError("Expecting {", this.lexer.location);
|
|
771
|
-
}
|
|
772
|
-
this.advance();
|
|
773
|
-
// determine if may be a derivative in Leibniz notation
|
|
774
|
-
if (this.opts.parseLeibnizNotation) {
|
|
775
|
-
let original_state = this.return_state();
|
|
776
|
-
let r = this.leibniz_notation();
|
|
777
|
-
if (r) {
|
|
778
|
-
// successfully parsed derivative in Leibniz notation, so return
|
|
779
|
-
return r;
|
|
780
|
-
}
|
|
781
|
-
else {
|
|
782
|
-
// didn't find a properly format Leibniz notation
|
|
783
|
-
// so reset state and continue
|
|
784
|
-
this.set_state(original_state);
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
let numerator = this.statement({
|
|
788
|
-
parse_absolute_value: parse_absolute_value,
|
|
789
|
-
unknownCommands: unknownCommands,
|
|
790
|
-
});
|
|
791
|
-
// @ts-ignore
|
|
792
|
-
if (this.token.token_type !== "}") {
|
|
793
|
-
throw new error_1.ParseError("Expecting }", this.lexer.location);
|
|
794
|
-
}
|
|
795
|
-
this.advance();
|
|
796
|
-
if (this.token.token_type !== "{") {
|
|
797
|
-
throw new error_1.ParseError("Expecting {", this.lexer.location);
|
|
798
|
-
}
|
|
799
|
-
this.advance();
|
|
800
|
-
let denominator = this.statement({
|
|
801
|
-
parse_absolute_value: parse_absolute_value,
|
|
802
|
-
unknownCommands: unknownCommands,
|
|
803
|
-
});
|
|
804
|
-
if (this.token.token_type !== "}") {
|
|
805
|
-
throw new error_1.ParseError("Expecting }", this.lexer.location);
|
|
806
|
-
}
|
|
807
|
-
this.advance();
|
|
808
|
-
return ["/", numerator, denominator];
|
|
809
|
-
}
|
|
810
|
-
baseFactor({ inside_absolute_value = 0, parse_absolute_value = true, allow_absolute_value_closing = false, unknownCommands = "error", } = {}) {
|
|
811
|
-
var result = false;
|
|
812
|
-
if (this.token.token_type === "MIXED_NUMBER") {
|
|
813
|
-
try {
|
|
814
|
-
const t = this.token.token_text.split("\\\\frac");
|
|
815
|
-
const numberString = t[0].trim();
|
|
816
|
-
const number = parseInt(numberString, 10);
|
|
817
|
-
const f = this.fraction({});
|
|
818
|
-
// this is correct, to convert a mixed number to an improper fraction we have to multiply the demoninator by the whole number and add the result to the numerator
|
|
819
|
-
return ["+", number, f];
|
|
820
|
-
}
|
|
821
|
-
catch (e) {
|
|
822
|
-
throw new error_1.ParseError(`Mixed number parsing failed: ${e.message}`);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
if (this.token.token_type === "FRAC") {
|
|
826
|
-
return this.fraction({});
|
|
827
|
-
}
|
|
828
|
-
if (this.token.token_type === "TEXT") {
|
|
829
|
-
const text = this.token.original_text.replace(/[[\]\\]/g, "");
|
|
830
|
-
this.advance();
|
|
831
|
-
return text.toString();
|
|
832
|
-
}
|
|
833
|
-
if (this.token.token_type === "BEGINENVIRONMENT") {
|
|
834
|
-
let environment = /\\begin\s*{\s*([a-zA-Z0-9]+)\s*}/.exec(this.token.token_text)[1];
|
|
835
|
-
if (["matrix", "pmatrix", "bmatrix"].includes(environment)) {
|
|
836
|
-
let n_rows = 0;
|
|
837
|
-
let n_cols = 0;
|
|
838
|
-
let all_rows = [];
|
|
839
|
-
let row = [];
|
|
840
|
-
let n_this_row = 0;
|
|
841
|
-
let last_token = this.token.token_type;
|
|
842
|
-
this.advance();
|
|
843
|
-
//@ts-ignore
|
|
844
|
-
while (this.token.token_type !== "ENDENVIRONMENT") {
|
|
845
|
-
//@ts-ignore
|
|
846
|
-
if (this.token.token_type === "&") {
|
|
847
|
-
if (last_token === "&" || last_token === "LINEBREAK") {
|
|
848
|
-
// blank entry, let entry be zero
|
|
849
|
-
row.push(0);
|
|
850
|
-
n_this_row += 1;
|
|
851
|
-
}
|
|
852
|
-
last_token = this.token.token_type;
|
|
853
|
-
this.advance();
|
|
854
|
-
//@ts-ignore
|
|
855
|
-
}
|
|
856
|
-
else if (this.token.token_type === "LINEBREAK") {
|
|
857
|
-
if (last_token === "&" || last_token === "LINEBREAK") {
|
|
858
|
-
// blank entry, let entry be zero
|
|
859
|
-
row.push(0);
|
|
860
|
-
n_this_row += 1;
|
|
861
|
-
}
|
|
862
|
-
all_rows.push(row);
|
|
863
|
-
if (n_this_row > n_cols)
|
|
864
|
-
n_cols = n_this_row;
|
|
865
|
-
n_rows += 1;
|
|
866
|
-
n_this_row = 0;
|
|
867
|
-
row = [];
|
|
868
|
-
last_token = this.token.token_type;
|
|
869
|
-
this.advance();
|
|
870
|
-
}
|
|
871
|
-
else {
|
|
872
|
-
if (last_token === "&" ||
|
|
873
|
-
last_token === "LINEBREAK" ||
|
|
874
|
-
"BEGINENVIRONMENT") {
|
|
875
|
-
row.push(this.statement({
|
|
876
|
-
parse_absolute_value: parse_absolute_value,
|
|
877
|
-
unknownCommands: unknownCommands,
|
|
878
|
-
}));
|
|
879
|
-
n_this_row += 1;
|
|
880
|
-
last_token = " ";
|
|
881
|
-
}
|
|
882
|
-
else {
|
|
883
|
-
throw new error_1.ParseError("Invalid location of " + this.token.original_text, this.lexer.location);
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
// token is ENDENVIRONMENT
|
|
888
|
-
let environment2 = /\\end\s*{\s*([a-zA-Z0-9]+)\s*}/.exec(this.token.token_text)[1];
|
|
889
|
-
if (environment2 !== environment) {
|
|
890
|
-
throw new error_1.ParseError("Expecting \\end{" + environment + "}", this.lexer.location);
|
|
891
|
-
}
|
|
892
|
-
// add last row
|
|
893
|
-
if (last_token === "&") {
|
|
894
|
-
// blank entry, let entry be zero
|
|
895
|
-
row.push(0);
|
|
896
|
-
n_this_row += 1;
|
|
897
|
-
}
|
|
898
|
-
all_rows.push(row);
|
|
899
|
-
if (n_this_row > n_cols)
|
|
900
|
-
n_cols = n_this_row;
|
|
901
|
-
n_rows += 1;
|
|
902
|
-
this.advance();
|
|
903
|
-
// create matrix
|
|
904
|
-
// @ts-ignore
|
|
905
|
-
result = ["matrix", ["tuple", n_rows, n_cols]];
|
|
906
|
-
let body = ["tuple"];
|
|
907
|
-
for (let r of all_rows) {
|
|
908
|
-
let new_row = ["tuple"].concat(r);
|
|
909
|
-
//@ts-ignore
|
|
910
|
-
for (let i = r.length; i < n_cols; i += 1)
|
|
911
|
-
new_row.push(0);
|
|
912
|
-
// @ts-ignore
|
|
913
|
-
body.push(new_row);
|
|
914
|
-
}
|
|
915
|
-
// @ts-ignore
|
|
916
|
-
result.push(body);
|
|
917
|
-
return result;
|
|
918
|
-
}
|
|
919
|
-
else {
|
|
920
|
-
throw new error_1.ParseError("Unrecognized environment " + environment, this.lexer.location);
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
if (this.token.token_type === "NUMBER") {
|
|
924
|
-
// @ts-ignore
|
|
925
|
-
result = this.token.token_text.replace(/,/g, "");
|
|
926
|
-
let removeLeadingZeros = (result) => result.indexOf(".") >= 0
|
|
927
|
-
? result.replace(/^[0]*([0-9])(.*)/, "$1$2")
|
|
928
|
-
: result.replace(/0*([1-9]*)/, "$1");
|
|
929
|
-
// @ts-ignore
|
|
930
|
-
let parsedNumber = result === "0" ? result : removeLeadingZeros(result);
|
|
931
|
-
if (parsedNumber.startsWith(".")) {
|
|
932
|
-
parsedNumber = "0" + parsedNumber;
|
|
933
|
-
}
|
|
934
|
-
const number = parseFloat(parsedNumber);
|
|
935
|
-
/** trailing zero number ['tzn', number, countOfZeros] */
|
|
936
|
-
// @ts-ignore
|
|
937
|
-
if (parsedNumber !== number.toString()) {
|
|
938
|
-
const p = number.toString();
|
|
939
|
-
// @ts-ignore
|
|
940
|
-
const sub = parsedNumber
|
|
941
|
-
// @ts-ignore
|
|
942
|
-
.substring(p.length)
|
|
943
|
-
.split("")
|
|
944
|
-
.filter((c) => c === "0");
|
|
945
|
-
const noOfTrailingZeros = sub.length;
|
|
946
|
-
// @ts-ignore
|
|
947
|
-
result = ["tzn", number, noOfTrailingZeros];
|
|
948
|
-
}
|
|
949
|
-
else {
|
|
950
|
-
// @ts-ignore
|
|
951
|
-
result = number;
|
|
952
|
-
}
|
|
953
|
-
this.advance();
|
|
954
|
-
}
|
|
955
|
-
else if (this.token.token_type === "INFINITY") {
|
|
956
|
-
// @ts-ignore
|
|
957
|
-
result = Infinity;
|
|
958
|
-
this.advance();
|
|
959
|
-
}
|
|
960
|
-
else if (this.token.token_type === "deg") {
|
|
961
|
-
// conversion of degrees in radians - angle configuration
|
|
962
|
-
const degree = 355 / (180 * 113);
|
|
963
|
-
// @ts-ignore
|
|
964
|
-
result = ["*", degree];
|
|
965
|
-
this.advance();
|
|
966
|
-
}
|
|
967
|
-
else if (this.token.token_type === "grad") {
|
|
968
|
-
//conversion of gradians in radians - angle configuration
|
|
969
|
-
const gradian = 355 / (200 * 113);
|
|
970
|
-
// @ts-ignore
|
|
971
|
-
result = ["*", gradian];
|
|
972
|
-
this.advance();
|
|
973
|
-
}
|
|
974
|
-
else if (this.token.token_type === "UNIT") {
|
|
975
|
-
// @ts-ignore
|
|
976
|
-
result = ["unit", this.token.token_text];
|
|
977
|
-
this.advance();
|
|
978
|
-
}
|
|
979
|
-
else if (this.token.token_type === "SQRT") {
|
|
980
|
-
this.advance();
|
|
981
|
-
let root = 2;
|
|
982
|
-
let parameter;
|
|
983
|
-
// @ts-ignore
|
|
984
|
-
if (this.token.token_type === "[") {
|
|
985
|
-
this.advance();
|
|
986
|
-
parameter = this.statement({
|
|
987
|
-
parse_absolute_value: parse_absolute_value,
|
|
988
|
-
unknownCommands: unknownCommands,
|
|
989
|
-
});
|
|
990
|
-
if (this.token.token_type !== "]") {
|
|
991
|
-
throw new error_1.ParseError("Expecting ]", this.lexer.location);
|
|
992
|
-
}
|
|
993
|
-
this.advance();
|
|
994
|
-
root = parameter;
|
|
995
|
-
}
|
|
996
|
-
// @ts-ignore
|
|
997
|
-
if (this.token.token_type == "{") {
|
|
998
|
-
this.advance();
|
|
999
|
-
parameter = this.statement({
|
|
1000
|
-
parse_absolute_value: parse_absolute_value,
|
|
1001
|
-
unknownCommands: unknownCommands,
|
|
1002
|
-
});
|
|
1003
|
-
// @ts-ignore
|
|
1004
|
-
if (this.token.token_type !== "}") {
|
|
1005
|
-
throw new error_1.ParseError("Expecting }", this.lexer.location);
|
|
1006
|
-
}
|
|
1007
|
-
this.advance();
|
|
1008
|
-
}
|
|
1009
|
-
else {
|
|
1010
|
-
parameter = this.statement({
|
|
1011
|
-
parse_absolute_value: parse_absolute_value,
|
|
1012
|
-
unknownCommands: unknownCommands,
|
|
1013
|
-
});
|
|
1014
|
-
}
|
|
1015
|
-
// @ts-ignore
|
|
1016
|
-
if (root === 2)
|
|
1017
|
-
result = ["apply", "sqrt", parameter];
|
|
1018
|
-
// @ts-ignore
|
|
1019
|
-
else
|
|
1020
|
-
result = ["^", parameter, ["/", 1, root]];
|
|
1021
|
-
}
|
|
1022
|
-
else if (this.token.token_type === "LOG" ||
|
|
1023
|
-
this.token.token_type === "LN") {
|
|
1024
|
-
// function log(x) in JS returns ln(x)
|
|
1025
|
-
let base = this.token.token_type === "LOG" ? 10 : "e";
|
|
1026
|
-
let parameter;
|
|
1027
|
-
this.advance();
|
|
1028
|
-
// @ts-ignore
|
|
1029
|
-
if (this.token.token_type === "_") {
|
|
1030
|
-
this.advance();
|
|
1031
|
-
// @ts-ignore
|
|
1032
|
-
if (this.token.token_type === "{") {
|
|
1033
|
-
this.advance();
|
|
1034
|
-
parameter = this.statement({
|
|
1035
|
-
parse_absolute_value: parse_absolute_value,
|
|
1036
|
-
unknownCommands: unknownCommands,
|
|
1037
|
-
});
|
|
1038
|
-
if (this.token.token_type !== "}") {
|
|
1039
|
-
throw new error_1.ParseError("Expecting }", this.lexer.location);
|
|
1040
|
-
}
|
|
1041
|
-
this.advance();
|
|
1042
|
-
base = parameter;
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
// @ts-ignore
|
|
1046
|
-
if (this.token.token_type == "(") {
|
|
1047
|
-
this.advance();
|
|
1048
|
-
parameter = this.statement({
|
|
1049
|
-
parse_absolute_value: parse_absolute_value,
|
|
1050
|
-
unknownCommands: unknownCommands,
|
|
1051
|
-
});
|
|
1052
|
-
if (this.token.token_type !== ")") {
|
|
1053
|
-
throw new error_1.ParseError("Expecting )", this.lexer.location);
|
|
1054
|
-
}
|
|
1055
|
-
this.advance();
|
|
1056
|
-
}
|
|
1057
|
-
else {
|
|
1058
|
-
parameter = this.token.token_text;
|
|
1059
|
-
this.advance();
|
|
1060
|
-
}
|
|
1061
|
-
// @ts-ignore
|
|
1062
|
-
if (base === 10)
|
|
1063
|
-
result = ["apply", "log", ["tuple", parameter, base]];
|
|
1064
|
-
// @ts-ignore
|
|
1065
|
-
else if (base === "e")
|
|
1066
|
-
result = ["apply", "log", parameter];
|
|
1067
|
-
// @ts-ignore
|
|
1068
|
-
else
|
|
1069
|
-
result = ["apply", "log", ["tuple", parameter, base]];
|
|
1070
|
-
}
|
|
1071
|
-
else if (this.token.token_type === "VAR" ||
|
|
1072
|
-
this.token.token_type === "LATEXCOMMAND" ||
|
|
1073
|
-
this.token.token_type === "VARMULTICHAR") {
|
|
1074
|
-
// @ts-ignore
|
|
1075
|
-
result = this.token.token_text;
|
|
1076
|
-
if (this.token.token_type === "LATEXCOMMAND") {
|
|
1077
|
-
// @ts-ignore
|
|
1078
|
-
result = result.slice(1);
|
|
1079
|
-
const isKnownCommand =
|
|
1080
|
-
// @ts-ignore
|
|
1081
|
-
this.opts.appliedFunctionSymbols.includes(result) ||
|
|
1082
|
-
// @ts-ignore
|
|
1083
|
-
this.opts.functionSymbols.includes(result) ||
|
|
1084
|
-
// @ts-ignore
|
|
1085
|
-
this.opts.allowedLatexSymbols.includes(result);
|
|
1086
|
-
if (!isKnownCommand) {
|
|
1087
|
-
if (this.unknownCommandBehavior === "error") {
|
|
1088
|
-
throw new error_1.ParseError("Unrecognized latex command " + this.token.original_text, this.lexer.location);
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
else if (this.token.token_type === "VARMULTICHAR") {
|
|
1093
|
-
// strip out name of variable from \var command
|
|
1094
|
-
// @ts-ignore
|
|
1095
|
-
result = /\\var\s*\{\s*([a-zA-Z0-9]+)\s*\}/.exec(result)[1];
|
|
1096
|
-
}
|
|
1097
|
-
if (
|
|
1098
|
-
// @ts-ignore
|
|
1099
|
-
this.opts.appliedFunctionSymbols.includes(result) ||
|
|
1100
|
-
// @ts-ignore
|
|
1101
|
-
this.opts.functionSymbols.includes(result)) {
|
|
1102
|
-
let must_apply = false;
|
|
1103
|
-
// @ts-ignore
|
|
1104
|
-
if (this.opts.appliedFunctionSymbols.includes(result))
|
|
1105
|
-
must_apply = true;
|
|
1106
|
-
this.advance();
|
|
1107
|
-
// @ts-ignore
|
|
1108
|
-
if (this.token.token_type === "_") {
|
|
1109
|
-
this.advance();
|
|
1110
|
-
let subresult = this.baseFactor({
|
|
1111
|
-
parse_absolute_value: parse_absolute_value,
|
|
1112
|
-
});
|
|
1113
|
-
// since baseFactor could return false, must check
|
|
1114
|
-
if (subresult === false) {
|
|
1115
|
-
if (this.token.token_type === "EOF") {
|
|
1116
|
-
throw new error_1.ParseError("Unexpected end of input", this.lexer.location);
|
|
1117
|
-
}
|
|
1118
|
-
else {
|
|
1119
|
-
throw new error_1.ParseError("Invalid location of '" + this.token.original_text + "'", this.lexer.location);
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
// @ts-ignore
|
|
1123
|
-
result = ["_", result, subresult];
|
|
1124
|
-
}
|
|
1125
|
-
// @ts-ignore
|
|
1126
|
-
while (this.token.token_type === "'") {
|
|
1127
|
-
// @ts-ignore
|
|
1128
|
-
result = ["prime", result];
|
|
1129
|
-
this.advance();
|
|
1130
|
-
}
|
|
1131
|
-
// @ts-ignore
|
|
1132
|
-
if (this.token.token_type === "^") {
|
|
1133
|
-
this.advance();
|
|
1134
|
-
// @ts-ignore
|
|
1135
|
-
result = [
|
|
1136
|
-
"^",
|
|
1137
|
-
result,
|
|
1138
|
-
this.factor({ parse_absolute_value: parse_absolute_value }),
|
|
1139
|
-
];
|
|
1140
|
-
}
|
|
1141
|
-
// @ts-ignore
|
|
1142
|
-
if (this.token.token_type === "{" || this.token.token_type === "(") {
|
|
1143
|
-
let expected_right;
|
|
1144
|
-
if (this.token.token_type === "{")
|
|
1145
|
-
expected_right = "}";
|
|
1146
|
-
else
|
|
1147
|
-
expected_right = ")";
|
|
1148
|
-
this.advance();
|
|
1149
|
-
let parameters = this.statement_list();
|
|
1150
|
-
if (this.token.token_type !== expected_right) {
|
|
1151
|
-
throw new error_1.ParseError("Expecting " + expected_right, this.lexer.location);
|
|
1152
|
-
}
|
|
1153
|
-
this.advance();
|
|
1154
|
-
// @ts-ignore
|
|
1155
|
-
result = ["apply", result, parameters];
|
|
1156
|
-
}
|
|
1157
|
-
else {
|
|
1158
|
-
// if was an applied function symbol,
|
|
1159
|
-
// cannot omit argument
|
|
1160
|
-
if (must_apply) {
|
|
1161
|
-
// @ts-ignore
|
|
1162
|
-
if (!this.opts.allowSimplifiedFunctionApplication)
|
|
1163
|
-
throw new error_1.ParseError("Expecting ( after function", this.lexer.location);
|
|
1164
|
-
// if allow simplied function application
|
|
1165
|
-
// let the argument be the next factor
|
|
1166
|
-
// @ts-ignore
|
|
1167
|
-
result = [
|
|
1168
|
-
"apply",
|
|
1169
|
-
result,
|
|
1170
|
-
this.factor({ parse_absolute_value: parse_absolute_value }),
|
|
1171
|
-
];
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
}
|
|
1175
|
-
else {
|
|
1176
|
-
this.advance();
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
else if (this.token.token_type === "(" ||
|
|
1180
|
-
this.token.token_type === "[" ||
|
|
1181
|
-
this.token.token_type === "{" ||
|
|
1182
|
-
this.token.token_type === "LBRACE") {
|
|
1183
|
-
let token_left = this.token.token_type;
|
|
1184
|
-
let expected_right, other_right;
|
|
1185
|
-
if (this.token.token_type === "(") {
|
|
1186
|
-
expected_right = ")";
|
|
1187
|
-
other_right = "]";
|
|
1188
|
-
}
|
|
1189
|
-
else if (this.token.token_type === "[") {
|
|
1190
|
-
expected_right = "]";
|
|
1191
|
-
other_right = ")";
|
|
1192
|
-
}
|
|
1193
|
-
else if (this.token.token_type === "{") {
|
|
1194
|
-
expected_right = "}";
|
|
1195
|
-
other_right = null;
|
|
1196
|
-
}
|
|
1197
|
-
else {
|
|
1198
|
-
expected_right = "RBRACE";
|
|
1199
|
-
other_right = null;
|
|
1200
|
-
}
|
|
1201
|
-
this.advance();
|
|
1202
|
-
// @ts-ignore
|
|
1203
|
-
result = this.statement_list();
|
|
1204
|
-
let n_elements = 1;
|
|
1205
|
-
if (result[0] === "list") {
|
|
1206
|
-
// @ts-ignore
|
|
1207
|
-
n_elements = result.length - 1;
|
|
1208
|
-
}
|
|
1209
|
-
if (this.token.token_type !== expected_right) {
|
|
1210
|
-
if (n_elements !== 2 || other_right === null) {
|
|
1211
|
-
throw new error_1.ParseError("Expecting " + expected_right, this.lexer.location);
|
|
1212
|
-
}
|
|
1213
|
-
else if (this.token.token_type !== other_right) {
|
|
1214
|
-
throw new error_1.ParseError("Expecting ) or ]", this.lexer.location);
|
|
1215
|
-
}
|
|
1216
|
-
// half-open interval
|
|
1217
|
-
result[0] = "list";
|
|
1218
|
-
// @ts-ignore
|
|
1219
|
-
result = ["interval", result];
|
|
1220
|
-
let closed;
|
|
1221
|
-
if (token_left === "(")
|
|
1222
|
-
closed = ["list", false, true];
|
|
1223
|
-
else
|
|
1224
|
-
closed = ["list", true, false];
|
|
1225
|
-
// @ts-ignore
|
|
1226
|
-
result.push(closed);
|
|
1227
|
-
}
|
|
1228
|
-
else if (n_elements >= 2) {
|
|
1229
|
-
if (token_left === "(" || token_left === "{") {
|
|
1230
|
-
result[0] = "list";
|
|
1231
|
-
}
|
|
1232
|
-
else if (token_left === "[") {
|
|
1233
|
-
result[0] = "list";
|
|
1234
|
-
}
|
|
1235
|
-
else {
|
|
1236
|
-
result[0] = "set";
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
else if (token_left === "LBRACE") {
|
|
1240
|
-
if (result[0] === "|" || result[0] === ":") {
|
|
1241
|
-
// @ts-ignore
|
|
1242
|
-
result = ["set", result]; // set builder notation
|
|
1243
|
-
}
|
|
1244
|
-
else {
|
|
1245
|
-
// @ts-ignore
|
|
1246
|
-
result = ["set", result]; // singleton set
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
this.advance();
|
|
1250
|
-
}
|
|
1251
|
-
else if (this.token.token_type[0] === "|" &&
|
|
1252
|
-
parse_absolute_value &&
|
|
1253
|
-
(inside_absolute_value === 0 ||
|
|
1254
|
-
!allow_absolute_value_closing ||
|
|
1255
|
-
this.token.token_type[1] === "L")) {
|
|
1256
|
-
// allow the opening of an absolute value here if either
|
|
1257
|
-
// - we aren't already inside an absolute value (inside_absolute_value==0),
|
|
1258
|
-
// - we don't allows an absolute value closing, or
|
|
1259
|
-
// - the | was marked as a left
|
|
1260
|
-
// otherwise, skip this token so that will drop out the factor (and entire statement)
|
|
1261
|
-
// to where the absolute value will close
|
|
1262
|
-
inside_absolute_value += 1;
|
|
1263
|
-
this.advance();
|
|
1264
|
-
result = this.statement({
|
|
1265
|
-
inside_absolute_value: inside_absolute_value,
|
|
1266
|
-
unknownCommands: unknownCommands,
|
|
1267
|
-
});
|
|
1268
|
-
// @ts-ignore
|
|
1269
|
-
result = ["apply", "abs", result];
|
|
1270
|
-
if (this.token.token_type !== "|") {
|
|
1271
|
-
throw new error_1.ParseError("Expecting |", this.lexer.location);
|
|
1272
|
-
}
|
|
1273
|
-
this.advance();
|
|
1274
|
-
}
|
|
1275
|
-
if (this.token.token_type === "_") {
|
|
1276
|
-
if (result === false) {
|
|
1277
|
-
throw new error_1.ParseError("Invalid location of _", this.lexer.location);
|
|
1278
|
-
}
|
|
1279
|
-
this.advance();
|
|
1280
|
-
let subresult = this.baseFactor({
|
|
1281
|
-
parse_absolute_value: parse_absolute_value,
|
|
1282
|
-
});
|
|
1283
|
-
if (subresult === false) {
|
|
1284
|
-
// @ts-ignore
|
|
1285
|
-
if (this.token.token_type === "EOF") {
|
|
1286
|
-
throw new error_1.ParseError("Unexpected end of input", this.lexer.location);
|
|
1287
|
-
}
|
|
1288
|
-
else {
|
|
1289
|
-
throw new error_1.ParseError("Invalid location of '" + this.token.original_text + "'", this.lexer.location);
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
return ["_", result, subresult];
|
|
1293
|
-
}
|
|
1294
|
-
return result;
|
|
1295
|
-
}
|
|
1296
|
-
leibniz_notation() {
|
|
1297
|
-
// attempt to find and return a derivative in Leibniz notation
|
|
1298
|
-
// if unsuccessful, return false
|
|
1299
|
-
var result = this.token.token_text;
|
|
1300
|
-
let deriv_symbol = "";
|
|
1301
|
-
let n_deriv = 1;
|
|
1302
|
-
let var1 = "";
|
|
1303
|
-
let var2s = [];
|
|
1304
|
-
let var2_exponents = [];
|
|
1305
|
-
if (this.token.token_type === "LATEXCOMMAND" &&
|
|
1306
|
-
result.slice(1) === "partial")
|
|
1307
|
-
deriv_symbol = "∂";
|
|
1308
|
-
else if (this.token.token_type === "VAR" && result === "d")
|
|
1309
|
-
deriv_symbol = "d";
|
|
1310
|
-
else
|
|
1311
|
-
return false;
|
|
1312
|
-
// since have just a d or ∂
|
|
1313
|
-
// one option is that have a ^ followed by an integer next possibly in {}
|
|
1314
|
-
this.advance();
|
|
1315
|
-
// @ts-ignore
|
|
1316
|
-
if (this.token.token_type === "^") {
|
|
1317
|
-
// so far have d or ∂ followed by ^
|
|
1318
|
-
// must be followed by an integer
|
|
1319
|
-
this.advance();
|
|
1320
|
-
let in_braces = false;
|
|
1321
|
-
if (this.token.token_type === "{") {
|
|
1322
|
-
in_braces = true;
|
|
1323
|
-
this.advance();
|
|
1324
|
-
}
|
|
1325
|
-
if (this.token.token_type !== "NUMBER") {
|
|
1326
|
-
return false;
|
|
1327
|
-
}
|
|
1328
|
-
n_deriv = parseFloat(this.token.token_text);
|
|
1329
|
-
if (!Number.isInteger(n_deriv)) {
|
|
1330
|
-
return false;
|
|
1331
|
-
}
|
|
1332
|
-
// found integer,
|
|
1333
|
-
// if in braces, require }
|
|
1334
|
-
if (in_braces) {
|
|
1335
|
-
this.advance();
|
|
1336
|
-
if (this.token.token_type !== "}") {
|
|
1337
|
-
return false;
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
this.advance();
|
|
1341
|
-
}
|
|
1342
|
-
// since have a d or ∂, optionally followed by ^ and integer
|
|
1343
|
-
// next we must have:
|
|
1344
|
-
// a VAR, a VARMULTICHAR, or a LATEXCOMMAND that is in allowedLatexSymbols
|
|
1345
|
-
if (this.token.token_type === "VAR")
|
|
1346
|
-
var1 = this.token.token_text;
|
|
1347
|
-
// @ts-ignore
|
|
1348
|
-
else if (this.token.token_type === "VARMULTICHAR") {
|
|
1349
|
-
// strip out name of variable from \var command
|
|
1350
|
-
var1 = /\\var\s*\{\s*([a-zA-Z0-9]+)\s*\}/.exec(this.token.token_text)[1];
|
|
1351
|
-
}
|
|
1352
|
-
else if (this.token.token_type === "LATEXCOMMAND") {
|
|
1353
|
-
result = this.token.token_text.slice(1);
|
|
1354
|
-
// @ts-ignore
|
|
1355
|
-
if (this.opts.allowedLatexSymbols.includes(result))
|
|
1356
|
-
var1 = result;
|
|
1357
|
-
else
|
|
1358
|
-
return false;
|
|
1359
|
-
}
|
|
1360
|
-
// Finished numerator.
|
|
1361
|
-
// Next need a } and {
|
|
1362
|
-
this.advance();
|
|
1363
|
-
// @ts-ignore
|
|
1364
|
-
if (this.token.token_type !== "}") {
|
|
1365
|
-
return false;
|
|
1366
|
-
}
|
|
1367
|
-
this.advance();
|
|
1368
|
-
if (this.token.token_type !== "{") {
|
|
1369
|
-
return false;
|
|
1370
|
-
}
|
|
1371
|
-
else {
|
|
1372
|
-
this.advance();
|
|
1373
|
-
}
|
|
1374
|
-
// In denominator now
|
|
1375
|
-
// find sequence of
|
|
1376
|
-
// derivative symbol followed by
|
|
1377
|
-
// - a VAR, a VARMULTICHAR, or a LATEXCOMMAND that is in allowedLatexSymbols
|
|
1378
|
-
// optionally followed by a ^ and an integer
|
|
1379
|
-
// End when sum of exponents meets or exceeds n_deriv
|
|
1380
|
-
let exponent_sum = 0;
|
|
1381
|
-
while (true) {
|
|
1382
|
-
// next must be
|
|
1383
|
-
// - a VAR equal to deriv_symbol="d" or \partial when deriv_symbol = "∂"
|
|
1384
|
-
if (!((deriv_symbol === "d" &&
|
|
1385
|
-
this.token.token_type === "VAR" &&
|
|
1386
|
-
this.token.token_text === "d") ||
|
|
1387
|
-
(deriv_symbol === "∂" &&
|
|
1388
|
-
this.token.token_type === "LATEXCOMMAND" &&
|
|
1389
|
-
this.token.token_text.slice(1) === "partial"))) {
|
|
1390
|
-
return false;
|
|
1391
|
-
}
|
|
1392
|
-
// followed by
|
|
1393
|
-
// - a VAR, a VARMULTICHAR, or a LATEXCOMMAND that is in allowedLatexSymbols
|
|
1394
|
-
this.advance();
|
|
1395
|
-
if (this.token.token_type === "VAR")
|
|
1396
|
-
var2s.push(this.token.token_text);
|
|
1397
|
-
else if (this.token.token_type === "VARMULTICHAR") {
|
|
1398
|
-
// strip out name of variable from \var command
|
|
1399
|
-
var2s.push(/\\var\s*\{\s*([a-zA-Z0-9]+)\s*\}/.exec(this.token.token_text)[1]);
|
|
1400
|
-
}
|
|
1401
|
-
else if (this.token.token_type === "LATEXCOMMAND") {
|
|
1402
|
-
let r = this.token.token_text.slice(1);
|
|
1403
|
-
// @ts-ignore
|
|
1404
|
-
if (this.allowedLatexSymbols.includes(r))
|
|
1405
|
-
var2s.push(r);
|
|
1406
|
-
else {
|
|
1407
|
-
return false;
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
else {
|
|
1411
|
-
return false;
|
|
1412
|
-
}
|
|
1413
|
-
// have derivative and variable, now check for optional ^ followed by number
|
|
1414
|
-
let this_exponent = 1;
|
|
1415
|
-
this.advance();
|
|
1416
|
-
if (this.token.token_type === "^") {
|
|
1417
|
-
this.advance();
|
|
1418
|
-
let in_braces = false;
|
|
1419
|
-
if (this.token.token_type === "{") {
|
|
1420
|
-
in_braces = true;
|
|
1421
|
-
this.advance();
|
|
1422
|
-
}
|
|
1423
|
-
if (this.token.token_type !== "NUMBER") {
|
|
1424
|
-
return false;
|
|
1425
|
-
}
|
|
1426
|
-
this_exponent = parseFloat(this.token.token_text);
|
|
1427
|
-
if (!Number.isInteger(this_exponent)) {
|
|
1428
|
-
return false;
|
|
1429
|
-
}
|
|
1430
|
-
// if in braces, require }
|
|
1431
|
-
if (in_braces) {
|
|
1432
|
-
this.advance();
|
|
1433
|
-
if (this.token.token_type !== "}") {
|
|
1434
|
-
return false;
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
this.advance();
|
|
1438
|
-
}
|
|
1439
|
-
var2_exponents.push(this_exponent);
|
|
1440
|
-
exponent_sum += this_exponent;
|
|
1441
|
-
if (exponent_sum > n_deriv) {
|
|
1442
|
-
return false;
|
|
1443
|
-
}
|
|
1444
|
-
// possibly found derivative
|
|
1445
|
-
if (exponent_sum === n_deriv) {
|
|
1446
|
-
// next token must be a }
|
|
1447
|
-
if (this.token.token_type !== "}") {
|
|
1448
|
-
return false;
|
|
1449
|
-
}
|
|
1450
|
-
// found derivative!
|
|
1451
|
-
this.advance();
|
|
1452
|
-
let result_name = "derivative_leibniz";
|
|
1453
|
-
if (deriv_symbol === "∂")
|
|
1454
|
-
result_name = "partial_" + result_name;
|
|
1455
|
-
// @ts-ignore
|
|
1456
|
-
result = [result_name];
|
|
1457
|
-
// @ts-ignore
|
|
1458
|
-
if (n_deriv === 1)
|
|
1459
|
-
result.push(var1);
|
|
1460
|
-
// @ts-ignore
|
|
1461
|
-
else
|
|
1462
|
-
result.push(["tuple", var1, n_deriv]);
|
|
1463
|
-
let r2 = [];
|
|
1464
|
-
for (let i = 0; i < var2s.length; i += 1) {
|
|
1465
|
-
if (var2_exponents[i] === 1)
|
|
1466
|
-
r2.push(var2s[i]);
|
|
1467
|
-
else
|
|
1468
|
-
r2.push(["tuple", var2s[i], var2_exponents[i]]);
|
|
1469
|
-
}
|
|
1470
|
-
r2 = ["tuple"].concat(r2);
|
|
1471
|
-
// @ts-ignore
|
|
1472
|
-
result.push(r2);
|
|
1473
|
-
return result;
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
exports.LatexToAst = LatexToAst;
|
|
1479
|
-
//# sourceMappingURL=latex-to-ast.js.map
|