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.

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