mathjs 5.0.0 → 5.0.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of mathjs might be problematic. Click here for more details.
- package/HISTORY.md +48 -1
- package/README.md +2 -1
- package/dist/math.js +20114 -20090
- package/dist/math.min.js +7 -7
- package/dist/math.min.map +1 -1
- package/docs/core/configuration.md +1 -1
- package/docs/datatypes/numbers.md +1 -1
- package/docs/datatypes/units.md +1 -1
- package/docs/expressions/algebra.md +25 -1
- package/docs/getting_started.md +2 -2
- package/docs/reference/functions/format.md +2 -2
- package/docs/reference/functions/qr.md +2 -1
- package/docs/reference/functions/rationalize.md +13 -10
- package/docs/reference/functions/stirlingS2.md +1 -1
- package/docs/reference/functions/typeof.md +13 -13
- package/examples/advanced/add_new_datatypes/MyType.js +0 -10
- package/examples/advanced/add_new_datatypes/index.js +2 -6
- package/examples/browser/rocket_trajectory_optimization.html +2 -2
- package/lib/constants.js +3 -1
- package/lib/core/function/import.js +15 -2
- package/lib/core/typed.js +1 -1
- package/lib/expression/node/FunctionNode.js +5 -4
- package/lib/expression/parse.js +429 -466
- package/lib/function/algebra/decomposition/qr.js +1 -1
- package/lib/function/algebra/rationalize.js +41 -45
- package/lib/function/algebra/simplify/resolve.js +1 -1
- package/lib/function/algebra/simplify/simplifyCore.js +3 -3
- package/lib/function/algebra/simplify/util.js +1 -1
- package/lib/function/algebra/simplify.js +5 -0
- package/lib/function/combinatorics/stirlingS2.js +1 -1
- package/lib/function/probability/combinations.js +11 -10
- package/lib/function/probability/gamma.js +5 -13
- package/lib/function/probability/permutations.js +2 -12
- package/lib/function/probability/product.js +19 -0
- package/lib/function/string/format.js +2 -2
- package/lib/function/utils/typeof.js +13 -13
- package/lib/index.js +5 -1
- package/lib/type/bignumber/BigNumber.js +6 -2
- package/lib/type/matrix/utils/algorithm13.js +0 -2
- package/lib/type/unit/Unit.js +2 -2
- package/lib/utils/array.js +27 -19
- package/lib/utils/bignumber/formatter.js +3 -2
- package/lib/utils/number.js +15 -10
- package/lib/version.js +1 -1
- package/package.json +13 -8
- package/src/constants.js +3 -1
- package/src/core/function/import.js +15 -2
- package/src/core/typed.js +1 -1
- package/src/expression/node/FunctionNode.js +3 -4
- package/src/expression/parse.js +432 -470
- package/src/function/algebra/decomposition/qr.js +1 -1
- package/src/function/algebra/rationalize.js +41 -43
- package/src/function/algebra/simplify/resolve.js +1 -1
- package/src/function/algebra/simplify/simplifyCore.js +3 -3
- package/src/function/algebra/simplify/util.js +1 -1
- package/src/function/algebra/simplify.js +5 -0
- package/src/function/combinatorics/stirlingS2.js +1 -1
- package/src/function/probability/combinations.js +10 -8
- package/src/function/probability/gamma.js +5 -13
- package/src/function/probability/permutations.js +2 -11
- package/src/function/probability/product.js +17 -0
- package/src/function/string/format.js +2 -2
- package/src/function/utils/typeof.js +13 -13
- package/src/index.js +5 -1
- package/src/type/bignumber/BigNumber.js +2 -1
- package/src/type/matrix/utils/algorithm13.js +0 -2
- package/src/type/unit/Unit.js +2 -2
- package/src/utils/array.js +31 -23
- package/src/utils/bignumber/formatter.js +3 -2
- package/src/utils/number.js +15 -10
- package/src/version.js +1 -1
package/src/expression/parse.js
CHANGED
@@ -59,19 +59,18 @@ function factory (type, config, load, typed) {
|
|
59
59
|
}
|
60
60
|
|
61
61
|
// pass extra nodes
|
62
|
-
extraNodes = (options && options.nodes) ? options.nodes : {}
|
62
|
+
let extraNodes = (options && options.nodes) ? options.nodes : {}
|
63
63
|
|
64
64
|
if (typeof expr === 'string') {
|
65
65
|
// parse a single expression
|
66
|
-
|
67
|
-
return parseStart()
|
66
|
+
|
67
|
+
return parseStart(expr, extraNodes)
|
68
68
|
} else if (Array.isArray(expr) || expr instanceof type.Matrix) {
|
69
69
|
// parse an array or matrix with expressions
|
70
70
|
return deepMap(expr, function (elem) {
|
71
71
|
if (typeof elem !== 'string') throw new TypeError('String expected')
|
72
72
|
|
73
|
-
|
74
|
-
return parseStart()
|
73
|
+
return parseStart(elem, extraNodes)
|
75
74
|
})
|
76
75
|
} else {
|
77
76
|
// oops
|
@@ -154,101 +153,68 @@ function factory (type, config, load, typed) {
|
|
154
153
|
'Infinity'
|
155
154
|
]
|
156
155
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
/**
|
169
|
-
* Get the first character from the expression.
|
170
|
-
* The character is stored into the char c. If the end of the expression is
|
171
|
-
* reached, the function puts an empty string in c.
|
172
|
-
* @private
|
173
|
-
*/
|
174
|
-
function first () {
|
175
|
-
index = 0
|
176
|
-
c = expression.charAt(0)
|
177
|
-
nestingLevel = 0
|
178
|
-
conditionalLevel = null
|
156
|
+
function initialState () {
|
157
|
+
return {
|
158
|
+
extraNodes: {}, // current extra nodes, must be careful not to mutate
|
159
|
+
expression: '', // current expression
|
160
|
+
comment: '', // last parsed comment
|
161
|
+
index: 0, // current index in expr
|
162
|
+
token: '', // current token
|
163
|
+
tokenType: TOKENTYPE.NULL, // type of the token
|
164
|
+
nestingLevel: 0, // level of nesting inside parameters, used to ignore newline characters
|
165
|
+
conditionalLevel: null // when a conditional is being parsed, the level of the conditional is stored here
|
166
|
+
}
|
179
167
|
}
|
180
168
|
|
181
169
|
/**
|
182
|
-
*
|
183
|
-
*
|
184
|
-
*
|
170
|
+
* View upto `length` characters of the expression starting at the current character.
|
171
|
+
*
|
172
|
+
* @param {State} state
|
173
|
+
* @param {number} [length=1] Number of characters to view
|
174
|
+
* @returns {string}
|
185
175
|
* @private
|
186
176
|
*/
|
187
|
-
function
|
188
|
-
index
|
189
|
-
c = expression.charAt(index)
|
177
|
+
function currentString (state, length) {
|
178
|
+
return state.expression.substr(state.index, length)
|
190
179
|
}
|
191
180
|
|
192
181
|
/**
|
193
|
-
*
|
194
|
-
*
|
182
|
+
* View the current character. Returns '' if end of expression is reached.
|
183
|
+
*
|
184
|
+
* @param {State} state
|
185
|
+
* @returns {string}
|
195
186
|
* @private
|
196
187
|
*/
|
197
|
-
function
|
198
|
-
return
|
188
|
+
function currentCharacter (state) {
|
189
|
+
return currentString(state, 1)
|
199
190
|
}
|
200
191
|
|
201
192
|
/**
|
202
|
-
*
|
203
|
-
*
|
193
|
+
* Get the next character from the expression.
|
194
|
+
* The character is stored into the char c. If the end of the expression is
|
195
|
+
* reached, the function puts an empty string in c.
|
204
196
|
* @private
|
205
197
|
*/
|
206
|
-
function
|
207
|
-
|
198
|
+
function next (state) {
|
199
|
+
state.index++
|
208
200
|
}
|
209
201
|
|
210
202
|
/**
|
211
|
-
* Preview the
|
203
|
+
* Preview the previous character from the expression.
|
212
204
|
* @return {string} cNext
|
213
205
|
* @private
|
214
206
|
*/
|
215
|
-
function
|
216
|
-
return expression.charAt(index
|
217
|
-
}
|
218
|
-
|
219
|
-
/**
|
220
|
-
* Save the current token state so we can rewind later if necessary.
|
221
|
-
* @private
|
222
|
-
*/
|
223
|
-
function pushTokenState () {
|
224
|
-
tokenStates.push({
|
225
|
-
tokenType: tokenType,
|
226
|
-
token: token,
|
227
|
-
comment: comment,
|
228
|
-
index: index,
|
229
|
-
c: c
|
230
|
-
})
|
231
|
-
}
|
232
|
-
|
233
|
-
/**
|
234
|
-
* Rewind the parser by one token by restoring the last saved token state
|
235
|
-
* @private
|
236
|
-
*/
|
237
|
-
function popTokenState () {
|
238
|
-
const restoredState = tokenStates.pop()
|
239
|
-
tokenType = restoredState.tokenType
|
240
|
-
token = restoredState.token
|
241
|
-
comment = restoredState.comment
|
242
|
-
index = restoredState.index
|
243
|
-
c = restoredState.c
|
207
|
+
function prevCharacter (state) {
|
208
|
+
return state.expression.charAt(state.index - 1)
|
244
209
|
}
|
245
210
|
|
246
211
|
/**
|
247
|
-
*
|
212
|
+
* Preview the next character from the expression.
|
213
|
+
* @return {string} cNext
|
248
214
|
* @private
|
249
215
|
*/
|
250
|
-
function
|
251
|
-
|
216
|
+
function nextCharacter (state) {
|
217
|
+
return state.expression.charAt(state.index + 1)
|
252
218
|
}
|
253
219
|
|
254
220
|
/**
|
@@ -256,125 +222,123 @@ function factory (type, config, load, typed) {
|
|
256
222
|
* The token and token type are available as token and tokenType
|
257
223
|
* @private
|
258
224
|
*/
|
259
|
-
function getToken () {
|
260
|
-
tokenType = TOKENTYPE.NULL
|
261
|
-
token = ''
|
262
|
-
comment = ''
|
225
|
+
function getToken (state) {
|
226
|
+
state.tokenType = TOKENTYPE.NULL
|
227
|
+
state.token = ''
|
228
|
+
state.comment = ''
|
263
229
|
|
264
230
|
// skip over whitespaces
|
265
231
|
// space, tab, and newline when inside parameters
|
266
|
-
while (parse.isWhitespace(
|
267
|
-
next()
|
232
|
+
while (parse.isWhitespace(currentCharacter(state), state.nestingLevel)) {
|
233
|
+
next(state)
|
268
234
|
}
|
269
235
|
|
270
236
|
// skip comment
|
271
|
-
if (
|
272
|
-
while (
|
273
|
-
comment +=
|
274
|
-
next()
|
237
|
+
if (currentCharacter(state) === '#') {
|
238
|
+
while (currentCharacter(state) !== '\n' && currentCharacter(state) !== '') {
|
239
|
+
state.comment += currentCharacter(state)
|
240
|
+
next(state)
|
275
241
|
}
|
276
242
|
}
|
277
243
|
|
278
244
|
// check for end of expression
|
279
|
-
if (
|
245
|
+
if (currentCharacter(state) === '') {
|
280
246
|
// token is still empty
|
281
|
-
tokenType = TOKENTYPE.DELIMITER
|
247
|
+
state.tokenType = TOKENTYPE.DELIMITER
|
282
248
|
return
|
283
249
|
}
|
284
250
|
|
285
251
|
// check for new line character
|
286
|
-
if (
|
287
|
-
tokenType = TOKENTYPE.DELIMITER
|
288
|
-
token =
|
289
|
-
next()
|
252
|
+
if (currentCharacter(state) === '\n' && !state.nestingLevel) {
|
253
|
+
state.tokenType = TOKENTYPE.DELIMITER
|
254
|
+
state.token = currentCharacter(state)
|
255
|
+
next(state)
|
290
256
|
return
|
291
257
|
}
|
292
258
|
|
293
|
-
|
294
|
-
|
295
|
-
const c3 =
|
259
|
+
const c1 = currentCharacter(state)
|
260
|
+
const c2 = currentString(state, 2)
|
261
|
+
const c3 = currentString(state, 3)
|
296
262
|
if (c3.length === 3 && DELIMITERS[c3]) {
|
297
|
-
tokenType = TOKENTYPE.DELIMITER
|
298
|
-
token = c3
|
299
|
-
next()
|
300
|
-
next()
|
301
|
-
next()
|
263
|
+
state.tokenType = TOKENTYPE.DELIMITER
|
264
|
+
state.token = c3
|
265
|
+
next(state)
|
266
|
+
next(state)
|
267
|
+
next(state)
|
302
268
|
return
|
303
269
|
}
|
304
270
|
|
305
271
|
// check for delimiters consisting of 2 characters
|
306
272
|
if (c2.length === 2 && DELIMITERS[c2]) {
|
307
|
-
tokenType = TOKENTYPE.DELIMITER
|
308
|
-
token = c2
|
309
|
-
next()
|
310
|
-
next()
|
273
|
+
state.tokenType = TOKENTYPE.DELIMITER
|
274
|
+
state.token = c2
|
275
|
+
next(state)
|
276
|
+
next(state)
|
311
277
|
return
|
312
278
|
}
|
313
279
|
|
314
280
|
// check for delimiters consisting of 1 character
|
315
|
-
if (DELIMITERS[
|
316
|
-
tokenType = TOKENTYPE.DELIMITER
|
317
|
-
token =
|
318
|
-
next()
|
281
|
+
if (DELIMITERS[c1]) {
|
282
|
+
state.tokenType = TOKENTYPE.DELIMITER
|
283
|
+
state.token = c1
|
284
|
+
next(state)
|
319
285
|
return
|
320
286
|
}
|
321
287
|
|
322
288
|
// check for a number
|
323
|
-
if (parse.isDigitDot(
|
324
|
-
tokenType = TOKENTYPE.NUMBER
|
289
|
+
if (parse.isDigitDot(c1)) {
|
290
|
+
state.tokenType = TOKENTYPE.NUMBER
|
325
291
|
|
326
292
|
// get number, can have a single dot
|
327
|
-
if (
|
328
|
-
token +=
|
329
|
-
next()
|
293
|
+
if (currentCharacter(state) === '.') {
|
294
|
+
state.token += currentCharacter(state)
|
295
|
+
next(state)
|
330
296
|
|
331
|
-
if (!parse.isDigit(
|
297
|
+
if (!parse.isDigit(currentCharacter(state))) {
|
332
298
|
// this is no number, it is just a dot (can be dot notation)
|
333
|
-
tokenType = TOKENTYPE.DELIMITER
|
299
|
+
state.tokenType = TOKENTYPE.DELIMITER
|
334
300
|
}
|
335
301
|
} else {
|
336
|
-
while (parse.isDigit(
|
337
|
-
token +=
|
338
|
-
next()
|
302
|
+
while (parse.isDigit(currentCharacter(state))) {
|
303
|
+
state.token += currentCharacter(state)
|
304
|
+
next(state)
|
339
305
|
}
|
340
|
-
if (parse.isDecimalMark(
|
341
|
-
token +=
|
342
|
-
next()
|
306
|
+
if (parse.isDecimalMark(currentCharacter(state), nextCharacter(state))) {
|
307
|
+
state.token += currentCharacter(state)
|
308
|
+
next(state)
|
343
309
|
}
|
344
310
|
}
|
345
|
-
while (parse.isDigit(c)) {
|
346
|
-
token += c
|
347
|
-
next()
|
348
|
-
}
|
349
311
|
|
312
|
+
while (parse.isDigit(currentCharacter(state))) {
|
313
|
+
state.token += currentCharacter(state)
|
314
|
+
next(state)
|
315
|
+
}
|
350
316
|
// check for exponential notation like "2.3e-4", "1.23e50" or "2e+4"
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
next()
|
317
|
+
if (currentCharacter(state) === 'E' || currentCharacter(state) === 'e') {
|
318
|
+
if (parse.isDigit(nextCharacter(state)) || nextCharacter(state) === '-' || nextCharacter(state) === '+') {
|
319
|
+
state.token += currentCharacter(state)
|
320
|
+
next(state)
|
321
|
+
|
322
|
+
if (currentCharacter(state) === '+' || currentCharacter(state) === '-') {
|
323
|
+
state.token += currentCharacter(state)
|
324
|
+
next(state)
|
360
325
|
}
|
361
|
-
|
362
326
|
// Scientific notation MUST be followed by an exponent
|
363
|
-
if (!parse.isDigit(
|
364
|
-
throw createSyntaxError('Digit expected, got "' +
|
327
|
+
if (!parse.isDigit(currentCharacter(state))) {
|
328
|
+
throw createSyntaxError(state, 'Digit expected, got "' + currentCharacter(state) + '"')
|
365
329
|
}
|
366
330
|
|
367
|
-
while (parse.isDigit(
|
368
|
-
token +=
|
369
|
-
next()
|
331
|
+
while (parse.isDigit(currentCharacter(state))) {
|
332
|
+
state.token += currentCharacter(state)
|
333
|
+
next(state)
|
370
334
|
}
|
371
335
|
|
372
|
-
if (parse.isDecimalMark(
|
373
|
-
throw createSyntaxError('Digit expected, got "' +
|
336
|
+
if (parse.isDecimalMark(currentCharacter(state), nextCharacter(state))) {
|
337
|
+
throw createSyntaxError(state, 'Digit expected, got "' + currentCharacter(state) + '"')
|
374
338
|
}
|
375
|
-
} else if (
|
376
|
-
next()
|
377
|
-
throw createSyntaxError('Digit expected, got "' +
|
339
|
+
} else if (nextCharacter(state) === '.') {
|
340
|
+
next(state)
|
341
|
+
throw createSyntaxError(state, 'Digit expected, got "' + currentCharacter(state) + '"')
|
378
342
|
}
|
379
343
|
}
|
380
344
|
|
@@ -382,54 +346,54 @@ function factory (type, config, load, typed) {
|
|
382
346
|
}
|
383
347
|
|
384
348
|
// check for variables, functions, named operators
|
385
|
-
if (parse.isAlpha(
|
386
|
-
while (parse.isAlpha(
|
387
|
-
token +=
|
388
|
-
next()
|
349
|
+
if (parse.isAlpha(currentCharacter(state), prevCharacter(state), nextCharacter(state))) {
|
350
|
+
while (parse.isAlpha(currentCharacter(state), prevCharacter(state), nextCharacter(state)) || parse.isDigit(currentCharacter(state))) {
|
351
|
+
state.token += currentCharacter(state)
|
352
|
+
next(state)
|
389
353
|
}
|
390
354
|
|
391
|
-
if (NAMED_DELIMITERS.hasOwnProperty(token)) {
|
392
|
-
tokenType = TOKENTYPE.DELIMITER
|
355
|
+
if (NAMED_DELIMITERS.hasOwnProperty(state.token)) {
|
356
|
+
state.tokenType = TOKENTYPE.DELIMITER
|
393
357
|
} else {
|
394
|
-
tokenType = TOKENTYPE.SYMBOL
|
358
|
+
state.tokenType = TOKENTYPE.SYMBOL
|
395
359
|
}
|
396
360
|
|
397
361
|
return
|
398
362
|
}
|
399
363
|
|
400
364
|
// something unknown is found, wrong characters -> a syntax error
|
401
|
-
tokenType = TOKENTYPE.UNKNOWN
|
402
|
-
while (
|
403
|
-
token +=
|
404
|
-
next()
|
365
|
+
state.tokenType = TOKENTYPE.UNKNOWN
|
366
|
+
while (currentCharacter(state) !== '') {
|
367
|
+
state.token += currentCharacter(state)
|
368
|
+
next(state)
|
405
369
|
}
|
406
|
-
throw createSyntaxError('Syntax error in part "' + token + '"')
|
370
|
+
throw createSyntaxError(state, 'Syntax error in part "' + state.token + '"')
|
407
371
|
}
|
408
372
|
|
409
373
|
/**
|
410
374
|
* Get next token and skip newline tokens
|
411
375
|
*/
|
412
|
-
function getTokenSkipNewline () {
|
376
|
+
function getTokenSkipNewline (state) {
|
413
377
|
do {
|
414
|
-
getToken()
|
378
|
+
getToken(state)
|
415
379
|
}
|
416
|
-
while (token === '\n') // eslint-disable-line no-unmodified-loop-condition
|
380
|
+
while (state.token === '\n') // eslint-disable-line no-unmodified-loop-condition
|
417
381
|
}
|
418
382
|
|
419
383
|
/**
|
420
384
|
* Open parameters.
|
421
|
-
* New line characters will be ignored until closeParams() is called
|
385
|
+
* New line characters will be ignored until closeParams(state) is called
|
422
386
|
*/
|
423
|
-
function openParams () {
|
424
|
-
nestingLevel++
|
387
|
+
function openParams (state) {
|
388
|
+
state.nestingLevel++
|
425
389
|
}
|
426
390
|
|
427
391
|
/**
|
428
392
|
* Close parameters.
|
429
393
|
* New line characters will no longer be ignored
|
430
394
|
*/
|
431
|
-
function closeParams () {
|
432
|
-
nestingLevel--
|
395
|
+
function closeParams (state) {
|
396
|
+
state.nestingLevel--
|
433
397
|
}
|
434
398
|
|
435
399
|
/**
|
@@ -531,24 +495,23 @@ function factory (type, config, load, typed) {
|
|
531
495
|
* @return {Node} node
|
532
496
|
* @private
|
533
497
|
*/
|
534
|
-
function parseStart () {
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
getToken()
|
498
|
+
function parseStart (expression, extraNodes) {
|
499
|
+
const state = initialState()
|
500
|
+
Object.assign(state, { expression, extraNodes })
|
501
|
+
getToken(state)
|
539
502
|
|
540
|
-
const node = parseBlock()
|
503
|
+
const node = parseBlock(state)
|
541
504
|
|
542
505
|
// check for garbage at the end of the expression
|
543
506
|
// an expression ends with a empty character '' and tokenType DELIMITER
|
544
|
-
if (token !== '') {
|
545
|
-
if (tokenType === TOKENTYPE.DELIMITER) {
|
507
|
+
if (state.token !== '') {
|
508
|
+
if (state.tokenType === TOKENTYPE.DELIMITER) {
|
546
509
|
// user entered a not existing operator like "//"
|
547
510
|
|
548
511
|
// TODO: give hints for aliases, for example with "<>" give as hint " did you mean !== ?"
|
549
|
-
throw createError('Unexpected operator ' + token)
|
512
|
+
throw createError(state, 'Unexpected operator ' + state.token)
|
550
513
|
} else {
|
551
|
-
throw createSyntaxError('Unexpected part "' + token + '"')
|
514
|
+
throw createSyntaxError(state, 'Unexpected part "' + state.token + '"')
|
552
515
|
}
|
553
516
|
}
|
554
517
|
|
@@ -562,32 +525,32 @@ function factory (type, config, load, typed) {
|
|
562
525
|
* @return {Node} node
|
563
526
|
* @private
|
564
527
|
*/
|
565
|
-
function parseBlock () {
|
528
|
+
function parseBlock (state) {
|
566
529
|
let node
|
567
530
|
const blocks = []
|
568
531
|
let visible
|
569
532
|
|
570
|
-
if (token !== '' && token !== '\n' && token !== ';') {
|
571
|
-
node = parseAssignment()
|
572
|
-
node.comment = comment
|
533
|
+
if (state.token !== '' && state.token !== '\n' && state.token !== ';') {
|
534
|
+
node = parseAssignment(state)
|
535
|
+
node.comment = state.comment
|
573
536
|
}
|
574
537
|
|
575
538
|
// TODO: simplify this loop
|
576
|
-
while (token === '\n' || token === ';') { // eslint-disable-line no-unmodified-loop-condition
|
539
|
+
while (state.token === '\n' || state.token === ';') { // eslint-disable-line no-unmodified-loop-condition
|
577
540
|
if (blocks.length === 0 && node) {
|
578
|
-
visible = (token !== ';')
|
541
|
+
visible = (state.token !== ';')
|
579
542
|
blocks.push({
|
580
543
|
node: node,
|
581
544
|
visible: visible
|
582
545
|
})
|
583
546
|
}
|
584
547
|
|
585
|
-
getToken()
|
586
|
-
if (token !== '\n' && token !== ';' && token !== '') {
|
587
|
-
node = parseAssignment()
|
588
|
-
node.comment = comment
|
548
|
+
getToken(state)
|
549
|
+
if (state.token !== '\n' && state.token !== ';' && state.token !== '') {
|
550
|
+
node = parseAssignment(state)
|
551
|
+
node.comment = state.comment
|
589
552
|
|
590
|
-
visible = (token !== ';')
|
553
|
+
visible = (state.token !== ';')
|
591
554
|
blocks.push({
|
592
555
|
node: node,
|
593
556
|
visible: visible
|
@@ -600,7 +563,7 @@ function factory (type, config, load, typed) {
|
|
600
563
|
} else {
|
601
564
|
if (!node) {
|
602
565
|
node = new ConstantNode(undefined)
|
603
|
-
node.comment = comment
|
566
|
+
node.comment = state.comment
|
604
567
|
}
|
605
568
|
|
606
569
|
return node
|
@@ -615,22 +578,22 @@ function factory (type, config, load, typed) {
|
|
615
578
|
* @return {Node} node
|
616
579
|
* @private
|
617
580
|
*/
|
618
|
-
function parseAssignment () {
|
581
|
+
function parseAssignment (state) {
|
619
582
|
let name, args, value, valid
|
620
583
|
|
621
|
-
const node = parseConditional()
|
584
|
+
const node = parseConditional(state)
|
622
585
|
|
623
|
-
if (token === '=') {
|
586
|
+
if (state.token === '=') {
|
624
587
|
if (type.isSymbolNode(node)) {
|
625
588
|
// parse a variable assignment like 'a = 2/3'
|
626
589
|
name = node.name
|
627
|
-
getTokenSkipNewline()
|
628
|
-
value = parseAssignment()
|
590
|
+
getTokenSkipNewline(state)
|
591
|
+
value = parseAssignment(state)
|
629
592
|
return new AssignmentNode(new SymbolNode(name), value)
|
630
593
|
} else if (type.isAccessorNode(node)) {
|
631
594
|
// parse a matrix subset assignment like 'A[1,2] = 4'
|
632
|
-
getTokenSkipNewline()
|
633
|
-
value = parseAssignment()
|
595
|
+
getTokenSkipNewline(state)
|
596
|
+
value = parseAssignment(state)
|
634
597
|
return new AssignmentNode(node.object, node.index, value)
|
635
598
|
} else if (type.isFunctionNode(node) && type.isSymbolNode(node.fn)) {
|
636
599
|
// parse function assignment like 'f(x) = x^2'
|
@@ -647,13 +610,13 @@ function factory (type, config, load, typed) {
|
|
647
610
|
})
|
648
611
|
|
649
612
|
if (valid) {
|
650
|
-
getTokenSkipNewline()
|
651
|
-
value = parseAssignment()
|
613
|
+
getTokenSkipNewline(state)
|
614
|
+
value = parseAssignment(state)
|
652
615
|
return new FunctionAssignmentNode(name, args, value)
|
653
616
|
}
|
654
617
|
}
|
655
618
|
|
656
|
-
throw createSyntaxError('Invalid left hand side of assignment operator =')
|
619
|
+
throw createSyntaxError(state, 'Invalid left hand side of assignment operator =')
|
657
620
|
}
|
658
621
|
|
659
622
|
return node
|
@@ -669,30 +632,30 @@ function factory (type, config, load, typed) {
|
|
669
632
|
* @return {Node} node
|
670
633
|
* @private
|
671
634
|
*/
|
672
|
-
function parseConditional () {
|
673
|
-
let node = parseLogicalOr()
|
635
|
+
function parseConditional (state) {
|
636
|
+
let node = parseLogicalOr(state)
|
674
637
|
|
675
|
-
while (token === '?') { // eslint-disable-line no-unmodified-loop-condition
|
638
|
+
while (state.token === '?') { // eslint-disable-line no-unmodified-loop-condition
|
676
639
|
// set a conditional level, the range operator will be ignored as long
|
677
|
-
// as conditionalLevel === nestingLevel.
|
678
|
-
const prev = conditionalLevel
|
679
|
-
conditionalLevel = nestingLevel
|
680
|
-
getTokenSkipNewline()
|
640
|
+
// as conditionalLevel === state.nestingLevel.
|
641
|
+
const prev = state.conditionalLevel
|
642
|
+
state.conditionalLevel = state.nestingLevel
|
643
|
+
getTokenSkipNewline(state)
|
681
644
|
|
682
645
|
const condition = node
|
683
|
-
const trueExpr = parseAssignment()
|
646
|
+
const trueExpr = parseAssignment(state)
|
684
647
|
|
685
|
-
if (token !== ':') throw createSyntaxError('False part of conditional expression expected')
|
648
|
+
if (state.token !== ':') throw createSyntaxError(state, 'False part of conditional expression expected')
|
686
649
|
|
687
|
-
conditionalLevel = null
|
688
|
-
getTokenSkipNewline()
|
650
|
+
state.conditionalLevel = null
|
651
|
+
getTokenSkipNewline(state)
|
689
652
|
|
690
|
-
const falseExpr = parseAssignment() // Note: check for conditional operator again, right associativity
|
653
|
+
const falseExpr = parseAssignment(state) // Note: check for conditional operator again, right associativity
|
691
654
|
|
692
655
|
node = new ConditionalNode(condition, trueExpr, falseExpr)
|
693
656
|
|
694
657
|
// restore the previous conditional level
|
695
|
-
conditionalLevel = prev
|
658
|
+
state.conditionalLevel = prev
|
696
659
|
}
|
697
660
|
|
698
661
|
return node
|
@@ -703,12 +666,12 @@ function factory (type, config, load, typed) {
|
|
703
666
|
* @return {Node} node
|
704
667
|
* @private
|
705
668
|
*/
|
706
|
-
function parseLogicalOr () {
|
707
|
-
let node = parseLogicalXor()
|
669
|
+
function parseLogicalOr (state) {
|
670
|
+
let node = parseLogicalXor(state)
|
708
671
|
|
709
|
-
while (token === 'or') { // eslint-disable-line no-unmodified-loop-condition
|
710
|
-
getTokenSkipNewline()
|
711
|
-
node = new OperatorNode('or', 'or', [node, parseLogicalXor()])
|
672
|
+
while (state.token === 'or') { // eslint-disable-line no-unmodified-loop-condition
|
673
|
+
getTokenSkipNewline(state)
|
674
|
+
node = new OperatorNode('or', 'or', [node, parseLogicalXor(state)])
|
712
675
|
}
|
713
676
|
|
714
677
|
return node
|
@@ -719,12 +682,12 @@ function factory (type, config, load, typed) {
|
|
719
682
|
* @return {Node} node
|
720
683
|
* @private
|
721
684
|
*/
|
722
|
-
function parseLogicalXor () {
|
723
|
-
let node = parseLogicalAnd()
|
685
|
+
function parseLogicalXor (state) {
|
686
|
+
let node = parseLogicalAnd(state)
|
724
687
|
|
725
|
-
while (token === 'xor') { // eslint-disable-line no-unmodified-loop-condition
|
726
|
-
getTokenSkipNewline()
|
727
|
-
node = new OperatorNode('xor', 'xor', [node, parseLogicalAnd()])
|
688
|
+
while (state.token === 'xor') { // eslint-disable-line no-unmodified-loop-condition
|
689
|
+
getTokenSkipNewline(state)
|
690
|
+
node = new OperatorNode('xor', 'xor', [node, parseLogicalAnd(state)])
|
728
691
|
}
|
729
692
|
|
730
693
|
return node
|
@@ -735,12 +698,12 @@ function factory (type, config, load, typed) {
|
|
735
698
|
* @return {Node} node
|
736
699
|
* @private
|
737
700
|
*/
|
738
|
-
function parseLogicalAnd () {
|
739
|
-
let node = parseBitwiseOr()
|
701
|
+
function parseLogicalAnd (state) {
|
702
|
+
let node = parseBitwiseOr(state)
|
740
703
|
|
741
|
-
while (token === 'and') { // eslint-disable-line no-unmodified-loop-condition
|
742
|
-
getTokenSkipNewline()
|
743
|
-
node = new OperatorNode('and', 'and', [node, parseBitwiseOr()])
|
704
|
+
while (state.token === 'and') { // eslint-disable-line no-unmodified-loop-condition
|
705
|
+
getTokenSkipNewline(state)
|
706
|
+
node = new OperatorNode('and', 'and', [node, parseBitwiseOr(state)])
|
744
707
|
}
|
745
708
|
|
746
709
|
return node
|
@@ -751,12 +714,12 @@ function factory (type, config, load, typed) {
|
|
751
714
|
* @return {Node} node
|
752
715
|
* @private
|
753
716
|
*/
|
754
|
-
function parseBitwiseOr () {
|
755
|
-
let node = parseBitwiseXor()
|
717
|
+
function parseBitwiseOr (state) {
|
718
|
+
let node = parseBitwiseXor(state)
|
756
719
|
|
757
|
-
while (token === '|') { // eslint-disable-line no-unmodified-loop-condition
|
758
|
-
getTokenSkipNewline()
|
759
|
-
node = new OperatorNode('|', 'bitOr', [node, parseBitwiseXor()])
|
720
|
+
while (state.token === '|') { // eslint-disable-line no-unmodified-loop-condition
|
721
|
+
getTokenSkipNewline(state)
|
722
|
+
node = new OperatorNode('|', 'bitOr', [node, parseBitwiseXor(state)])
|
760
723
|
}
|
761
724
|
|
762
725
|
return node
|
@@ -767,12 +730,12 @@ function factory (type, config, load, typed) {
|
|
767
730
|
* @return {Node} node
|
768
731
|
* @private
|
769
732
|
*/
|
770
|
-
function parseBitwiseXor () {
|
771
|
-
let node = parseBitwiseAnd()
|
733
|
+
function parseBitwiseXor (state) {
|
734
|
+
let node = parseBitwiseAnd(state)
|
772
735
|
|
773
|
-
while (token === '^|') { // eslint-disable-line no-unmodified-loop-condition
|
774
|
-
getTokenSkipNewline()
|
775
|
-
node = new OperatorNode('^|', 'bitXor', [node, parseBitwiseAnd()])
|
736
|
+
while (state.token === '^|') { // eslint-disable-line no-unmodified-loop-condition
|
737
|
+
getTokenSkipNewline(state)
|
738
|
+
node = new OperatorNode('^|', 'bitXor', [node, parseBitwiseAnd(state)])
|
776
739
|
}
|
777
740
|
|
778
741
|
return node
|
@@ -783,12 +746,12 @@ function factory (type, config, load, typed) {
|
|
783
746
|
* @return {Node} node
|
784
747
|
* @private
|
785
748
|
*/
|
786
|
-
function parseBitwiseAnd () {
|
787
|
-
let node = parseRelational()
|
749
|
+
function parseBitwiseAnd (state) {
|
750
|
+
let node = parseRelational(state)
|
788
751
|
|
789
|
-
while (token === '&') { // eslint-disable-line no-unmodified-loop-condition
|
790
|
-
getTokenSkipNewline()
|
791
|
-
node = new OperatorNode('&', 'bitAnd', [node, parseRelational()])
|
752
|
+
while (state.token === '&') { // eslint-disable-line no-unmodified-loop-condition
|
753
|
+
getTokenSkipNewline(state)
|
754
|
+
node = new OperatorNode('&', 'bitAnd', [node, parseRelational(state)])
|
792
755
|
}
|
793
756
|
|
794
757
|
return node
|
@@ -799,10 +762,10 @@ function factory (type, config, load, typed) {
|
|
799
762
|
* @return {Node} node
|
800
763
|
* @private
|
801
764
|
*/
|
802
|
-
function parseRelational () {
|
765
|
+
function parseRelational (state) {
|
803
766
|
let node, operators, name, fn, params
|
804
767
|
|
805
|
-
node = parseShift()
|
768
|
+
node = parseShift(state)
|
806
769
|
|
807
770
|
operators = {
|
808
771
|
'==': 'equal',
|
@@ -812,12 +775,12 @@ function factory (type, config, load, typed) {
|
|
812
775
|
'<=': 'smallerEq',
|
813
776
|
'>=': 'largerEq'
|
814
777
|
}
|
815
|
-
while (operators.hasOwnProperty(token)) {
|
816
|
-
name = token
|
778
|
+
while (operators.hasOwnProperty(state.token)) {
|
779
|
+
name = state.token
|
817
780
|
fn = operators[name]
|
818
781
|
|
819
|
-
getTokenSkipNewline()
|
820
|
-
params = [node, parseShift()]
|
782
|
+
getTokenSkipNewline(state)
|
783
|
+
params = [node, parseShift(state)]
|
821
784
|
node = new OperatorNode(name, fn, params)
|
822
785
|
}
|
823
786
|
|
@@ -829,10 +792,10 @@ function factory (type, config, load, typed) {
|
|
829
792
|
* @return {Node} node
|
830
793
|
* @private
|
831
794
|
*/
|
832
|
-
function parseShift () {
|
795
|
+
function parseShift (state) {
|
833
796
|
let node, operators, name, fn, params
|
834
797
|
|
835
|
-
node = parseConversion()
|
798
|
+
node = parseConversion(state)
|
836
799
|
|
837
800
|
operators = {
|
838
801
|
'<<': 'leftShift',
|
@@ -840,12 +803,12 @@ function factory (type, config, load, typed) {
|
|
840
803
|
'>>>': 'rightLogShift'
|
841
804
|
}
|
842
805
|
|
843
|
-
while (operators.hasOwnProperty(token)) {
|
844
|
-
name = token
|
806
|
+
while (operators.hasOwnProperty(state.token)) {
|
807
|
+
name = state.token
|
845
808
|
fn = operators[name]
|
846
809
|
|
847
|
-
getTokenSkipNewline()
|
848
|
-
params = [node, parseConversion()]
|
810
|
+
getTokenSkipNewline(state)
|
811
|
+
params = [node, parseConversion(state)]
|
849
812
|
node = new OperatorNode(name, fn, params)
|
850
813
|
}
|
851
814
|
|
@@ -857,28 +820,28 @@ function factory (type, config, load, typed) {
|
|
857
820
|
* @return {Node} node
|
858
821
|
* @private
|
859
822
|
*/
|
860
|
-
function parseConversion () {
|
823
|
+
function parseConversion (state) {
|
861
824
|
let node, operators, name, fn, params
|
862
825
|
|
863
|
-
node = parseRange()
|
826
|
+
node = parseRange(state)
|
864
827
|
|
865
828
|
operators = {
|
866
829
|
'to': 'to',
|
867
830
|
'in': 'to' // alias of 'to'
|
868
831
|
}
|
869
832
|
|
870
|
-
while (operators.hasOwnProperty(token)) {
|
871
|
-
name = token
|
833
|
+
while (operators.hasOwnProperty(state.token)) {
|
834
|
+
name = state.token
|
872
835
|
fn = operators[name]
|
873
836
|
|
874
|
-
getTokenSkipNewline()
|
837
|
+
getTokenSkipNewline(state)
|
875
838
|
|
876
|
-
if (name === 'in' && token === '') {
|
839
|
+
if (name === 'in' && state.token === '') {
|
877
840
|
// end of expression -> this is the unit 'in' ('inch')
|
878
841
|
node = new OperatorNode('*', 'multiply', [node, new SymbolNode('in')], true)
|
879
842
|
} else {
|
880
843
|
// operator 'a to b' or 'a in b'
|
881
|
-
params = [node, parseRange()]
|
844
|
+
params = [node, parseRange(state)]
|
882
845
|
node = new OperatorNode(name, fn, params)
|
883
846
|
}
|
884
847
|
}
|
@@ -891,32 +854,32 @@ function factory (type, config, load, typed) {
|
|
891
854
|
* @return {Node} node
|
892
855
|
* @private
|
893
856
|
*/
|
894
|
-
function parseRange () {
|
857
|
+
function parseRange (state) {
|
895
858
|
let node
|
896
859
|
const params = []
|
897
860
|
|
898
|
-
if (token === ':') {
|
861
|
+
if (state.token === ':') {
|
899
862
|
// implicit start=1 (one-based)
|
900
863
|
node = new ConstantNode(1)
|
901
864
|
} else {
|
902
865
|
// explicit start
|
903
|
-
node = parseAddSubtract()
|
866
|
+
node = parseAddSubtract(state)
|
904
867
|
}
|
905
868
|
|
906
|
-
if (token === ':' && (conditionalLevel !== nestingLevel)) {
|
869
|
+
if (state.token === ':' && (state.conditionalLevel !== state.nestingLevel)) {
|
907
870
|
// we ignore the range operator when a conditional operator is being processed on the same level
|
908
871
|
params.push(node)
|
909
872
|
|
910
873
|
// parse step and end
|
911
|
-
while (token === ':' && params.length < 3) { // eslint-disable-line no-unmodified-loop-condition
|
912
|
-
getTokenSkipNewline()
|
874
|
+
while (state.token === ':' && params.length < 3) { // eslint-disable-line no-unmodified-loop-condition
|
875
|
+
getTokenSkipNewline(state)
|
913
876
|
|
914
|
-
if (token === ')' || token === ']' || token === ',' || token === '') {
|
877
|
+
if (state.token === ')' || state.token === ']' || state.token === ',' || state.token === '') {
|
915
878
|
// implicit end
|
916
879
|
params.push(new SymbolNode('end'))
|
917
880
|
} else {
|
918
881
|
// explicit end
|
919
|
-
params.push(parseAddSubtract())
|
882
|
+
params.push(parseAddSubtract(state))
|
920
883
|
}
|
921
884
|
}
|
922
885
|
|
@@ -937,21 +900,21 @@ function factory (type, config, load, typed) {
|
|
937
900
|
* @return {Node} node
|
938
901
|
* @private
|
939
902
|
*/
|
940
|
-
function parseAddSubtract () {
|
903
|
+
function parseAddSubtract (state) {
|
941
904
|
let node, operators, name, fn, params
|
942
905
|
|
943
|
-
node = parseMultiplyDivide()
|
906
|
+
node = parseMultiplyDivide(state)
|
944
907
|
|
945
908
|
operators = {
|
946
909
|
'+': 'add',
|
947
910
|
'-': 'subtract'
|
948
911
|
}
|
949
|
-
while (operators.hasOwnProperty(token)) {
|
950
|
-
name = token
|
912
|
+
while (operators.hasOwnProperty(state.token)) {
|
913
|
+
name = state.token
|
951
914
|
fn = operators[name]
|
952
915
|
|
953
|
-
getTokenSkipNewline()
|
954
|
-
params = [node, parseMultiplyDivide()]
|
916
|
+
getTokenSkipNewline(state)
|
917
|
+
params = [node, parseMultiplyDivide(state)]
|
955
918
|
node = new OperatorNode(name, fn, params)
|
956
919
|
}
|
957
920
|
|
@@ -963,10 +926,10 @@ function factory (type, config, load, typed) {
|
|
963
926
|
* @return {Node} node
|
964
927
|
* @private
|
965
928
|
*/
|
966
|
-
function parseMultiplyDivide () {
|
929
|
+
function parseMultiplyDivide (state) {
|
967
930
|
let node, last, operators, name, fn
|
968
931
|
|
969
|
-
node = parseImplicitMultiplication()
|
932
|
+
node = parseImplicitMultiplication(state)
|
970
933
|
last = node
|
971
934
|
|
972
935
|
operators = {
|
@@ -979,14 +942,14 @@ function factory (type, config, load, typed) {
|
|
979
942
|
}
|
980
943
|
|
981
944
|
while (true) {
|
982
|
-
if (operators.hasOwnProperty(token)) {
|
945
|
+
if (operators.hasOwnProperty(state.token)) {
|
983
946
|
// explicit operators
|
984
|
-
name = token
|
947
|
+
name = state.token
|
985
948
|
fn = operators[name]
|
986
949
|
|
987
|
-
getTokenSkipNewline()
|
950
|
+
getTokenSkipNewline(state)
|
988
951
|
|
989
|
-
last = parseImplicitMultiplication()
|
952
|
+
last = parseImplicitMultiplication(state)
|
990
953
|
node = new OperatorNode(name, fn, [node, last])
|
991
954
|
} else {
|
992
955
|
break
|
@@ -1001,25 +964,25 @@ function factory (type, config, load, typed) {
|
|
1001
964
|
* @return {Node} node
|
1002
965
|
* @private
|
1003
966
|
*/
|
1004
|
-
function parseImplicitMultiplication () {
|
967
|
+
function parseImplicitMultiplication (state) {
|
1005
968
|
let node, last
|
1006
969
|
|
1007
|
-
node = parseRule2()
|
970
|
+
node = parseRule2(state)
|
1008
971
|
last = node
|
1009
972
|
|
1010
973
|
while (true) {
|
1011
|
-
if ((tokenType === TOKENTYPE.SYMBOL) ||
|
1012
|
-
(token === 'in' && type.isConstantNode(node)) ||
|
1013
|
-
(tokenType === TOKENTYPE.NUMBER &&
|
974
|
+
if ((state.tokenType === TOKENTYPE.SYMBOL) ||
|
975
|
+
(state.token === 'in' && type.isConstantNode(node)) ||
|
976
|
+
(state.tokenType === TOKENTYPE.NUMBER &&
|
1014
977
|
!type.isConstantNode(last) &&
|
1015
978
|
(!type.isOperatorNode(last) || last.op === '!')) ||
|
1016
|
-
(token === '(')) {
|
979
|
+
(state.token === '(')) {
|
1017
980
|
// parse implicit multiplication
|
1018
981
|
//
|
1019
982
|
// symbol: implicit multiplication like '2a', '(2+3)a', 'a b'
|
1020
983
|
// number: implicit multiplication like '(2+3)2'
|
1021
984
|
// parenthesis: implicit multiplication like '2(3+4)', '(3+4)(1+2)'
|
1022
|
-
last = parseRule2()
|
985
|
+
last = parseRule2(state)
|
1023
986
|
node = new OperatorNode('*', 'multiply', [node, last], true /* implicit */)
|
1024
987
|
} else {
|
1025
988
|
break
|
@@ -1036,42 +999,41 @@ function factory (type, config, load, typed) {
|
|
1036
999
|
* @return {Node} node
|
1037
1000
|
* @private
|
1038
1001
|
*/
|
1039
|
-
function parseRule2 () {
|
1040
|
-
let node
|
1041
|
-
|
1042
|
-
|
1043
|
-
last = node
|
1002
|
+
function parseRule2 (state) {
|
1003
|
+
let node = parseUnary(state)
|
1004
|
+
let last = node
|
1005
|
+
let tokenStates = []
|
1044
1006
|
|
1045
1007
|
while (true) {
|
1046
1008
|
// Match the "number /" part of the pattern "number / number symbol"
|
1047
|
-
if (token === '/' && type.isConstantNode(last)) {
|
1009
|
+
if (state.token === '/' && type.isConstantNode(last)) {
|
1048
1010
|
// Look ahead to see if the next token is a number
|
1049
|
-
|
1050
|
-
getTokenSkipNewline()
|
1011
|
+
tokenStates.push(Object.assign({}, state))
|
1012
|
+
getTokenSkipNewline(state)
|
1051
1013
|
|
1052
1014
|
// Match the "number / number" part of the pattern
|
1053
|
-
if (tokenType === TOKENTYPE.NUMBER) {
|
1015
|
+
if (state.tokenType === TOKENTYPE.NUMBER) {
|
1054
1016
|
// Look ahead again
|
1055
|
-
|
1056
|
-
getTokenSkipNewline()
|
1017
|
+
tokenStates.push(Object.assign({}, state))
|
1018
|
+
getTokenSkipNewline(state)
|
1057
1019
|
|
1058
1020
|
// Match the "symbol" part of the pattern, or a left parenthesis
|
1059
|
-
if (tokenType === TOKENTYPE.SYMBOL || token === '(') {
|
1021
|
+
if (state.tokenType === TOKENTYPE.SYMBOL || state.token === '(') {
|
1060
1022
|
// We've matched the pattern "number / number symbol".
|
1061
1023
|
// Rewind once and build the "number / number" node; the symbol will be consumed later
|
1062
|
-
|
1063
|
-
|
1064
|
-
last = parseUnary()
|
1024
|
+
Object.assign(state, tokenStates.pop())
|
1025
|
+
tokenStates.pop()
|
1026
|
+
last = parseUnary(state)
|
1065
1027
|
node = new OperatorNode('/', 'divide', [node, last])
|
1066
1028
|
} else {
|
1067
1029
|
// Not a match, so rewind
|
1068
|
-
|
1069
|
-
|
1030
|
+
tokenStates.pop()
|
1031
|
+
Object.assign(state, tokenStates.pop())
|
1070
1032
|
break
|
1071
1033
|
}
|
1072
1034
|
} else {
|
1073
1035
|
// Not a match, so rewind
|
1074
|
-
|
1036
|
+
Object.assign(state, tokenStates.pop())
|
1075
1037
|
break
|
1076
1038
|
}
|
1077
1039
|
} else {
|
@@ -1087,7 +1049,7 @@ function factory (type, config, load, typed) {
|
|
1087
1049
|
* @return {Node} node
|
1088
1050
|
* @private
|
1089
1051
|
*/
|
1090
|
-
function parseUnary () {
|
1052
|
+
function parseUnary (state) {
|
1091
1053
|
let name, params, fn
|
1092
1054
|
const operators = {
|
1093
1055
|
'-': 'unaryMinus',
|
@@ -1096,17 +1058,17 @@ function factory (type, config, load, typed) {
|
|
1096
1058
|
'not': 'not'
|
1097
1059
|
}
|
1098
1060
|
|
1099
|
-
if (operators.hasOwnProperty(token)) {
|
1100
|
-
fn = operators[token]
|
1101
|
-
name = token
|
1061
|
+
if (operators.hasOwnProperty(state.token)) {
|
1062
|
+
fn = operators[state.token]
|
1063
|
+
name = state.token
|
1102
1064
|
|
1103
|
-
getTokenSkipNewline()
|
1104
|
-
params = [parseUnary()]
|
1065
|
+
getTokenSkipNewline(state)
|
1066
|
+
params = [parseUnary(state)]
|
1105
1067
|
|
1106
1068
|
return new OperatorNode(name, fn, params)
|
1107
1069
|
}
|
1108
1070
|
|
1109
|
-
return parsePow()
|
1071
|
+
return parsePow(state)
|
1110
1072
|
}
|
1111
1073
|
|
1112
1074
|
/**
|
@@ -1115,17 +1077,17 @@ function factory (type, config, load, typed) {
|
|
1115
1077
|
* @return {Node} node
|
1116
1078
|
* @private
|
1117
1079
|
*/
|
1118
|
-
function parsePow () {
|
1080
|
+
function parsePow (state) {
|
1119
1081
|
let node, name, fn, params
|
1120
1082
|
|
1121
|
-
node = parseLeftHandOperators()
|
1083
|
+
node = parseLeftHandOperators(state)
|
1122
1084
|
|
1123
|
-
if (token === '^' || token === '.^') {
|
1124
|
-
name = token
|
1085
|
+
if (state.token === '^' || state.token === '.^') {
|
1086
|
+
name = state.token
|
1125
1087
|
fn = (name === '^') ? 'pow' : 'dotPow'
|
1126
1088
|
|
1127
|
-
getTokenSkipNewline()
|
1128
|
-
params = [node, parseUnary()] // Go back to unary, we can have '2^-3'
|
1089
|
+
getTokenSkipNewline(state)
|
1090
|
+
params = [node, parseUnary(state)] // Go back to unary, we can have '2^-3'
|
1129
1091
|
node = new OperatorNode(name, fn, params)
|
1130
1092
|
}
|
1131
1093
|
|
@@ -1137,25 +1099,25 @@ function factory (type, config, load, typed) {
|
|
1137
1099
|
* @return {Node} node
|
1138
1100
|
* @private
|
1139
1101
|
*/
|
1140
|
-
function parseLeftHandOperators () {
|
1102
|
+
function parseLeftHandOperators (state) {
|
1141
1103
|
let node, operators, name, fn, params
|
1142
1104
|
|
1143
|
-
node = parseCustomNodes()
|
1105
|
+
node = parseCustomNodes(state)
|
1144
1106
|
|
1145
1107
|
operators = {
|
1146
1108
|
'!': 'factorial',
|
1147
1109
|
'\'': 'ctranspose'
|
1148
1110
|
}
|
1149
1111
|
|
1150
|
-
while (operators.hasOwnProperty(token)) {
|
1151
|
-
name = token
|
1112
|
+
while (operators.hasOwnProperty(state.token)) {
|
1113
|
+
name = state.token
|
1152
1114
|
fn = operators[name]
|
1153
1115
|
|
1154
|
-
getToken()
|
1116
|
+
getToken(state)
|
1155
1117
|
params = [node]
|
1156
1118
|
|
1157
1119
|
node = new OperatorNode(name, fn, params)
|
1158
|
-
node = parseAccessors(node)
|
1120
|
+
node = parseAccessors(state, node)
|
1159
1121
|
}
|
1160
1122
|
|
1161
1123
|
return node
|
@@ -1189,36 +1151,36 @@ function factory (type, config, load, typed) {
|
|
1189
1151
|
* @return {Node} node
|
1190
1152
|
* @private
|
1191
1153
|
*/
|
1192
|
-
function parseCustomNodes () {
|
1154
|
+
function parseCustomNodes (state) {
|
1193
1155
|
let params = []
|
1194
1156
|
|
1195
|
-
if (tokenType === TOKENTYPE.SYMBOL && extraNodes.hasOwnProperty(token)) {
|
1196
|
-
const CustomNode = extraNodes[token]
|
1157
|
+
if (state.tokenType === TOKENTYPE.SYMBOL && state.extraNodes.hasOwnProperty(state.token)) {
|
1158
|
+
const CustomNode = state.extraNodes[state.token]
|
1197
1159
|
|
1198
|
-
getToken()
|
1160
|
+
getToken(state)
|
1199
1161
|
|
1200
1162
|
// parse parameters
|
1201
|
-
if (token === '(') {
|
1163
|
+
if (state.token === '(') {
|
1202
1164
|
params = []
|
1203
1165
|
|
1204
|
-
openParams()
|
1205
|
-
getToken()
|
1166
|
+
openParams(state)
|
1167
|
+
getToken(state)
|
1206
1168
|
|
1207
|
-
if (token !== ')') {
|
1208
|
-
params.push(parseAssignment())
|
1169
|
+
if (state.token !== ')') {
|
1170
|
+
params.push(parseAssignment(state))
|
1209
1171
|
|
1210
1172
|
// parse a list with parameters
|
1211
|
-
while (token === ',') { // eslint-disable-line no-unmodified-loop-condition
|
1212
|
-
getToken()
|
1213
|
-
params.push(parseAssignment())
|
1173
|
+
while (state.token === ',') { // eslint-disable-line no-unmodified-loop-condition
|
1174
|
+
getToken(state)
|
1175
|
+
params.push(parseAssignment(state))
|
1214
1176
|
}
|
1215
1177
|
}
|
1216
1178
|
|
1217
|
-
if (token !== ')') {
|
1218
|
-
throw createSyntaxError('Parenthesis ) expected')
|
1179
|
+
if (state.token !== ')') {
|
1180
|
+
throw createSyntaxError(state, 'Parenthesis ) expected')
|
1219
1181
|
}
|
1220
|
-
closeParams()
|
1221
|
-
getToken()
|
1182
|
+
closeParams(state)
|
1183
|
+
getToken(state)
|
1222
1184
|
}
|
1223
1185
|
|
1224
1186
|
// create a new custom node
|
@@ -1226,7 +1188,7 @@ function factory (type, config, load, typed) {
|
|
1226
1188
|
return new CustomNode(params)
|
1227
1189
|
}
|
1228
1190
|
|
1229
|
-
return parseSymbol()
|
1191
|
+
return parseSymbol(state)
|
1230
1192
|
}
|
1231
1193
|
|
1232
1194
|
/**
|
@@ -1234,14 +1196,14 @@ function factory (type, config, load, typed) {
|
|
1234
1196
|
* @return {Node} node
|
1235
1197
|
* @private
|
1236
1198
|
*/
|
1237
|
-
function parseSymbol () {
|
1199
|
+
function parseSymbol (state) {
|
1238
1200
|
let node, name
|
1239
1201
|
|
1240
|
-
if (tokenType === TOKENTYPE.SYMBOL ||
|
1241
|
-
(tokenType === TOKENTYPE.DELIMITER && token in NAMED_DELIMITERS)) {
|
1242
|
-
name = token
|
1202
|
+
if (state.tokenType === TOKENTYPE.SYMBOL ||
|
1203
|
+
(state.tokenType === TOKENTYPE.DELIMITER && state.token in NAMED_DELIMITERS)) {
|
1204
|
+
name = state.token
|
1243
1205
|
|
1244
|
-
getToken()
|
1206
|
+
getToken(state)
|
1245
1207
|
|
1246
1208
|
if (CONSTANTS.hasOwnProperty(name)) { // true, false, null, ...
|
1247
1209
|
node = new ConstantNode(CONSTANTS[name])
|
@@ -1252,11 +1214,11 @@ function factory (type, config, load, typed) {
|
|
1252
1214
|
}
|
1253
1215
|
|
1254
1216
|
// parse function parameters and matrix index
|
1255
|
-
node = parseAccessors(node)
|
1217
|
+
node = parseAccessors(state, node)
|
1256
1218
|
return node
|
1257
1219
|
}
|
1258
1220
|
|
1259
|
-
return parseString()
|
1221
|
+
return parseString(state)
|
1260
1222
|
}
|
1261
1223
|
|
1262
1224
|
/**
|
@@ -1272,34 +1234,34 @@ function factory (type, config, load, typed) {
|
|
1272
1234
|
* @return {Node} node
|
1273
1235
|
* @private
|
1274
1236
|
*/
|
1275
|
-
function parseAccessors (node, types) {
|
1237
|
+
function parseAccessors (state, node, types) {
|
1276
1238
|
let params
|
1277
1239
|
|
1278
|
-
while ((token === '(' || token === '[' || token === '.') &&
|
1279
|
-
(!types || types.indexOf(token) !== -1)) { // eslint-disable-line no-unmodified-loop-condition
|
1240
|
+
while ((state.token === '(' || state.token === '[' || state.token === '.') &&
|
1241
|
+
(!types || types.indexOf(state.token) !== -1)) { // eslint-disable-line no-unmodified-loop-condition
|
1280
1242
|
params = []
|
1281
1243
|
|
1282
|
-
if (token === '(') {
|
1244
|
+
if (state.token === '(') {
|
1283
1245
|
if (type.isSymbolNode(node) || type.isAccessorNode(node)) {
|
1284
1246
|
// function invocation like fn(2, 3) or obj.fn(2, 3)
|
1285
|
-
openParams()
|
1286
|
-
getToken()
|
1247
|
+
openParams(state)
|
1248
|
+
getToken(state)
|
1287
1249
|
|
1288
|
-
if (token !== ')') {
|
1289
|
-
params.push(parseAssignment())
|
1250
|
+
if (state.token !== ')') {
|
1251
|
+
params.push(parseAssignment(state))
|
1290
1252
|
|
1291
1253
|
// parse a list with parameters
|
1292
|
-
while (token === ',') { // eslint-disable-line no-unmodified-loop-condition
|
1293
|
-
getToken()
|
1294
|
-
params.push(parseAssignment())
|
1254
|
+
while (state.token === ',') { // eslint-disable-line no-unmodified-loop-condition
|
1255
|
+
getToken(state)
|
1256
|
+
params.push(parseAssignment(state))
|
1295
1257
|
}
|
1296
1258
|
}
|
1297
1259
|
|
1298
|
-
if (token !== ')') {
|
1299
|
-
throw createSyntaxError('Parenthesis ) expected')
|
1260
|
+
if (state.token !== ')') {
|
1261
|
+
throw createSyntaxError(state, 'Parenthesis ) expected')
|
1300
1262
|
}
|
1301
|
-
closeParams()
|
1302
|
-
getToken()
|
1263
|
+
closeParams(state)
|
1264
|
+
getToken(state)
|
1303
1265
|
|
1304
1266
|
node = new FunctionNode(node, params)
|
1305
1267
|
} else {
|
@@ -1308,37 +1270,37 @@ function factory (type, config, load, typed) {
|
|
1308
1270
|
// with correct precedence
|
1309
1271
|
return node
|
1310
1272
|
}
|
1311
|
-
} else if (token === '[') {
|
1273
|
+
} else if (state.token === '[') {
|
1312
1274
|
// index notation like variable[2, 3]
|
1313
|
-
openParams()
|
1314
|
-
getToken()
|
1275
|
+
openParams(state)
|
1276
|
+
getToken(state)
|
1315
1277
|
|
1316
|
-
if (token !== ']') {
|
1317
|
-
params.push(parseAssignment())
|
1278
|
+
if (state.token !== ']') {
|
1279
|
+
params.push(parseAssignment(state))
|
1318
1280
|
|
1319
1281
|
// parse a list with parameters
|
1320
|
-
while (token === ',') { // eslint-disable-line no-unmodified-loop-condition
|
1321
|
-
getToken()
|
1322
|
-
params.push(parseAssignment())
|
1282
|
+
while (state.token === ',') { // eslint-disable-line no-unmodified-loop-condition
|
1283
|
+
getToken(state)
|
1284
|
+
params.push(parseAssignment(state))
|
1323
1285
|
}
|
1324
1286
|
}
|
1325
1287
|
|
1326
|
-
if (token !== ']') {
|
1327
|
-
throw createSyntaxError('Parenthesis ] expected')
|
1288
|
+
if (state.token !== ']') {
|
1289
|
+
throw createSyntaxError(state, 'Parenthesis ] expected')
|
1328
1290
|
}
|
1329
|
-
closeParams()
|
1330
|
-
getToken()
|
1291
|
+
closeParams(state)
|
1292
|
+
getToken(state)
|
1331
1293
|
|
1332
1294
|
node = new AccessorNode(node, new IndexNode(params))
|
1333
1295
|
} else {
|
1334
1296
|
// dot notation like variable.prop
|
1335
|
-
getToken()
|
1297
|
+
getToken(state)
|
1336
1298
|
|
1337
|
-
if (tokenType !== TOKENTYPE.SYMBOL) {
|
1338
|
-
throw createSyntaxError('Property name expected after dot')
|
1299
|
+
if (state.tokenType !== TOKENTYPE.SYMBOL) {
|
1300
|
+
throw createSyntaxError(state, 'Property name expected after dot')
|
1339
1301
|
}
|
1340
|
-
params.push(new ConstantNode(token))
|
1341
|
-
getToken()
|
1302
|
+
params.push(new ConstantNode(state.token))
|
1303
|
+
getToken(state)
|
1342
1304
|
|
1343
1305
|
const dotNotation = true
|
1344
1306
|
node = new AccessorNode(node, new IndexNode(params, dotNotation))
|
@@ -1354,48 +1316,48 @@ function factory (type, config, load, typed) {
|
|
1354
1316
|
* @return {Node} node
|
1355
1317
|
* @private
|
1356
1318
|
*/
|
1357
|
-
function parseString () {
|
1319
|
+
function parseString (state) {
|
1358
1320
|
let node, str
|
1359
1321
|
|
1360
|
-
if (token === '"') {
|
1361
|
-
str = parseStringToken()
|
1322
|
+
if (state.token === '"') {
|
1323
|
+
str = parseStringToken(state)
|
1362
1324
|
|
1363
1325
|
// create constant
|
1364
1326
|
node = new ConstantNode(str)
|
1365
1327
|
|
1366
1328
|
// parse index parameters
|
1367
|
-
node = parseAccessors(node)
|
1329
|
+
node = parseAccessors(state, node)
|
1368
1330
|
|
1369
1331
|
return node
|
1370
1332
|
}
|
1371
1333
|
|
1372
|
-
return parseMatrix()
|
1334
|
+
return parseMatrix(state)
|
1373
1335
|
}
|
1374
1336
|
|
1375
1337
|
/**
|
1376
1338
|
* Parse a string surrounded by double quotes "..."
|
1377
1339
|
* @return {string}
|
1378
1340
|
*/
|
1379
|
-
function parseStringToken () {
|
1341
|
+
function parseStringToken (state) {
|
1380
1342
|
let str = ''
|
1381
1343
|
|
1382
|
-
while (
|
1383
|
-
if (
|
1344
|
+
while (currentCharacter(state) !== '' && currentCharacter(state) !== '"') {
|
1345
|
+
if (currentCharacter(state) === '\\') {
|
1384
1346
|
// escape character, immediately process the next
|
1385
1347
|
// character to prevent stopping at a next '\"'
|
1386
|
-
str +=
|
1387
|
-
next()
|
1348
|
+
str += currentCharacter(state)
|
1349
|
+
next(state)
|
1388
1350
|
}
|
1389
1351
|
|
1390
|
-
str +=
|
1391
|
-
next()
|
1352
|
+
str += currentCharacter(state)
|
1353
|
+
next(state)
|
1392
1354
|
}
|
1393
1355
|
|
1394
|
-
getToken()
|
1395
|
-
if (token !== '"') {
|
1396
|
-
throw createSyntaxError('End of string " expected')
|
1356
|
+
getToken(state)
|
1357
|
+
if (state.token !== '"') {
|
1358
|
+
throw createSyntaxError(state, 'End of string " expected')
|
1397
1359
|
}
|
1398
|
-
getToken()
|
1360
|
+
getToken(state)
|
1399
1361
|
|
1400
1362
|
return JSON.parse('"' + str + '"') // unescape escaped characters
|
1401
1363
|
}
|
@@ -1405,42 +1367,42 @@ function factory (type, config, load, typed) {
|
|
1405
1367
|
* @return {Node} node
|
1406
1368
|
* @private
|
1407
1369
|
*/
|
1408
|
-
function parseMatrix () {
|
1370
|
+
function parseMatrix (state) {
|
1409
1371
|
let array, params, rows, cols
|
1410
1372
|
|
1411
|
-
if (token === '[') {
|
1373
|
+
if (state.token === '[') {
|
1412
1374
|
// matrix [...]
|
1413
|
-
openParams()
|
1414
|
-
getToken()
|
1375
|
+
openParams(state)
|
1376
|
+
getToken(state)
|
1415
1377
|
|
1416
|
-
if (token !== ']') {
|
1378
|
+
if (state.token !== ']') {
|
1417
1379
|
// this is a non-empty matrix
|
1418
|
-
const row = parseRow()
|
1380
|
+
const row = parseRow(state)
|
1419
1381
|
|
1420
|
-
if (token === ';') {
|
1382
|
+
if (state.token === ';') {
|
1421
1383
|
// 2 dimensional array
|
1422
1384
|
rows = 1
|
1423
1385
|
params = [row]
|
1424
1386
|
|
1425
1387
|
// the rows of the matrix are separated by dot-comma's
|
1426
|
-
while (token === ';') { // eslint-disable-line no-unmodified-loop-condition
|
1427
|
-
getToken()
|
1388
|
+
while (state.token === ';') { // eslint-disable-line no-unmodified-loop-condition
|
1389
|
+
getToken(state)
|
1428
1390
|
|
1429
|
-
params[rows] = parseRow()
|
1391
|
+
params[rows] = parseRow(state)
|
1430
1392
|
rows++
|
1431
1393
|
}
|
1432
1394
|
|
1433
|
-
if (token !== ']') {
|
1434
|
-
throw createSyntaxError('End of matrix ] expected')
|
1395
|
+
if (state.token !== ']') {
|
1396
|
+
throw createSyntaxError(state, 'End of matrix ] expected')
|
1435
1397
|
}
|
1436
|
-
closeParams()
|
1437
|
-
getToken()
|
1398
|
+
closeParams(state)
|
1399
|
+
getToken(state)
|
1438
1400
|
|
1439
1401
|
// check if the number of columns matches in all rows
|
1440
1402
|
cols = params[0].items.length
|
1441
1403
|
for (let r = 1; r < rows; r++) {
|
1442
1404
|
if (params[r].items.length !== cols) {
|
1443
|
-
throw createError('Column dimensions mismatch ' +
|
1405
|
+
throw createError(state, 'Column dimensions mismatch ' +
|
1444
1406
|
'(' + params[r].items.length + ' !== ' + cols + ')')
|
1445
1407
|
}
|
1446
1408
|
}
|
@@ -1448,40 +1410,40 @@ function factory (type, config, load, typed) {
|
|
1448
1410
|
array = new ArrayNode(params)
|
1449
1411
|
} else {
|
1450
1412
|
// 1 dimensional vector
|
1451
|
-
if (token !== ']') {
|
1452
|
-
throw createSyntaxError('End of matrix ] expected')
|
1413
|
+
if (state.token !== ']') {
|
1414
|
+
throw createSyntaxError(state, 'End of matrix ] expected')
|
1453
1415
|
}
|
1454
|
-
closeParams()
|
1455
|
-
getToken()
|
1416
|
+
closeParams(state)
|
1417
|
+
getToken(state)
|
1456
1418
|
|
1457
1419
|
array = row
|
1458
1420
|
}
|
1459
1421
|
} else {
|
1460
1422
|
// this is an empty matrix "[ ]"
|
1461
|
-
closeParams()
|
1462
|
-
getToken()
|
1423
|
+
closeParams(state)
|
1424
|
+
getToken(state)
|
1463
1425
|
array = new ArrayNode([])
|
1464
1426
|
}
|
1465
1427
|
|
1466
|
-
return parseAccessors(array)
|
1428
|
+
return parseAccessors(state, array)
|
1467
1429
|
}
|
1468
1430
|
|
1469
|
-
return parseObject()
|
1431
|
+
return parseObject(state)
|
1470
1432
|
}
|
1471
1433
|
|
1472
1434
|
/**
|
1473
1435
|
* Parse a single comma-separated row from a matrix, like 'a, b, c'
|
1474
1436
|
* @return {ArrayNode} node
|
1475
1437
|
*/
|
1476
|
-
function parseRow () {
|
1477
|
-
const params = [parseAssignment()]
|
1438
|
+
function parseRow (state) {
|
1439
|
+
const params = [parseAssignment(state)]
|
1478
1440
|
let len = 1
|
1479
1441
|
|
1480
|
-
while (token === ',') { // eslint-disable-line no-unmodified-loop-condition
|
1481
|
-
getToken()
|
1442
|
+
while (state.token === ',') { // eslint-disable-line no-unmodified-loop-condition
|
1443
|
+
getToken(state)
|
1482
1444
|
|
1483
1445
|
// parse expression
|
1484
|
-
params[len] = parseAssignment()
|
1446
|
+
params[len] = parseAssignment(state)
|
1485
1447
|
len++
|
1486
1448
|
}
|
1487
1449
|
|
@@ -1493,51 +1455,51 @@ function factory (type, config, load, typed) {
|
|
1493
1455
|
* @return {Node} node
|
1494
1456
|
* @private
|
1495
1457
|
*/
|
1496
|
-
function parseObject () {
|
1497
|
-
if (token === '{') {
|
1458
|
+
function parseObject (state) {
|
1459
|
+
if (state.token === '{') {
|
1498
1460
|
let key
|
1499
1461
|
|
1500
1462
|
const properties = {}
|
1501
1463
|
do {
|
1502
|
-
getToken()
|
1464
|
+
getToken(state)
|
1503
1465
|
|
1504
|
-
if (token !== '}') {
|
1466
|
+
if (state.token !== '}') {
|
1505
1467
|
// parse key
|
1506
|
-
if (token === '"') {
|
1507
|
-
key = parseStringToken()
|
1508
|
-
} else if (tokenType === TOKENTYPE.SYMBOL) {
|
1509
|
-
key = token
|
1510
|
-
getToken()
|
1468
|
+
if (state.token === '"') {
|
1469
|
+
key = parseStringToken(state)
|
1470
|
+
} else if (state.tokenType === TOKENTYPE.SYMBOL) {
|
1471
|
+
key = state.token
|
1472
|
+
getToken(state)
|
1511
1473
|
} else {
|
1512
|
-
throw createSyntaxError('Symbol or string expected as object key')
|
1474
|
+
throw createSyntaxError(state, 'Symbol or string expected as object key')
|
1513
1475
|
}
|
1514
1476
|
|
1515
1477
|
// parse key/value separator
|
1516
|
-
if (token !== ':') {
|
1517
|
-
throw createSyntaxError('Colon : expected after object key')
|
1478
|
+
if (state.token !== ':') {
|
1479
|
+
throw createSyntaxError(state, 'Colon : expected after object key')
|
1518
1480
|
}
|
1519
|
-
getToken()
|
1481
|
+
getToken(state)
|
1520
1482
|
|
1521
1483
|
// parse key
|
1522
|
-
properties[key] = parseAssignment()
|
1484
|
+
properties[key] = parseAssignment(state)
|
1523
1485
|
}
|
1524
1486
|
}
|
1525
|
-
while (token === ',') // eslint-disable-line no-unmodified-loop-condition
|
1487
|
+
while (state.token === ',') // eslint-disable-line no-unmodified-loop-condition
|
1526
1488
|
|
1527
|
-
if (token !== '}') {
|
1528
|
-
throw createSyntaxError('Comma , or bracket } expected after object value')
|
1489
|
+
if (state.token !== '}') {
|
1490
|
+
throw createSyntaxError(state, 'Comma , or bracket } expected after object value')
|
1529
1491
|
}
|
1530
|
-
getToken()
|
1492
|
+
getToken(state)
|
1531
1493
|
|
1532
1494
|
let node = new ObjectNode(properties)
|
1533
1495
|
|
1534
1496
|
// parse index parameters
|
1535
|
-
node = parseAccessors(node)
|
1497
|
+
node = parseAccessors(state, node)
|
1536
1498
|
|
1537
1499
|
return node
|
1538
1500
|
}
|
1539
1501
|
|
1540
|
-
return parseNumber()
|
1502
|
+
return parseNumber(state)
|
1541
1503
|
}
|
1542
1504
|
|
1543
1505
|
/**
|
@@ -1545,18 +1507,18 @@ function factory (type, config, load, typed) {
|
|
1545
1507
|
* @return {Node} node
|
1546
1508
|
* @private
|
1547
1509
|
*/
|
1548
|
-
function parseNumber () {
|
1510
|
+
function parseNumber (state) {
|
1549
1511
|
let numberStr
|
1550
1512
|
|
1551
|
-
if (tokenType === TOKENTYPE.NUMBER) {
|
1513
|
+
if (state.tokenType === TOKENTYPE.NUMBER) {
|
1552
1514
|
// this is a number
|
1553
|
-
numberStr = token
|
1554
|
-
getToken()
|
1515
|
+
numberStr = state.token
|
1516
|
+
getToken(state)
|
1555
1517
|
|
1556
1518
|
return new ConstantNode(numeric(numberStr, config.number))
|
1557
1519
|
}
|
1558
1520
|
|
1559
|
-
return parseParentheses()
|
1521
|
+
return parseParentheses(state)
|
1560
1522
|
}
|
1561
1523
|
|
1562
1524
|
/**
|
@@ -1564,29 +1526,29 @@ function factory (type, config, load, typed) {
|
|
1564
1526
|
* @return {Node} node
|
1565
1527
|
* @private
|
1566
1528
|
*/
|
1567
|
-
function parseParentheses () {
|
1529
|
+
function parseParentheses (state) {
|
1568
1530
|
let node
|
1569
1531
|
|
1570
1532
|
// check if it is a parenthesized expression
|
1571
|
-
if (token === '(') {
|
1533
|
+
if (state.token === '(') {
|
1572
1534
|
// parentheses (...)
|
1573
|
-
openParams()
|
1574
|
-
getToken()
|
1535
|
+
openParams(state)
|
1536
|
+
getToken(state)
|
1575
1537
|
|
1576
|
-
node = parseAssignment() // start again
|
1538
|
+
node = parseAssignment(state) // start again
|
1577
1539
|
|
1578
|
-
if (token !== ')') {
|
1579
|
-
throw createSyntaxError('Parenthesis ) expected')
|
1540
|
+
if (state.token !== ')') {
|
1541
|
+
throw createSyntaxError(state, 'Parenthesis ) expected')
|
1580
1542
|
}
|
1581
|
-
closeParams()
|
1582
|
-
getToken()
|
1543
|
+
closeParams(state)
|
1544
|
+
getToken(state)
|
1583
1545
|
|
1584
1546
|
node = new ParenthesisNode(node)
|
1585
|
-
node = parseAccessors(node)
|
1547
|
+
node = parseAccessors(state, node)
|
1586
1548
|
return node
|
1587
1549
|
}
|
1588
1550
|
|
1589
|
-
return parseEnd()
|
1551
|
+
return parseEnd(state)
|
1590
1552
|
}
|
1591
1553
|
|
1592
1554
|
/**
|
@@ -1594,14 +1556,14 @@ function factory (type, config, load, typed) {
|
|
1594
1556
|
* @return {Node} res
|
1595
1557
|
* @private
|
1596
1558
|
*/
|
1597
|
-
function parseEnd () {
|
1598
|
-
if (token === '') {
|
1559
|
+
function parseEnd (state) {
|
1560
|
+
if (state.token === '') {
|
1599
1561
|
// syntax error or unexpected end of expression
|
1600
|
-
throw createSyntaxError('Unexpected end of expression')
|
1601
|
-
} else if (token === "'") {
|
1602
|
-
throw createSyntaxError('Value expected. Note: strings must be enclosed by double quotes')
|
1562
|
+
throw createSyntaxError(state, 'Unexpected end of expression')
|
1563
|
+
} else if (state.token === "'") {
|
1564
|
+
throw createSyntaxError(state, 'Value expected. Note: strings must be enclosed by double quotes')
|
1603
1565
|
} else {
|
1604
|
-
throw createSyntaxError('Value expected')
|
1566
|
+
throw createSyntaxError(state, 'Value expected')
|
1605
1567
|
}
|
1606
1568
|
}
|
1607
1569
|
|
@@ -1618,11 +1580,11 @@ function factory (type, config, load, typed) {
|
|
1618
1580
|
|
1619
1581
|
/**
|
1620
1582
|
* Shortcut for getting the current col value (one based)
|
1621
|
-
* Returns the column (position) where the last token starts
|
1583
|
+
* Returns the column (position) where the last state.token starts
|
1622
1584
|
* @private
|
1623
1585
|
*/
|
1624
|
-
function col () {
|
1625
|
-
return index - token.length + 1
|
1586
|
+
function col (state) {
|
1587
|
+
return state.index - state.token.length + 1
|
1626
1588
|
}
|
1627
1589
|
|
1628
1590
|
/**
|
@@ -1631,8 +1593,8 @@ function factory (type, config, load, typed) {
|
|
1631
1593
|
* @return {SyntaxError} instantiated error
|
1632
1594
|
* @private
|
1633
1595
|
*/
|
1634
|
-
function createSyntaxError (message) {
|
1635
|
-
const c = col()
|
1596
|
+
function createSyntaxError (state, message) {
|
1597
|
+
const c = col(state)
|
1636
1598
|
const error = new SyntaxError(message + ' (char ' + c + ')')
|
1637
1599
|
error['char'] = c
|
1638
1600
|
|
@@ -1645,8 +1607,8 @@ function factory (type, config, load, typed) {
|
|
1645
1607
|
* @return {Error} instantiated error
|
1646
1608
|
* @private
|
1647
1609
|
*/
|
1648
|
-
function createError (message) {
|
1649
|
-
const c = col()
|
1610
|
+
function createError (state, message) {
|
1611
|
+
const c = col(state)
|
1650
1612
|
const error = new SyntaxError(message + ' (char ' + c + ')')
|
1651
1613
|
error['char'] = c
|
1652
1614
|
|