math-exercises 2.0.19 → 2.0.20
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/lib/exercises/trigonometry/remarkableValues.js +1 -1
- package/lib/server.js +10 -7
- package/lib/tree/nodes/functions/oppositeNode.d.ts +1 -1
- package/lib/tree/nodes/functions/oppositeNode.js +2 -1
- package/lib/tree/nodes/operators/powerNode.d.ts.map +1 -1
- package/lib/tree/nodes/operators/powerNode.js +6 -3
- package/lib/tree/nodes/operators/substractNode.js +1 -1
- package/lib/tree/parsers/latexParser.d.ts +1 -0
- package/lib/tree/parsers/latexParser.d.ts.map +1 -1
- package/lib/tree/parsers/latexParser.js +240 -133
- package/package.json +1 -1
|
@@ -52,7 +52,7 @@ const getPropositions = (n, { answer }) => {
|
|
|
52
52
|
return (0, shuffle_1.shuffle)(propositions);
|
|
53
53
|
};
|
|
54
54
|
const isAnswerValid = (ans, { mainValue, isCos }) => {
|
|
55
|
-
const remarkableValue = remarkableValues_1.remarkableTrigoValues.find((point) => point.angle.evaluate({})
|
|
55
|
+
const remarkableValue = remarkableValues_1.remarkableTrigoValues.find((point) => Math.abs(point.angle.evaluate({}) - mainValue) < 0.0001);
|
|
56
56
|
const answer = isCos ? remarkableValue.cos : remarkableValue.sin;
|
|
57
57
|
const texs = answer.toAllValidTexs({
|
|
58
58
|
allowFractionToDecimal: true,
|
package/lib/server.js
CHANGED
|
@@ -41,13 +41,16 @@ const runServer = () => {
|
|
|
41
41
|
dotenv_1.default.config();
|
|
42
42
|
const app = (0, express_1.default)();
|
|
43
43
|
app.use((0, cors_1.default)());
|
|
44
|
-
// const
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
//
|
|
44
|
+
// const string = "\\frac{9}{12}";
|
|
45
|
+
// const a = string.match(/^[0-9]+,?[0-9]*/);
|
|
46
|
+
// const before = Date.now();
|
|
47
|
+
// const parsed = parseLatex(string);
|
|
48
|
+
// console.log("res", parsed);
|
|
49
|
+
// console.log(parsed?.toTex());
|
|
50
|
+
// console.log(parsed?.simplify().toTex());
|
|
51
|
+
// console.log(parsed?.evaluate({ x: 1 }));
|
|
52
|
+
// console.log("time", Date.now() - before);
|
|
53
|
+
// tokenize(string);
|
|
51
54
|
app.get("/", (req, res) => {
|
|
52
55
|
res.json(allExercises);
|
|
53
56
|
});
|
|
@@ -19,7 +19,7 @@ export declare class OppositeNode implements FunctionNode {
|
|
|
19
19
|
*/
|
|
20
20
|
toAllValidTexs(opts?: NodeOptions): string[];
|
|
21
21
|
evaluate(vars: Record<string, number>): number;
|
|
22
|
-
simplify(opts?: SimplifyOptions):
|
|
22
|
+
simplify(opts?: SimplifyOptions): AlgebraicNode;
|
|
23
23
|
equals(node: AlgebraicNode): boolean;
|
|
24
24
|
}
|
|
25
25
|
//# sourceMappingURL=oppositeNode.d.ts.map
|
|
@@ -6,6 +6,7 @@ const node_1 = require("../node");
|
|
|
6
6
|
const operatorNode_1 = require("../operators/operatorNode");
|
|
7
7
|
const functionNode_1 = require("./functionNode");
|
|
8
8
|
const numberNode_1 = require("../numbers/numberNode");
|
|
9
|
+
const multiplyNode_1 = require("../operators/multiplyNode");
|
|
9
10
|
const fractionNode_1 = require("../operators/fractionNode");
|
|
10
11
|
function isOppositeNode(a) {
|
|
11
12
|
return (0, functionNode_1.isFunctionNode)(a) && a.id === functionNode_1.FunctionsIds.opposite;
|
|
@@ -70,7 +71,7 @@ class OppositeNode {
|
|
|
70
71
|
return -this.child.evaluate(vars);
|
|
71
72
|
}
|
|
72
73
|
simplify(opts) {
|
|
73
|
-
return new
|
|
74
|
+
return new multiplyNode_1.MultiplyNode(new numberNode_1.NumberNode(-1), this.child).simplify(opts);
|
|
74
75
|
}
|
|
75
76
|
equals(node) {
|
|
76
77
|
return isOppositeNode(node) && node.child.equals(this.child);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"powerNode.d.ts","sourceRoot":"","sources":["../../../../src/tree/nodes/operators/powerNode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAkB,MAAM,gBAAgB,CAAC;AAG3E,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAOlE,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI,SAAS,CAEnD;AAED,qBAAa,SAAU,YAAW,YAAY;IAC5C,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,EAAE,EAAE,WAAW,CAAC;IAChB,SAAS,EAAE,aAAa,CAAC;IACzB,UAAU,EAAE,aAAa,CAAC;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;gBAEjB,SAAS,EAAE,aAAa,EACxB,UAAU,EAAE,aAAa,EACzB,IAAI,CAAC,EAAE,WAAW;IAUpB,YAAY,IAAI,MAAM;IAItB,iBAAiB;IAqBjB,cAAc,IAAI,MAAM,EAAE;IAI1B,KAAK,IAAI,MAAM;IAuBf,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IA+FrC,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,GAAG,aAAa;
|
|
1
|
+
{"version":3,"file":"powerNode.d.ts","sourceRoot":"","sources":["../../../../src/tree/nodes/operators/powerNode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAkB,MAAM,gBAAgB,CAAC;AAG3E,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAOlE,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI,SAAS,CAEnD;AAED,qBAAa,SAAU,YAAW,YAAY;IAC5C,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,EAAE,EAAE,WAAW,CAAC;IAChB,SAAS,EAAE,aAAa,CAAC;IACzB,UAAU,EAAE,aAAa,CAAC;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;gBAEjB,SAAS,EAAE,aAAa,EACxB,UAAU,EAAE,aAAa,EACzB,IAAI,CAAC,EAAE,WAAW;IAUpB,YAAY,IAAI,MAAM;IAItB,iBAAiB;IAqBjB,cAAc,IAAI,MAAM,EAAE;IAI1B,KAAK,IAAI,MAAM;IAuBf,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IA+FrC,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,GAAG,aAAa;IAY/C,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO;CAOrC;AAED,qBAAa,UAAW,SAAQ,SAAS;gBAC3B,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,WAAW;CAGrD"}
|
|
@@ -157,11 +157,14 @@ class PowerNode {
|
|
|
157
157
|
// // puissances négatives ?
|
|
158
158
|
// }
|
|
159
159
|
simplify(opts) {
|
|
160
|
+
const leftSimplified = this.leftChild.simplify(opts);
|
|
161
|
+
const rightSimplified = this.rightChild.simplify(opts);
|
|
162
|
+
const copy = new PowerNode(leftSimplified, rightSimplified, this.opts);
|
|
160
163
|
//! temporaire
|
|
161
|
-
if ((0, numberNode_1.isNumberNode)(
|
|
162
|
-
return new multiplyNode_1.MultiplyNode(
|
|
164
|
+
if ((0, numberNode_1.isNumberNode)(copy.rightChild) && copy.rightChild.value === 2) {
|
|
165
|
+
return new multiplyNode_1.MultiplyNode(copy.leftChild, copy.leftChild).simplify(opts);
|
|
163
166
|
}
|
|
164
|
-
return
|
|
167
|
+
return copy;
|
|
165
168
|
}
|
|
166
169
|
equals(node) {
|
|
167
170
|
return (isPowerNode(node) &&
|
|
@@ -43,7 +43,7 @@ class SubstractNode {
|
|
|
43
43
|
[operatorNode_1.OperatorIds.add, operatorNode_1.OperatorIds.substract].includes(this.rightChild.id)) ||
|
|
44
44
|
rightTex[0] === "-";
|
|
45
45
|
if (needBrackets)
|
|
46
|
-
rightTex =
|
|
46
|
+
rightTex = `\\left(${rightTex}\\right)`;
|
|
47
47
|
return `${leftTex}-${rightTex}`;
|
|
48
48
|
}
|
|
49
49
|
evaluate(vars) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"latexParser.d.ts","sourceRoot":"","sources":["../../../src/tree/parsers/latexParser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"latexParser.d.ts","sourceRoot":"","sources":["../../../src/tree/parsers/latexParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AA0CvD,eAAO,MAAM,QAAQ,UAAW,MAAM,aA4BrC,CAAC;AAEF,eAAO,MAAM,UAAU,UAAW,MAAM,kBAavC,CAAC"}
|
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseLatex = void 0;
|
|
4
|
-
const
|
|
3
|
+
exports.parseLatex = exports.tokenize = void 0;
|
|
4
|
+
const oppositeNode_1 = require("../nodes/functions/oppositeNode");
|
|
5
5
|
const sqrtNode_1 = require("../nodes/functions/sqrtNode");
|
|
6
6
|
const numberNode_1 = require("../nodes/numbers/numberNode");
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const addNode_1 = require("../nodes/operators/addNode");
|
|
8
|
+
const fractionNode_1 = require("../nodes/operators/fractionNode");
|
|
9
|
+
const multiplyNode_1 = require("../nodes/operators/multiplyNode");
|
|
10
|
+
const powerNode_1 = require("../nodes/operators/powerNode");
|
|
11
|
+
const substractNode_1 = require("../nodes/operators/substractNode");
|
|
12
|
+
const variableNode_1 = require("../nodes/variables/variableNode");
|
|
13
|
+
//cmd that needs a child, like \exp{3}
|
|
14
|
+
const functions = [
|
|
15
|
+
"\\exp",
|
|
16
|
+
"\\sqrt",
|
|
17
|
+
"\\log",
|
|
18
|
+
"\\ln",
|
|
19
|
+
"\\cos",
|
|
20
|
+
"\\sin",
|
|
21
|
+
"\\frac",
|
|
22
|
+
];
|
|
23
|
+
const operators = ["+", "-", "\\div", "\\times", "^"];
|
|
24
|
+
const isDyck = (tokens) => {
|
|
25
|
+
const brackets = tokens.filter((el) => el === "(" || el === ")");
|
|
9
26
|
while (brackets.length) {
|
|
10
27
|
const rightIndex = brackets.findIndex((el) => el == ")");
|
|
11
28
|
if (rightIndex === -1 || rightIndex === 0)
|
|
@@ -24,157 +41,247 @@ const isDyck = (latex) => {
|
|
|
24
41
|
}
|
|
25
42
|
return true;
|
|
26
43
|
};
|
|
44
|
+
const tokenize = (latex) => {
|
|
45
|
+
const tokens = [];
|
|
46
|
+
for (let i = 0; i < latex.length; i++) {
|
|
47
|
+
const char = latex[i];
|
|
48
|
+
if (char === " ")
|
|
49
|
+
continue;
|
|
50
|
+
const match = char.match(/[\+\-\(\)\^a-zA-Z_=\{\}]/);
|
|
51
|
+
if (match) {
|
|
52
|
+
tokens.push(char);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const substring = latex.substring(i);
|
|
56
|
+
const nbMatch = substring.match(/^[0-9]+,?[0-9]*/); //x nombres éventuellement séparés par une virgule
|
|
57
|
+
if (nbMatch) {
|
|
58
|
+
tokens.push(nbMatch[0].replace(",", "."));
|
|
59
|
+
i += nbMatch[0].length - 1;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const cmdMatch = substring.match(/^\\[a-z]+/i);
|
|
63
|
+
if (cmdMatch) {
|
|
64
|
+
tokens.push(cmdMatch[0]);
|
|
65
|
+
i += cmdMatch[0].length - 1;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return tokens;
|
|
70
|
+
};
|
|
71
|
+
exports.tokenize = tokenize;
|
|
27
72
|
const parseLatex = (latex) => {
|
|
28
73
|
const formattedLatex = latex
|
|
29
74
|
.replaceAll("\\left", "")
|
|
30
75
|
.replaceAll("\\right", "");
|
|
31
|
-
const
|
|
32
|
-
if (!
|
|
76
|
+
const tokens = (0, exports.tokenize)(formattedLatex);
|
|
77
|
+
if (!isDyck(tokens))
|
|
33
78
|
throw Error("Problème de parenthèses.");
|
|
34
|
-
let currentTree;
|
|
35
|
-
let currentItem;
|
|
36
|
-
const length = formattedLatex.length;
|
|
37
79
|
try {
|
|
38
|
-
const parsed =
|
|
39
|
-
return parsed
|
|
80
|
+
const parsed = buildTree(tokens);
|
|
81
|
+
return parsed;
|
|
40
82
|
}
|
|
41
83
|
catch (err) {
|
|
42
84
|
throw err;
|
|
43
85
|
}
|
|
44
86
|
};
|
|
45
87
|
exports.parseLatex = parseLatex;
|
|
46
|
-
const
|
|
47
|
-
let
|
|
48
|
-
let
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
node: currentTree,
|
|
63
|
-
jump,
|
|
64
|
-
};
|
|
88
|
+
const buildTree = (tokens) => {
|
|
89
|
+
let currentDepth = 0;
|
|
90
|
+
let maxDepth = 0;
|
|
91
|
+
const depthedTokens = [];
|
|
92
|
+
for (const token of tokens) {
|
|
93
|
+
if (token === "(" || token === "{")
|
|
94
|
+
currentDepth++;
|
|
95
|
+
depthedTokens.push({
|
|
96
|
+
token,
|
|
97
|
+
depth: currentDepth,
|
|
98
|
+
});
|
|
99
|
+
if (currentDepth > maxDepth)
|
|
100
|
+
maxDepth = currentDepth;
|
|
101
|
+
if (token === ")" || token === "}")
|
|
102
|
+
currentDepth--;
|
|
65
103
|
}
|
|
66
|
-
|
|
67
|
-
|
|
104
|
+
console.log("depthed: ", depthedTokens);
|
|
105
|
+
while (true) {
|
|
106
|
+
if (maxDepth === 0) {
|
|
107
|
+
const tree = buildTreeForSameDepthTokens(depthedTokens.map((el) => el.token));
|
|
108
|
+
return tree;
|
|
109
|
+
}
|
|
110
|
+
for (let i = 0; i < depthedTokens.length; i++) {
|
|
111
|
+
const token = depthedTokens[i];
|
|
112
|
+
if (token.depth < maxDepth)
|
|
113
|
+
continue;
|
|
114
|
+
//le token est forcément ici ( ou {
|
|
115
|
+
//et on est sur qu'il n'y a aucun autre nestage à l'intérieur
|
|
116
|
+
const endIndex = depthedTokens.findIndex((el, index) => index > i && (el.token === ")" || el.token === "}"));
|
|
117
|
+
const tree = buildTreeForSameDepthTokens(depthedTokens.slice(i + 1, endIndex).map((el) => el.token));
|
|
118
|
+
depthedTokens.splice(i, endIndex - i + 1, {
|
|
119
|
+
token: tree,
|
|
120
|
+
depth: token.depth - 1,
|
|
121
|
+
});
|
|
122
|
+
console.log(`depthed after iter ${i}`, depthedTokens);
|
|
123
|
+
}
|
|
124
|
+
maxDepth--;
|
|
68
125
|
}
|
|
69
126
|
};
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
127
|
+
const buildTreeForSameDepthTokens = (tokens) => {
|
|
128
|
+
console.log("start: ", tokens);
|
|
129
|
+
let tempTokens = [];
|
|
130
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
131
|
+
const token = tokens[i];
|
|
132
|
+
if (typeof token !== "string") {
|
|
133
|
+
tempTokens[i] = token;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (token[0].match(/[0-9]/)) {
|
|
137
|
+
tempTokens[i] = new numberNode_1.NumberNode(Number(token));
|
|
138
|
+
}
|
|
139
|
+
else if (token[0].match(/[a-z]/i))
|
|
140
|
+
tempTokens[i] = new variableNode_1.VariableNode(token);
|
|
141
|
+
//! les fonctions qui attendent un child ne sont pas encore parsées
|
|
142
|
+
else if (functions.includes(token)) {
|
|
143
|
+
tempTokens[i] = token;
|
|
144
|
+
}
|
|
145
|
+
//!idem pour les opérators
|
|
146
|
+
else if (operators.includes(token))
|
|
147
|
+
tempTokens[i] = token;
|
|
148
|
+
else
|
|
149
|
+
throw Error(`token not implemented: ${token}`);
|
|
75
150
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
151
|
+
console.log("after parses : ", tempTokens);
|
|
152
|
+
//1 build les fct
|
|
153
|
+
for (let i = 0; i < tempTokens.length; i++) {
|
|
154
|
+
if (typeof tempTokens[i] !== "string")
|
|
155
|
+
continue;
|
|
156
|
+
const token = tempTokens[i];
|
|
157
|
+
if (functions.includes(token)) {
|
|
158
|
+
if (typeof tempTokens[i + 1] === "string")
|
|
159
|
+
throw Error(`Function child has not been parsed at index ${i}`);
|
|
160
|
+
switch (token) {
|
|
161
|
+
case "\\sqrt":
|
|
162
|
+
tempTokens[i] = new sqrtNode_1.SqrtNode(tempTokens[i + 1]);
|
|
163
|
+
tempTokens.splice(i + 1, 1);
|
|
164
|
+
break;
|
|
165
|
+
case "\\frac":
|
|
166
|
+
tempTokens[i] = new fractionNode_1.FractionNode(tempTokens[i + 1], tempTokens[i + 2]);
|
|
167
|
+
tempTokens.splice(i + 1, 2);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (token === "^") {
|
|
171
|
+
if (!tempTokens[i - 1] ||
|
|
172
|
+
typeof tempTokens[i - 1] === "string" ||
|
|
173
|
+
!tempTokens[i + 1] ||
|
|
174
|
+
typeof tempTokens[i + 1] === "string")
|
|
175
|
+
throw Error("Error parsing power node");
|
|
176
|
+
else {
|
|
177
|
+
tempTokens[i - 1] = new powerNode_1.PowerNode(tempTokens[i - 1], tempTokens[i + 1]);
|
|
178
|
+
tempTokens.splice(i, 2);
|
|
179
|
+
}
|
|
88
180
|
}
|
|
89
181
|
}
|
|
90
|
-
|
|
182
|
+
//2 build les opposites
|
|
183
|
+
for (let i = 0; i < tempTokens.length; i++) {
|
|
184
|
+
const token = tempTokens[i];
|
|
185
|
+
if (token === "-") {
|
|
186
|
+
if (i === 0 ||
|
|
187
|
+
tempTokens[i - 1] === "\\times" ||
|
|
188
|
+
tempTokens[i - 1] === "+" ||
|
|
189
|
+
tempTokens[i - 1] === "-") {
|
|
190
|
+
//faire la liste des - conéscutifs
|
|
191
|
+
let j = i + 1;
|
|
192
|
+
while (tempTokens[j] === "-" && j < tempTokens.length) {
|
|
193
|
+
j++;
|
|
194
|
+
}
|
|
195
|
+
if (j === tempTokens.length)
|
|
196
|
+
throw Error("Nothing after minus");
|
|
197
|
+
const nextToken = tempTokens[j];
|
|
198
|
+
//! à ce stade, le nextToken est soit un node, soit : + ou \\times
|
|
199
|
+
//!on fait ici le choix d'interdire -+x
|
|
200
|
+
if (typeof nextToken === "string") {
|
|
201
|
+
throw Error("Opposé pas clair");
|
|
202
|
+
}
|
|
203
|
+
const oppositeCount = j - i;
|
|
204
|
+
let node = nextToken;
|
|
205
|
+
for (let k = 0; k < oppositeCount; k++) {
|
|
206
|
+
node = new oppositeNode_1.OppositeNode(node);
|
|
207
|
+
}
|
|
208
|
+
tempTokens[i] = node;
|
|
209
|
+
tempTokens.splice(i + 1, oppositeCount);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
91
212
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
213
|
+
console.log("after fcts: ", tempTokens);
|
|
214
|
+
//3 build les *
|
|
215
|
+
let currentProduct;
|
|
216
|
+
let currentProductStartIndex;
|
|
217
|
+
for (let i = 0; i < tempTokens.length; i++) {
|
|
218
|
+
const token = tempTokens[i];
|
|
219
|
+
if (token === "\\times")
|
|
220
|
+
continue;
|
|
221
|
+
//la seule chose qui arrete un produit est + ou -
|
|
222
|
+
//y a t il d'autres cas ?
|
|
223
|
+
//? rappel ici on est sur une expression de niveau uniforme (sans parentheses ni childs)
|
|
224
|
+
if (token === "+" || token === "-") {
|
|
225
|
+
if (currentProduct &&
|
|
226
|
+
(0, multiplyNode_1.isMultiplyNode)(currentProduct) &&
|
|
227
|
+
currentProductStartIndex !== undefined) {
|
|
228
|
+
tempTokens[currentProductStartIndex] = currentProduct;
|
|
229
|
+
tempTokens.splice(currentProductStartIndex + 1, i - currentProductStartIndex - 1);
|
|
230
|
+
i = currentProductStartIndex + 1;
|
|
231
|
+
}
|
|
232
|
+
currentProduct = undefined;
|
|
233
|
+
currentProductStartIndex = undefined;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
if (currentProduct) {
|
|
238
|
+
currentProduct = new multiplyNode_1.MultiplyNode(currentProduct, token);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
currentProduct = token;
|
|
242
|
+
currentProductStartIndex = i;
|
|
112
243
|
}
|
|
113
|
-
else
|
|
114
|
-
leftBracesCount--;
|
|
115
244
|
}
|
|
116
245
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
*/
|
|
123
|
-
const parseCommand = (latex) => {
|
|
124
|
-
let nextChar = latex[1];
|
|
125
|
-
const length = latex.length;
|
|
126
|
-
if (!nextChar)
|
|
127
|
-
throw Error("Antislash mais pas de nom de commande");
|
|
128
|
-
let j = 1;
|
|
129
|
-
let cmd = "";
|
|
130
|
-
while (j < length && (0, isLetter_1.isLetter)(nextChar)) {
|
|
131
|
-
cmd += nextChar;
|
|
132
|
-
j++;
|
|
133
|
-
nextChar = latex[j];
|
|
246
|
+
if (currentProduct &&
|
|
247
|
+
(0, multiplyNode_1.isMultiplyNode)(currentProduct) &&
|
|
248
|
+
currentProductStartIndex !== undefined) {
|
|
249
|
+
tempTokens[currentProductStartIndex] = currentProduct;
|
|
250
|
+
tempTokens.splice(currentProductStartIndex + 1, tempTokens.length - 1 - currentProductStartIndex);
|
|
134
251
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
252
|
+
//4 build les +
|
|
253
|
+
let currentAdd;
|
|
254
|
+
console.log("beforeAdd", tempTokens);
|
|
255
|
+
for (let i = 0; i < tempTokens.length; i++) {
|
|
256
|
+
const token = tempTokens[i];
|
|
257
|
+
if (!currentAdd) {
|
|
258
|
+
if (typeof token === "string") {
|
|
259
|
+
if (token === "+" || token === "-") {
|
|
260
|
+
throw Error("Addition with no first term");
|
|
261
|
+
}
|
|
262
|
+
else
|
|
263
|
+
throw Error(`unexpected non parsed token ${token}`);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
currentAdd = token;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
if (typeof token !== "string" || (token !== "+" && token !== "-")) {
|
|
271
|
+
throw Error(`unexpected consecutive nodes without addition : ${token}`);
|
|
272
|
+
}
|
|
273
|
+
const next = tempTokens[i + 1];
|
|
274
|
+
if (typeof next === "string") {
|
|
275
|
+
throw Error(`unexpected non parsed token ${next}`);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
if (token === "+")
|
|
279
|
+
currentAdd = new addNode_1.AddNode(currentAdd, next);
|
|
280
|
+
else
|
|
281
|
+
currentAdd = new substractNode_1.SubstractNode(currentAdd, next);
|
|
282
|
+
i++;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
155
285
|
}
|
|
156
|
-
|
|
157
|
-
throw Error(`Nombre ${numberString} avec virgule mais sans partie décimale`);
|
|
158
|
-
if (numberString.split(",").length > 2)
|
|
159
|
-
throw Error(`Trop de virgules dans le nombre ${numberString}`);
|
|
160
|
-
const number = Number(numberString.replace(",", "."));
|
|
161
|
-
return {
|
|
162
|
-
node: new numberNode_1.NumberNode(number),
|
|
163
|
-
jump: numberString.length,
|
|
164
|
-
};
|
|
165
|
-
};
|
|
166
|
-
/***
|
|
167
|
-
* Nombres
|
|
168
|
-
* Constantes
|
|
169
|
-
* Opérations :
|
|
170
|
-
* - +
|
|
171
|
-
* - -
|
|
172
|
-
* - *
|
|
173
|
-
* - /
|
|
174
|
-
* Fonctions :
|
|
175
|
-
* - exp
|
|
176
|
-
* - ln
|
|
177
|
-
*/
|
|
178
|
-
const charIsNumber = (s) => {
|
|
179
|
-
return ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"].includes(s);
|
|
286
|
+
return currentAdd;
|
|
180
287
|
};
|