spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[ParseEngine] removing a lot of stuff so I can focus on getting one thing working
author
Ben Vogt <[email protected]>
date
2017-12-10 00:33:34
stats
1 file(s) changed, 97 insertions(+), 439 deletions(-)
files
src/Parser/ParseEngine.ts
  1diff --git a/src/Parser/ParseEngine.ts b/src/Parser/ParseEngine.ts
  2index 9257846..8691b8f 100644
  3--- a/src/Parser/ParseEngine.ts
  4+++ b/src/Parser/ParseEngine.ts
  5@@ -174,115 +174,27 @@ const RulesSeq = [
  6 enum Symbol {
  7   ACCEPT = 0,
  8   END = 1,
  9-  ERROR = 2,
 10-  EXPRESSIONS = 3,
 11-  EXPRESSION = 4,
 12   EOF = 5,
 13-  VARIABLE = 6,
 14-  VARIABLE_SEQUENCE = 7,
 15   NUMBER = 8,
 16-  STRING = 9,
 17-  FORMULA = 10,
 18-  BOOLEAN = 11,
 19-  CELL_REF = 12,
 20-  FIXED_CELL_REF = 13,
 21-  CELL = 14,
 22-  OPEN_ARRAY = 15,
 23-  CLOSE_ARRAY = 16,
 24-  PERIOD = 17,
 25-  AMPERSAND = 18,
 26-  EQUALS = 19,
 27-  PLUS = 20,
 28-  OPEN_PAREN = 21,
 29-  CLOSE_PAREN = 22,
 30-  LESS_THAN = 23,
 31-  GREATER_THAN = 24,
 32-  MINUS = 25,
 33   ASTERISK = 26,
 34-  DIVIDE = 27,
 35-  CARROT = 28,
 36-  COLON = 29,
 37-  SEMI_COLON = 30,
 38-  COMMA = 31,
 39-  PERCENT = 32,
 40-  POUND = 33,
 41-  EXCLAMATION_POINT = 34,
 42   WHITE_SPACE = 35
 43 }
 44 
 45 const SYMBOL_NAME_TO_INDEX = {
 46   "ACCEPT": Symbol.ACCEPT,
 47   "END": Symbol.END,
 48-  "ERROR": Symbol.ERROR,
 49-  "EXPRESSIONS": Symbol.EXPRESSIONS,
 50-  "EXPRESSION": Symbol.EXPRESSION,
 51   "EOF": Symbol.EOF,
 52-  "VARIABLE": Symbol.VARIABLE,
 53-  "VARIABLE_SEQUENCE": Symbol.VARIABLE_SEQUENCE,
 54   "NUMBER": Symbol.NUMBER,
 55-  "STRING": Symbol.STRING,
 56-  "FORMULA": Symbol.FORMULA,
 57-  "CELL_REF": Symbol.CELL_REF,
 58-  "FIXED_CELL_REF": Symbol.FIXED_CELL_REF,
 59-  "CELL": Symbol.CELL,
 60-  "OPEN_ARRAY": Symbol.OPEN_ARRAY,
 61-  "CLOSE_ARRAY": Symbol.CLOSE_ARRAY,
 62-  "PERIOD": Symbol.PERIOD,
 63-  "&": Symbol.AMPERSAND,
 64-  "=": Symbol.EQUALS,
 65-  "+": Symbol.PLUS,
 66-  "(": Symbol.OPEN_PAREN,
 67-  ")": Symbol.CLOSE_PAREN,
 68-  "<": Symbol.LESS_THAN,
 69-  ">": Symbol.GREATER_THAN,
 70-  "-": Symbol.MINUS,
 71   "*": Symbol.ASTERISK,
 72-  "/": Symbol.DIVIDE,
 73-  "^": Symbol.CARROT,
 74-  ":": Symbol.COLON,
 75-  ";": Symbol.SEMI_COLON,
 76-  ",": Symbol.COMMA,
 77-  "%": Symbol.PERCENT,
 78-  "#": Symbol.POUND,
 79-  "!": Symbol.EXCLAMATION_POINT,
 80   "WHITE_SPACE": Symbol.WHITE_SPACE
 81 };
 82 
 83 let symbolIndexToName = {};
 84 symbolIndexToName[Symbol.ACCEPT] = "ACCEPT";
 85 symbolIndexToName[Symbol.END] = "END";
 86-symbolIndexToName[Symbol.ERROR] = "ERROR";
 87-symbolIndexToName[Symbol.EXPRESSIONS] = "EXPRESSIONS";
 88-symbolIndexToName[Symbol.EXPRESSION] = "EXPRESSION";
 89 symbolIndexToName[Symbol.EOF] = "EOF";
 90-symbolIndexToName[Symbol.VARIABLE] = "VARIABLE";
 91-symbolIndexToName[Symbol.VARIABLE_SEQUENCE] = "VARIABLE_SEQUENCE";
 92 symbolIndexToName[Symbol.NUMBER] = "NUMBER";
 93-symbolIndexToName[Symbol.STRING] = "STRING";
 94-symbolIndexToName[Symbol.FORMULA] = "FORMULA";
 95-symbolIndexToName[Symbol.CELL_REF] = "CELL_REF";
 96-symbolIndexToName[Symbol.FIXED_CELL_REF] = "FIXED_CELL_REF";
 97-symbolIndexToName[Symbol.CELL] = "CELL";
 98-symbolIndexToName[Symbol.OPEN_ARRAY] = "OPEN_ARRAY";
 99-symbolIndexToName[Symbol.CLOSE_ARRAY] = "CLOSE_ARRAY";
100-symbolIndexToName[Symbol.PERIOD] = ".";
101-symbolIndexToName[Symbol.AMPERSAND] = "&";
102-symbolIndexToName[Symbol.EQUALS] = "=";
103-symbolIndexToName[Symbol.PLUS] = "+";
104-symbolIndexToName[Symbol.OPEN_PAREN] = "(";
105-symbolIndexToName[Symbol.CLOSE_PAREN] = ")";
106-symbolIndexToName[Symbol.LESS_THAN] = "<";
107-symbolIndexToName[Symbol.GREATER_THAN] = ">";
108-symbolIndexToName[Symbol.MINUS] = "-";
109 symbolIndexToName[Symbol.ASTERISK] = "*";
110-symbolIndexToName[Symbol.DIVIDE] = "/";
111-symbolIndexToName[Symbol.CARROT] = "^";
112-symbolIndexToName[Symbol.SEMI_COLON] = ";";
113-symbolIndexToName[Symbol.COLON] = ";";
114-symbolIndexToName[Symbol.COMMA] = ",";
115-symbolIndexToName[Symbol.PERCENT] = "%";
116-symbolIndexToName[Symbol.POUND] = "#";
117-symbolIndexToName[Symbol.EXCLAMATION_POINT] = "!";
118 symbolIndexToName[Symbol.WHITE_SPACE] = "WHITE_SPACE";
119 const SYMBOL_INDEX_TO_NAME = symbolIndexToName;
120 
121@@ -296,41 +208,23 @@ const REDUCE = 2;
122 const ACCEPT = 3;
123 
124 const enum ReduceActions {
125-  NO_ACTION = 0,
126-  RETURN_LAST = 1,
127-  CALL_VARIABLE = 2,
128-  AS_NUMBER = 3,
129-  AS_STRING = 4,
130-  AMPERSAND = 5,
131-  EQUALS = 6,
132-  PLUS = 7,
133-  LAST_NUMBER = 8,
134-  LTE = 9,
135-  GTE = 10,
136-  NOT_EQ = 11,
137-  NOT = 12,
138-  GT = 13,
139-  LT = 14,
140-  MINUS = 15,
141-  MULTIPLY = 16,
142-  DIVIDE = 17,
143-  TO_POWER = 18,
144-  AS_ERROR = 19,
145-  TO_NUMBER_NAN_AS_ZERO = 20,
146-  CALL_FUNCTION_LAST_BLANK = 21,
147-  CALL_FUNCTION = 22,
148-  FIXED_CELL_VAL = 23,
149-  FIXED_CELL_RANGE_VAL = 24,
150-  CELL_VALUE = 25,
151-  CELL_RANGE_VALUE = 26,
152-  PERCENT = 27,
153-  START_ARRAY = 28,
154-  INVERT_NUMBER = 29,
155-  EXPRESSION = 30,
156-  AS_ARRAY = 31,
157-  REFLEXIVE_REDUCE = 31,
158-  RETURN_LAST_AS_NUMBER = 32
159-};
160+  NO_ACTION = 100,
161+  RETURN_LAST = 101,
162+  AS_NUMBER = 103,
163+  LAST_NUMBER = 108,
164+  MULTIPLY = 1016,
165+  REFLEXIVE_REDUCE = 1031,
166+  RETURN_LAST_AS_NUMBER = 1032
167+}
168+
169+let REDUCTION_ACTION_NAMES = {};
170+REDUCTION_ACTION_NAMES[ReduceActions.NO_ACTION] = "ReduceActions.NO_ACTION";
171+REDUCTION_ACTION_NAMES[ReduceActions.RETURN_LAST] = "ReduceActions.RETURN_LAST";
172+REDUCTION_ACTION_NAMES[ReduceActions.AS_NUMBER] = "ReduceActions.AS_NUMBER";
173+REDUCTION_ACTION_NAMES[ReduceActions.LAST_NUMBER] = "ReduceActions.LAST_NUMBER";
174+REDUCTION_ACTION_NAMES[ReduceActions.MULTIPLY] = "ReduceActions.MULTIPLY";
175+REDUCTION_ACTION_NAMES[ReduceActions.REFLEXIVE_REDUCE] = "ReduceActions.REFLEXIVE_REDUCE";
176+REDUCTION_ACTION_NAMES[ReduceActions.RETURN_LAST_AS_NUMBER] = "ReduceActions.RETURN_LAST_AS_NUMBER";
177 
178 /**
179  * Represents the length to reduce the stack by, and the token index value that will replace those tokens in the stack.
180@@ -360,39 +254,23 @@ class ReductionPair {
181   }
182 }
183 
184-const enum Tree {
185+const enum State {
186   START = 0,
187   NUMBER = 1,
188-  STRING = 2,
189-  BOOLEAN = 3,
190   VARIABLE = 4,
191-  ERROR = 5,
192-  FORMULA = 6,
193-  PLUS = 7,
194-  MINUS = 8,
195-  ASTERISK = 9,
196-  SLASH = 10,
197-  CARROT = 11,
198-  AMPERSAND = 12,
199-  PERCENT = 13,
200-  LESS_THAN = 15,
201-  GREATER_THAN = 16,
202-  EQUALS = 17,
203-  COMMA = 18,
204-  OPEN_PAREN = 19,
205-  CLOSE_PAREN = 20,
206-  CELL_REF = 21,
207-  FIXED_CELL_REF = 22,
208-  CELL_RANGE_REF = 23,
209-  FIXED_CELL_RANGE_REF = 24,
210-  // OPEN_ARRAY = 25,
211-  // CLOSE_ARRAY = 26,
212-  INVERT_NEXT = 27,
213-  EXPRESSION = 28,
214+  MULTIPLICATION = 9,
215   TERMINATE_NUMBER = 29,
216   TERMINATE = 30
217 }
218 
219+let STATE_NAMES = {};
220+STATE_NAMES[State.START] = "State.START";
221+STATE_NAMES[State.NUMBER] = "State.NUMBER";
222+STATE_NAMES[State.VARIABLE] = "State.VARIABLE";
223+STATE_NAMES[State.MULTIPLICATION] = "State.MULTIPLICATION";
224+STATE_NAMES[State.TERMINATE_NUMBER] = "State.TERMINATE_NUMBER";
225+STATE_NAMES[State.TERMINATE] = "State.TERMINATE";
226+
227 /**
228  * Productions is used to look up both the number to use when reducing the stack (productions[x][1]) and the semantic
229  * value that will replace the tokens in the stack (productions[x][0]).
230@@ -402,34 +280,12 @@ const enum Tree {
231  */
232 let productions : Array<ReductionPair> = [];
233 productions[ReduceActions.NO_ACTION] = null;
234-productions[ReduceActions.RETURN_LAST] = new ReductionPair(Tree.NUMBER, 2);
235-productions[ReduceActions.CALL_VARIABLE] = new ReductionPair(Tree.VARIABLE, 1);
236-productions[ReduceActions.AS_NUMBER] = new ReductionPair(Tree.NUMBER, 1);
237-productions[ReduceActions.INVERT_NUMBER] = new ReductionPair(Tree.NUMBER, 1);
238-productions[ReduceActions.AS_STRING] = new ReductionPair(Tree.VARIABLE, 1);
239-productions[ReduceActions.AMPERSAND] = new ReductionPair(Tree.AMPERSAND, 3);
240-productions[ReduceActions.EQUALS] = new ReductionPair(Tree.EQUALS, 3);
241-productions[ReduceActions.PLUS] = new ReductionPair(Tree.PLUS, 3);
242-productions[ReduceActions.LAST_NUMBER] = new ReductionPair(Tree.NUMBER, 3);
243-productions[ReduceActions.LTE] = new ReductionPair(Tree.NUMBER, 4);
244-productions[ReduceActions.GTE] = new ReductionPair(Tree.NUMBER, 4);
245-productions[ReduceActions.NOT_EQ] = new ReductionPair(Tree.NUMBER, 4);
246-productions[ReduceActions.GT] = new ReductionPair(Tree.NUMBER, 3);
247-productions[ReduceActions.LT] = new ReductionPair(Tree.NUMBER, 3);
248-productions[ReduceActions.MINUS] = new ReductionPair(Tree.NUMBER, 3);
249-productions[ReduceActions.MULTIPLY] = new ReductionPair(Tree.NUMBER, 3);
250-productions[ReduceActions.DIVIDE] = new ReductionPair(Tree.NUMBER, 3);
251-productions[ReduceActions.TO_POWER] = new ReductionPair(Tree.NUMBER, 3);
252-productions[ReduceActions.TO_NUMBER_NAN_AS_ZERO] = new ReductionPair(Tree.NUMBER, 2);
253-productions[ReduceActions.FIXED_CELL_VAL] = new ReductionPair(Tree.VARIABLE, 1);
254-productions[ReduceActions.FIXED_CELL_RANGE_VAL] = new ReductionPair(Tree.VARIABLE, 3);
255-productions[ReduceActions.CELL_VALUE] = new ReductionPair(Tree.VARIABLE, 1);
256-productions[ReduceActions.CELL_RANGE_VALUE] = new ReductionPair(Tree.VARIABLE, 3);
257-productions[ReduceActions.PERCENT] = new ReductionPair(Tree.NUMBER, 3);
258-productions[ReduceActions.AS_ERROR] = new ReductionPair(Tree.ERROR, 1);
259-productions[ReduceActions.AS_ARRAY] = new ReductionPair(Tree.VARIABLE, 1);
260-productions[ReduceActions.REFLEXIVE_REDUCE] = new ReductionPair(Tree.VARIABLE, 1);
261-productions[ReduceActions.RETURN_LAST_AS_NUMBER] = new ReductionPair(Tree.NUMBER, 2);
262+productions[ReduceActions.RETURN_LAST] = new ReductionPair(State.NUMBER, 2);
263+productions[ReduceActions.AS_NUMBER] = new ReductionPair(State.NUMBER, 1);
264+productions[ReduceActions.LAST_NUMBER] = new ReductionPair(State.NUMBER, 3);
265+productions[ReduceActions.MULTIPLY] = new ReductionPair(State.NUMBER, 3);
266+productions[ReduceActions.REFLEXIVE_REDUCE] = new ReductionPair(State.VARIABLE, 1);
267+productions[ReduceActions.RETURN_LAST_AS_NUMBER] = new ReductionPair(State.NUMBER, 2);
268 const PRODUCTIONS = productions;
269 
270 
271@@ -441,24 +297,25 @@ const PRODUCTIONS = productions;
272 let table = [];
273 // All functions in the spreadsheet start with a 0-token.
274 // `=`
275-table[Tree.START] = ObjectBuilder
276-  .add(Symbol.NUMBER, Tree.NUMBER)
277-  .add(Symbol.WHITE_SPACE, Tree.START)
278-  .add(Symbol.END, Tree.TERMINATE_NUMBER)
279+table[State.START] = ObjectBuilder
280+  .add(Symbol.NUMBER, [SHIFT, State.NUMBER])
281+  .add(Symbol.WHITE_SPACE, State.START)
282+  .add(Symbol.END, State.TERMINATE)
283   .build();
284-table[Tree.NUMBER] = ObjectBuilder
285-  .add(Symbol.ASTERISK, [SHIFT, ReduceActions.MULTIPLY])
286-  .add(Symbol.WHITE_SPACE, Tree.NUMBER)
287-  .add(Symbol.END, Tree.TERMINATE_NUMBER)
288+table[State.NUMBER] = ObjectBuilder
289+  .add(Symbol.ASTERISK, [SHIFT, State.MULTIPLICATION])
290+  .add(Symbol.WHITE_SPACE, State.NUMBER)
291+  .add(Symbol.END, State.TERMINATE_NUMBER)
292   .build();
293-table[Tree.ASTERISK] = ObjectBuilder
294-  .add(Symbol.WHITE_SPACE, Tree.ASTERISK)
295-  .add(Symbol.END, Tree.TERMINATE_NUMBER)
296+table[State.MULTIPLICATION] = ObjectBuilder
297+  .add(Symbol.NUMBER, [REDUCE, ReduceActions.MULTIPLY])
298+  .add(Symbol.WHITE_SPACE, State.MULTIPLICATION)
299+  .add(Symbol.END, State.TERMINATE_NUMBER)
300   .build();
301-table[Tree.TERMINATE] = ObjectBuilder
302+table[State.TERMINATE] = ObjectBuilder
303   .add(Symbol.END, [REDUCE, ReduceActions.RETURN_LAST])
304   .build();
305-table[Tree.TERMINATE_NUMBER] = ObjectBuilder
306+table[State.TERMINATE_NUMBER] = ObjectBuilder
307   .add(Symbol.END, [REDUCE, ReduceActions.RETURN_LAST_AS_NUMBER])
308   .build();
309 const ACTION_TABLE = table;
310@@ -492,84 +349,15 @@ let Parser = (function () {
311             return virtualStack[vsl - 1];
312           case ReduceActions.RETURN_LAST_AS_NUMBER:
313             return sharedStateYY.handler.helper.number(virtualStack[vsl - 1]);
314-          case ReduceActions.CALL_VARIABLE:
315-            this.$ = sharedStateYY.handler.helper.callVariable.call(this, virtualStack[vsl]);
316-            break;
317           case ReduceActions.AS_NUMBER:
318             this.$ = sharedStateYY.handler.helper.number(virtualStack[vsl]);
319             break;
320-          case ReduceActions.AS_STRING:
321-            this.$ = sharedStateYY.handler.helper.string(virtualStack[vsl]);
322-            break;
323-          case ReduceActions.AMPERSAND:
324-            this.$ = sharedStateYY.handler.helper.specialMatch('&', virtualStack[vsl - 2], virtualStack[vsl]);
325-            break;
326-          case ReduceActions.EQUALS:
327-            this.$ = sharedStateYY.handler.helper.logicMatch('=', virtualStack[vsl - 2], virtualStack[vsl]);
328-            break;
329-          case ReduceActions.PLUS:
330-            this.$ = sharedStateYY.handler.helper.mathMatch('+', virtualStack[vsl - 2], virtualStack[vsl]);
331-            break;
332           case ReduceActions.LAST_NUMBER:
333             this.$ = sharedStateYY.handler.helper.number(virtualStack[vsl - 1]);
334             break;
335-          case ReduceActions.LTE:
336-            this.$ = sharedStateYY.handler.helper.logicMatch('<=', virtualStack[vsl - 3], virtualStack[vsl]);
337-            break;
338-          case ReduceActions.GTE:
339-            this.$ = sharedStateYY.handler.helper.logicMatch('>=', virtualStack[vsl - 3], virtualStack[vsl]);
340-            break;
341-          case ReduceActions.NOT_EQ:
342-            this.$ = sharedStateYY.handler.helper.logicMatch('<>', virtualStack[vsl - 3], virtualStack[vsl]);
343-            break;
344-          case ReduceActions.GT:
345-            this.$ = sharedStateYY.handler.helper.logicMatch('>', virtualStack[vsl - 2], virtualStack[vsl]);
346-            break;
347-          case ReduceActions.LT:
348-            this.$ = sharedStateYY.handler.helper.logicMatch('<', virtualStack[vsl - 2], virtualStack[vsl]);
349-            break;
350-          case ReduceActions.MINUS:
351-            this.$ = sharedStateYY.handler.helper.mathMatch('-', virtualStack[vsl - 2], virtualStack[vsl]);
352-            break;
353           case ReduceActions.MULTIPLY:
354             this.$ = sharedStateYY.handler.helper.mathMatch('*', virtualStack[vsl - 2], virtualStack[vsl]);
355             break;
356-          case ReduceActions.DIVIDE:
357-            this.$ = sharedStateYY.handler.helper.mathMatch('/', virtualStack[vsl - 2], virtualStack[vsl]);
358-            break;
359-          case ReduceActions.TO_POWER:
360-            this.$ = sharedStateYY.handler.helper.mathMatch('^', virtualStack[vsl - 2], virtualStack[vsl]);
361-            break;
362-          case ReduceActions.INVERT_NUMBER:
363-            this.$ = sharedStateYY.handler.helper.numberInverted(virtualStack[vsl]);
364-            if (isNaN(this.$)) {
365-              this.$ = 0;
366-            }
367-            break;
368-          case ReduceActions.TO_NUMBER_NAN_AS_ZERO:
369-            this.$ = sharedStateYY.handler.helper.number(virtualStack[vsl]);
370-            if (isNaN(this.$)) {
371-              this.$ = 0;
372-            }
373-            break;
374-          case ReduceActions.CALL_FUNCTION_LAST_BLANK:
375-            this.$ = sharedStateYY.handler.helper.callFunction.call(this, virtualStack[vsl - 2], '');
376-            break;
377-          case ReduceActions.FIXED_CELL_VAL:
378-            this.$ = sharedStateYY.handler.helper.fixedCellValue.call(sharedStateYY.obj, virtualStack[vsl]);
379-            break;
380-          case ReduceActions.FIXED_CELL_RANGE_VAL:
381-            this.$ = sharedStateYY.handler.helper.fixedCellRangeValue.call(sharedStateYY.obj, virtualStack[vsl - 2], virtualStack[vsl]);
382-            break;
383-          case ReduceActions.CELL_VALUE:
384-            this.$ = sharedStateYY.handler.helper.cellValue.call(sharedStateYY.obj, virtualStack[vsl]);
385-            break;
386-          case ReduceActions.CELL_RANGE_VALUE:
387-            this.$ = sharedStateYY.handler.helper.cellRangeValue.call(sharedStateYY.obj, virtualStack[vsl - 2], virtualStack[vsl]);
388-            break;
389-          case ReduceActions.AS_ERROR:
390-            this.$ = constructErrorByName(virtualStack[vsl]);
391-            break;
392           case ReduceActions.REFLEXIVE_REDUCE:
393             this.$ = virtualStack[vsl];
394             break;
395@@ -580,43 +368,11 @@ let Parser = (function () {
396           switch (reduceActionToPerform) {
397             case ReduceActions.RETURN_LAST:
398               return virtualStack[vsl - 1];
399-            case ReduceActions.CALL_VARIABLE:
400             case ReduceActions.AS_NUMBER:
401-            case ReduceActions.AS_STRING:
402-            case ReduceActions.AMPERSAND:
403-            case ReduceActions.EQUALS:
404-            case ReduceActions.PLUS:
405             case ReduceActions.LAST_NUMBER:
406-            case ReduceActions.LTE:
407-            case ReduceActions.GTE:
408-            case ReduceActions.NOT_EQ:
409-            case ReduceActions.NOT:
410-            case ReduceActions.GT:
411-            case ReduceActions.LT:
412-            case ReduceActions.MINUS:
413             case ReduceActions.MULTIPLY:
414-            case ReduceActions.DIVIDE:
415-            case ReduceActions.TO_POWER:
416-            case ReduceActions.CALL_FUNCTION_LAST_BLANK:
417-            case ReduceActions.CALL_FUNCTION:
418-            case ReduceActions.FIXED_CELL_VAL:
419-            case ReduceActions.FIXED_CELL_RANGE_VAL:
420-            case ReduceActions.CELL_VALUE:
421-            case ReduceActions.CELL_RANGE_VALUE:
422               this.$ = e;
423               break;
424-            case ReduceActions.INVERT_NUMBER:
425-              this.$ = e;
426-              if (isNaN(this.$)) {
427-                this.$ = 0;
428-              }
429-              break;
430-            case ReduceActions.TO_NUMBER_NAN_AS_ZERO:
431-              this.$ = e;
432-              if (isNaN(this.$)) {
433-                this.$ = 0;
434-              }
435-              break;
436           }
437         } else {
438           throw e;
439@@ -678,12 +434,6 @@ let Parser = (function () {
440         this.parseError = Object.getPrototypeOf(this).parseError;
441       }
442 
443-      function popStack(n) {
444-        stack.length = stack.length - 2 * n;
445-        semanticValueStack.length = semanticValueStack.length - n;
446-        locationStack.length = locationStack.length - n;
447-      }
448-
449       function lex() {
450         let token = lexer.lex() || EOF;
451         // if token isn't its numeric value, convert
452@@ -730,6 +480,7 @@ let Parser = (function () {
453           line: lexer.yylineno,
454           loc: yyloc,
455           state: state,
456+          stateName: STATE_NAMES[state] || REDUCTION_ACTION_NAMES[state],
457           stack: stack,
458           semanticValueStack: semanticValueStack
459         });
460@@ -743,64 +494,39 @@ let Parser = (function () {
461           continue;
462           // handle parse error
463         } else if (typeof action === 'undefined' || !action.length || !action[0]) {
464-          let error_rule_depth;
465           let errStr = '';
466 
467-          // Return the rule stack depth where the nearest error rule can be found.
468-          // Return FALSE when no error recovery rule was found.
469-          this.locateNearestErrorRecoveryRule = function(state) {
470-            let stack_probe = stack.length - 1;
471-            let depth = 0;
472 
473-            // try to recover from error
474-            for (; ;) {
475-              if (isUndefined(state)) {
476-                return false;
477-              }
478-              if (state === 0 || stack_probe < 2) {
479-                return false; // No suitable error recovery rule available.
480-              }
481-              stack_probe -= 2; // popStack(1): [symbol, action]
482-              state = stack[stack_probe];
483-              ++depth;
484-            }
485-          };
486-
487-          if (!recovering) {
488-            // first see if there's any chance at hitting an error recovery rule:
489-            error_rule_depth = this.locateNearestErrorRecoveryRule(state);
490-
491-            // Report error
492-            expected = [];
493-            let expectedIndexes = [];
494-            let tableState = ACTION_TABLE[state];
495-            for (p in ACTION_TABLE[state]) {
496-              if (SYMBOL_INDEX_TO_NAME[p]) {
497-                expected.push(SYMBOL_INDEX_TO_NAME[p]);
498-                expectedIndexes.push(p);
499-              }
500+          // Report error
501+          expected = [];
502+          let expectedIndexes = [];
503+          let tableState = ACTION_TABLE[state];
504+          for (p in ACTION_TABLE[state]) {
505+            if (SYMBOL_INDEX_TO_NAME[p]) {
506+              expected.push(SYMBOL_INDEX_TO_NAME[p]);
507+              expectedIndexes.push(p);
508             }
509-            if (lexer.showPosition) {
510-              errStr = 'Parse error on line ' + (yylineno + 1) + ":  " + lexer.showPosition() + "  Expecting " + expected.join(', ') + ", got " + (SYMBOL_INDEX_TO_NAME[symbol] || symbol);
511-            } else {
512-              errStr = 'Parse error on line ' + (yylineno + 1) + ": Unexpected " +
513-                (symbol == EOF ? "end of input" :
514-                  ("'" + (SYMBOL_INDEX_TO_NAME[symbol] || symbol) + "'"));
515-            }
516-            this.parseError(errStr, {
517-              text: lexer.match,
518-              token: SYMBOL_INDEX_TO_NAME[symbol] || symbol,
519-              tokenIndex: symbol,
520-              line: lexer.yylineno,
521-              loc: yyloc,
522-              expected: expected,
523-              expectedIndexes: expectedIndexes,
524-              state: state,
525-              tableState: tableState,
526-              stack: stack,
527-              semanticValueStack: semanticValueStack
528-            });
529           }
530+          if (lexer.showPosition) {
531+            errStr = 'Parse error on line ' + (yylineno + 1) + ":  " + lexer.showPosition() + "  Expecting " + expected.join(', ') + ", got " + (SYMBOL_INDEX_TO_NAME[symbol] || symbol);
532+          } else {
533+            errStr = 'Parse error on line ' + (yylineno + 1) + ": Unexpected " +
534+              (symbol == EOF ? "end of input" :
535+                ("'" + (SYMBOL_INDEX_TO_NAME[symbol] || symbol) + "'"));
536+          }
537+          this.parseError(errStr, {
538+            text: lexer.match,
539+            token: SYMBOL_INDEX_TO_NAME[symbol] || symbol,
540+            tokenIndex: symbol,
541+            line: lexer.yylineno,
542+            loc: yyloc,
543+            expected: expected,
544+            expectedIndexes: expectedIndexes,
545+            state: state,
546+            tableState: tableState,
547+            stack: stack,
548+            semanticValueStack: semanticValueStack
549+          });
550         }
551 
552         // this shouldn't happen, unless resolve defaults are off
553@@ -1018,9 +744,7 @@ let Parser = (function () {
554       // test the lexed token: return FALSE when not a match, otherwise return token
555       test_match: function (match, indexed_rule) {
556         let token,
557-          lines,
558-          backup;
559-
560+          lines;
561 
562         lines = match[0].match(/(?:\r\n?|\n).*/g);
563         if (lines) {
564@@ -1118,68 +842,12 @@ let Parser = (function () {
565 
566       mapActionToActionIndex: function (ruleIndex) {
567         switch (ruleIndex) {
568-          case 0:
569-            // skip whitespace
570+          case RuleIndex.WHITE_SPACE:
571             break;
572-          case 1:
573-            return ReduceActions.LAST_NUMBER;
574-          case 2:
575-            return ReduceActions.LAST_NUMBER;
576-          case 3:
577-            return ReduceActions.CALL_FUNCTION_LAST_BLANK;
578-          case 4:
579-            return ReduceActions.AMPERSAND;
580-          case 5:
581-            return ReduceActions.EQUALS;
582-          case 7:
583-            return ReduceActions.FIXED_CELL_VAL;
584-          case 8:
585-            return ReduceActions.CALL_FUNCTION_LAST_BLANK;
586-          case 9:
587+          case RuleIndex.INTEGER:
588             return Symbol.NUMBER;
589-          case 12:
590-            return ReduceActions.FIXED_CELL_RANGE_VAL;
591-          case 13:
592-            // skip whitespace??
593-            break;
594-          case 14:
595-            return ReduceActions.LTE;
596-          case 15:
597-            return ' ';
598-          case 18:
599-            return ReduceActions.CELL_VALUE;
600-          case 19:
601-            return ReduceActions.CELL_RANGE_VALUE;
602-          case 20:
603-            return ReduceActions.TO_POWER;
604-          case 21:
605-            return ReduceActions.INVERT_NUMBER;
606-          case 22:
607-            return ReduceActions.DIVIDE;
608-          case 23:
609-            return ReduceActions.NOT_EQ;
610-          case 24:
611-            return ReduceActions.TO_NUMBER_NAN_AS_ZERO;
612-          case 25:
613-            return ReduceActions.NOT;
614-          case 26:
615-            return ReduceActions.GT;
616-          case 27:
617-            return ReduceActions.MINUS;
618-          case 28:
619-            return ReduceActions.LT;
620-          case 29:
621-            return ReduceActions.MULTIPLY;
622-          case 30:
623-            return '"';
624-          case 31:
625-            return "'";
626-          case 32:
627-            return "!";
628-          case 33:
629-            return ReduceActions.GTE;
630-          case 36:
631-            return ReduceActions.AS_NUMBER;
632+          case RuleIndex.ASTERISK:
633+            return Symbol.ASTERISK;
634         }
635       },
636       conditions: {