text: 
  // hack:
  var assert;
  
  /* parser generated by jison 0.6.1-205 */
  
  /*
   * Returns a Parser object of the following structure:
   *
   *  Parser: {
   *    yy: {}     The so-called "shared state" or rather the *source* of it;
   *               the real "shared state" `yy` passed around to
   *               the rule actions, etc. is a derivative/copy of this one,
   *               not a direct reference!
   *  }
   *
   *  Parser.prototype: {
   *    yy: {},
   *    EOF: 1,
   *    TERROR: 2,
   *
   *    trace: function(errorMessage, ...),
   *
   *    JisonParserError: function(msg, hash),
   *
   *    quoteName: function(name),
   *               Helper function which can be overridden by user code later on: put suitable
   *               quotes around literal IDs in a description string.
   *
   *    originalQuoteName: function(name),
   *               The basic quoteName handler provided by JISON.
   *               `cleanupAfterParse()` will clean up and reset `quoteName()` to reference this function
   *               at the end of the `parse()`.
   *
   *    describeSymbol: function(symbol),
   *               Return a more-or-less human-readable description of the given symbol, when
   *               available, or the symbol itself, serving as its own 'description' for lack
   *               of something better to serve up.
   *
   *               Return NULL when the symbol is unknown to the parser.
   *
   *    symbols_: {associative list: name ==> number},
   *    terminals_: {associative list: number ==> name},
   *    nonterminals: {associative list: rule-name ==> {associative list: number ==> rule-alt}},
   *    terminal_descriptions_: (if there are any) {associative list: number ==> description},
   *    productions_: [...],
   *
   *    performAction: function parser__performAction(yytext, yyleng, yylineno, yyloc, yystate, yysp, yyvstack, yylstack, yystack, yysstack),
   *
   *               The function parameters and `this` have the following value/meaning:
   *               - `this`    : reference to the `yyval` internal object, which has members (`$` and `_$`)
   *                             to store/reference the rule value `$$` and location info `@$`.
   *
   *                 One important thing to note about `this` a.k.a. `yyval`: every *reduce* action gets
   *                 to see the same object via the `this` reference, i.e. if you wish to carry custom
   *                 data from one reduce action through to the next within a single parse run, then you
   *                 may get nasty and use `yyval` a.k.a. `this` for storing you own semi-permanent data.
   *
   *                 `this.yy` is a direct reference to the `yy` shared state object.
   *
   *                 `%parse-param`-specified additional `parse()` arguments have been added to this `yy`
   *                 object at `parse()` start and are therefore available to the action code via the
   *                 same named `yy.xxxx` attributes (where `xxxx` represents a identifier name from
   *                 the %parse-param` list.
   *
   *               - `yytext`  : reference to the lexer value which belongs to the last lexer token used
   *                             to match this rule. This is *not* the look-ahead token, but the last token
   *                             that's actually part of this rule.
   *
   *                 Formulated another way, `yytext` is the value of the token immediately preceeding
   *                 the current look-ahead token.
   *                 Caveats apply for rules which don't require look-ahead, such as epsilon rules.
   *
   *               - `yyleng`  : ditto as `yytext`, only now for the lexer.yyleng value.
   *
   *               - `yylineno`: ditto as `yytext`, only now for the lexer.yylineno value.
   *
   *               - `yyloc`   : ditto as `yytext`, only now for the lexer.yylloc lexer token location info.
   *
   *                               WARNING: since jison 0.4.18-186 this entry may be NULL/UNDEFINED instead
   *                               of an empty object when no suitable location info can be provided.
   *
   *               - `yystate` : the current parser state number, used internally for dispatching and
   *                               executing the action code chunk matching the rule currently being reduced.
   *
   *               - `yysp`    : the current state stack position (a.k.a. 'stack pointer')
   *
   *                 This one comes in handy when you are going to do advanced things to the parser
   *                 stacks, all of which are accessible from your action code (see the next entries below).
   *
   *                 Also note that you can access this and other stack index values using the new double-hash
   *                 syntax, i.e. `##$ === ##0 === yysp`, while `##1` is the stack index for all things
   *                 related to the first rule term, just like you have `$1`, `@1` and `#1`.
   *                 This is made available to write very advanced grammar action rules, e.g. when you want
   *                 to investigate the parse state stack in your action code, which would, for example,
   *                 be relevant when you wish to implement error diagnostics and reporting schemes similar
   *                 to the work described here:
   *
   *                 + Pottier, F., 2016. Reachability and error diagnosis in LR(1) automata.
   *                   In Journées Francophones des Languages Applicatifs.
   *
   *                 + Jeffery, C.L., 2003. Generating LR syntax error messages from examples.
   *                   ACM Transactions on Programming Languages and Systems (TOPLAS), 25(5), pp.631–640.
   *
   *               - `yyrulelength`: the current rule's term count, i.e. the number of entries occupied on the stack.
   *
   *                 This one comes in handy when you are going to do advanced things to the parser
   *                 stacks, all of which are accessible from your action code (see the next entries below).
   *
   *               - `yyvstack`: reference to the parser value stack. Also accessed via the `$1` etc.
   *                             constructs.
   *
   *               - `yylstack`: reference to the parser token location stack. Also accessed via
   *                             the `@1` etc. constructs.
   *
   *                             WARNING: since jison 0.4.18-186 this array MAY contain slots which are
   *                             UNDEFINED rather than an empty (location) object, when the lexer/parser
   *                             action code did not provide a suitable location info object when such a
   *                             slot was filled!
   *
   *               - `yystack` : reference to the parser token id stack. Also accessed via the
   *                             `#1` etc. constructs.
   *
   *                 Note: this is a bit of a **white lie** as we can statically decode any `#n` reference to
   *                 its numeric token id value, hence that code wouldn't need the `yystack` but *you* might
   *                 want access this array for your own purposes, such as error analysis as mentioned above!
   *
   *                 Note that this stack stores the current stack of *tokens*, that is the sequence of
   *                 already parsed=reduced *nonterminals* (tokens representing rules) and *terminals*
   *                 (lexer tokens *shifted* onto the stack until the rule they belong to is found and
   *                 *reduced*.
   *
   *               - `yysstack`: reference to the parser state stack. This one carries the internal parser
   *                             *states* such as the one in `yystate`, which are used to represent
   *                             the parser state machine in the *parse table*. *Very* *internal* stuff,
   *                             what can I say? If you access this one, you're clearly doing wicked things
   *
   *               - `...`     : the extra arguments you specified in the `%parse-param` statement in your
   *                             grammar definition file.
   *
   *    table: [...],
   *               State transition table
   *               ----------------------
   *
   *               index levels are:
   *               - `state`  --> hash table
   *               - `symbol` --> action (number or array)
   *
   *                 If the `action` is an array, these are the elements' meaning:
   *                 - index [0]: 1 = shift, 2 = reduce, 3 = accept
   *                 - index [1]: GOTO `state`
   *
   *                 If the `action` is a number, it is the GOTO `state`
   *
   *    defaultActions: {...},
   *
   *    parseError: function(str, hash, ExceptionClass),
   *    yyError: function(str, ...),
   *    yyRecovering: function(),
   *    yyErrOk: function(),
   *    yyClearIn: function(),
   *
   *    constructParseErrorInfo: function(error_message, exception_object, expected_token_set, is_recoverable),
   *               Helper function **which will be set up during the first invocation of the `parse()` method**.
   *               Produces a new errorInfo 'hash object' which can be passed into `parseError()`.
   *               See it's use in this parser kernel in many places; example usage:
   *
   *                   var infoObj = parser.constructParseErrorInfo('fail!', null,
   *                                     parser.collect_expected_token_set(state), true);
   *                   var retVal = parser.parseError(infoObj.errStr, infoObj, parser.JisonParserError);
   *
   *    originalParseError: function(str, hash, ExceptionClass),
   *               The basic `parseError` handler provided by JISON.
   *               `cleanupAfterParse()` will clean up and reset `parseError()` to reference this function
   *               at the end of the `parse()`.
   *
   *    options: { ... parser %options ... },
   *
   *    parse: function(input[, args...]),
   *               Parse the given `input` and return the parsed value (or `true` when none was provided by
   *               the root action, in which case the parser is acting as a *matcher*).
   *               You MAY use the additional `args...` parameters as per `%parse-param` spec of this grammar:
   *               these extra `args...` are added verbatim to the `yy` object reference as member variables.
   *
   *               WARNING:
   *               Parser's additional `args...` parameters (via `%parse-param`) MAY conflict with
   *               any attributes already added to `yy` by the jison run-time;
   *               when such a collision is detected an exception is thrown to prevent the generated run-time
   *               from silently accepting this confusing and potentially hazardous situation!
   *
   *               The lexer MAY add its own set of additional parameters (via the `%parse-param` line in
   *               the lexer section of the grammar spec): these will be inserted in the `yy` shared state
   *               object and any collision with those will be reported by the lexer via a thrown exception.
   *
   *    cleanupAfterParse: function(resultValue, invoke_post_methods, do_not_nuke_errorinfos),
   *               Helper function **which will be set up during the first invocation of the `parse()` method**.
   *               This helper API is invoked at the end of the `parse()` call, unless an exception was thrown
   *               and `%options no-try-catch` has been defined for this grammar: in that case this helper MAY
   *               be invoked by calling user code to ensure the `post_parse` callbacks are invoked and
   *               the internal parser gets properly garbage collected under these particular circumstances.
   *
   *    yyMergeLocationInfo: function(first_index, last_index, first_yylloc, last_yylloc, dont_look_back),
   *               Helper function **which will be set up during the first invocation of the `parse()` method**.
   *               This helper API can be invoked to calculate a spanning `yylloc` location info object.
   *
   *               Note: %epsilon rules MAY specify no `first_index` and `first_yylloc`, in which case
   *               this function will attempt to obtain a suitable location marker by inspecting the location stack
   *               backwards.
   *
   *               For more info see the documentation comment further below, immediately above this function's
   *               implementation.
   *
   *    lexer: {
   *        yy: {...},           A reference to the so-called "shared state" `yy` once
   *                             received via a call to the `.setInput(input, yy)` lexer API.
   *        EOF: 1,
   *        ERROR: 2,
   *        JisonLexerError: function(msg, hash),
   *        parseError: function(str, hash, ExceptionClass),
   *        setInput: function(input, [yy]),
   *        input: function(),
   *        unput: function(str),
   *        more: function(),
   *        reject: function(),
   *        less: function(n),
   *        pastInput: function(n),
   *        upcomingInput: function(n),
   *        showPosition: function(),
   *        test_match: function(regex_match_array, rule_index, ...),
   *        next: function(...),
   *        lex: function(...),
   *        begin: function(condition),
   *        pushState: function(condition),
   *        popState: function(),
   *        topState: function(),
   *        _currentRules: function(),
   *        stateStackSize: function(),
   *        cleanupAfterLex: function()
   *
   *        options: { ... lexer %options ... },
   *
   *        performAction: function(yy, yy_, $avoiding_name_collisions, YY_START, ...),
   *        rules: [...],
   *        conditions: {associative list: name ==> set},
   *    }
   *  }
   *
   *
   *  token location info (@$, _$, etc.): {
   *    first_line: n,
   *    last_line: n,
   *    first_column: n,
   *    last_column: n,
   *    range: [start_number, end_number]
   *               (where the numbers are indexes into the input string, zero-based)
   *  }
   *
   * ---
   *
   * The `parseError` function receives a 'hash' object with these members for lexer and
   * parser errors:
   *
   *  {
   *    text:        (matched text)
   *    token:       (the produced terminal token, if any)
   *    token_id:    (the produced terminal token numeric ID, if any)
   *    line:        (yylineno)
   *    loc:         (yylloc)
   *  }
   *
   * parser (grammar) errors will also provide these additional members:
   *
   *  {
   *    expected:    (array describing the set of expected tokens;
   *                  may be UNDEFINED when we cannot easily produce such a set)
   *    state:       (integer (or array when the table includes grammar collisions);
   *                  represents the current internal state of the parser kernel.
   *                  can, for example, be used to pass to the `collect_expected_token_set()`
   *                  API to obtain the expected token set)
   *    action:      (integer; represents the current internal action which will be executed)
   *    new_state:   (integer; represents the next/planned internal state, once the current
   *                  action has executed)
   *    recoverable: (boolean: TRUE when the parser MAY have an error recovery rule
   *                  available for this particular error)
   *    state_stack: (array: the current parser LALR/LR internal state stack; this can be used,
   *                  for instance, for advanced error analysis and reporting)
   *    value_stack: (array: the current parser LALR/LR internal `$$` value stack; this can be used,
   *                  for instance, for advanced error analysis and reporting)
   *    location_stack: (array: the current parser LALR/LR internal location stack; this can be used,
   *                  for instance, for advanced error analysis and reporting)
   *    yy:          (object: the current parser internal "shared state" `yy`
   *                  as is also available in the rule actions; this can be used,
   *                  for instance, for advanced error analysis and reporting)
   *    lexer:       (reference to the current lexer instance used by the parser)
   *    parser:      (reference to the current parser instance)
   *  }
   *
   * while `this` will reference the current parser instance.
   *
   * When `parseError` is invoked by the lexer, `this` will still reference the related *parser*
   * instance, while these additional `hash` fields will also be provided:
   *
   *  {
   *    lexer:       (reference to the current lexer instance which reported the error)
   *  }
   *
   * When `parseError` is invoked by the parser due to a **JavaScript exception** being fired
   * from either the parser or lexer, `this` will still reference the related *parser*
   * instance, while these additional `hash` fields will also be provided:
   *
   *  {
   *    exception:   (reference to the exception thrown)
   *  }
   *
   * Please do note that in the latter situation, the `expected` field will be omitted as
   * this type of failure is assumed not to be due to *parse errors* but rather due to user
   * action code in either parser or lexer failing unexpectedly.
   *
   * ---
   *
   * You can specify parser options by setting / modifying the `.yy` object of your Parser instance.
   * These options are available:
   *
   * ### options which are global for all parser instances
   *
   *  Parser.pre_parse: function(yy)
   *                 optional: you can specify a pre_parse() function in the chunk following
   *                 the grammar, i.e. after the last `%%`.
   *  Parser.post_parse: function(yy, retval, parseInfo) { return retval; }
   *                 optional: you can specify a post_parse() function in the chunk following
   *                 the grammar, i.e. after the last `%%`. When it does not return any value,
   *                 the parser will return the original `retval`.
   *
   * ### options which can be set up per parser instance
   *
   *  yy: {
   *      pre_parse:  function(yy)
   *                 optional: is invoked before the parse cycle starts (and before the first
   *                 invocation of `lex()`) but immediately after the invocation of
   *                 `parser.pre_parse()`).
   *      post_parse: function(yy, retval, parseInfo) { return retval; }
   *                 optional: is invoked when the parse terminates due to success ('accept')
   *                 or failure (even when exceptions are thrown).
   *                 `retval` contains the return value to be produced by `Parser.parse()`;
   *                 this function can override the return value by returning another.
   *                 When it does not return any value, the parser will return the original
   *                 `retval`.
   *                 This function is invoked immediately before `parser.post_parse()`.
   *
   *      parseError: function(str, hash, ExceptionClass)
   *                 optional: overrides the default `parseError` function.
   *      quoteName: function(name),
   *                 optional: overrides the default `quoteName` function.
   *  }
   *
   *  parser.lexer.options: {
   *      pre_lex:  function()
   *                 optional: is invoked before the lexer is invoked to produce another token.
   *                 `this` refers to the Lexer object.
   *      post_lex: function(token) { return token; }
   *                 optional: is invoked when the lexer has produced a token `token`;
   *                 this function can override the returned token value by returning another.
   *                 When it does not return any (truthy) value, the lexer will return
   *                 the original `token`.
   *                 `this` refers to the Lexer object.
   *
   *      ranges: boolean
   *                 optional: `true` ==> token location info will include a .range[] member.
   *      flex: boolean
   *                 optional: `true` ==> flex-like lexing behaviour where the rules are tested
   *                 exhaustively to find the longest match.
   *      backtrack_lexer: boolean
   *                 optional: `true` ==> lexer regexes are tested in order and for invoked;
   *                 the lexer terminates the scan when a token is returned by the action code.
   *      xregexp: boolean
   *                 optional: `true` ==> lexer rule regexes are "extended regex format" requiring the
   *                 `XRegExp` library. When this `%option` has not been specified at compile time, all lexer
   *                 rule regexes have been written as standard JavaScript RegExp expressions.
   *  }
   */
  
  
  import XRegExp from '@gerhobbelt/xregexp';       // for helping out the `%options xregexp` in the lexer
    import helpers from 'jison-helpers-lib';
    import fs from 'fs';
    import transform from './ebnf-transform';
  
  // See also:
  // http://stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript/#35881508
  // but we keep the prototype.constructor and prototype.name assignment lines too for compatibility
  // with userland code which might access the derived class in a 'classic' way.
  function JisonParserError(msg, hash) {
      Object.defineProperty(this, 'name', {
          enumerable: false,
          writable: false,
          value: 'JisonParserError'
      });
  
      if (msg == null) msg = '???';
  
      Object.defineProperty(this, 'message', {
          enumerable: false,
          writable: true,
          value: msg
      });
  
      this.hash = hash;
  
      var stacktrace;
      if (hash && hash.exception instanceof Error) {
          var ex2 = hash.exception;
          this.message = ex2.message || msg;
          stacktrace = ex2.stack;
      }
      if (!stacktrace) {
          if (Error.hasOwnProperty('captureStackTrace')) {        // V8/Chrome engine
              Error.captureStackTrace(this, this.constructor);
          } else {
              stacktrace = (new Error(msg)).stack;
          }
      }
      if (stacktrace) {
          Object.defineProperty(this, 'stack', {
              enumerable: false,
              writable: false,
              value: stacktrace
          });
      }
  }
  
  if (typeof Object.setPrototypeOf === 'function') {
      Object.setPrototypeOf(JisonParserError.prototype, Error.prototype);
  } else {
      JisonParserError.prototype = Object.create(Error.prototype);
  }
  JisonParserError.prototype.constructor = JisonParserError;
  JisonParserError.prototype.name = 'JisonParserError';
  
  
  
          // helper: reconstruct the productions[] table
          function bp(s) {
              var rv = [];
              var p = s.pop;
              var r = s.rule;
              for (var i = 0, l = p.length; i < l; i++) {
                  rv.push([
                      p[i],
                      r[i]
                  ]);
              }
              return rv;
          }
      
  
  
          // helper: reconstruct the defaultActions[] table
          function bda(s) {
              var rv = {};
              var d = s.idx;
              var g = s.goto;
              for (var i = 0, l = d.length; i < l; i++) {
                  var j = d[i];
                  rv[j] = g[i];
              }
              return rv;
          }
      
  
  
          // helper: reconstruct the 'goto' table
          function bt(s) {
              var rv = [];
              var d = s.len;
              var y = s.symbol;
              var t = s.type;
              var a = s.state;
              var m = s.mode;
              var g = s.goto;
              for (var i = 0, l = d.length; i < l; i++) {
                  var n = d[i];
                  var q = {};
                  for (var j = 0; j < n; j++) {
                      var z = y.shift();
                      switch (t.shift()) {
                      case 2:
                          q[z] = [
                              m.shift(),
                              g.shift()
                          ];
                          break;
  
                      case 0:
                          q[z] = a.shift();
                          break;
  
                      default:
                          // type === 1: accept
                          q[z] = [
                              3
                          ];
                      }
                  }
                  rv.push(q);
              }
              return rv;
          }
      
  
  
          // helper: runlength encoding with increment step: code, length: step (default step = 0)
          // `this` references an array
          function s(c, l, a) {
              a = a || 0;
              for (var i = 0; i < l; i++) {
                  this.push(c);
                  c += a;
              }
          }
  
          // helper: duplicate sequence from *relative* offset and length.
          // `this` references an array
          function c(i, l) {
              i = this.length - i;
              for (l += i; i < l; i++) {
                  this.push(this[i]);
              }
          }
  
          // helper: unpack an array using helpers and data, all passed in an array argument 'a'.
          function u(a) {
              var rv = [];
              for (var i = 0, l = a.length; i < l; i++) {
                  var e = a[i];
                  // Is this entry a helper function?
                  if (typeof e === 'function') {
                      i++;
                      e.apply(rv, a[i]);
                  } else {
                      rv.push(e);
                  }
              }
              return rv;
          }
      
  
  var parser = {
      // Code Generator Information Report
      // ---------------------------------
      //
      // Options:
      //
      //   default action mode: ............. classic,merge
      //   no try..catch: ................... false
      //   no default resolve on conflict:    false
      //   on-demand look-ahead: ............ false
      //   error recovery token skip maximum: 3
      //   yyerror in parse actions is: ..... NOT recoverable,
      //   yyerror in lexer actions and other non-fatal lexer are:
      //   .................................. NOT recoverable,
      //   debug grammar/output: ............ false
      //   has partial LR conflict upgrade:   true
      //   rudimentary token-stack support:   false
      //   parser table compression mode: ... 2
      //   export debug tables: ............. false
      //   export *all* tables: ............. false
      //   module type: ..................... es
      //   parser engine type: .............. lalr
      //   output main() in the module: ..... true
      //   has user-specified main(): ....... false
      //   has user-specified require()/import modules for main(): 
      //   .................................. false
      //   number of expected conflicts: .... 0
      //
      //
      // Parser Analysis flags:
      //
      //   no significant actions (parser is a language matcher only):
      //   .................................. false
      //   uses yyleng: ..................... false
      //   uses yylineno: ................... false
      //   uses yytext: ..................... false
      //   uses yylloc: ..................... false
      //   uses ParseError API: ............. false
      //   uses YYERROR: .................... true
      //   uses YYRECOVERING: ............... false
      //   uses YYERROK: .................... false
      //   uses YYCLEARIN: .................. false
      //   tracks rule values: .............. true
      //   assigns rule values: ............. true
      //   uses location tracking: .......... true
      //   assigns location: ................ true
      //   uses yystack: .................... false
      //   uses yysstack: ................... false
      //   uses yysp: ....................... true
      //   uses yyrulelength: ............... false
      //   uses yyMergeLocationInfo API: .... true
      //   has error recovery: .............. true
      //   has error reporting: ............. true
      //
      // --------- END OF REPORT -----------
  
  trace: function no_op_trace() {},
  JisonParserError: JisonParserError,
  yy: {},
  options: {
    type: "lalr",
    hasPartialLrUpgradeOnConflict: true,
    errorRecoveryTokenDiscardCount: 3
  },
  symbols_: {
    "$accept": 0,
    "$end": 1,
    "%%": 14,
    "(": 7,
    ")": 8,
    "*": 9,
    "+": 11,
    ":": 5,
    ";": 4,
    "=": 3,
    "?": 10,
    "ACTION": 15,
    "ACTION_BODY": 43,
    "ALIAS": 39,
    "ARROW_ACTION": 42,
    "CODE": 46,
    "DEBUG": 19,
    "EBNF": 20,
    "EOF": 1,
    "EOF_ID": 40,
    "EPSILON": 38,
    "ID": 24,
    "IMPORT": 22,
    "INCLUDE": 44,
    "INIT_CODE": 23,
    "INTEGER": 37,
    "LEFT": 33,
    "LEX_BLOCK": 17,
    "NAME": 25,
    "NONASSOC": 35,
    "OPTIONS": 27,
    "OPTIONS_END": 28,
    "OPTION_STRING_VALUE": 29,
    "OPTION_VALUE": 30,
    "PARSER_TYPE": 32,
    "PARSE_PARAM": 31,
    "PATH": 45,
    "PREC": 41,
    "RIGHT": 34,
    "START": 16,
    "STRING": 26,
    "TOKEN": 18,
    "TOKEN_TYPE": 36,
    "UNKNOWN_DECL": 21,
    "action": 85,
    "action_body": 86,
    "action_comments_body": 87,
    "action_ne": 84,
    "associativity": 61,
    "declaration": 51,
    "declaration_list": 50,
    "error": 2,
    "expression": 79,
    "extra_parser_module_code": 88,
    "full_token_definitions": 63,
    "grammar": 69,
    "handle": 76,
    "handle_action": 75,
    "handle_list": 74,
    "handle_sublist": 77,
    "id": 83,
    "id_list": 68,
    "import_name": 53,
    "import_path": 54,
    "include_macro_code": 89,
    "init_code_name": 52,
    "module_code_chunk": 90,
    "one_full_token": 64,
    "operator": 60,
    "option": 57,
    "option_list": 56,
    "optional_action_header_block": 49,
    "optional_end_block": 48,
    "optional_module_code_chunk": 91,
    "optional_production_description": 73,
    "optional_token_type": 65,
    "options": 55,
    "parse_params": 58,
    "parser_type": 59,
    "prec": 81,
    "production": 71,
    "production_id": 72,
    "production_list": 70,
    "spec": 47,
    "suffix": 80,
    "suffixed_expression": 78,
    "symbol": 82,
    "token_description": 67,
    "token_list": 62,
    "token_value": 66,
    "{": 12,
    "|": 6,
    "}": 13
  },
  terminals_: {
    1: "EOF",
    2: "error",
    3: "=",
    4: ";",
    5: ":",
    6: "|",
    7: "(",
    8: ")",
    9: "*",
    10: "?",
    11: "+",
    12: "{",
    13: "}",
    14: "%%",
    15: "ACTION",
    16: "START",
    17: "LEX_BLOCK",
    18: "TOKEN",
    19: "DEBUG",
    20: "EBNF",
    21: "UNKNOWN_DECL",
    22: "IMPORT",
    23: "INIT_CODE",
    24: "ID",
    25: "NAME",
    26: "STRING",
    27: "OPTIONS",
    28: "OPTIONS_END",
    29: "OPTION_STRING_VALUE",
    30: "OPTION_VALUE",
    31: "PARSE_PARAM",
    32: "PARSER_TYPE",
    33: "LEFT",
    34: "RIGHT",
    35: "NONASSOC",
    36: "TOKEN_TYPE",
    37: "INTEGER",
    38: "EPSILON",
    39: "ALIAS",
    40: "EOF_ID",
    41: "PREC",
    42: "ARROW_ACTION",
    43: "ACTION_BODY",
    44: "INCLUDE",
    45: "PATH",
    46: "CODE"
  },
  TERROR: 2,
  EOF: 1,
  
  // internals: defined here so the object *structure* doesn't get modified by parse() et al,
  // thus helping JIT compilers like Chrome V8.
  originalQuoteName: null,
  originalParseError: null,
  cleanupAfterParse: null,
  constructParseErrorInfo: null,
  yyMergeLocationInfo: null,
  
  __reentrant_call_depth: 0, // INTERNAL USE ONLY
  __error_infos: [], // INTERNAL USE ONLY: the set of parseErrorInfo objects created since the last cleanup
  __error_recovery_infos: [], // INTERNAL USE ONLY: the set of parseErrorInfo objects created since the last cleanup
  
  // APIs which will be set up depending on user action code analysis:
  //yyRecovering: 0,
  //yyErrOk: 0,
  //yyClearIn: 0,
  
  // Helper APIs
  // -----------
  
  // Helper function which can be overridden by user code later on: put suitable quotes around
  // literal IDs in a description string.
  quoteName: function parser_quoteName(id_str) {
      return '"' + id_str + '"';
  },
  
  // Return the name of the given symbol (terminal or non-terminal) as a string, when available.
  //
  // Return NULL when the symbol is unknown to the parser.
  getSymbolName: function parser_getSymbolName(symbol) {
      if (this.terminals_[symbol]) {
          return this.terminals_[symbol];
      }
  
      // Otherwise... this might refer to a RULE token i.e. a non-terminal: see if we can dig that one up.
      //
      // An example of this may be where a rule's action code contains a call like this:
      //
      //      parser.getSymbolName(#$)
      //
      // to obtain a human-readable name of the current grammar rule.
      var s = this.symbols_;
      for (var key in s) {
          if (s[key] === symbol) {
              return key;
          }
      }
      return null;
  },
  
  // Return a more-or-less human-readable description of the given symbol, when available,
  // or the symbol itself, serving as its own 'description' for lack of something better to serve up.
  //
  // Return NULL when the symbol is unknown to the parser.
  describeSymbol: function parser_describeSymbol(symbol) {
      if (symbol !== this.EOF && this.terminal_descriptions_ && this.terminal_descriptions_[symbol]) {
          return this.terminal_descriptions_[symbol];
      } else if (symbol === this.EOF) {
          return 'end of input';
      }
      var id = this.getSymbolName(symbol);
      if (id) {
          return this.quoteName(id);
      }
      return null;
  },
  
  // Produce a (more or less) human-readable list of expected tokens at the point of failure.
  //
  // The produced list may contain token or token set descriptions instead of the tokens
  // themselves to help turning this output into something that easier to read by humans
  // unless `do_not_describe` parameter is set, in which case a list of the raw, *numeric*,
  // expected terminals and nonterminals is produced.
  //
  // The returned list (array) will not contain any duplicate entries.
  collect_expected_token_set: function parser_collect_expected_token_set(state, do_not_describe) {
      var TERROR = this.TERROR;
      var tokenset = [];
      var check = {};
      // Has this (error?) state been outfitted with a custom expectations description text for human consumption?
      // If so, use that one instead of the less palatable token set.
      if (!do_not_describe && this.state_descriptions_ && this.state_descriptions_[state]) {
          return [this.state_descriptions_[state]];
      }
      for (var p in this.table[state]) {
          p = +p;
          if (p !== TERROR) {
              var d = do_not_describe ? p : this.describeSymbol(p);
              if (d && !check[d]) {
                  tokenset.push(d);
                  check[d] = true; // Mark this token description as already mentioned to prevent outputting duplicate entries.
              }
          }
      }
      return tokenset;
  },
  productions_: bp({
    pop: u([
    s,
    [47, 3],
    48,
    48,
    s,
    [49, 3],
    s,
    [50, 3],
    s,
    [51, 20],
    s,
    [52, 3],
    53,
    53,
    54,
    54,
    s,
    [55, 3],
    56,
    56,
    s,
    [57, 6],
    58,
    58,
    59,
    59,
    60,
    60,
    s,
    [61, 3],
    62,
    62,
    63,
    63,
    s,
    [64, 3],
    65,
    s,
    [65, 4, 1],
    68,
    69,
    70,
    70,
    s,
    [71, 3],
    72,
    72,
    73,
    73,
    s,
    [74, 4],
    s,
    [75, 3],
    76,
    76,
    77,
    77,
    78,
    78,
    s,
    [79, 5],
    s,
    [80, 4],
    s,
    [81, 3],
    82,
    82,
    83,
    s,
    [84, 4],
    s,
    [85, 3],
    s,
    [86, 5],
    87,
    87,
    88,
    88,
    89,
    89,
    s,
    [90, 3],
    91,
    91
  ]),
    rule: u([
    5,
    5,
    3,
    0,
    2,
    0,
    s,
    [2, 3],
    c,
    [4, 3],
    1,
    1,
    c,
    [3, 3],
    s,
    [1, 6],
    s,
    [3, 5],
    s,
    [2, 3],
    c,
    [15, 9],
    c,
    [11, 4],
    c,
    [20, 7],
    s,
    [2, 4],
    s,
    [1, 3],
    2,
    1,
    2,
    2,
    c,
    [15, 3],
    0,
    c,
    [11, 7],
    c,
    [36, 4],
    3,
    3,
    1,
    0,
    3,
    c,
    [39, 4],
    c,
    [80, 4],
    c,
    [9, 3],
    c,
    [39, 4],
    3,
    3,
    c,
    [34, 5],
    c,
    [40, 5],
    c,
    [32, 3],
    s,
    [1, 3],
    0,
    0,
    1,
    5,
    4,
    4,
    c,
    [53, 3],
    c,
    [85, 4],
    c,
    [35, 3],
    0
  ])
  }),
  performAction: function parser__PerformAction(yyloc, yystate /* action[1] */, yysp, yyvstack, yylstack) {
  
            /* this == yyval */
  
            // the JS engine itself can go and remove these statements when `yy` turns out to be unused in any action code!
            var yy = this.yy;
            var yyparser = yy.parser;
            var yylexer = yy.lexer;
  
            
  
            switch (yystate) {
  case 0:
      /*! Production::    $accept : spec $end */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yylstack[yysp - 1];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      break;
  
  case 1:
      /*! Production::    spec : declaration_list "%%" grammar optional_end_block EOF */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 4, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 4];
      if (yyvstack[yysp - 1].trim() !== '') {
          yy.addDeclaration(this.$, { include: yyvstack[yysp - 1] });
      }
      return extend(this.$, yyvstack[yysp - 2]);
      break;
  
  case 2:
      /*! Production::    spec : declaration_list "%%" grammar error EOF */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 4];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 4, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      yyparser.yyError(rmCommonWS`
          Maybe you did not correctly separate trailing code from the grammar rule set with a '%%' marker on an otherwise empty line?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2])}
      `);
      break;
  
  case 3:
      /*! Production::    spec : declaration_list error EOF */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      yyparser.yyError(rmCommonWS`
          Maybe you did not correctly separate the parse 'header section' (token definitions, options, lexer spec, etc.) from the grammar rule set with a '%%' on an otherwise empty line?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2])}
      `);
      break;
  
  case 4:
      /*! Production::    optional_end_block : %epsilon */
  case 100:
      /*! Production::    suffix : %epsilon */
  case 116:
      /*! Production::    action : %epsilon */
  case 117:
      /*! Production::    action_body : %epsilon */
  case 132:
      /*! Production::    optional_module_code_chunk : %epsilon */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(null, null, null, null, true);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = '';
      break;
  
  case 5:
      /*! Production::    optional_end_block : "%%" extra_parser_module_code */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]);
      if (rv) {
          yyparser.yyError(rmCommonWS`
              The extra parser module code section (a.k.a. 'epilogue') does not compile: ${rv}
      
                Erroneous area:
              ${yylexer.prettyPrintRange(yylstack[yysp])}
          `);
      }
      this.$ = yyvstack[yysp];
      break;
  
  case 6:
      /*! Production::    optional_action_header_block : %epsilon */
  case 10:
      /*! Production::    declaration_list : %epsilon */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(null, null, null, null, true);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {};
      break;
  
  case 7:
      /*! Production::    optional_action_header_block : optional_action_header_block ACTION */
  case 8:
      /*! Production::    optional_action_header_block : optional_action_header_block include_macro_code */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 1];
      var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]);
      if (rv) {
          yyparser.yyError(rmCommonWS`
              action header code block does not compile: ${rv}
      
                Erroneous area:
              ${yylexer.prettyPrintRange(yylstack[yysp])}
          `);
      }
      yy.addDeclaration(this.$, { actionInclude: yyvstack[yysp] });
      break;
  
  case 9:
      /*! Production::    declaration_list : declaration_list declaration */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 1]; yy.addDeclaration(this.$, yyvstack[yysp]);
      break;
  
  case 11:
      /*! Production::    declaration_list : declaration_list error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          declaration list error?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 12:
      /*! Production::    declaration : START id */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {start: yyvstack[yysp]};
      break;
  
  case 13:
      /*! Production::    declaration : LEX_BLOCK */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {lex: {text: yyvstack[yysp], position: yylstack[yysp]}};
      break;
  
  case 14:
      /*! Production::    declaration : operator */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {operator: yyvstack[yysp]};
      break;
  
  case 15:
      /*! Production::    declaration : TOKEN full_token_definitions */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {token_list: yyvstack[yysp]};
      break;
  
  case 16:
      /*! Production::    declaration : ACTION */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]);
      if (rv) {
          yyparser.yyError(rmCommonWS`
              action code block does not compile: ${rv}
      
                Erroneous area:
              ${yylexer.prettyPrintRange(yylstack[yysp])}
          `);
      }
      this.$ = {include: yyvstack[yysp]};
      break;
  
  case 17:
      /*! Production::    declaration : include_macro_code */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]);
      if (rv) {
          yyparser.yyError(rmCommonWS`
              action header code block does not compile: ${rv}
      
                Erroneous area:
              ${yylexer.prettyPrintRange(yylstack[yysp])}
          `);
      }
      this.$ = {include: yyvstack[yysp]};
      break;
  
  case 18:
      /*! Production::    declaration : parse_params */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {parseParams: yyvstack[yysp]};
      break;
  
  case 19:
      /*! Production::    declaration : parser_type */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {parserType: yyvstack[yysp]};
      break;
  
  case 20:
      /*! Production::    declaration : options */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {options: yyvstack[yysp]};
      break;
  
  case 21:
      /*! Production::    declaration : DEBUG */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {options: [['debug', true]]};
      break;
  
  case 22:
      /*! Production::    declaration : EBNF */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      ebnf = true; 
      this.$ = {options: [['ebnf', true]]};
      break;
  
  case 23:
      /*! Production::    declaration : UNKNOWN_DECL */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {unknownDecl: yyvstack[yysp]};
      break;
  
  case 24:
      /*! Production::    declaration : IMPORT import_name import_path */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {imports: {name: yyvstack[yysp - 1], path: yyvstack[yysp]}};
      break;
  
  case 25:
      /*! Production::    declaration : IMPORT import_name error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      yyparser.yyError(rmCommonWS`
          You did not specify a legal file path for the '%import' initialization code statement, which must have the format:
      
              %import qualifier_name file_path
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])}
      `);
      break;
  
  case 26:
      /*! Production::    declaration : IMPORT error import_path */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      yyparser.yyError(rmCommonWS`
          Each '%import'-ed initialization code section must be qualified by a name, e.g. 'required' before the import path itself:
      
              %import qualifier_name file_path
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2])}
      `);
      break;
  
  case 27:
      /*! Production::    declaration : INIT_CODE init_code_name action_ne */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]);
      if (rv) {
          yyparser.yyError(rmCommonWS`
              %code "${$init_code_name}" initialization section action code block does not compile: ${rv}
      
                Erroneous area:
              ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])}
          `);
      }
      this.$ = {
          initCode: {
              qualifier: yyvstack[yysp - 1],
              include: yyvstack[yysp]
          }
      };
      break;
  
  case 28:
      /*! Production::    declaration : INIT_CODE error action_ne */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      yyparser.yyError(rmCommonWS`
          Each '%code' initialization code section must be qualified by a name, e.g. 'required' before the action code itself:
      
              %code qualifier_name {action code}
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2], yylstack[yysp])}
      `);
      break;
  
  case 29:
      /*! Production::    declaration : START error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          %start token error?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 30:
      /*! Production::    declaration : TOKEN error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          %token definition list error?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 31:
      /*! Production::    declaration : IMPORT error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          %import name or source filename missing maybe?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 32:
      /*! Production::    init_code_name : ID */
  case 33:
      /*! Production::    init_code_name : NAME */
  case 34:
      /*! Production::    init_code_name : STRING */
  case 35:
      /*! Production::    import_name : ID */
  case 36:
      /*! Production::    import_name : STRING */
  case 37:
      /*! Production::    import_path : ID */
  case 38:
      /*! Production::    import_path : STRING */
  case 67:
      /*! Production::    optional_token_type : TOKEN_TYPE */
  case 68:
      /*! Production::    token_value : INTEGER */
  case 69:
      /*! Production::    token_description : STRING */
  case 80:
      /*! Production::    optional_production_description : STRING */
  case 95:
      /*! Production::    expression : ID */
  case 101:
      /*! Production::    suffix : "*" */
  case 102:
      /*! Production::    suffix : "?" */
  case 103:
      /*! Production::    suffix : "+" */
  case 107:
      /*! Production::    symbol : id */
  case 108:
      /*! Production::    symbol : STRING */
  case 109:
      /*! Production::    id : ID */
  case 112:
      /*! Production::    action_ne : ACTION */
  case 113:
      /*! Production::    action_ne : include_macro_code */
  case 114:
      /*! Production::    action : action_ne */
  case 118:
      /*! Production::    action_body : action_comments_body */
  case 122:
      /*! Production::    action_comments_body : ACTION_BODY */
  case 124:
      /*! Production::    extra_parser_module_code : optional_module_code_chunk */
  case 128:
      /*! Production::    module_code_chunk : CODE */
  case 131:
      /*! Production::    optional_module_code_chunk : module_code_chunk */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp];
      break;
  
  case 39:
      /*! Production::    options : OPTIONS option_list OPTIONS_END */
  case 110:
      /*! Production::    action_ne : "{" action_body "}" */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 1];
      break;
  
  case 40:
      /*! Production::    options : OPTIONS error OPTIONS_END */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          %options ill defined / error?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2], yylstack[yysp])}
      `);
      break;
  
  case 41:
      /*! Production::    options : OPTIONS error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          %options don't seem terminated?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 42:
      /*! Production::    option_list : option_list option */
  case 59:
      /*! Production::    token_list : token_list symbol */
  case 70:
      /*! Production::    id_list : id_list id */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 1]; this.$.push(yyvstack[yysp]);
      break;
  
  case 43:
      /*! Production::    option_list : option */
  case 60:
      /*! Production::    token_list : symbol */
  case 71:
      /*! Production::    id_list : id */
  case 83:
      /*! Production::    handle_list : handle_action */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = [yyvstack[yysp]];
      break;
  
  case 44:
      /*! Production::    option : NAME */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = [yyvstack[yysp], true];
      break;
  
  case 45:
      /*! Production::    option : NAME "=" OPTION_STRING_VALUE */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = [yyvstack[yysp - 2], yyvstack[yysp]];
      break;
  
  case 46:
      /*! Production::    option : NAME "=" OPTION_VALUE */
  case 47:
      /*! Production::    option : NAME "=" NAME */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = [yyvstack[yysp - 2], parseValue(yyvstack[yysp])];
      break;
  
  case 48:
      /*! Production::    option : NAME "=" error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          named %option value error for ${yyvstack[yysp - 2]}?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])}
      `);
      break;
  
  case 49:
      /*! Production::    option : NAME error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          named %option value assignment error?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 50:
      /*! Production::    parse_params : PARSE_PARAM token_list */
  case 52:
      /*! Production::    parser_type : PARSER_TYPE symbol */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp];
      break;
  
  case 51:
      /*! Production::    parse_params : PARSE_PARAM error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          %parse-params declaration error?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 53:
      /*! Production::    parser_type : PARSER_TYPE error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          %parser-type declaration error?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 54:
      /*! Production::    operator : associativity token_list */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = [yyvstack[yysp - 1]]; this.$.push.apply(this.$, yyvstack[yysp]);
      break;
  
  case 55:
      /*! Production::    operator : associativity error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          operator token list error in an associativity statement?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 56:
      /*! Production::    associativity : LEFT */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = 'left';
      break;
  
  case 57:
      /*! Production::    associativity : RIGHT */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = 'right';
      break;
  
  case 58:
      /*! Production::    associativity : NONASSOC */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = 'nonassoc';
      break;
  
  case 61:
      /*! Production::    full_token_definitions : optional_token_type id_list */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      var rv = [];
      var lst = yyvstack[yysp];
      for (var i = 0, len = lst.length; i < len; i++) {
          var id = lst[i];
          var m = {id: id};
          if (yyvstack[yysp - 1]) {
              m.type = yyvstack[yysp - 1];
          }
          rv.push(m);
      }
      this.$ = rv;
      break;
  
  case 62:
      /*! Production::    full_token_definitions : optional_token_type one_full_token */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      var m = yyvstack[yysp];
      if (yyvstack[yysp - 1]) {
          m.type = yyvstack[yysp - 1];
      }
      this.$ = [m];
      break;
  
  case 63:
      /*! Production::    one_full_token : id token_value token_description */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {
          id: yyvstack[yysp - 2],
          value: yyvstack[yysp - 1],
          description: yyvstack[yysp]
      };
      break;
  
  case 64:
      /*! Production::    one_full_token : id token_description */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {
          id: yyvstack[yysp - 1],
          description: yyvstack[yysp]
      };
      break;
  
  case 65:
      /*! Production::    one_full_token : id token_value */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {
          id: yyvstack[yysp - 1],
          value: yyvstack[yysp]
      };
      break;
  
  case 66:
      /*! Production::    optional_token_type : %epsilon */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(null, null, null, null, true);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = false;
      break;
  
  case 72:
      /*! Production::    grammar : optional_action_header_block production_list */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 1];
      this.$.grammar = yyvstack[yysp];
      break;
  
  case 73:
      /*! Production::    production_list : production_list production */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 1];
      if (yyvstack[yysp][0] in this.$) {
          this.$[yyvstack[yysp][0]] = this.$[yyvstack[yysp][0]].concat(yyvstack[yysp][1]);
      } else {
          this.$[yyvstack[yysp][0]] = yyvstack[yysp][1];
      }
      break;
  
  case 74:
      /*! Production::    production_list : production */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = {}; this.$[yyvstack[yysp][0]] = yyvstack[yysp][1];
      break;
  
  case 75:
      /*! Production::    production : production_id handle_list ";" */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = [yyvstack[yysp - 2], yyvstack[yysp - 1]];
      break;
  
  case 76:
      /*! Production::    production : production_id error ";" */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          rule production declaration error?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2])}
      `);
      break;
  
  case 77:
      /*! Production::    production : production_id error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          rule production declaration error: did you terminate the rule production set with a semicolon?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 78:
      /*! Production::    production_id : id optional_production_description ":" */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 2];
      
      // TODO: carry rule description support into the parser generator...
      break;
  
  case 79:
      /*! Production::    production_id : id optional_production_description error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          rule id should be followed by a colon, but that one seems missing?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])}
      `);
      break;
  
  case 81:
      /*! Production::    optional_production_description : %epsilon */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = undefined;
      this._$ = yyparser.yyMergeLocationInfo(null, null, null, null, true);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      break;
  
  case 82:
      /*! Production::    handle_list : handle_list "|" handle_action */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 2];
      this.$.push(yyvstack[yysp]);
      break;
  
  case 84:
      /*! Production::    handle_list : handle_list "|" error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          rule alternative production declaration error?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])}
      `);
      break;
  
  case 85:
      /*! Production::    handle_list : handle_list ":" error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          multiple alternative rule productions should be separated by a '|' pipe character, not a ':' colon!
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])}
      `);
      break;
  
  case 86:
      /*! Production::    handle_action : handle prec action */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = [(yyvstack[yysp - 2].length ? yyvstack[yysp - 2].join(' ') : '')];
      if (yyvstack[yysp]) {
          var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]);
          if (rv) {
              yyparser.yyError(rmCommonWS`
                  production rule action code block does not compile: ${rv}
      
                    Erroneous area:
                  ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])}
              `);
          }
          this.$.push(yyvstack[yysp]);
      }
      if (yyvstack[yysp - 1]) {
          if (yyvstack[yysp - 2].length === 0) {
              yyparser.yyError(rmCommonWS`
                  You cannot specify a precedence override for an epsilon (a.k.a. empty) rule!
      
                    Erroneous area:
                  ${yylexer.prettyPrintRange(yylstack[yysp - 2])}
              `);
          }
          this.$.push(yyvstack[yysp - 1]);
      }
      if (this.$.length === 1) {
          this.$ = this.$[0];
      }
      break;
  
  case 87:
      /*! Production::    handle_action : EPSILON action */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = [''];
      if (yyvstack[yysp]) {
          var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]);
          if (rv) {
              yyparser.yyError(rmCommonWS`
                  epsilon production rule action code block does not compile: ${rv}
      
                    Erroneous area:
                  ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
              `);
          }
          this.$.push(yyvstack[yysp]);
      }
      if (this.$.length === 1) {
          this.$ = this.$[0];
      }
      break;
  
  case 88:
      /*! Production::    handle_action : EPSILON error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          %epsilon rule action declaration error?
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 89:
      /*! Production::    handle : handle suffixed_expression */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 1];
      this.$.push(yyvstack[yysp]);
      break;
  
  case 90:
      /*! Production::    handle : %epsilon */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(null, null, null, null, true);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = [];
      break;
  
  case 91:
      /*! Production::    handle_sublist : handle_sublist "|" handle */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 2];
      this.$.push(yyvstack[yysp].join(' '));
      break;
  
  case 92:
      /*! Production::    handle_sublist : handle */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = [yyvstack[yysp].join(' ')];
      break;
  
  case 93:
      /*! Production::    suffixed_expression : expression suffix ALIAS */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 2] + yyvstack[yysp - 1] + "[" + yyvstack[yysp] + "]";
      break;
  
  case 94:
      /*! Production::    suffixed_expression : expression suffix */
  case 123:
      /*! Production::    action_comments_body : action_comments_body ACTION_BODY */
  case 129:
      /*! Production::    module_code_chunk : module_code_chunk CODE */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 1] + yyvstack[yysp];
      break;
  
  case 96:
      /*! Production::    expression : EOF_ID */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = '$end';
      break;
  
  case 97:
      /*! Production::    expression : STRING */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      // Re-encode the string *anyway* as it will
      // be made part of the rule rhs a.k.a. production (type: *string*) again and we want
      // to be able to handle all tokens, including *significant space*
      // encoded as literal tokens in a grammar such as this: `rule: A ' ' B`.
      this.$ = dquote(yyvstack[yysp]);
      break;
  
  case 98:
      /*! Production::    expression : "(" handle_sublist ")" */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = '(' + yyvstack[yysp - 1].join(' | ') + ')';
      break;
  
  case 99:
      /*! Production::    expression : "(" handle_sublist error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      yyparser.yyError(rmCommonWS`
          Seems you did not correctly bracket a grammar rule sublist in '( ... )' brackets.
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])}
      `);
      break;
  
  case 104:
      /*! Production::    prec : PREC symbol */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = { prec: yyvstack[yysp] };
      break;
  
  case 105:
      /*! Production::    prec : PREC error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          %prec precedence override declaration error?
      
            Erroneous precedence declaration:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
      `);
      break;
  
  case 106:
      /*! Production::    prec : %epsilon */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(null, null, null, null, true);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = null;
      break;
  
  case 111:
      /*! Production::    action_ne : "{" action_body error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 2];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      yyparser.yyError(rmCommonWS`
          Seems you did not correctly bracket a parser rule action block in curly braces: '{ ... }'.
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])}
      `);
      break;
  
  case 115:
      /*! Production::    action : ARROW_ACTION */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = '$$ = ' + yyvstack[yysp];
      break;
  
  case 119:
      /*! Production::    action_body : action_body "{" action_body "}" action_comments_body */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 4, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 4] + yyvstack[yysp - 3] + yyvstack[yysp - 2] + yyvstack[yysp - 1] + yyvstack[yysp];
      break;
  
  case 120:
      /*! Production::    action_body : action_body "{" action_body "}" */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 3, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 3] + yyvstack[yysp - 2] + yyvstack[yysp - 1] + yyvstack[yysp];
      break;
  
  case 121:
      /*! Production::    action_body : action_body "{" action_body error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 3];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 3, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      yyparser.yyError(rmCommonWS`
          Seems you did not correctly match curly braces '{ ... }' in a parser rule action block.
      
            Erroneous area:
          ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])}
      `);
      break;
  
  case 125:
      /*! Production::    extra_parser_module_code : optional_module_code_chunk include_macro_code extra_parser_module_code */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 2, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      this.$ = yyvstack[yysp - 2] + yyvstack[yysp - 1] + yyvstack[yysp];
      break;
  
  case 126:
      /*! Production::    include_macro_code : INCLUDE PATH */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-):
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,VU,-,LT,LA,-,-)
      
      
      var fileContent = fs.readFileSync(yyvstack[yysp], { encoding: 'utf-8' });
      var rv = checkActionBlock(fileContent);
      if (rv) {
          yyparser.yyError(rmCommonWS`
              included action code file "${$PATH}" does not compile: ${rv}
      
                Erroneous area:
              ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])}
          `);
      }
      // And no, we don't support nested '%include':
      this.$ = '\n// Included by Jison: ' + yyvstack[yysp] + ':\n\n' + fileContent + '\n\n// End Of Include by Jison: ' + yyvstack[yysp] + '\n\n';
      break;
  
  case 127:
      /*! Production::    include_macro_code : INCLUDE error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp - 1];
      this._$ = yyparser.yyMergeLocationInfo(yysp - 1, yysp);
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      yyparser.yyError(rmCommonWS`
      %include MUST be followed by a valid file path.
      
        Erroneous path:
      ` + yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1]));
      break;
  
  case 130:
      /*! Production::    module_code_chunk : error */
  
      // default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-):
      this.$ = yyvstack[yysp];
      this._$ = yylstack[yysp];
      // END of default action (generated by JISON mode classic/merge :: VT,VA,-,-,LT,LA,-,-)
      
      
      // TODO ...
      yyparser.yyError(rmCommonWS`
          module code declaration error?
      
            Erroneous area:
          ` + yylexer.prettyPrintRange(yylstack[yysp]));
      break;
  
  case 164:       // === NO_ACTION[1] :: ensures that anyone (but us) using this new state will fail dramatically!
                  // error recovery reduction action (action generated by jison,
                  // using the user-specified `%code error_recovery_reduction` %{...%}
                  // code chunk below.
  
                  
                  break;
              
  }
  },
  table: bt({
    len: u([
    20,
    1,
    25,
    5,
    19,
    18,
    3,
    18,
    18,
    5,
    s,
    [18, 8],
    4,
    5,
    6,
    2,
    s,
    [6, 4, -1],
    3,
    3,
    4,
    8,
    1,
    18,
    18,
    26,
    c,
    [18, 3],
    1,
    4,
    21,
    3,
    3,
    5,
    5,
    s,
    [3, 3],
    22,
    18,
    20,
    25,
    25,
    24,
    24,
    22,
    s,
    [18, 3],
    3,
    19,
    2,
    4,
    1,
    1,
    7,
    7,
    c,
    [40, 3],
    17,
    4,
    20,
    18,
    23,
    s,
    [18, 6],
    6,
    21,
    21,
    18,
    20,
    18,
    2,
    18,
    4,
    2,
    s,
    [1, 3],
    s,
    [3, 4],
    4,
    3,
    5,
    3,
    15,
    11,
    2,
    2,
    19,
    20,
    18,
    c,
    [104, 3],
    4,
    4,
    s,
    [2, 4],
    7,
    3,
    4,
    16,
    1,
    4,
    10,
    14,
    c,
    [122, 3],
    18,
    18,
    9,
    s,
    [3, 4],
    14,
    14,
    18,
    21,
    21,
    6,
    4,
    c,
    [50, 5],
    7,
    7,
    s,
    [15, 4],
    3,
    9,
    3,
    14,
    18,
    18,
    8,
    5,
    3,
    9,
    4
  ]),
    symbol: u([
    2,
    s,
    [14, 10, 1],
    27,
    s,
    [31, 5, 1],
    44,
    47,
    50,
    1,
    c,
    [21, 18],
    51,
    55,
    s,
    [58, 4, 1],
    89,
    15,
    24,
    44,
    49,
    69,
    c,
    [31, 19],
    c,
    [18, 19],
    24,
    83,
    c,
    [39, 38],
    36,
    63,
    65,
    c,
    [41, 37],
    c,
    [18, 108],
    24,
    26,
    53,
    2,
    24,
    25,
    26,
    52,
    c,
    [9, 3],
    62,
    82,
    83,
    2,
    45,
    c,
    [8, 7],
    24,
    26,
    c,
    [5, 3],
    25,
    56,
    57,
    c,
    [9, 3],
    c,
    [3, 6],
    c,
    [266, 3],
    48,
    c,
    [275, 3],
    70,
    71,
    72,
    83,
    89,
    c,
    [278, 38],
    4,
    5,
    6,
    12,
    s,
    [14, 11, 1],
    26,
    c,
    [24, 6],
    37,
    42,
    c,
    [152, 37],
    24,
    64,
    68,
    83,
    24,
    c,
    [119, 3],
    54,
    c,
    [27, 11],
    c,
    [67, 8],
    44,
    54,
    c,
    [147, 6],
    12,
    15,
    44,
    84,
    89,
    c,
    [5, 8],
    c,
    [3, 6],
    c,
    [46, 20],
    c,
    [201, 3],
    c,
    [113, 28],
    c,
    [40, 9],
    c,
    [177, 23],
    c,
    [176, 3],
    c,
    [25, 24],
    1,
    c,
    [26, 4],
    c,
    [25, 11],
    c,
    [73, 7],
    46,
    c,
    [24, 24],
    c,
    [158, 51],
    c,
    [18, 25],
    25,
    28,
    57,
    c,
    [21, 12],
    28,
    c,
    [22, 8],
    2,
    3,
    25,
    28,
    s,
    [1, 3],
    2,
    44,
    46,
    88,
    90,
    91,
    c,
    [425, 3],
    24,
    c,
    [433, 3],
    c,
    [440, 3],
    c,
    [3, 3],
    c,
    [13, 4],
    c,
    [153, 4],
    7,
    12,
    15,
    24,
    26,
    38,
    40,
    41,
    42,
    44,
    74,
    75,
    76,
    2,
    5,
    26,
    73,
    c,
    [151, 12],
    c,
    [94, 7],
    c,
    [307, 38],
    37,
    44,
    66,
    67,
    c,
    [685, 109],
    12,
    13,
    43,
    86,
    87,
    c,
    [349, 14],
    c,
    [445, 11],
    c,
    [84, 46],
    c,
    [504, 10],
    c,
    [348, 19],
    c,
    [58, 19],
    25,
    29,
    30,
    c,
    [346, 5],
    1,
    44,
    89,
    1,
    c,
    [483, 3],
    c,
    [3, 6],
    c,
    [339, 3],
    c,
    [121, 3],
    c,
    [496, 3],
    c,
    [8, 5],
    c,
    [349, 8],
    c,
    [348, 4],
    78,
    79,
    81,
    c,
    [568, 5],
    15,
    42,
    44,
    84,
    85,
    89,
    2,
    5,
    2,
    5,
    c,
    [359, 19],
    c,
    [19, 11],
    c,
    [142, 8],
    c,
    [337, 30],
    c,
    [180, 26],
    c,
    [284, 3],
    c,
    [287, 4],
    c,
    [4, 4],
    25,
    28,
    25,
    28,
    c,
    [4, 4],
    c,
    [517, 8],
    c,
    [168, 6],
    c,
    [507, 14],
    c,
    [506, 3],
    c,
    [189, 7],
    c,
    [162, 8],
    s,
    [4, 5, 1],
    c,
    [190, 8],
    c,
    [1024, 6],
    s,
    [4, 9, 1],
    c,
    [22, 3],
    s,
    [39, 4, 1],
    44,
    80,
    c,
    [19, 18],
    c,
    [18, 37],
    c,
    [16, 3],
    c,
    [88, 3],
    76,
    77,
    c,
    [292, 6],
    c,
    [3, 6],
    c,
    [144, 14],
    c,
    [14, 15],
    c,
    [480, 39],
    c,
    [21, 21],
    c,
    [549, 6],
    c,
    [6, 3],
    1,
    c,
    [111, 12],
    c,
    [234, 7],
    c,
    [7, 7],
    c,
    [238, 10],
    c,
    [179, 11],
    c,
    [15, 40],
    6,
    8,
    c,
    [209, 7],
    78,
    79,
    c,
    [374, 4],
    c,
    [313, 14],
    c,
    [271, 43],
    c,
    [164, 4],
    c,
    [169, 4],
    c,
    [78, 12],
    43
  ]),
    type: u([
    s,
    [2, 18],
    0,
    0,
    1,
    c,
    [21, 20],
    s,
    [0, 5],
    c,
    [10, 5],
    s,
    [2, 39],
    c,
    [40, 41],
    c,
    [41, 40],
    s,
    [2, 108],
    c,
    [148, 5],
    c,
    [239, 6],
    c,
    [159, 6],
    c,
    [253, 10],
    c,
    [176, 14],
    c,
    [36, 7],
    c,
    [197, 102],
    c,
    [103, 7],
    c,
    [108, 21],
    c,
    [21, 10],
    c,
    [423, 36],
    c,
    [373, 149],
    c,
    [158, 67],
    c,
    [57, 32],
    c,
    [322, 8],
    c,
    [98, 26],
    c,
    [489, 7],
    c,
    [721, 173],
    c,
    [462, 131],
    c,
    [130, 37],
    c,
    [375, 11],
    c,
    [818, 45],
    c,
    [223, 79],
    c,
    [124, 24],
    c,
    [986, 15],
    c,
    [38, 19],
    c,
    [57, 20],
    c,
    [157, 62],
    c,
    [443, 106],
    c,
    [106, 103],
    c,
    [103, 62],
    c,
    [1248, 16],
    c,
    [78, 6]
  ]),
    state: u([
    1,
    2,
    5,
    14,
    12,
    13,
    8,
    20,
    11,
    29,
    28,
    31,
    34,
    36,
    38,
    42,
    47,
    49,
    50,
    54,
    49,
    50,
    56,
    50,
    58,
    60,
    62,
    65,
    68,
    69,
    70,
    67,
    72,
    71,
    73,
    74,
    78,
    79,
    82,
    83,
    82,
    84,
    50,
    84,
    50,
    86,
    92,
    94,
    93,
    97,
    69,
    70,
    98,
    100,
    101,
    103,
    105,
    106,
    107,
    110,
    111,
    117,
    124,
    126,
    123,
    133,
    131,
    82,
    137,
    142,
    94,
    93,
    143,
    101,
    133,
    146,
    82,
    147,
    50,
    149,
    154,
    153,
    155,
    111,
    124,
    126,
    162,
    163,
    124,
    126
  ]),
    mode: u([
    s,
    [2, 18],
    s,
    [1, 18],
    c,
    [21, 4],
    s,
    [2, 36],
    c,
    [42, 5],
    c,
    [38, 34],
    c,
    [77, 38],
    s,
    [2, 108],
    s,
    [1, 20],
    c,
    [30, 15],
    c,
    [134, 100],
    c,
    [106, 4],
    c,
    [335, 26],
    c,
    [151, 16],
    c,
    [376, 48],
    c,
    [347, 120],
    c,
    [63, 75],
    c,
    [13, 9],
    c,
    [23, 4],
    c,
    [4, 3],
    c,
    [587, 6],
    c,
    [427, 12],
    c,
    [9, 15],
    c,
    [335, 13],
    c,
    [389, 39],
    c,
    [45, 43],
    c,
    [509, 77],
    c,
    [762, 121],
    c,
    [129, 9],
    c,
    [756, 14],
    c,
    [334, 14],
    c,
    [41, 6],
    c,
    [367, 5],
    c,
    [784, 37],
    c,
    [208, 63],
    c,
    [1142, 20],
    c,
    [1081, 10],
    c,
    [487, 14],
    c,
    [22, 9],
    c,
    [151, 17],
    c,
    [221, 10],
    c,
    [803, 156],
    c,
    [318, 61],
    c,
    [216, 50],
    c,
    [457, 7],
    c,
    [455, 38],
    c,
    [123, 34],
    c,
    [1206, 8],
    1
  ]),
    goto: u([
    s,
    [10, 18],
    4,
    3,
    10,
    6,
    7,
    9,
    s,
    [15, 5, 1],
    24,
    22,
    23,
    25,
    26,
    27,
    21,
    s,
    [6, 3],
    30,
    s,
    [11, 18],
    s,
    [9, 18],
    32,
    33,
    s,
    [13, 18],
    s,
    [14, 18],
    35,
    66,
    37,
    s,
    [16, 18],
    s,
    [17, 18],
    s,
    [18, 18],
    s,
    [19, 18],
    s,
    [20, 18],
    s,
    [21, 18],
    s,
    [22, 18],
    s,
    [23, 18],
    39,
    40,
    41,
    s,
    [43, 4, 1],
    48,
    33,
    51,
    53,
    52,
    55,
    33,
    51,
    57,
    33,
    51,
    59,
    61,
    s,
    [56, 3],
    s,
    [57, 3],
    s,
    [58, 3],
    4,
    63,
    64,
    66,
    33,
    21,
    3,
    s,
    [12, 18],
    s,
    [29, 18],
    s,
    [109, 26],
    s,
    [15, 18],
    s,
    [30, 18],
    33,
    67,
    75,
    76,
    77,
    s,
    [31, 11],
    c,
    [13, 9],
    s,
    [35, 3],
    s,
    [36, 3],
    80,
    81,
    21,
    c,
    [3, 3],
    s,
    [32, 3],
    s,
    [33, 3],
    s,
    [34, 3],
    s,
    [54, 11],
    33,
    51,
    s,
    [54, 7],
    s,
    [55, 18],
    s,
    [60, 20],
    s,
    [107, 25],
    s,
    [108, 25],
    s,
    [126, 24],
    s,
    [127, 24],
    s,
    [50, 11],
    33,
    51,
    s,
    [50, 7],
    s,
    [51, 18],
    s,
    [52, 18],
    s,
    [53, 18],
    61,
    85,
    s,
    [41, 12],
    87,
    s,
    [41, 6],
    43,
    43,
    89,
    88,
    44,
    44,
    90,
    91,
    132,
    96,
    132,
    95,
    s,
    [72, 3],
    33,
    s,
    [7, 3],
    s,
    [8, 3],
    s,
    [74, 4],
    99,
    s,
    [90, 8],
    102,
    s,
    [90, 4],
    81,
    81,
    104,
    s,
    [61, 11],
    33,
    s,
    [61, 7],
    s,
    [62, 18],
    s,
    [71, 12],
    109,
    s,
    [71, 6],
    108,
    71,
    s,
    [24, 18],
    s,
    [25, 18],
    s,
    [37, 18],
    s,
    [38, 18],
    s,
    [26, 18],
    s,
    [27, 18],
    s,
    [117, 3],
    s,
    [112, 22],
    s,
    [113, 21],
    s,
    [28, 18],
    s,
    [59, 20],
    s,
    [39, 18],
    42,
    42,
    s,
    [40, 18],
    116,
    115,
    113,
    114,
    49,
    49,
    1,
    2,
    5,
    124,
    21,
    131,
    131,
    118,
    s,
    [128, 3],
    s,
    [130, 3],
    s,
    [73, 4],
    119,
    121,
    120,
    77,
    77,
    122,
    77,
    77,
    s,
    [83, 3],
    s,
    [106, 3],
    130,
    106,
    106,
    127,
    129,
    128,
    125,
    106,
    106,
    132,
    s,
    [116, 3],
    80,
    81,
    134,
    21,
    136,
    135,
    80,
    80,
    s,
    [70, 19],
    s,
    [65, 11],
    109,
    s,
    [65, 7],
    s,
    [64, 18],
    s,
    [68, 19],
    s,
    [69, 18],
    139,
    140,
    138,
    s,
    [118, 3],
    141,
    s,
    [122, 4],
    45,
    45,
    46,
    46,
    47,
    47,
    48,
    48,
    c,
    [494, 4],
    s,
    [129, 3],
    s,
    [75, 4],
    144,
    c,
    [487, 13],
    145,
    s,
    [76, 4],
    c,
    [153, 7],
    s,
    [89, 14],
    148,
    33,
    51,
    s,
    [100, 6],
    150,
    151,
    152,
    s,
    [100, 9],
    s,
    [95, 18],
    s,
    [96, 18],
    s,
    [97, 18],
    s,
    [90, 7],
    s,
    [87, 3],
    s,
    [88, 3],
    s,
    [114, 3],
    s,
    [115, 3],
    s,
    [78, 14],
    s,
    [79, 14],
    s,
    [63, 18],
    s,
    [110, 21],
    s,
    [111, 21],
    c,
    [526, 4],
    s,
    [123, 4],
    125,
    s,
    [82, 3],
    s,
    [84, 3],
    s,
    [85, 3],
    s,
    [86, 3],
    s,
    [104, 7],
    s,
    [105, 7],
    s,
    [94, 10],
    156,
    s,
    [94, 4],
    s,
    [101, 15],
    s,
    [102, 15],
    s,
    [103, 15],
    158,
    159,
    157,
    92,
    92,
    130,
    92,
    c,
    [465, 3],
    161,
    140,
    160,
    s,
    [93, 14],
    s,
    [98, 18],
    s,
    [99, 18],
    s,
    [90, 7],
    s,
    [120, 3],
    112,
    s,
    [121, 3],
    91,
    91,
    130,
    91,
    c,
    [74, 3],
    s,
    [119, 3],
    141
  ])
  }),
  defaultActions: bda({
    idx: u([
    0,
    3,
    5,
    7,
    8,
    s,
    [10, 8, 1],
    25,
    26,
    27,
    s,
    [30, 6, 1],
    37,
    40,
    41,
    44,
    45,
    46,
    s,
    [48, 6, 1],
    55,
    56,
    57,
    60,
    66,
    67,
    68,
    72,
    s,
    [74, 6, 1],
    s,
    [81, 7, 1],
    s,
    [89, 4, 1],
    95,
    96,
    97,
    100,
    104,
    105,
    107,
    108,
    109,
    s,
    [112, 5, 1],
    118,
    119,
    122,
    124,
    s,
    [127, 13, 1],
    s,
    [141, 8, 1],
    150,
    151,
    152,
    s,
    [156, 4, 1],
    161
  ]),
    goto: u([
    10,
    6,
    9,
    13,
    14,
    s,
    [16, 8, 1],
    56,
    57,
    58,
    3,
    12,
    29,
    109,
    15,
    30,
    67,
    35,
    36,
    32,
    33,
    34,
    55,
    60,
    107,
    108,
    126,
    127,
    51,
    52,
    53,
    43,
    7,
    8,
    74,
    62,
    24,
    25,
    37,
    38,
    26,
    27,
    112,
    113,
    28,
    59,
    39,
    42,
    40,
    49,
    1,
    2,
    5,
    128,
    130,
    73,
    83,
    80,
    70,
    64,
    68,
    69,
    122,
    s,
    [45, 4, 1],
    129,
    75,
    76,
    89,
    95,
    96,
    97,
    90,
    87,
    88,
    114,
    115,
    78,
    79,
    63,
    110,
    111,
    123,
    125,
    82,
    84,
    85,
    86,
    104,
    105,
    101,
    102,
    103,
    93,
    98,
    99,
    90,
    121
  ])
  }),
  parseError: function parseError(str, hash, ExceptionClass) {
      if (hash.recoverable && typeof this.trace === 'function') {
          this.trace(str);
          hash.destroy(); // destroy... well, *almost*!
      } else {
          if (!ExceptionClass) {
              ExceptionClass = this.JisonParserError;
          }
          throw new ExceptionClass(str, hash);
      }
  },
  parse: function parse(input) {
      var self = this;
      var stack = new Array(128);         // token stack: stores token which leads to state at the same index (column storage)
      var sstack = new Array(128);        // state stack: stores states (column storage)
  
      var vstack = new Array(128);        // semantic value stack
      var lstack = new Array(128);        // location stack
      var table = this.table;
      var sp = 0;                         // 'stack pointer': index into the stacks
      var yyloc;
  
      var yylineno;
  
  
      var symbol = 0;
      var preErrorSymbol = 0;
      var lastEofErrorStateDepth = 0;
      var recoveringErrorInfo = null;
      var recovering = 0;                 // (only used when the grammar contains error recovery rules)
      var TERROR = this.TERROR;
      var EOF = this.EOF;
      var ERROR_RECOVERY_TOKEN_DISCARD_COUNT = (this.options.errorRecoveryTokenDiscardCount | 0) || 3;
      var NO_ACTION = [0, 164 /* === table.length :: ensures that anyone using this new state will fail dramatically! */];
  
      var lexer;
      if (this.__lexer__) {
          lexer = this.__lexer__;
      } else {
          lexer = this.__lexer__ = Object.create(this.lexer);
      }
  
      var sharedState_yy = {
          parseError: undefined,
          quoteName: undefined,
          lexer: undefined,
          parser: undefined,
          pre_parse: undefined,
          post_parse: undefined,
          pre_lex: undefined,
          post_lex: undefined      // WARNING: must be written this way for the code expanders to work correctly in both ES5 and ES6 modes!
      };
  
      var ASSERT;
      if (typeof assert !== 'function') {
          ASSERT = function JisonAssert(cond, msg) {
              if (!cond) {
                  throw new Error('assertion failed: ' + (msg || '***'));
              }
          };
      } else {
          ASSERT = assert;
      }
  
      this.yyGetSharedState = function yyGetSharedState() {
          return sharedState_yy;
      };
  
  
      this.yyGetErrorInfoTrack = function yyGetErrorInfoTrack() {
          return recoveringErrorInfo;
      };
  
  
      // shallow clone objects, straight copy of simple `src` values
      // e.g. `lexer.yytext` MAY be a complex value object,
      // rather than a simple string/value.
      function shallow_copy(src) {
          if (typeof src === 'object') {
              var dst = {};
              for (var k in src) {
                  if (Object.prototype.hasOwnProperty.call(src, k)) {
                      dst[k] = src[k];
                  }
              }
              return dst;
          }
          return src;
      }
      function shallow_copy_noclobber(dst, src) {
          for (var k in src) {
              if (typeof dst[k] === 'undefined' && Object.prototype.hasOwnProperty.call(src, k)) {
                  dst[k] = src[k];
              }
          }
      }
      function copy_yylloc(loc) {
          var rv = shallow_copy(loc);
          if (rv && rv.range) {
              rv.range = rv.range.slice(0);
          }
          return rv;
      }
  
      // copy state
      shallow_copy_noclobber(sharedState_yy, this.yy);
  
      sharedState_yy.lexer = lexer;
      sharedState_yy.parser = this;
  
  
  
  
  
      // *Always* setup `yyError`, `YYRECOVERING`, `yyErrOk` and `yyClearIn` functions as it is paramount
      // to have *their* closure match ours -- if we only set them up once,
      // any subsequent `parse()` runs will fail in very obscure ways when
      // these functions are invoked in the user action code block(s) as
      // their closure will still refer to the `parse()` instance which set
      // them up. Hence we MUST set them up at the start of every `parse()` run!
      if (this.yyError) {
          this.yyError = function yyError(str /*, ...args */) {
  
  
  
  
  
  
  
  
  
  
  
              var error_rule_depth = (this.options.parserErrorsAreRecoverable ? locateNearestErrorRecoveryRule(state) : -1);
              var expected = this.collect_expected_token_set(state);
              var hash = this.constructParseErrorInfo(str, null, expected, (error_rule_depth >= 0));
              // append to the old one?
              if (recoveringErrorInfo) {
                  var esp = recoveringErrorInfo.info_stack_pointer;
  
                  recoveringErrorInfo.symbol_stack[esp] = symbol;
                  var v = this.shallowCopyErrorInfo(hash);
                  v.yyError = true;
                  v.errorRuleDepth = error_rule_depth;
                  v.recovering = recovering;
                  // v.stackSampleLength = error_rule_depth + EXTRA_STACK_SAMPLE_DEPTH;
  
                  recoveringErrorInfo.value_stack[esp] = v;
                  recoveringErrorInfo.location_stack[esp] = copy_yylloc(lexer.yylloc);
                  recoveringErrorInfo.state_stack[esp] = newState || NO_ACTION[1];
  
                  ++esp;
                  recoveringErrorInfo.info_stack_pointer = esp;
              } else {
                  recoveringErrorInfo = this.shallowCopyErrorInfo(hash);
                  recoveringErrorInfo.yyError = true;
                  recoveringErrorInfo.errorRuleDepth = error_rule_depth;
                  recoveringErrorInfo.recovering = recovering;
              }
  
  
              // Add any extra args to the hash under the name `extra_error_attributes`:
              var args = Array.prototype.slice.call(arguments, 1);
              if (args.length) {
                  hash.extra_error_attributes = args;
              }
  
              var r = this.parseError(str, hash, this.JisonParserError);
              return r;
          };
      }
  
  
  
  
  
  
  
      // Does the shared state override the default `parseError` that already comes with this instance?
      if (typeof sharedState_yy.parseError === 'function') {
          this.parseError = function parseErrorAlt(str, hash, ExceptionClass) {
              if (!ExceptionClass) {
                  ExceptionClass = this.JisonParserError;
              }
              return sharedState_yy.parseError.call(this, str, hash, ExceptionClass);
          };
      } else {
          this.parseError = this.originalParseError;
      }
  
      // Does the shared state override the default `quoteName` that already comes with this instance?
      if (typeof sharedState_yy.quoteName === 'function') {
          this.quoteName = function quoteNameAlt(id_str) {
              return sharedState_yy.quoteName.call(this, id_str);
          };
      } else {
          this.quoteName = this.originalQuoteName;
      }
  
      // set up the cleanup function; make it an API so that external code can re-use this one in case of
      // calamities or when the `%options no-try-catch` option has been specified for the grammar, in which
      // case this parse() API method doesn't come with a `finally { ... }` block any more!
      //
      // NOTE: as this API uses parse() as a closure, it MUST be set again on every parse() invocation,
      //       or else your `sharedState`, etc. references will be *wrong*!
      this.cleanupAfterParse = function parser_cleanupAfterParse(resultValue, invoke_post_methods, do_not_nuke_errorinfos) {
          var rv;
  
          if (invoke_post_methods) {
              var hash;
  
              if (sharedState_yy.post_parse || this.post_parse) {
                  // create an error hash info instance: we re-use this API in a **non-error situation**
                  // as this one delivers all parser internals ready for access by userland code.
                  hash = this.constructParseErrorInfo(null /* no error! */, null /* no exception! */, null, false);
              }
  
              if (sharedState_yy.post_parse) {
                  rv = sharedState_yy.post_parse.call(this, sharedState_yy, resultValue, hash);
                  if (typeof rv !== 'undefined') resultValue = rv;
              }
              if (this.post_parse) {
                  rv = this.post_parse.call(this, sharedState_yy, resultValue, hash);
                  if (typeof rv !== 'undefined') resultValue = rv;
              }
  
              // cleanup:
              if (hash && hash.destroy) {
                  hash.destroy();
              }
          }
  
          if (this.__reentrant_call_depth > 1) return resultValue;        // do not (yet) kill the sharedState when this is a reentrant run.
  
          // clean up the lingering lexer structures as well:
          if (lexer.cleanupAfterLex) {
              lexer.cleanupAfterLex(do_not_nuke_errorinfos);
          }
  
          // prevent lingering circular references from causing memory leaks:
          if (sharedState_yy) {
              sharedState_yy.lexer = undefined;
              sharedState_yy.parser = undefined;
              if (lexer.yy === sharedState_yy) {
                  lexer.yy = undefined;
              }
          }
          sharedState_yy = undefined;
          this.parseError = this.originalParseError;
          this.quoteName = this.originalQuoteName;
  
          // nuke the vstack[] array at least as that one will still reference obsoleted user values.
          // To be safe, we nuke the other internal stack columns as well...
          stack.length = 0;               // fastest way to nuke an array without overly bothering the GC
          sstack.length = 0;
          lstack.length = 0;
          vstack.length = 0;
          sp = 0;
  
          // nuke the error hash info instances created during this run.
          // Userland code must COPY any data/references
          // in the error hash instance(s) it is more permanently interested in.
          if (!do_not_nuke_errorinfos) {
              for (var i = this.__error_infos.length - 1; i >= 0; i--) {
                  var el = this.__error_infos[i];
                  if (el && typeof el.destroy === 'function') {
                      el.destroy();
                  }
              }
              this.__error_infos.length = 0;
  
  
              for (var i = this.__error_recovery_infos.length - 1; i >= 0; i--) {
                  var el = this.__error_recovery_infos[i];
                  if (el && typeof el.destroy === 'function') {
                      el.destroy();
                  }
              }
              this.__error_recovery_infos.length = 0;
  
              if (recoveringErrorInfo && typeof recoveringErrorInfo.destroy === 'function') {
                  recoveringErrorInfo.destroy();
                  recoveringErrorInfo = undefined;
              }
  
  
          }
  
          return resultValue;
      };
  
      // merge yylloc info into a new yylloc instance.
      //
      // `first_index` and `last_index` MAY be UNDEFINED/NULL or these are indexes into the `lstack[]` location stack array.
      //
      // `first_yylloc` and `last_yylloc` MAY be UNDEFINED/NULL or explicit (custom or regular) `yylloc` instances, in which
      // case these override the corresponding first/last indexes.
      //
      // `dont_look_back` is an optional flag (default: FALSE), which instructs this merge operation NOT to search
      // through the parse location stack for a location, which would otherwise be used to construct the new (epsilon!)
      // yylloc info.
      //
      // Note: epsilon rule's yylloc situation is detected by passing both `first_index` and `first_yylloc` as UNDEFINED/NULL.
      this.yyMergeLocationInfo = function parser_yyMergeLocationInfo(first_index, last_index, first_yylloc, last_yylloc, dont_look_back) {
          var i1 = first_index | 0,
              i2 = last_index | 0;
          var l1 = first_yylloc,
              l2 = last_yylloc;
          var rv;
  
          // rules:
          // - first/last yylloc entries override first/last indexes
  
          if (!l1) {
              if (first_index != null) {
                  for (var i = i1; i <= i2; i++) {
                      l1 = lstack[i];
                      if (l1) {
                          break;
                      }
                  }
              }
          }
  
          if (!l2) {
              if (last_index != null) {
                  for (var i = i2; i >= i1; i--) {
                      l2 = lstack[i];
                      if (l2) {
                          break;
                      }
                  }
              }
          }
  
          // - detect if an epsilon rule is being processed and act accordingly:
          if (!l1 && first_index == null) {
              // epsilon rule span merger. With optional look-ahead in l2.
              if (!dont_look_back) {
                  for (var i = (i1 || sp) - 1; i >= 0; i--) {
                      l1 = lstack[i];
                      if (l1) {
                          break;
                      }
                  }
              }
              if (!l1) {
                  if (!l2) {
                      // when we still don't have any valid yylloc info, we're looking at an epsilon rule
                      // without look-ahead and no preceding terms and/or `dont_look_back` set:
                      // in that case we ca do nothing but return NULL/UNDEFINED:
                      return undefined;
                  } else {
                      // shallow-copy L2: after all, we MAY be looking
                      // at unconventional yylloc info objects...
                      rv = shallow_copy(l2);
                      if (rv.range) {
                          // shallow copy the yylloc ranges info to prevent us from modifying the original arguments' entries:
                          rv.range = rv.range.slice(0);
                      }
                      return rv;
                  }
              } else {
                  // shallow-copy L1, then adjust first col/row 1 column past the end.
                  rv = shallow_copy(l1);
                  rv.first_line = rv.last_line;
                  rv.first_column = rv.last_column;
                  if (rv.range) {
                      // shallow copy the yylloc ranges info to prevent us from modifying the original arguments' entries:
                      rv.range = rv.range.slice(0);
                      rv.range[0] = rv.range[1];
                  }
  
                  if (l2) {
                      // shallow-mixin L2, then adjust last col/row accordingly.
                      shallow_copy_noclobber(rv, l2);
                      rv.last_line = l2.last_line;
                      rv.last_column = l2.last_column;
                      if (rv.range && l2.range) {
                          rv.range[1] = l2.range[1];
                      }
                  }
                  return rv;
              }
          }
  
          if (!l1) {
              l1 = l2;
              l2 = null;
          }
          if (!l1) {
              return undefined;
          }
  
          // shallow-copy L1|L2, before we try to adjust the yylloc values: after all, we MAY be looking
          // at unconventional yylloc info objects...
          rv = shallow_copy(l1);
  
          // first_line: ...,
          // first_column: ...,
          // last_line: ...,
          // last_column: ...,
          if (rv.range) {
              // shallow copy the yylloc ranges info to prevent us from modifying the original arguments' entries:
              rv.range = rv.range.slice(0);
          }
  
          if (l2) {
              shallow_copy_noclobber(rv, l2);
              rv.last_line = l2.last_line;
              rv.last_column = l2.last_column;
              if (rv.range && l2.range) {
                  rv.range[1] = l2.range[1];
              }
          }
  
          return rv;
      };
  
      // NOTE: as this API uses parse() as a closure, it MUST be set again on every parse() invocation,
      //       or else your `lexer`, `sharedState`, etc. references will be *wrong*!
      this.constructParseErrorInfo = function parser_constructParseErrorInfo(msg, ex, expected, recoverable) {
          var pei = {
              errStr: msg,
              exception: ex,
              text: lexer.match,
              value: lexer.yytext,
              token: this.describeSymbol(symbol) || symbol,
              token_id: symbol,
              line: lexer.yylineno,
              loc: copy_yylloc(lexer.yylloc),
              expected: expected,
              recoverable: recoverable,
              state: state,
              action: action,
              new_state: newState,
              symbol_stack: stack,
              state_stack: sstack,
              value_stack: vstack,
              location_stack: lstack,
              stack_pointer: sp,
              yy: sharedState_yy,
              lexer: lexer,
              parser: this,
  
              // and make sure the error info doesn't stay due to potential
              // ref cycle via userland code manipulations.
              // These would otherwise all be memory leak opportunities!
              //
              // Note that only array and object references are nuked as those
              // constitute the set of elements which can produce a cyclic ref.
              // The rest of the members is kept intact as they are harmless.
              destroy: function destructParseErrorInfo() {
                  // remove cyclic references added to error info:
                  // info.yy = null;
                  // info.lexer = null;
                  // info.value = null;
                  // info.value_stack = null;
                  // ...
                  var rec = !!this.recoverable;
                  for (var key in this) {
                      if (this.hasOwnProperty(key) && typeof key === 'object') {
                          this[key] = undefined;
                      }
                  }
                  this.recoverable = rec;
              }
          };
          // track this instance so we can `destroy()` it once we deem it superfluous and ready for garbage collection!
          this.__error_infos.push(pei);
          return pei;
      };
  
      // clone some parts of the (possibly enhanced!) errorInfo object
      // to give them some persistence.
      this.shallowCopyErrorInfo = function parser_shallowCopyErrorInfo(p) {
          var rv = shallow_copy(p);
  
          // remove the large parts which can only cause cyclic references
          // and are otherwise available from the parser kernel anyway.
          delete rv.sharedState_yy;
          delete rv.parser;
          delete rv.lexer;
  
          // lexer.yytext MAY be a complex value object, rather than a simple string/value:
          rv.value = shallow_copy(rv.value);
  
          // yylloc info:
          rv.loc = copy_yylloc(rv.loc);
  
          // the 'expected' set won't be modified, so no need to clone it:
          //rv.expected = rv.expected.slice(0);
  
          //symbol stack is a simple array:
          rv.symbol_stack = rv.symbol_stack.slice(0);
          // ditto for state stack:
          rv.state_stack = rv.state_stack.slice(0);
          // clone the yylloc's in the location stack?:
          rv.location_stack = rv.location_stack.map(copy_yylloc);
          // and the value stack may carry both simple and complex values:
          // shallow-copy the latter.
          rv.value_stack = rv.value_stack.map(shallow_copy);
  
          // and we don't bother with the sharedState_yy reference:
          //delete rv.yy;
  
          // now we prepare for tracking the COMBINE actions
          // in the error recovery code path:
          //
          // as we want to keep the maximum error info context, we
          // *scan* the state stack to find the first *empty* slot.
          // This position will surely be AT OR ABOVE the current
          // stack pointer, but we want to keep the 'used but discarded'
          // part of the parse stacks *intact* as those slots carry
          // error context that may be useful when you want to produce
          // very detailed error diagnostic reports.
          //
          // ### Purpose of each stack pointer:
          //
          // - stack_pointer: points at the top of the parse stack
          //                  **as it existed at the time of the error
          //                  occurrence, i.e. at the time the stack
          //                  snapshot was taken and copied into the
          //                  errorInfo object.**
          // - base_pointer:  the bottom of the **empty part** of the
          //                  stack, i.e. **the start of the rest of
          //                  the stack space /above/ the existing
          //                  parse stack. This section will be filled
          //                  by the error recovery process as it
          //                  travels the parse state machine to
          //                  arrive at the resolving error recovery rule.**
          // - info_stack_pointer:
          //                  this stack pointer points to the **top of
          //                  the error ecovery tracking stack space**, i.e.
          //                  this stack pointer takes up the role of
          //                  the `stack_pointer` for the error recovery
          //                  process. Any mutations in the **parse stack**
          //                  are **copy-appended** to this part of the
          //                  stack space, keeping the bottom part of the
          //                  stack (the 'snapshot' part where the parse
          //                  state at the time of error occurrence was kept)
          //                  intact.
          // - root_failure_pointer:
          //                  copy of the `stack_pointer`...
          //
          for (var i = rv.stack_pointer; typeof rv.state_stack[i] !== 'undefined'; i++) {
              // empty
          }
          rv.base_pointer = i;
          rv.info_stack_pointer = i;
  
          rv.root_failure_pointer = rv.stack_pointer;
  
          // track this instance so we can `destroy()` it once we deem it superfluous and ready for garbage collection!
          this.__error_recovery_infos.push(rv);
  
          return rv;
      };
  
      function getNonTerminalFromCode(symbol) {
          var tokenName = self.getSymbolName(symbol);
          if (!tokenName) {
              tokenName = symbol;
          }
          return tokenName;
      }
  
  
      function lex() {
          var token = lexer.lex();
          // if token isn't its numeric value, convert
          if (typeof token !== 'number') {
              token = self.symbols_[token] || token;
          }
  
          return token || EOF;
      }
  
  
      var state, action, r, t;
      var yyval = {
          $: true,
          _$: undefined,
          yy: sharedState_yy
      };
      var p;
      var yyrulelen;
      var this_production;
      var newState;
      var retval = false;
  
  
      // Return the rule stack depth where the nearest error rule can be found.
      // Return -1 when no error recovery rule was found.
      function locateNearestErrorRecoveryRule(state) {
          var stack_probe = sp - 1;
          var depth = 0;
  
          // try to recover from error
          for (;;) {
              // check for error recovery rule in this state
  
  
  
  
  
  
  
  
  
              var t = table[state][TERROR] || NO_ACTION;
              if (t[0]) {
                  // We need to make sure we're not cycling forever:
                  // once we hit EOF, even when we `yyerrok()` an error, we must
                  // prevent the core from running forever,
                  // e.g. when parent rules are still expecting certain input to
                  // follow after this, for example when you handle an error inside a set
                  // of braces which are matched by a parent rule in your grammar.
                  //
                  // Hence we require that every error handling/recovery attempt
                  // *after we've hit EOF* has a diminishing state stack: this means
                  // we will ultimately have unwound the state stack entirely and thus
                  // terminate the parse in a controlled fashion even when we have
                  // very complex error/recovery code interplay in the core + user
                  // action code blocks:
  
  
  
  
  
  
  
  
  
                  if (symbol === EOF) {
                      if (!lastEofErrorStateDepth) {
                          lastEofErrorStateDepth = sp - 1 - depth;
                      } else if (lastEofErrorStateDepth <= sp - 1 - depth) {
  
  
  
  
  
  
  
  
  
                          --stack_probe; // popStack(1): [symbol, action]
                          state = sstack[stack_probe];
                          ++depth;
                          continue;
                      }
                  }
                  return depth;
              }
              if (state === 0 /* $accept rule */ || stack_probe < 1) {
  
  
  
  
  
  
  
  
  
                  return -1; // No suitable error recovery rule available.
              }
              --stack_probe; // popStack(1): [symbol, action]
              state = sstack[stack_probe];
              ++depth;
          }
      }
  
  
      try {
          this.__reentrant_call_depth++;
  
          lexer.setInput(input, sharedState_yy);
  
          yyloc = lexer.yylloc;
          lstack[sp] = yyloc;
          vstack[sp] = null;
          sstack[sp] = 0;
          stack[sp] = 0;
          ++sp;
  
  
  
  
  
          if (this.pre_parse) {
              this.pre_parse.call(this, sharedState_yy);
          }
          if (sharedState_yy.pre_parse) {
              sharedState_yy.pre_parse.call(this, sharedState_yy);
          }
  
          newState = sstack[sp - 1];
          for (;;) {
              // retrieve state number from top of stack
              state = newState;               // sstack[sp - 1];
  
              // use default actions if available
              if (this.defaultActions[state]) {
                  action = 2;
                  newState = this.defaultActions[state];
              } else {
                  // The single `==` condition below covers both these `===` comparisons in a single
                  // operation:
                  //
                  //     if (symbol === null || typeof symbol === 'undefined') ...
                  if (!symbol) {
                      symbol = lex();
                  }
                  // read action for current state and first input
                  t = (table[state] && table[state][symbol]) || NO_ACTION;
                  newState = t[1];
                  action = t[0];
  
  
  
  
  
  
  
  
  
  
  
                  // handle parse error
                  if (!action) {
                      // first see if there's any chance at hitting an error recovery rule:
                      var error_rule_depth = locateNearestErrorRecoveryRule(state);
                      var errStr = null;
                      var errSymbolDescr = (this.describeSymbol(symbol) || symbol);
                      var expected = this.collect_expected_token_set(state);
  
                      if (!recovering) {
                          // Report error
                          if (typeof lexer.yylineno === 'number') {
                              errStr = 'Parse error on line ' + (lexer.yylineno + 1) + ': ';
                          } else {
                              errStr = 'Parse error: ';
                          }
  
                          if (typeof lexer.showPosition === 'function') {
                              errStr += '\n' + lexer.showPosition(79 - 10, 10) + '\n';
                          }
                          if (expected.length) {
                              errStr += 'Expecting ' + expected.join(', ') + ', got unexpected ' + errSymbolDescr;
                          } else {
                              errStr += 'Unexpected ' + errSymbolDescr;
                          }
  
                          p = this.constructParseErrorInfo(errStr, null, expected, (error_rule_depth >= 0));
  
                          // cleanup the old one before we start the new error info track:
                          if (recoveringErrorInfo && typeof recoveringErrorInfo.destroy === 'function') {
                              recoveringErrorInfo.destroy();
                          }
                          recoveringErrorInfo = this.shallowCopyErrorInfo(p);
  
                          r = this.parseError(p.errStr, p, this.JisonParserError);
  
  
  
  
  
  
  
  
  
                          // Protect against overly blunt userland `parseError` code which *sets*
                          // the `recoverable` flag without properly checking first:
                          // we always terminate the parse when there's no recovery rule available anyhow!
                          if (!p.recoverable || error_rule_depth < 0) {
                              retval = r;
                              break;
                          } else {
                              // TODO: allow parseError callback to edit symbol and or state at the start of the error recovery process...
                          }
                      }
  
  
  
  
  
  
  
  
  
  
                      var esp = recoveringErrorInfo.info_stack_pointer;
  
                      // just recovered from another error
                      if (recovering === ERROR_RECOVERY_TOKEN_DISCARD_COUNT && error_rule_depth >= 0) {
                          // SHIFT current lookahead and grab another
                          recoveringErrorInfo.symbol_stack[esp] = symbol;
                          recoveringErrorInfo.value_stack[esp] = shallow_copy(lexer.yytext);
                          recoveringErrorInfo.location_stack[esp] = copy_yylloc(lexer.yylloc);
                          recoveringErrorInfo.state_stack[esp] = newState; // push state
                          ++esp;
  
                          // Pick up the lexer details for the current symbol as that one is not 'look-ahead' any more:
  
  
  
                          yyloc = lexer.yylloc;
  
                          preErrorSymbol = 0;
                          symbol = lex();
  
  
  
  
  
  
  
  
  
                      }
  
                      // try to recover from error
                      if (error_rule_depth < 0) {
                          ASSERT(recovering > 0);
                          recoveringErrorInfo.info_stack_pointer = esp;
  
                          // barf a fatal hairball when we're out of look-ahead symbols and none hit a match
                          // while we are still busy recovering from another error:
                          var po = this.__error_infos[this.__error_infos.length - 1];
                          if (!po) {
                              p = this.constructParseErrorInfo('Parsing halted while starting to recover from another error.', null, expected, false);
                          } else {
                              p = this.constructParseErrorInfo('Parsing halted while starting to recover from another error. Previous error which resulted in this fatal result: ' + po.errStr, null, expected, false);
                              p.extra_error_attributes = po;
                          }
                          retval = this.parseError(p.errStr, p, this.JisonParserError);
                          break;
                      }
  
                      preErrorSymbol = (symbol === TERROR ? 0 : symbol); // save the lookahead token
                      symbol = TERROR;            // insert generic error symbol as new lookahead
  
                      const EXTRA_STACK_SAMPLE_DEPTH = 3;
  
                      // REDUCE/COMBINE the pushed terms/tokens to a new ERROR token:
                      recoveringErrorInfo.symbol_stack[esp] = preErrorSymbol;
                      if (errStr) {
                          recoveringErrorInfo.value_stack[esp] = {
                              yytext: shallow_copy(lexer.yytext),
                              errorRuleDepth: error_rule_depth,
                              errorStr: errStr,
                              errorSymbolDescr: errSymbolDescr,
                              expectedStr: expected,
                              stackSampleLength: error_rule_depth + EXTRA_STACK_SAMPLE_DEPTH
                          };
  
  
  
  
  
  
  
  
  
                      } else {
                          recoveringErrorInfo.value_stack[esp] = {
                              yytext: shallow_copy(lexer.yytext),
                              errorRuleDepth: error_rule_depth,
                              stackSampleLength: error_rule_depth + EXTRA_STACK_SAMPLE_DEPTH
                          };
                      }
                      recoveringErrorInfo.location_stack[esp] = copy_yylloc(lexer.yylloc);
                      recoveringErrorInfo.state_stack[esp] = newState || NO_ACTION[1];
  
                      ++esp;
                      recoveringErrorInfo.info_stack_pointer = esp;
  
                      yyval.$ = recoveringErrorInfo;
                      yyval._$ = undefined;
  
                      yyrulelen = error_rule_depth;
  
  
  
  
  
  
  
  
  
                      r = this.performAction.call(yyval, yyloc, NO_ACTION[1], sp - 1, vstack, lstack);
  
                      if (typeof r !== 'undefined') {
                          retval = r;
                          break;
                      }
  
                      // pop off stack
                      sp -= yyrulelen;
  
                      // and move the top entries + discarded part of the parse stacks onto the error info stack:
                      for (var idx = sp - EXTRA_STACK_SAMPLE_DEPTH, top = idx + yyrulelen; idx < top; idx++, esp++) {
                          recoveringErrorInfo.symbol_stack[esp] = stack[idx];
                          recoveringErrorInfo.value_stack[esp] = shallow_copy(vstack[idx]);
                          recoveringErrorInfo.location_stack[esp] = copy_yylloc(lstack[idx]);
                          recoveringErrorInfo.state_stack[esp] = sstack[idx];
                      }
  
                      recoveringErrorInfo.symbol_stack[esp] = TERROR;
                      recoveringErrorInfo.value_stack[esp] = shallow_copy(yyval.$);
                      recoveringErrorInfo.location_stack[esp] = copy_yylloc(yyval._$);
  
                      // goto new state = table[STATE][NONTERMINAL]
                      newState = sstack[sp - 1];
  
                      if (this.defaultActions[newState]) {
                          recoveringErrorInfo.state_stack[esp] = this.defaultActions[newState];
                      } else {
                          t = (table[newState] && table[newState][symbol]) || NO_ACTION;
                          recoveringErrorInfo.state_stack[esp] = t[1];
                      }
  
                      ++esp;
                      recoveringErrorInfo.info_stack_pointer = esp;
  
                      // allow N (default: 3) real symbols to be shifted before reporting a new error
                      recovering = ERROR_RECOVERY_TOKEN_DISCARD_COUNT;
  
  
  
  
  
  
  
  
  
  
                      // Now duplicate the standard parse machine here, at least its initial
                      // couple of rounds until the TERROR symbol is **pushed onto the parse stack**,
                      // as we wish to push something special then!
  
  
                      // Run the state machine in this copy of the parser state machine
                      // until we *either* consume the error symbol (and its related information)
                      // *or* we run into another error while recovering from this one
                      // *or* we execute a `reduce` action which outputs a final parse
                      // result (yes, that MAY happen!)...
  
                      ASSERT(recoveringErrorInfo);
                      ASSERT(symbol === TERROR);
                      while (symbol) {
                          // retrieve state number from top of stack
                          state = newState;               // sstack[sp - 1];
  
                          // use default actions if available
                          if (this.defaultActions[state]) {
                              action = 2;
                              newState = this.defaultActions[state];
                          } else {
                              // read action for current state and first input
                              t = (table[state] && table[state][symbol]) || NO_ACTION;
                              newState = t[1];
                              action = t[0];
  
  
  
  
  
  
  
  
  
  
                              // encountered another parse error? If so, break out to main loop
                              // and take it from there!
                              if (!action) {
                                  newState = state;
                                  break;
                              }
                          }
  
  
  
  
  
  
  
  
  
  
                          switch (action) {
                          // catch misc. parse failures:
                          default:
                              // this shouldn't happen, unless resolve defaults are off
                              if (action instanceof Array) {
                                  p = this.constructParseErrorInfo('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol, null, null, false);
                                  retval = this.parseError(p.errStr, p, this.JisonParserError);
                                  // signal end of error recovery loop AND end of outer parse loop
                                  action = 3;
                                  break;
                              }
                              // Another case of better safe than sorry: in case state transitions come out of another error recovery process
                              // or a buggy LUT (LookUp Table):
                              p = this.constructParseErrorInfo('Parsing halted. No viable error recovery approach available due to internal system failure.', null, null, false);
                              retval = this.parseError(p.errStr, p, this.JisonParserError);
                              // signal end of error recovery loop AND end of outer parse loop
                              action = 3;
                              break;
  
                          // shift:
                          case 1:
                              stack[sp] = symbol;
                              //vstack[sp] = lexer.yytext;
                              ASSERT(recoveringErrorInfo);
                              vstack[sp] = recoveringErrorInfo;
                              //lstack[sp] = copy_yylloc(lexer.yylloc);
                              lstack[sp] = this.yyMergeLocationInfo(null, null, recoveringErrorInfo.loc, lexer.yylloc, true);
                              sstack[sp] = newState; // push state
                              ++sp;
                              symbol = 0;
                              if (!preErrorSymbol) { // normal execution / no error
                                  // Pick up the lexer details for the current symbol as that one is not 'look-ahead' any more:
  
  
  
                                  yyloc = lexer.yylloc;
  
                                  if (recovering > 0) {
                                      recovering--;
  
  
  
  
  
  
  
  
  
                                  }
                              } else {
                                  // error just occurred, resume old lookahead f/ before error, *unless* that drops us straight back into error mode:
                                  symbol = preErrorSymbol;
                                  preErrorSymbol = 0;
  
  
  
  
  
  
  
  
  
                                  // read action for current state and first input
                                  t = (table[newState] && table[newState][symbol]) || NO_ACTION;
                                  if (!t[0] || symbol === TERROR) {
                                      // forget about that symbol and move forward: this wasn't a 'forgot to insert' error type where
                                      // (simple) stuff might have been missing before the token which caused the error we're
                                      // recovering from now...
                                      //
                                      // Also check if the LookAhead symbol isn't the ERROR token we set as part of the error
                                      // recovery, for then this we would we idling (cycling) on the error forever.
                                      // Yes, this does not take into account the possibility that the *lexer* may have
                                      // produced a *new* TERROR token all by itself, but that would be a very peculiar grammar!
  
  
  
  
  
  
  
  
  
                                      symbol = 0;
                                  }
                              }
  
                              // once we have pushed the special ERROR token value, we're done in this inner loop!
                              break;
  
                          // reduce:
                          case 2:
                              this_production = this.productions_[newState - 1];  // `this.productions_[]` is zero-based indexed while states start from 1 upwards...
                              yyrulelen = this_production[1];
  
  
  
  
  
  
  
  
  
  
                              r = this.performAction.call(yyval, yyloc, newState, sp - 1, vstack, lstack);
  
                              if (typeof r !== 'undefined') {
                                  // signal end of error recovery loop AND end of outer parse loop
                                  action = 3;
                                  retval = r;
                                  break;
                              }
  
                              // pop off stack
                              sp -= yyrulelen;
  
                              // don't overwrite the `symbol` variable: use a local var to speed things up:
                              var ntsymbol = this_production[0];    // push nonterminal (reduce)
                              stack[sp] = ntsymbol;
                              vstack[sp] = yyval.$;
                              lstack[sp] = yyval._$;
                              // goto new state = table[STATE][NONTERMINAL]
                              newState = table[sstack[sp - 1]][ntsymbol];
                              sstack[sp] = newState;
                              ++sp;
  
  
  
  
  
  
  
  
  
                              continue;
  
                          // accept:
                          case 3:
                              retval = true;
                              // Return the `$accept` rule's `$$` result, if available.
                              //
                              // Also note that JISON always adds this top-most `$accept` rule (with implicit,
                              // default, action):
                              //
                              //     $accept: <startSymbol> $end
                              //                  %{ $$ = $1; @$ = @1; %}
                              //
                              // which, combined with the parse kernel's `$accept` state behaviour coded below,
                              // will produce the `$$` value output of the <startSymbol> rule as the parse result,
                              // IFF that result is *not* `undefined`. (See also the parser kernel code.)
                              //
                              // In code:
                              //
                              //                  %{
                              //                      @$ = @1;            // if location tracking support is included
                              //                      if (typeof $1 !== 'undefined')
                              //                          return $1;
                              //                      else
                              //                          return true;           // the default parse result if the rule actions don't produce anything
                              //                  %}
                              sp--;
                              if (typeof vstack[sp] !== 'undefined') {
                                  retval = vstack[sp];
                              }
                              break;
                          }
  
                          // break out of loop: we accept or fail with error
                          break;
                      }
  
                      // should we also break out of the regular/outer parse loop,
                      // i.e. did the parser already produce a parse result in here?!
                      if (action === 3) {
                          break;
                      }
                      continue;
                  }
  
  
              }
  
  
  
  
  
  
  
  
  
  
              switch (action) {
              // catch misc. parse failures:
              default:
                  // this shouldn't happen, unless resolve defaults are off
                  if (action instanceof Array) {
                      p = this.constructParseErrorInfo('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol, null, null, false);
                      retval = this.parseError(p.errStr, p, this.JisonParserError);
                      break;
                  }
                  // Another case of better safe than sorry: in case state transitions come out of another error recovery process
                  // or a buggy LUT (LookUp Table):
                  p = this.constructParseErrorInfo('Parsing halted. No viable error recovery approach available due to internal system failure.', null, null, false);
                  retval = this.parseError(p.errStr, p, this.JisonParserError);
                  break;
  
              // shift:
              case 1:
                  stack[sp] = symbol;
                  vstack[sp] = lexer.yytext;
                  lstack[sp] = copy_yylloc(lexer.yylloc);
                  sstack[sp] = newState; // push state
  
                  ++sp;
                  symbol = 0;
                  ASSERT(preErrorSymbol === 0);
                  if (!preErrorSymbol) { // normal execution / no error
                      // Pick up the lexer details for the current symbol as that one is not 'look-ahead' any more:
  
  
  
                      yyloc = lexer.yylloc;
  
                      if (recovering > 0) {
                          recovering--;
  
  
  
  
  
  
  
  
  
                      }
                  } else {
                      // error just occurred, resume old lookahead f/ before error, *unless* that drops us straight back into error mode:
                      symbol = preErrorSymbol;
                      preErrorSymbol = 0;
  
  
  
  
  
  
  
  
  
                      // read action for current state and first input
                      t = (table[newState] && table[newState][symbol]) || NO_ACTION;
                      if (!t[0] || symbol === TERROR) {
                          // forget about that symbol and move forward: this wasn't a 'forgot to insert' error type where
                          // (simple) stuff might have been missing before the token which caused the error we're
                          // recovering from now...
                          //
                          // Also check if the LookAhead symbol isn't the ERROR token we set as part of the error
                          // recovery, for then this we would we idling (cycling) on the error forever.
                          // Yes, this does not take into account the possibility that the *lexer* may have
                          // produced a *new* TERROR token all by itself, but that would be a very peculiar grammar!
  
  
  
  
  
  
  
  
  
                          symbol = 0;
                      }
                  }
  
                  continue;
  
              // reduce:
              case 2:
                  this_production = this.productions_[newState - 1];  // `this.productions_[]` is zero-based indexed while states start from 1 upwards...
                  yyrulelen = this_production[1];
  
  
  
  
  
  
  
  
  
  
                  r = this.performAction.call(yyval, yyloc, newState, sp - 1, vstack, lstack);
  
                  if (typeof r !== 'undefined') {
                      retval = r;
                      break;
                  }
  
                  // pop off stack
                  sp -= yyrulelen;
  
                  // don't overwrite the `symbol` variable: use a local var to speed things up:
                  var ntsymbol = this_production[0];    // push nonterminal (reduce)
                  stack[sp] = ntsymbol;
                  vstack[sp] = yyval.$;
                  lstack[sp] = yyval._$;
                  // goto new state = table[STATE][NONTERMINAL]
                  newState = table[sstack[sp - 1]][ntsymbol];
                  sstack[sp] = newState;
                  ++sp;
  
  
  
  
  
  
  
  
  
                  continue;
  
              // accept:
              case 3:
                  retval = true;
                  // Return the `$accept` rule's `$$` result, if available.
                  //
                  // Also note that JISON always adds this top-most `$accept` rule (with implicit,
                  // default, action):
                  //
                  //     $accept: <startSymbol> $end
                  //                  %{ $$ = $1; @$ = @1; %}
                  //
                  // which, combined with the parse kernel's `$accept` state behaviour coded below,
                  // will produce the `$$` value output of the <startSymbol> rule as the parse result,
                  // IFF that result is *not* `undefined`. (See also the parser kernel code.)
                  //
                  // In code:
                  //
                  //                  %{
                  //                      @$ = @1;            // if location tracking support is included
                  //                      if (typeof $1 !== 'undefined')
                  //                          return $1;
                  //                      else
                  //                          return true;           // the default parse result if the rule actions don't produce anything
                  //                  %}
                  sp--;
                  if (typeof vstack[sp] !== 'undefined') {
                      retval = vstack[sp];
                  }
  
                  break;
              }
  
              // break out of loop: we accept or fail with error
              break;
          }
      } catch (ex) {
          // report exceptions through the parseError callback too, but keep the exception intact
          // if it is a known parser or lexer error which has been thrown by parseError() already:
          if (ex instanceof this.JisonParserError) {
              throw ex;
          }
          else if (lexer && typeof lexer.JisonLexerError === 'function' && ex instanceof lexer.JisonLexerError) {
              throw ex;
          }
          else {
              p = this.constructParseErrorInfo('Parsing aborted due to exception.', ex, null, false);
              retval = this.parseError(p.errStr, p, this.JisonParserError);
          }
      } finally {
          retval = this.cleanupAfterParse(retval, true, true);
          this.__reentrant_call_depth--;
      }   // /finally
  
      return retval;
  },
  yyError: 1
  };
  parser.originalParseError = parser.parseError;
  parser.originalQuoteName = parser.quoteName;
  
  var ebnf = false;
  
  
  
  var rmCommonWS = helpers.rmCommonWS;
  var dquote = helpers.dquote;
  var checkActionBlock = helpers.checkActionBlock;
  
  
  // transform ebnf to bnf if necessary
  function extend(json, grammar) {
      if (ebnf) {
          json.ebnf = grammar.grammar;        // keep the original source EBNF around for possible pretty-printing & AST exports.
          json.bnf = transform(grammar.grammar);
      }
      else {
          json.bnf = grammar.grammar;
      }
      if (grammar.actionInclude) {
          json.actionInclude = grammar.actionInclude;
      }
      return json;
  }
  
  // convert string value to number or boolean value, when possible
  // (and when this is more or less obviously the intent)
  // otherwise produce the string itself as value.
  function parseValue(v) {
      if (v === 'false') {
          return false;
      }
      if (v === 'true') {
          return true;
      }
      // http://stackoverflow.com/questions/175739/is-there-a-built-in-way-in-javascript-to-check-if-a-string-is-a-valid-number
      // Note that the `v` check ensures that we do not convert `undefined`, `null` and `''` (empty string!)
      if (v && !isNaN(v)) {
          var rv = +v;
          if (isFinite(rv)) {
              return rv;
          }
      }
      return v;
  }
  
  
  parser.warn = function p_warn() {
      console.warn.apply(console, arguments);
  };
  
  parser.log = function p_log() {
      console.log.apply(console, arguments);
  };
  /* lexer generated by jison-lex 0.6.1-205 */
  
  /*
   * Returns a Lexer object of the following structure:
   *
   *  Lexer: {
   *    yy: {}     The so-called "shared state" or rather the *source* of it;
   *               the real "shared state" `yy` passed around to
   *               the rule actions, etc. is a direct reference!
   *
   *               This "shared context" object was passed to the lexer by way of 
   *               the `lexer.setInput(str, yy)` API before you may use it.
   *
   *               This "shared context" object is passed to the lexer action code in `performAction()`
   *               so userland code in the lexer actions may communicate with the outside world 
   *               and/or other lexer rules' actions in more or less complex ways.
   *
   *  }
   *
   *  Lexer.prototype: {
   *    EOF: 1,
   *    ERROR: 2,
   *
   *    yy:        The overall "shared context" object reference.
   *
   *    JisonLexerError: function(msg, hash),
   *
   *    performAction: function lexer__performAction(yy, yyrulenumber, YY_START),
   *
   *               The function parameters and `this` have the following value/meaning:
   *               - `this`    : reference to the `lexer` instance. 
   *                               `yy_` is an alias for `this` lexer instance reference used internally.
   *
   *               - `yy`      : a reference to the `yy` "shared state" object which was passed to the lexer
   *                             by way of the `lexer.setInput(str, yy)` API before.
   *
   *                             Note:
   *                             The extra arguments you specified in the `%parse-param` statement in your
   *                             **parser** grammar definition file are passed to the lexer via this object
   *                             reference as member variables.
   *
   *               - `yyrulenumber`   : index of the matched lexer rule (regex), used internally.
   *
   *               - `YY_START`: the current lexer "start condition" state.
   *
   *    parseError: function(str, hash, ExceptionClass),
   *
   *    constructLexErrorInfo: function(error_message, is_recoverable),
   *               Helper function.
   *               Produces a new errorInfo 'hash object' which can be passed into `parseError()`.
   *               See it's use in this lexer kernel in many places; example usage:
   *
   *                   var infoObj = lexer.constructParseErrorInfo('fail!', true);
   *                   var retVal = lexer.parseError(infoObj.errStr, infoObj, lexer.JisonLexerError);
   *
   *    options: { ... lexer %options ... },
   *
   *    lex: function(),
   *               Produce one token of lexed input, which was passed in earlier via the `lexer.setInput()` API.
   *               You MAY use the additional `args...` parameters as per `%parse-param` spec of the **lexer** grammar:
   *               these extra `args...` are added verbatim to the `yy` object reference as member variables.
   *
   *               WARNING:
   *               Lexer's additional `args...` parameters (via lexer's `%parse-param`) MAY conflict with
   *               any attributes already added to `yy` by the **parser** or the jison run-time; 
   *               when such a collision is detected an exception is thrown to prevent the generated run-time 
   *               from silently accepting this confusing and potentially hazardous situation! 
   *
   *    cleanupAfterLex: function(do_not_nuke_errorinfos),
   *               Helper function.
   *
   *               This helper API is invoked when the **parse process** has completed: it is the responsibility
   *               of the **parser** (or the calling userland code) to invoke this method once cleanup is desired. 
   *
   *               This helper may be invoked by user code to ensure the internal lexer gets properly garbage collected.
   *
   *    setInput: function(input, [yy]),
   *
   *
   *    input: function(),
   *
   *
   *    unput: function(str),
   *
   *
   *    more: function(),
   *
   *
   *    reject: function(),
   *
   *
   *    less: function(n),
   *
   *
   *    pastInput: function(n),
   *
   *
   *    upcomingInput: function(n),
   *
   *
   *    showPosition: function(),
   *
   *
   *    test_match: function(regex_match_array, rule_index),
   *
   *
   *    next: function(),
   *
   *
   *    begin: function(condition),
   *
   *
   *    pushState: function(condition),
   *
   *
   *    popState: function(),
   *
   *
   *    topState: function(),
   *
   *
   *    _currentRules: function(),
   *
   *
   *    stateStackSize: function(),
   *
   *
   *    performAction: function(yy, yy_, yyrulenumber, YY_START),
   *
   *
   *    rules: [...],
   *
   *
   *    conditions: {associative list: name ==> set},
   *  }
   *
   *
   *  token location info (`yylloc`): {
   *    first_line: n,
   *    last_line: n,
   *    first_column: n,
   *    last_column: n,
   *    range: [start_number, end_number]
   *               (where the numbers are indexes into the input string, zero-based)
   *  }
   *
   * ---
   *
   * The `parseError` function receives a 'hash' object with these members for lexer errors:
   *
   *  {
   *    text:        (matched text)
   *    token:       (the produced terminal token, if any)
   *    token_id:    (the produced terminal token numeric ID, if any)
   *    line:        (yylineno)
   *    loc:         (yylloc)
   *    recoverable: (boolean: TRUE when the parser MAY have an error recovery rule
   *                  available for this particular error)
   *    yy:          (object: the current parser internal "shared state" `yy`
   *                  as is also available in the rule actions; this can be used,
   *                  for instance, for advanced error analysis and reporting)
   *    lexer:       (reference to the current lexer instance used by the parser)
   *  }
   *
   * while `this` will reference the current lexer instance.
   *
   * When `parseError` is invoked by the lexer, the default implementation will
   * attempt to invoke `yy.parser.parseError()`; when this callback is not provided
   * it will try to invoke `yy.parseError()` instead. When that callback is also not
   * provided, a `JisonLexerError` exception will be thrown containing the error
   * message and `hash`, as constructed by the `constructLexErrorInfo()` API.
   *
   * Note that the lexer's `JisonLexerError` error class is passed via the
   * `ExceptionClass` argument, which is invoked to construct the exception
   * instance to be thrown, so technically `parseError` will throw the object
   * produced by the `new ExceptionClass(str, hash)` JavaScript expression.
   *
   * ---
   *
   * You can specify lexer options by setting / modifying the `.options` object of your Lexer instance.
   * These options are available:
   *
   * (Options are permanent.)
   *  
   *  yy: {
   *      parseError: function(str, hash, ExceptionClass)
   *                 optional: overrides the default `parseError` function.
   *  }
   *
   *  lexer.options: {
   *      pre_lex:  function()
   *                 optional: is invoked before the lexer is invoked to produce another token.
   *                 `this` refers to the Lexer object.
   *      post_lex: function(token) { return token; }
   *                 optional: is invoked when the lexer has produced a token `token`;
   *                 this function can override the returned token value by returning another.
   *                 When it does not return any (truthy) value, the lexer will return
   *                 the original `token`.
   *                 `this` refers to the Lexer object.
   *
   * WARNING: the next set of options are not meant to be changed. They echo the abilities of
   * the lexer as per when it was compiled!
   *
   *      ranges: boolean
   *                 optional: `true` ==> token location info will include a .range[] member.
   *      flex: boolean
   *                 optional: `true` ==> flex-like lexing behaviour where the rules are tested
   *                 exhaustively to find the longest match.
   *      backtrack_lexer: boolean
   *                 optional: `true` ==> lexer regexes are tested in order and for invoked;
   *                 the lexer terminates the scan when a token is returned by the action code.
   *      xregexp: boolean
   *                 optional: `true` ==> lexer rule regexes are "extended regex format" requiring the
   *                 `XRegExp` library. When this %option has not been specified at compile time, all lexer
   *                 rule regexes have been written as standard JavaScript RegExp expressions.
   *  }
   */
  
  
  var lexer = function() {
    /**
     * See also:
     * http://stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript/#35881508
     * but we keep the prototype.constructor and prototype.name assignment lines too for compatibility
     * with userland code which might access the derived class in a 'classic' way.
     *
     * @public
     * @constructor
     * @nocollapse
     */
    function JisonLexerError(msg, hash) {
      Object.defineProperty(this, 'name', {
        enumerable: false,
        writable: false,
        value: 'JisonLexerError'
      });
  
      if (msg == null)
        msg = '???';
  
      Object.defineProperty(this, 'message', {
        enumerable: false,
        writable: true,
        value: msg
      });
  
      this.hash = hash;
      var stacktrace;
  
      if (hash && hash.exception instanceof Error) {
        var ex2 = hash.exception;
        this.message = ex2.message || msg;
        stacktrace = ex2.stack;
      }
  
      if (!stacktrace) {
        if (Error.hasOwnProperty('captureStackTrace')) {
          // V8
          Error.captureStackTrace(this, this.constructor);
        } else {
          stacktrace = new Error(msg).stack;
        }
      }
  
      if (stacktrace) {
        Object.defineProperty(this, 'stack', {
          enumerable: false,
          writable: false,
          value: stacktrace
        });
      }
    }
  
    if (typeof Object.setPrototypeOf === 'function') {
      Object.setPrototypeOf(JisonLexerError.prototype, Error.prototype);
    } else {
      JisonLexerError.prototype = Object.create(Error.prototype);
    }
  
    JisonLexerError.prototype.constructor = JisonLexerError;
    JisonLexerError.prototype.name = 'JisonLexerError';
  
    var lexer = {
      
  // Code Generator Information Report
  // ---------------------------------
  //
  // Options:
  //
  //   backtracking: .................... false
  //   location.ranges: ................. true
  //   location line+column tracking: ... true
  //
  //
  // Forwarded Parser Analysis flags:
  //
  //   uses yyleng: ..................... false
  //   uses yylineno: ................... false
  //   uses yytext: ..................... false
  //   uses yylloc: ..................... false
  //   uses lexer values: ............... true / true
  //   location tracking: ............... true
  //   location assignment: ............. true
  //
  //
  // Lexer Analysis flags:
  //
  //   uses yyleng: ..................... ???
  //   uses yylineno: ................... ???
  //   uses yytext: ..................... ???
  //   uses yylloc: ..................... ???
  //   uses ParseError API: ............. ???
  //   uses yyerror: .................... ???
  //   uses location tracking & editing:  ???
  //   uses more() API: ................. ???
  //   uses unput() API: ................ ???
  //   uses reject() API: ............... ???
  //   uses less() API: ................. ???
  //   uses display APIs pastInput(), upcomingInput(), showPosition():
  //        ............................. ???
  //   uses describeYYLLOC() API: ....... ???
  //
  // --------- END OF REPORT -----------
  
  EOF: 1,
      ERROR: 2,
  
      // JisonLexerError: JisonLexerError,        /// <-- injected by the code generator
  
      // options: {},                             /// <-- injected by the code generator
  
      // yy: ...,                                 /// <-- injected by setInput()
  
      __currentRuleSet__: null,                   /// INTERNAL USE ONLY: internal rule set cache for the current lexer state  
  
      __error_infos: [],                          /// INTERNAL USE ONLY: the set of lexErrorInfo objects created since the last cleanup  
      __decompressed: false,                      /// INTERNAL USE ONLY: mark whether the lexer instance has been 'unfolded' completely and is now ready for use  
      done: false,                                /// INTERNAL USE ONLY  
      _backtrack: false,                          /// INTERNAL USE ONLY  
      _input: '',                                 /// INTERNAL USE ONLY  
      _more: false,                               /// INTERNAL USE ONLY  
      _signaled_error_token: false,               /// INTERNAL USE ONLY  
      conditionStack: [],                         /// INTERNAL USE ONLY; managed via `pushState()`, `popState()`, `topState()` and `stateStackSize()`  
      match: '',                                  /// READ-ONLY EXTERNAL ACCESS - ADVANCED USE ONLY: tracks input which has been matched so far for the lexer token under construction. `match` is identical to `yytext` except that this one still contains the matched input string after `lexer.performAction()` has been invoked, where userland code MAY have changed/replaced the `yytext` value entirely!  
      matched: '',                                /// READ-ONLY EXTERNAL ACCESS - ADVANCED USE ONLY: tracks entire input which has been matched so far  
      matches: false,                             /// READ-ONLY EXTERNAL ACCESS - ADVANCED USE ONLY: tracks RE match result for last (successful) match attempt  
      yytext: '',                                 /// ADVANCED USE ONLY: tracks input which has been matched so far for the lexer token under construction; this value is transferred to the parser as the 'token value' when the parser consumes the lexer token produced through a call to the `lex()` API.  
      offset: 0,                                  /// READ-ONLY EXTERNAL ACCESS - ADVANCED USE ONLY: tracks the 'cursor position' in the input string, i.e. the number of characters matched so far  
      yyleng: 0,                                  /// READ-ONLY EXTERNAL ACCESS - ADVANCED USE ONLY: length of matched input for the token under construction (`yytext`)  
      yylineno: 0,                                /// READ-ONLY EXTERNAL ACCESS - ADVANCED USE ONLY: 'line number' at which the token under construction is located  
      yylloc: null,                               /// READ-ONLY EXTERNAL ACCESS - ADVANCED USE ONLY: tracks location info (lines + columns) for the token under construction  
  
      /**
       * INTERNAL USE: construct a suitable error info hash object instance for `parseError`.
       * 
       * @public
       * @this {RegExpLexer}
       */
      constructLexErrorInfo: function lexer_constructLexErrorInfo(msg, recoverable, show_input_position) {
        msg = '' + msg;
  
        // heuristic to determine if the error message already contains a (partial) source code dump
        // as produced by either `showPosition()` or `prettyPrintRange()`:
        if (show_input_position == undefined) {
          show_input_position = !(msg.indexOf('\n') > 0 && msg.indexOf('^') > 0);
        }
  
        if (this.yylloc && show_input_position) {
          if (typeof this.prettyPrintRange === 'function') {
            var pretty_src = this.prettyPrintRange(this.yylloc);
  
            if (!/\n\s*$/.test(msg)) {
              msg += '\n';
            }
  
            msg += '\n  Erroneous area:\n' + this.prettyPrintRange(this.yylloc);
          } else if (typeof this.showPosition === 'function') {
            var pos_str = this.showPosition();
  
            if (pos_str) {
              if (msg.length && msg[msg.length - 1] !== '\n' && pos_str[0] !== '\n') {
                msg += '\n' + pos_str;
              } else {
                msg += pos_str;
              }
            }
          }
        }
  
        /** @constructor */
        var pei = {
          errStr: msg,
          recoverable: !!recoverable,
          text: this.match,           // This one MAY be empty; userland code should use the `upcomingInput` API to obtain more text which follows the 'lexer cursor position'...  
          token: null,
          line: this.yylineno,
          loc: this.yylloc,
          yy: this.yy,
          lexer: this,
  
          /**
           * and make sure the error info doesn't stay due to potential
           * ref cycle via userland code manipulations.
           * These would otherwise all be memory leak opportunities!
           * 
           * Note that only array and object references are nuked as those
           * constitute the set of elements which can produce a cyclic ref.
           * The rest of the members is kept intact as they are harmless.
           * 
           * @public
           * @this {LexErrorInfo}
           */
          destroy: function destructLexErrorInfo() {
            // remove cyclic references added to error info:
            // info.yy = null;
            // info.lexer = null;
            // ...
            var rec = !!this.recoverable;
  
            for (var key in this) {
              if (this.hasOwnProperty(key) && typeof key === 'object') {
                this[key] = undefined;
              }
            }
  
            this.recoverable = rec;
          }
        };
  
        // track this instance so we can `destroy()` it once we deem it superfluous and ready for garbage collection!
        this.__error_infos.push(pei);
  
        return pei;
      },
  
      /**
       * handler which is invoked when a lexer error occurs.
       * 
       * @public
       * @this {RegExpLexer}
       */
      parseError: function lexer_parseError(str, hash, ExceptionClass) {
        if (!ExceptionClass) {
          ExceptionClass = this.JisonLexerError;
        }
  
        if (this.yy) {
          if (this.yy.parser && typeof this.yy.parser.parseError === 'function') {
            return this.yy.parser.parseError.call(this, str, hash, ExceptionClass) || this.ERROR;
          } else if (typeof this.yy.parseError === 'function') {
            return this.yy.parseError.call(this, str, hash, ExceptionClass) || this.ERROR;
          }
        }
  
        throw new ExceptionClass(str, hash);
      },
  
      /**
       * method which implements `yyerror(str, ...args)` functionality for use inside lexer actions.
       * 
       * @public
       * @this {RegExpLexer}
       */
      yyerror: function yyError(str /*, ...args */) {
        var lineno_msg = '';
  
        if (this.yylloc) {
          lineno_msg = ' on line ' + (this.yylineno + 1);
        }
  
        var p = this.constructLexErrorInfo(
          'Lexical error' + lineno_msg + ': ' + str,
          this.options.lexerErrorsAreRecoverable
        );
  
        // Add any extra args to the hash under the name `extra_error_attributes`:
        var args = Array.prototype.slice.call(arguments, 1);
  
        if (args.length) {
          p.extra_error_attributes = args;
        }
  
        return this.parseError(p.errStr, p, this.JisonLexerError) || this.ERROR;
      },
  
      /**
       * final cleanup function for when we have completed lexing the input;
       * make it an API so that external code can use this one once userland
       * code has decided it's time to destroy any lingering lexer error
       * hash object instances and the like: this function helps to clean
       * up these constructs, which *may* carry cyclic references which would
       * otherwise prevent the instances from being properly and timely
       * garbage-collected, i.e. this function helps prevent memory leaks!
       * 
       * @public
       * @this {RegExpLexer}
       */
      cleanupAfterLex: function lexer_cleanupAfterLex(do_not_nuke_errorinfos) {
        // prevent lingering circular references from causing memory leaks:
        this.setInput('', {});
  
        // nuke the error hash info instances created during this run.
        // Userland code must COPY any data/references
        // in the error hash instance(s) it is more permanently interested in.
        if (!do_not_nuke_errorinfos) {
          for (var i = this.__error_infos.length - 1; i >= 0; i--) {
            var el = this.__error_infos[i];
  
            if (el && typeof el.destroy === 'function') {
              el.destroy();
            }
          }
  
          this.__error_infos.length = 0;
        }
  
        return this;
      },
  
      /**
       * clear the lexer token context; intended for internal use only
       * 
       * @public
       * @this {RegExpLexer}
       */
      clear: function lexer_clear() {
        this.yytext = '';
        this.yyleng = 0;
        this.match = '';
  
        // - DO NOT reset `this.matched`
        this.matches = false;
  
        this._more = false;
        this._backtrack = false;
        var col = (this.yylloc ? this.yylloc.last_column : 0);
  
        this.yylloc = {
          first_line: this.yylineno + 1,
          first_column: col,
          last_line: this.yylineno + 1,
          last_column: col,
          range: [this.offset, this.offset]
        };
      },
  
      /**
       * resets the lexer, sets new input
       * 
       * @public
       * @this {RegExpLexer}
       */
      setInput: function lexer_setInput(input, yy) {
        this.yy = yy || this.yy || {};
  
        // also check if we've fully initialized the lexer instance,
        // including expansion work to be done to go from a loaded
        // lexer to a usable lexer:
        if (!this.__decompressed) {
          // step 1: decompress the regex list:
          var rules = this.rules;
  
          for (var i = 0, len = rules.length; i < len; i++) {
            var rule_re = rules[i];
  
            // compression: is the RE an xref to another RE slot in the rules[] table?
            if (typeof rule_re === 'number') {
              rules[i] = rules[rule_re];
            }
          }
  
          // step 2: unfold the conditions[] set to make these ready for use:
          var conditions = this.conditions;
  
          for (var k in conditions) {
            var spec = conditions[k];
            var rule_ids = spec.rules;
            var len = rule_ids.length;
            var rule_regexes = new Array(len + 1);             // slot 0 is unused; we use a 1-based index approach here to keep the hottest code in `lexer_next()` fast and simple! 
            var rule_new_ids = new Array(len + 1);
  
            for (var i = 0; i < len; i++) {
              var idx = rule_ids[i];
              var rule_re = rules[idx];
              rule_regexes[i + 1] = rule_re;
              rule_new_ids[i + 1] = idx;
            }
  
            spec.rules = rule_new_ids;
            spec.__rule_regexes = rule_regexes;
            spec.__rule_count = len;
          }
  
          this.__decompressed = true;
        }
  
        this._input = input || '';
        this.clear();
        this._signaled_error_token = false;
        this.done = false;
        this.yylineno = 0;
        this.matched = '';
        this.conditionStack = ['INITIAL'];
        this.__currentRuleSet__ = null;
  
        this.yylloc = {
          first_line: 1,
          first_column: 0,
          last_line: 1,
          last_column: 0,
          range: [0, 0]
        };
  
        this.offset = 0;
        return this;
      },
  
      /**
       * edit the remaining input via user-specified callback.
       * This can be used to forward-adjust the input-to-parse, 
       * e.g. inserting macro expansions and alike in the
       * input which has yet to be lexed.
       * The behaviour of this API contrasts the `unput()` et al
       * APIs as those act on the *consumed* input, while this
       * one allows one to manipulate the future, without impacting
       * the current `yyloc` cursor location or any history. 
       * 
       * Use this API to help implement C-preprocessor-like
       * `#include` statements, etc.
       * 
       * The provided callback must be synchronous and is
       * expected to return the edited input (string).
       *
       * The `cpsArg` argument value is passed to the callback
       * as-is.
       *
       * `callback` interface: 
       * `function callback(input, cpsArg)`
       * 
       * - `input` will carry the remaining-input-to-lex string
       *   from the lexer.
       * - `cpsArg` is `cpsArg` passed into this API.
       * 
       * The `this` reference for the callback will be set to
       * reference this lexer instance so that userland code
       * in the callback can easily and quickly access any lexer
       * API. 
       *
       * When the callback returns a non-string-type falsey value,
       * we assume the callback did not edit the input and we
       * will using the input as-is.
       *
       * When the callback returns a non-string-type value, it
       * is converted to a string for lexing via the `"" + retval`
       * operation. (See also why: http://2ality.com/2012/03/converting-to-string.html 
       * -- that way any returned object's `toValue()` and `toString()`
       * methods will be invoked in a proper/desirable order.)
       * 
       * @public
       * @this {RegExpLexer}
       */
      editRemainingInput: function lexer_editRemainingInput(callback, cpsArg) {
        var rv = callback.call(this, this._input, cpsArg);
  
        if (typeof rv !== 'string') {
          if (rv) {
            this._input = '' + rv;
          } 
          // else: keep `this._input` as is.  
        } else {
          this._input = rv;
        }
  
        return this;
      },
  
      /**
       * consumes and returns one char from the input
       * 
       * @public
       * @this {RegExpLexer}
       */
      input: function lexer_input() {
        if (!this._input) {
          //this.done = true;    -- don't set `done` as we want the lex()/next() API to be able to produce one custom EOF token match after this anyhow. (lexer can match special <<EOF>> tokens and perform user action code for a <<EOF>> match, but only does so *once*)
          return null;
        }
  
        var ch = this._input[0];
        this.yytext += ch;
        this.yyleng++;
        this.offset++;
        this.match += ch;
        this.matched += ch;
  
        // Count the linenumber up when we hit the LF (or a stand-alone CR).
        // On CRLF, the linenumber is incremented when you fetch the CR or the CRLF combo
        // and we advance immediately past the LF as well, returning both together as if
        // it was all a single 'character' only.
        var slice_len = 1;
  
        var lines = false;
  
        if (ch === '\n') {
          lines = true;
        } else if (ch === '\r') {
          lines = true;
          var ch2 = this._input[1];
  
          if (ch2 === '\n') {
            slice_len++;
            ch += ch2;
            this.yytext += ch2;
            this.yyleng++;
            this.offset++;
            this.match += ch2;
            this.matched += ch2;
            this.yylloc.range[1]++;
          }
        }
  
        if (lines) {
          this.yylineno++;
          this.yylloc.last_line++;
          this.yylloc.last_column = 0;
        } else {
          this.yylloc.last_column++;
        }
  
        this.yylloc.range[1]++;
        this._input = this._input.slice(slice_len);
        return ch;
      },
  
      /**
       * unshifts one char (or an entire string) into the input
       * 
       * @public
       * @this {RegExpLexer}
       */
      unput: function lexer_unput(ch) {
        var len = ch.length;
        var lines = ch.split(/(?:\r\n?|\n)/g);
        this._input = ch + this._input;
        this.yytext = this.yytext.substr(0, this.yytext.length - len);
        this.yyleng = this.yytext.length;
        this.offset -= len;
        this.match = this.match.substr(0, this.match.length - len);
        this.matched = this.matched.substr(0, this.matched.length - len);
  
        if (lines.length > 1) {
          this.yylineno -= lines.length - 1;
          this.yylloc.last_line = this.yylineno + 1;
  
          // Get last entirely matched line into the `pre_lines[]` array's
          // last index slot; we don't mind when other previously 
          // matched lines end up in the array too. 
          var pre = this.match;
  
          var pre_lines = pre.split(/(?:\r\n?|\n)/g);
  
          if (pre_lines.length === 1) {
            pre = this.matched;
            pre_lines = pre.split(/(?:\r\n?|\n)/g);
          }
  
          this.yylloc.last_column = pre_lines[pre_lines.length - 1].length;
        } else {
          this.yylloc.last_column -= len;
        }
  
        this.yylloc.range[1] = this.yylloc.range[0] + this.yyleng;
        this.done = false;
        return this;
      },
  
      /**
       * cache matched text and append it on next action
       * 
       * @public
       * @this {RegExpLexer}
       */
      more: function lexer_more() {
        this._more = true;
        return this;
      },
  
      /**
       * signal the lexer that this rule fails to match the input, so the
       * next matching rule (regex) should be tested instead.
       * 
       * @public
       * @this {RegExpLexer}
       */
      reject: function lexer_reject() {
        if (this.options.backtrack_lexer) {
          this._backtrack = true;
        } else {
          // when the `parseError()` call returns, we MUST ensure that the error is registered.
          // We accomplish this by signaling an 'error' token to be produced for the current
          // `.lex()` run.
          var lineno_msg = '';
  
          if (this.yylloc) {
            lineno_msg = ' on line ' + (this.yylineno + 1);
          }
  
          var p = this.constructLexErrorInfo(
            'Lexical error' + lineno_msg + ': You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).',
            false
          );
  
          this._signaled_error_token = this.parseError(p.errStr, p, this.JisonLexerError) || this.ERROR;
        }
  
        return this;
      },
  
      /**
       * retain first n characters of the match
       * 
       * @public
       * @this {RegExpLexer}
       */
      less: function lexer_less(n) {
        return this.unput(this.match.slice(n));
      },
  
      /**
       * return (part of the) already matched input, i.e. for error
       * messages.
       * 
       * Limit the returned string length to `maxSize` (default: 20).
       * 
       * Limit the returned string to the `maxLines` number of lines of
       * input (default: 1).
       * 
       * Negative limit values equal *unlimited*.
       * 
       * @public
       * @this {RegExpLexer}
       */
      pastInput: function lexer_pastInput(maxSize, maxLines) {
        var past = this.matched.substring(0, this.matched.length - this.match.length);
  
        if (maxSize < 0)
          maxSize = past.length;
        else if (!maxSize)
          maxSize = 20;
  
        if (maxLines < 0)
          maxLines = past.length;          // can't ever have more input lines than this! 
        else if (!maxLines)
          maxLines = 1;
  
        // `substr` anticipation: treat \r\n as a single character and take a little
        // more than necessary so that we can still properly check against maxSize
        // after we've transformed and limited the newLines in here:
        past = past.substr(-maxSize * 2 - 2);
  
        // now that we have a significantly reduced string to process, transform the newlines
        // and chop them, then limit them:
        var a = past.replace(/\r\n|\r/g, '\n').split('\n');
  
        a = a.slice(-maxLines);
        past = a.join('\n');
  
        // When, after limiting to maxLines, we still have too much to return,
        // do add an ellipsis prefix...
        if (past.length > maxSize) {
          past = '...' + past.substr(-maxSize);
        }
  
        return past;
      },
  
      /**
       * return (part of the) upcoming input, i.e. for error messages.
       * 
       * Limit the returned string length to `maxSize` (default: 20).
       * 
       * Limit the returned string to the `maxLines` number of lines of input (default: 1).
       * 
       * Negative limit values equal *unlimited*.
       *
       * > ### NOTE ###
       * >
       * > *"upcoming input"* is defined as the whole of the both
       * > the *currently lexed* input, together with any remaining input
       * > following that. *"currently lexed"* input is the input 
       * > already recognized by the lexer but not yet returned with
       * > the lexer token. This happens when you are invoking this API
       * > from inside any lexer rule action code block. 
       * >
       * 
       * @public
       * @this {RegExpLexer}
       */
      upcomingInput: function lexer_upcomingInput(maxSize, maxLines) {
        var next = this.match;
  
        if (maxSize < 0)
          maxSize = next.length + this._input.length;
        else if (!maxSize)
          maxSize = 20;
  
        if (maxLines < 0)
          maxLines = maxSize;          // can't ever have more input lines than this! 
        else if (!maxLines)
          maxLines = 1;
  
        // `substring` anticipation: treat \r\n as a single character and take a little
        // more than necessary so that we can still properly check against maxSize
        // after we've transformed and limited the newLines in here:
        if (next.length < maxSize * 2 + 2) {
          next += this._input.substring(0, maxSize * 2 + 2);   // substring is faster on Chrome/V8 
        }
  
        // now that we have a significantly reduced string to process, transform the newlines
        // and chop them, then limit them:
        var a = next.replace(/\r\n|\r/g, '\n').split('\n');
  
        a = a.slice(0, maxLines);
        next = a.join('\n');
  
        // When, after limiting to maxLines, we still have too much to return,
        // do add an ellipsis postfix...
        if (next.length > maxSize) {
          next = next.substring(0, maxSize) + '...';
        }
  
        return next;
      },
  
      /**
       * return a string which displays the character position where the
       * lexing error occurred, i.e. for error messages
       * 
       * @public
       * @this {RegExpLexer}
       */
      showPosition: function lexer_showPosition(maxPrefix, maxPostfix) {
        var pre = this.pastInput(maxPrefix).replace(/\s/g, ' ');
        var c = new Array(pre.length + 1).join('-');
        return pre + this.upcomingInput(maxPostfix).replace(/\s/g, ' ') + '\n' + c + '^';
      },
  
      /**
       * return a string which displays the lines & columns of input which are referenced 
       * by the given location info range, plus a few lines of context.
       * 
       * This function pretty-prints the indicated section of the input, with line numbers 
       * and everything!
       * 
       * This function is very useful to provide highly readable error reports, while
       * the location range may be specified in various flexible ways:
       * 
       * - `loc` is the location info object which references the area which should be
       *   displayed and 'marked up': these lines & columns of text are marked up by `^`
       *   characters below each character in the entire input range.
       * 
       * - `context_loc` is the *optional* location info object which instructs this
       *   pretty-printer how much *leading* context should be displayed alongside
       *   the area referenced by `loc`. This can help provide context for the displayed
       *   error, etc.
       * 
       *   When this location info is not provided, a default context of 3 lines is
       *   used.
       * 
       * - `context_loc2` is another *optional* location info object, which serves
       *   a similar purpose to `context_loc`: it specifies the amount of *trailing*
       *   context lines to display in the pretty-print output.
       * 
       *   When this location info is not provided, a default context of 1 line only is
       *   used.
       * 
       * Special Notes:
       * 
       * - when the `loc`-indicated range is very large (about 5 lines or more), then
       *   only the first and last few lines of this block are printed while a
       *   `...continued...` message will be printed between them.
       * 
       *   This serves the purpose of not printing a huge amount of text when the `loc`
       *   range happens to be huge: this way a manageable & readable output results
       *   for arbitrary large ranges.
       * 
       * - this function can display lines of input which whave not yet been lexed.
       *   `prettyPrintRange()` can access the entire input!
       * 
       * @public
       * @this {RegExpLexer}
       */
      prettyPrintRange: function lexer_prettyPrintRange(loc, context_loc, context_loc2) {
        var error_size = loc.last_line - loc.first_line;
        const CONTEXT = 3;
        const CONTEXT_TAIL = 1;
        const MINIMUM_VISIBLE_NONEMPTY_LINE_COUNT = 2;
        var input = this.matched + this._input;
        var lines = input.split('\n');
  
        //var show_context = (error_size < 5 || context_loc);
        var l0 = Math.max(1, (context_loc ? context_loc.first_line : loc.first_line - CONTEXT));
  
        var l1 = Math.max(1, (context_loc2 ? context_loc2.last_line : loc.last_line + CONTEXT_TAIL));
        var lineno_display_width = 1 + Math.log10(l1 | 1) | 0;
        var ws_prefix = new Array(lineno_display_width).join(' ');
        var nonempty_line_indexes = [];
  
        var rv = lines.slice(l0 - 1, l1 + 1).map(function injectLineNumber(line, index) {
          var lno = index + l0;
          var lno_pfx = (ws_prefix + lno).substr(-lineno_display_width);
          var rv = lno_pfx + ': ' + line;
          var errpfx = new Array(lineno_display_width + 1).join('^');
          var offset = 2 + 1;
          var len = 0;
  
          if (lno === loc.first_line) {
            offset += loc.first_column;
  
            len = Math.max(
              2,
              ((lno === loc.last_line ? loc.last_column : line.length)) - loc.first_column + 1
            );
          } else if (lno === loc.last_line) {
            len = Math.max(2, loc.last_column + 1);
          } else if (lno > loc.first_line && lno < loc.last_line) {
            len = Math.max(2, line.length + 1);
          }
  
          if (len) {
            var lead = new Array(offset).join('.');
            var mark = new Array(len).join('^');
            rv += '\n' + errpfx + lead + mark;
  
            if (line.trim().length > 0) {
              nonempty_line_indexes.push(index);
            }
          }
  
          rv = rv.replace(/\t/g, ' ');
          return rv;
        });
  
        // now make sure we don't print an overly large amount of error area: limit it 
        // to the top and bottom line count:
        if (nonempty_line_indexes.length > 2 * MINIMUM_VISIBLE_NONEMPTY_LINE_COUNT) {
          var clip_start = nonempty_line_indexes[MINIMUM_VISIBLE_NONEMPTY_LINE_COUNT - 1] + 1;
          var clip_end = nonempty_line_indexes[nonempty_line_indexes.length - MINIMUM_VISIBLE_NONEMPTY_LINE_COUNT] - 1;
          var intermediate_line = new Array(lineno_display_width + 1).join(' ') + '  (...continued...)';
          intermediate_line += '\n' + new Array(lineno_display_width + 1).join('-') + '  (---------------)';
          rv.splice(clip_start, clip_end - clip_start + 1, intermediate_line);
        }
  
        return rv.join('\n');
      },
  
      /**
       * helper function, used to produce a human readable description as a string, given
       * the input `yylloc` location object.
       * 
       * Set `display_range_too` to TRUE to include the string character index position(s)
       * in the description if the `yylloc.range` is available.
       * 
       * @public
       * @this {RegExpLexer}
       */
      describeYYLLOC: function lexer_describe_yylloc(yylloc, display_range_too) {
        var l1 = yylloc.first_line;
        var l2 = yylloc.last_line;
        var c1 = yylloc.first_column;
        var c2 = yylloc.last_column;
        var dl = l2 - l1;
        var dc = c2 - c1;
        var rv;
  
        if (dl === 0) {
          rv = 'line ' + l1 + ', ';
  
          if (dc <= 1) {
            rv += 'column ' + c1;
          } else {
            rv += 'columns ' + c1 + ' .. ' + c2;
          }
        } else {
          rv = 'lines ' + l1 + '(column ' + c1 + ') .. ' + l2 + '(column ' + c2 + ')';
        }
  
        if (yylloc.range && display_range_too) {
          var r1 = yylloc.range[0];
          var r2 = yylloc.range[1] - 1;
  
          if (r2 <= r1) {
            rv += ' {String Offset: ' + r1 + '}';
          } else {
            rv += ' {String Offset range: ' + r1 + ' .. ' + r2 + '}';
          }
        }
  
        return rv;
      },
  
      /**
       * test the lexed token: return FALSE when not a match, otherwise return token.
       * 
       * `match` is supposed to be an array coming out of a regex match, i.e. `match[0]`
       * contains the actually matched text string.
       * 
       * Also move the input cursor forward and update the match collectors:
       * 
       * - `yytext`
       * - `yyleng`
       * - `match`
       * - `matches`
       * - `yylloc`
       * - `offset`
       * 
       * @public
       * @this {RegExpLexer}
       */
      test_match: function lexer_test_match(match, indexed_rule) {
        var token, lines, backup, match_str, match_str_len;
  
        if (this.options.backtrack_lexer) {
          // save context
          backup = {
            yylineno: this.yylineno,
  
            yylloc: {
              first_line: this.yylloc.first_line,
              last_line: this.yylloc.last_line,
              first_column: this.yylloc.first_column,
              last_column: this.yylloc.last_column,
              range: this.yylloc.range.slice(0)
            },
  
            yytext: this.yytext,
            match: this.match,
            matches: this.matches,
            matched: this.matched,
            yyleng: this.yyleng,
            offset: this.offset,
            _more: this._more,
            _input: this._input,
  
            //_signaled_error_token: this._signaled_error_token,
            yy: this.yy,
  
            conditionStack: this.conditionStack.slice(0),
            done: this.done
          };
        }
  
        match_str = match[0];
        match_str_len = match_str.length;
  
        // if (match_str.indexOf('\n') !== -1 || match_str.indexOf('\r') !== -1) {
        lines = match_str.split(/(?:\r\n?|\n)/g);
  
        if (lines.length > 1) {
          this.yylineno += lines.length - 1;
          this.yylloc.last_line = this.yylineno + 1;
          this.yylloc.last_column = lines[lines.length - 1].length;
        } else {
          this.yylloc.last_column += match_str_len;
        }
  
        // }
        this.yytext += match_str;
  
        this.match += match_str;
        this.matched += match_str;
        this.matches = match;
        this.yyleng = this.yytext.length;
        this.yylloc.range[1] += match_str_len;
  
        // previous lex rules MAY have invoked the `more()` API rather than producing a token:
        // those rules will already have moved this `offset` forward matching their match lengths,
        // hence we must only add our own match length now:
        this.offset += match_str_len;
  
        this._more = false;
        this._backtrack = false;
        this._input = this._input.slice(match_str_len);
  
        // calling this method:
        //
        //   function lexer__performAction(yy, yyrulenumber, YY_START) {...}
        token = this.performAction.call(
          this,
          this.yy,
          indexed_rule,
          this.conditionStack[this.conditionStack.length - 1] /* = YY_START */
        );
  
        // otherwise, when the action codes are all simple return token statements:
        //token = this.simpleCaseActionClusters[indexed_rule];
  
        if (this.done && this._input) {
          this.done = false;
        }
  
        if (token) {
          return token;
        } else if (this._backtrack) {
          // recover context
          for (var k in backup) {
            this[k] = backup[k];
          }
  
          this.__currentRuleSet__ = null;
          return false;  // rule action called reject() implying the next rule should be tested instead. 
        } else if (this._signaled_error_token) {
          // produce one 'error' token as `.parseError()` in `reject()`
          // did not guarantee a failure signal by throwing an exception!
          token = this._signaled_error_token;
  
          this._signaled_error_token = false;
          return token;
        }
  
        return false;
      },
  
      /**
       * return next match in input
       * 
       * @public
       * @this {RegExpLexer}
       */
      next: function lexer_next() {
        if (this.done) {
          this.clear();
          return this.EOF;
        }
  
        if (!this._input) {
          this.done = true;
        }
  
        var token, match, tempMatch, index;
  
        if (!this._more) {
          this.clear();
        }
  
        var spec = this.__currentRuleSet__;
  
        if (!spec) {
          // Update the ruleset cache as we apparently encountered a state change or just started lexing.
          // The cache is set up for fast lookup -- we assume a lexer will switch states much less often than it will
          // invoke the `lex()` token-producing API and related APIs, hence caching the set for direct access helps
          // speed up those activities a tiny bit.
          spec = this.__currentRuleSet__ = this._currentRules();
  
          // Check whether a *sane* condition has been pushed before: this makes the lexer robust against
          // user-programmer bugs such as https://github.com/zaach/jison-lex/issues/19
          if (!spec || !spec.rules) {
            var lineno_msg = '';
  
            if (this.options.trackPosition) {
              lineno_msg = ' on line ' + (this.yylineno + 1);
            }
  
            var p = this.constructLexErrorInfo(
              'Internal lexer engine error' + lineno_msg + ': The lex grammar programmer pushed a non-existing condition name "' + this.topState() + '"; this is a fatal error and should be reported to the application programmer team!',
              false
            );
  
            // produce one 'error' token until this situation has been resolved, most probably by parse termination!
            return this.parseError(p.errStr, p, this.JisonLexerError) || this.ERROR;
          }
        }
  
        var rule_ids = spec.rules;
        var regexes = spec.__rule_regexes;
        var len = spec.__rule_count;
  
        // Note: the arrays are 1-based, while `len` itself is a valid index,
        // hence the non-standard less-or-equal check in the next loop condition!
        for (var i = 1; i <= len; i++) {
          tempMatch = this._input.match(regexes[i]);
  
          if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
            match = tempMatch;
            index = i;
  
            if (this.options.backtrack_lexer) {
              token = this.test_match(tempMatch, rule_ids[i]);
  
              if (token !== false) {
                return token;
              } else if (this._backtrack) {
                match = undefined;
                continue;  // rule action called reject() implying a rule MISmatch. 
              } else {
                // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
                return false;
              }
            } else if (!this.options.flex) {
              break;
            }
          }
        }
  
        if (match) {
          token = this.test_match(match, rule_ids[index]);
  
          if (token !== false) {
            return token;
          }
  
          // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
          return false;
        }
  
        if (!this._input) {
          this.done = true;
          this.clear();
          return this.EOF;
        } else {
          var lineno_msg = '';
  
          if (this.options.trackPosition) {
            lineno_msg = ' on line ' + (this.yylineno + 1);
          }
  
          var p = this.constructLexErrorInfo(
            'Lexical error' + lineno_msg + ': Unrecognized text.',
            this.options.lexerErrorsAreRecoverable
          );
  
          var pendingInput = this._input;
          var activeCondition = this.topState();
          var conditionStackDepth = this.conditionStack.length;
          token = this.parseError(p.errStr, p, this.JisonLexerError) || this.ERROR;
  
          if (token === this.ERROR) {
            // we can try to recover from a lexer error that `parseError()` did not 'recover' for us
            // by moving forward at least one character at a time IFF the (user-specified?) `parseError()`
            // has not consumed/modified any pending input or changed state in the error handler:
            if (!this.matches && // and make sure the input has been modified/consumed ...
            pendingInput === this._input && // ...or the lexer state has been modified significantly enough
            // to merit a non-consuming error handling action right now.
            activeCondition === this.topState() && conditionStackDepth === this.conditionStack.length) {
              this.input();
            }
          }
  
          return token;
        }
      },
  
      /**
       * return next match that has a token
       * 
       * @public
       * @this {RegExpLexer}
       */
      lex: function lexer_lex() {
        var r;
  
        // allow the PRE/POST handlers set/modify the return token for maximum flexibility of the generated lexer:
        if (typeof this.options.pre_lex === 'function') {
          r = this.options.pre_lex.call(this);
        }
  
        while (!r) {
          r = this.next();
        }
  
        if (typeof this.options.post_lex === 'function') {
          // (also account for a userdef function which does not return any value: keep the token as is)
          r = this.options.post_lex.call(this, r) || r;
        }
  
        return r;
      },
  
      /**
       * backwards compatible alias for `pushState()`;
       * the latter is symmetrical with `popState()` and we advise to use
       * those APIs in any modern lexer code, rather than `begin()`.
       * 
       * @public
       * @this {RegExpLexer}
       */
      begin: function lexer_begin(condition) {
        return this.pushState(condition);
      },
  
      /**
       * activates a new lexer condition state (pushes the new lexer
       * condition state onto the condition stack)
       * 
       * @public
       * @this {RegExpLexer}
       */
      pushState: function lexer_pushState(condition) {
        this.conditionStack.push(condition);
        this.__currentRuleSet__ = null;
        return this;
      },
  
      /**
       * pop the previously active lexer condition state off the condition
       * stack
       * 
       * @public
       * @this {RegExpLexer}
       */
      popState: function lexer_popState() {
        var n = this.conditionStack.length - 1;
  
        if (n > 0) {
          this.__currentRuleSet__ = null;
          return this.conditionStack.pop();
        } else {
          return this.conditionStack[0];
        }
      },
  
      /**
       * return the currently active lexer condition state; when an index
       * argument is provided it produces the N-th previous condition state,
       * if available
       * 
       * @public
       * @this {RegExpLexer}
       */
      topState: function lexer_topState(n) {
        n = this.conditionStack.length - 1 - Math.abs(n || 0);
  
        if (n >= 0) {
          return this.conditionStack[n];
        } else {
          return 'INITIAL';
        }
      },
  
      /**
       * (internal) determine the lexer rule set which is active for the
       * currently active lexer condition state
       * 
       * @public
       * @this {RegExpLexer}
       */
      _currentRules: function lexer__currentRules() {
        if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
          return this.conditions[this.conditionStack[this.conditionStack.length - 1]];
        } else {
          return this.conditions['INITIAL'];
        }
      },
  
      /**
       * return the number of states currently on the stack
       * 
       * @public
       * @this {RegExpLexer}
       */
      stateStackSize: function lexer_stateStackSize() {
        return this.conditionStack.length;
      },
  
      options: {
        xregexp: true,
        ranges: true,
        trackPosition: true,
        parseActionsUseYYMERGELOCATIONINFO: true,
        easy_keyword_rules: true
      },
  
      JisonLexerError: JisonLexerError,
  
      performAction: function lexer__performAction(yy, yyrulenumber, YY_START) {
        var yy_ = this;
        var YYSTATE = YY_START;
  
        switch (yyrulenumber) {
        case 2:
          /*! Conditions:: action */
          /*! Rule::       \/[^ /]*?['"{}][^ ]*?\/ */
          return 43;  // regexp with braces or quotes (and no spaces)  
  
          break;
  
        case 7:
          /*! Conditions:: action */
          /*! Rule::       \{ */
          yy.depth++;
  
          return 12;
          break;
  
        case 8:
          /*! Conditions:: action */
          /*! Rule::       \} */
          if (yy.depth === 0) {
            this.popState();
          } else {
            yy.depth--;
          }
  
          return 13;
          break;
  
        case 9:
          /*! Conditions:: token */
          /*! Rule::       {BR} */
          this.popState();
  
          break;
  
        case 10:
          /*! Conditions:: token */
          /*! Rule::       %% */
          this.popState();
  
          break;
  
        case 11:
          /*! Conditions:: token */
          /*! Rule::       ; */
          this.popState();
  
          break;
  
        case 12:
          /*! Conditions:: bnf ebnf */
          /*! Rule::       %% */
          this.pushState('code');
  
          return 14;
          break;
  
        case 25:
          /*! Conditions:: options */
          /*! Rule::       = */
          this.pushState('option_values');
  
          return 3;
          break;
  
        case 26:
          /*! Conditions:: option_values */
          /*! Rule::       "{DOUBLEQUOTED_STRING_CONTENT}" */
          yy_.yytext = unescQuote(this.matches[1], /\\"/g);
  
          this.popState();
          return 29;    // value is always a string type  
          break;
  
        case 27:
          /*! Conditions:: option_values */
          /*! Rule::       '{QUOTED_STRING_CONTENT}' */
          yy_.yytext = unescQuote(this.matches[1], /\\'/g);
  
          this.popState();
          return 29;    // value is always a string type  
          break;
  
        case 28:
          /*! Conditions:: option_values */
          /*! Rule::       `{ES2017_STRING_CONTENT}` */
          yy_.yytext = unescQuote(this.matches[1], /\\`/g);
  
          this.popState();
          return 29;    // value is always a string type  
          break;
  
        case 29:
          /*! Conditions:: INITIAL ebnf bnf token path options option_values */
          /*! Rule::       \/\/[^\r\n]* */
          /* skip single-line comment */
          break;
  
        case 30:
          /*! Conditions:: INITIAL ebnf bnf token path options option_values */
          /*! Rule::       \/\*[^]*?\*\/ */
          /* skip multi-line comment */
          break;
  
        case 31:
          /*! Conditions:: option_values */
          /*! Rule::       [^\s\r\n]+ */
          this.popState();
  
          return 30;
          break;
  
        case 32:
          /*! Conditions:: options */
          /*! Rule::       {BR}{WS}+(?=\S) */
          /* skip leading whitespace on the next line of input, when followed by more options */
          break;
  
        case 33:
          /*! Conditions:: options */
          /*! Rule::       {BR} */
          this.popState();
  
          return 28;
          break;
  
        case 34:
          /*! Conditions:: options option_values */
          /*! Rule::       {WS}+ */
          /* skip whitespace */
          break;
  
        case 35:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       {WS}+ */
          /* skip whitespace */
          break;
  
        case 36:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       {BR}+ */
          /* skip newlines */
          break;
  
        case 37:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       \[{ID}\] */
          yy_.yytext = this.matches[1];
  
          return 39;
          break;
  
        case 42:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       "{DOUBLEQUOTED_STRING_CONTENT}" */
          yy_.yytext = unescQuote(this.matches[1], /\\"/g);
  
          return 26;
          break;
  
        case 43:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       '{QUOTED_STRING_CONTENT}' */
          yy_.yytext = unescQuote(this.matches[1], /\\'/g);
  
          return 26;
          break;
  
        case 48:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       %% */
          this.pushState((yy.ebnf ? 'ebnf' : 'bnf'));
  
          return 14;
          break;
  
        case 49:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       %ebnf\b */
          yy.ebnf = true;
  
          return 20;
          break;
  
        case 57:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       %token\b */
          this.pushState('token');
  
          return 18;
          break;
  
        case 59:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       %options\b */
          this.pushState('options');
  
          return 27;
          break;
  
        case 60:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       %lex{LEX_CONTENT}\/lex\b */
          // remove the %lex../lex wrapper and return the pure lex section:
          yy_.yytext = this.matches[1];
  
          return 17;
          break;
  
        case 63:
          /*! Conditions:: INITIAL ebnf bnf code */
          /*! Rule::       %include\b */
          this.pushState('path');
  
          return 44;
          break;
  
        case 64:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       %{NAME}([^\r\n]*) */
          /* ignore unrecognized decl */
          this.warn(rmCommonWS`
                                                  EBNF: ignoring unsupported parser option ${dquote(yy_.yytext)}
                                                  while lexing in ${dquote(this.topState())} state.
  
                                                    Erroneous area:
                                                  ` + this.prettyPrintRange(yy_.yylloc));
  
          yy_.yytext = [
            this.matches[1],            // {NAME}  
            this.matches[2].trim()       // optional value/parameters 
          ];
  
          return 21;
          break;
  
        case 65:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       <{ID}> */
          yy_.yytext = this.matches[1];
  
          return 36;
          break;
  
        case 66:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       \{\{([^]*?)\}\} */
          yy_.yytext = this.matches[1].replace(/\}\\\}/g, '}}');   // unescape any literal '}\}' that exists within the action code block 
  
          return 15;
          break;
  
        case 67:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       %\{([^]*?)%\} */
          yy_.yytext = this.matches[1].replace(/%\\\}/g, '%}');    // unescape any literal '%\}' that exists within the action code block 
  
          return 15;
          break;
  
        case 68:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       \{ */
          yy.depth = 0;
  
          this.pushState('action');
          return 12;
          break;
  
        case 69:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       ->.* */
          yy_.yytext = yy_.yytext.substr(2, yy_.yyleng - 2).trim();
  
          return 42;
          break;
  
        case 70:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       →.* */
          yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 1).trim();
  
          return 42;
          break;
  
        case 71:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       =>.* */
          yy_.yytext = yy_.yytext.substr(2, yy_.yyleng - 2).trim();
  
          return 42;
          break;
  
        case 72:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       {HEX_NUMBER} */
          yy_.yytext = parseInt(yy_.yytext, 16);
  
          return 37;
          break;
  
        case 73:
          /*! Conditions:: token bnf ebnf INITIAL */
          /*! Rule::       {DECIMAL_NUMBER}(?![xX0-9a-fA-F]) */
          yy_.yytext = parseInt(yy_.yytext, 10);
  
          return 37;
          break;
  
        case 75:
          /*! Conditions:: code */
          /*! Rule::       [^\r\n]+ */
          return 46;       // the bit of CODE just before EOF...  
  
          break;
  
        case 76:
          /*! Conditions:: path */
          /*! Rule::       {BR} */
          this.popState();
  
          this.unput(yy_.yytext);
          break;
  
        case 77:
          /*! Conditions:: path */
          /*! Rule::       "{DOUBLEQUOTED_STRING_CONTENT}" */
          yy_.yytext = unescQuote(this.matches[1]);
  
          this.popState();
          return 45;
          break;
  
        case 78:
          /*! Conditions:: path */
          /*! Rule::       '{QUOTED_STRING_CONTENT}' */
          yy_.yytext = unescQuote(this.matches[1]);
  
          this.popState();
          return 45;
          break;
  
        case 79:
          /*! Conditions:: path */
          /*! Rule::       {WS}+ */
          // skip whitespace in the line 
          break;
  
        case 80:
          /*! Conditions:: path */
          /*! Rule::       [^\s\r\n]+ */
          this.popState();
  
          return 45;
          break;
  
        case 81:
          /*! Conditions:: action */
          /*! Rule::       " */
          yy_.yyerror(rmCommonWS`
                                              unterminated string constant in lexer rule action block.
  
                                                Erroneous area:
                                              ` + this.prettyPrintRange(yy_.yylloc));
  
          return 2;
          break;
  
        case 82:
          /*! Conditions:: action */
          /*! Rule::       ' */
          yy_.yyerror(rmCommonWS`
                                              unterminated string constant in lexer rule action block.
  
                                                Erroneous area:
                                              ` + this.prettyPrintRange(yy_.yylloc));
  
          return 2;
          break;
  
        case 83:
          /*! Conditions:: action */
          /*! Rule::       ` */
          yy_.yyerror(rmCommonWS`
                                              unterminated string constant in lexer rule action block.
  
                                                Erroneous area:
                                              ` + this.prettyPrintRange(yy_.yylloc));
  
          return 2;
          break;
  
        case 84:
          /*! Conditions:: option_values */
          /*! Rule::       " */
          yy_.yyerror(rmCommonWS`
                                              unterminated string constant in %options entry.
  
                                                Erroneous area:
                                              ` + this.prettyPrintRange(yy_.yylloc));
  
          return 2;
          break;
  
        case 85:
          /*! Conditions:: option_values */
          /*! Rule::       ' */
          yy_.yyerror(rmCommonWS`
                                              unterminated string constant in %options entry.
  
                                                Erroneous area:
                                              ` + this.prettyPrintRange(yy_.yylloc));
  
          return 2;
          break;
  
        case 86:
          /*! Conditions:: option_values */
          /*! Rule::       ` */
          yy_.yyerror(rmCommonWS`
                                              unterminated string constant in %options entry.
  
                                                Erroneous area:
                                              ` + this.prettyPrintRange(yy_.yylloc));
  
          return 2;
          break;
  
        case 87:
          /*! Conditions:: * */
          /*! Rule::       " */
          var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState());
  
          yy_.yyerror(rmCommonWS`
                                              unterminated string constant  encountered while lexing
                                              ${rules}.
  
                                                Erroneous area:
                                              ` + this.prettyPrintRange(yy_.yylloc));
  
          return 2;
          break;
  
        case 88:
          /*! Conditions:: * */
          /*! Rule::       ' */
          var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState());
  
          yy_.yyerror(rmCommonWS`
                                              unterminated string constant  encountered while lexing
                                              ${rules}.
  
                                                Erroneous area:
                                              ` + this.prettyPrintRange(yy_.yylloc));
  
          return 2;
          break;
  
        case 89:
          /*! Conditions:: * */
          /*! Rule::       ` */
          var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState());
  
          yy_.yyerror(rmCommonWS`
                                              unterminated string constant  encountered while lexing
                                              ${rules}.
  
                                                Erroneous area:
                                              ` + this.prettyPrintRange(yy_.yylloc));
  
          return 2;
          break;
  
        case 90:
          /*! Conditions:: * */
          /*! Rule::       . */
          /* b0rk on bad characters */
          yy_.yyerror(rmCommonWS`
                                                  unsupported parser input: ${dquote(yy_.yytext)}
                                                  while lexing in ${dquote(this.topState())} state.
                                                  
                                                    Erroneous area:
                                                  ` + this.prettyPrintRange(yy_.yylloc));
  
          break;
  
        default:
          return this.simpleCaseActionClusters[yyrulenumber];
        }
      },
  
      simpleCaseActionClusters: {
        /*! Conditions:: action */
        /*! Rule::       \/\*[^]*?\*\/ */
        0: 43,
  
        /*! Conditions:: action */
        /*! Rule::       \/\/[^\r\n]* */
        1: 43,
  
        /*! Conditions:: action */
        /*! Rule::       "{DOUBLEQUOTED_STRING_CONTENT}" */
        3: 43,
  
        /*! Conditions:: action */
        /*! Rule::       '{QUOTED_STRING_CONTENT}' */
        4: 43,
  
        /*! Conditions:: action */
        /*! Rule::       [/"'][^{}/"']+ */
        5: 43,
  
        /*! Conditions:: action */
        /*! Rule::       [^{}/"']+ */
        6: 43,
  
        /*! Conditions:: bnf ebnf */
        /*! Rule::       %empty\b */
        13: 38,
  
        /*! Conditions:: bnf ebnf */
        /*! Rule::       %epsilon\b */
        14: 38,
  
        /*! Conditions:: bnf ebnf */
        /*! Rule::       \u0190 */
        15: 38,
  
        /*! Conditions:: bnf ebnf */
        /*! Rule::       \u025B */
        16: 38,
  
        /*! Conditions:: bnf ebnf */
        /*! Rule::       \u03B5 */
        17: 38,
  
        /*! Conditions:: bnf ebnf */
        /*! Rule::       \u03F5 */
        18: 38,
  
        /*! Conditions:: ebnf */
        /*! Rule::       \( */
        19: 7,
  
        /*! Conditions:: ebnf */
        /*! Rule::       \) */
        20: 8,
  
        /*! Conditions:: ebnf */
        /*! Rule::       \* */
        21: 9,
  
        /*! Conditions:: ebnf */
        /*! Rule::       \? */
        22: 10,
  
        /*! Conditions:: ebnf */
        /*! Rule::       \+ */
        23: 11,
  
        /*! Conditions:: options */
        /*! Rule::       {NAME} */
        24: 25,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       {ID} */
        38: 24,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       {NAME} */
        39: 25,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       \$end\b */
        40: 40,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       \$eof\b */
        41: 40,
  
        /*! Conditions:: token */
        /*! Rule::       [^\s\r\n]+ */
        44: 'TOKEN_WORD',
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       : */
        45: 5,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       ; */
        46: 4,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       \| */
        47: 6,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       %debug\b */
        50: 19,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       %parser-type\b */
        51: 32,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       %prec\b */
        52: 41,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       %start\b */
        53: 16,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       %left\b */
        54: 33,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       %right\b */
        55: 34,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       %nonassoc\b */
        56: 35,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       %parse-param\b */
        58: 31,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       %code\b */
        61: 23,
  
        /*! Conditions:: token bnf ebnf INITIAL */
        /*! Rule::       %import\b */
        62: 22,
  
        /*! Conditions:: code */
        /*! Rule::       [^\r\n]*(\r|\n)+ */
        74: 46,
  
        /*! Conditions:: * */
        /*! Rule::       $ */
        91: 1
      },
  
      rules: [
        /*  0: */  new XRegExp('^(?:\\/\\*[^]*?\\*\\/)', ''),
        /*  1: */  /^(?:\/\/[^\r\n]*)/,
        /*  2: */  /^(?:\/[^ \/]*?['"{}][^ ]*?\/)/,
        /*  3: */  /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/,
        /*  4: */  /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/,
        /*  5: */  /^(?:[\/"'][^{}\/"']+)/,
        /*  6: */  /^(?:[^{}\/"']+)/,
        /*  7: */  /^(?:\{)/,
        /*  8: */  /^(?:\})/,
        /*  9: */  /^(?:(\r\n|\n|\r))/,
        /* 10: */  /^(?:%%)/,
        /* 11: */  /^(?:;)/,
        /* 12: */  /^(?:%%)/,
        /* 13: */  /^(?:%empty\b)/,
        /* 14: */  /^(?:%epsilon\b)/,
        /* 15: */  /^(?:\u0190)/,
        /* 16: */  /^(?:\u025B)/,
        /* 17: */  /^(?:\u03B5)/,
        /* 18: */  /^(?:\u03F5)/,
        /* 19: */  /^(?:\()/,
        /* 20: */  /^(?:\))/,
        /* 21: */  /^(?:\*)/,
        /* 22: */  /^(?:\?)/,
        /* 23: */  /^(?:\+)/,
        /* 24: */  new XRegExp(
          '^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))',
          ''
        ),
        /* 25: */  /^(?:=)/,
        /* 26: */  /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/,
        /* 27: */  /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/,
        /* 28: */  /^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/,
        /* 29: */  /^(?:\/\/[^\r\n]*)/,
        /* 30: */  new XRegExp('^(?:\\/\\*[^]*?\\*\\/)', ''),
        /* 31: */  /^(?:\S+)/,
        /* 32: */  /^(?:(\r\n|\n|\r)([^\S\n\r])+(?=\S))/,
        /* 33: */  /^(?:(\r\n|\n|\r))/,
        /* 34: */  /^(?:([^\S\n\r])+)/,
        /* 35: */  /^(?:([^\S\n\r])+)/,
        /* 36: */  /^(?:(\r\n|\n|\r)+)/,
        /* 37: */  new XRegExp('^(?:\\[([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\])', ''),
        /* 38: */  new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''),
        /* 39: */  new XRegExp(
          '^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))',
          ''
        ),
        /* 40: */  /^(?:\$end\b)/,
        /* 41: */  /^(?:\$eof\b)/,
        /* 42: */  /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/,
        /* 43: */  /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/,
        /* 44: */  /^(?:\S+)/,
        /* 45: */  /^(?::)/,
        /* 46: */  /^(?:;)/,
        /* 47: */  /^(?:\|)/,
        /* 48: */  /^(?:%%)/,
        /* 49: */  /^(?:%ebnf\b)/,
        /* 50: */  /^(?:%debug\b)/,
        /* 51: */  /^(?:%parser-type\b)/,
        /* 52: */  /^(?:%prec\b)/,
        /* 53: */  /^(?:%start\b)/,
        /* 54: */  /^(?:%left\b)/,
        /* 55: */  /^(?:%right\b)/,
        /* 56: */  /^(?:%nonassoc\b)/,
        /* 57: */  /^(?:%token\b)/,
        /* 58: */  /^(?:%parse-param\b)/,
        /* 59: */  /^(?:%options\b)/,
        /* 60: */  new XRegExp(
          '^(?:%lex((?:[^\\S\\n\\r])*(?:(?:\\r\\n|\\n|\\r)[^]*?)?(?:\\r\\n|\\n|\\r)(?:[^\\S\\n\\r])*)\\/lex\\b)',
          ''
        ),
        /* 61: */  /^(?:%code\b)/,
        /* 62: */  /^(?:%import\b)/,
        /* 63: */  /^(?:%include\b)/,
        /* 64: */  new XRegExp(
          '^(?:%([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?)([^\\n\\r]*))',
          ''
        ),
        /* 65: */  new XRegExp('^(?:<([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)>)', ''),
        /* 66: */  new XRegExp('^(?:\\{\\{([^]*?)\\}\\})', ''),
        /* 67: */  new XRegExp('^(?:%\\{([^]*?)%\\})', ''),
        /* 68: */  /^(?:\{)/,
        /* 69: */  /^(?:->.*)/,
        /* 70: */  /^(?:→.*)/,
        /* 71: */  /^(?:=>.*)/,
        /* 72: */  /^(?:(0[Xx][\dA-Fa-f]+))/,
        /* 73: */  /^(?:([1-9]\d*)(?![\dA-FXa-fx]))/,
        /* 74: */  /^(?:[^\r\n]*(\r|\n)+)/,
        /* 75: */  /^(?:[^\r\n]+)/,
        /* 76: */  /^(?:(\r\n|\n|\r))/,
        /* 77: */  /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/,
        /* 78: */  /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/,
        /* 79: */  /^(?:([^\S\n\r])+)/,
        /* 80: */  /^(?:\S+)/,
        /* 81: */  /^(?:")/,
        /* 82: */  /^(?:')/,
        /* 83: */  /^(?:`)/,
        /* 84: */  /^(?:")/,
        /* 85: */  /^(?:')/,
        /* 86: */  /^(?:`)/,
        /* 87: */  /^(?:")/,
        /* 88: */  /^(?:')/,
        /* 89: */  /^(?:`)/,
        /* 90: */  /^(?:.)/,
        /* 91: */  /^(?:$)/
      ],
  
      conditions: {
        'action': {
          rules: [0, 1, 2, 3, 4, 5, 6, 7, 8, 81, 82, 83, 87, 88, 89, 90, 91],
          inclusive: false
        },
  
        'code': {
          rules: [63, 74, 75, 87, 88, 89, 90, 91],
          inclusive: false
        },
  
        'path': {
          rules: [29, 30, 76, 77, 78, 79, 80, 87, 88, 89, 90, 91],
          inclusive: false
        },
  
        'options': {
          rules: [24, 25, 29, 30, 32, 33, 34, 87, 88, 89, 90, 91],
          inclusive: false
        },
  
        'option_values': {
          rules: [26, 27, 28, 29, 30, 31, 34, 84, 85, 86, 87, 88, 89, 90, 91],
          inclusive: false
        },
  
        'token': {
          rules: [
            9,
            10,
            11,
            29,
            30,
            35,
            36,
            37,
            38,
            39,
            40,
            41,
            42,
            43,
            44,
            45,
            46,
            47,
            48,
            49,
            50,
            51,
            52,
            53,
            54,
            55,
            56,
            57,
            58,
            59,
            60,
            61,
            62,
            64,
            65,
            66,
            67,
            68,
            69,
            70,
            71,
            72,
            73,
            87,
            88,
            89,
            90,
            91
          ],
  
          inclusive: true
        },
  
        'bnf': {
          rules: [
            12,
            13,
            14,
            15,
            16,
            17,
            18,
            29,
            30,
            35,
            36,
            37,
            38,
            39,
            40,
            41,
            42,
            43,
            45,
            46,
            47,
            48,
            49,
            50,
            51,
            52,
            53,
            54,
            55,
            56,
            57,
            58,
            59,
            60,
            61,
            62,
            63,
            64,
            65,
            66,
            67,
            68,
            69,
            70,
            71,
            72,
            73,
            87,
            88,
            89,
            90,
            91
          ],
  
          inclusive: true
        },
  
        'ebnf': {
          rules: [
            12,
            13,
            14,
            15,
            16,
            17,
            18,
            19,
            20,
            21,
            22,
            23,
            29,
            30,
            35,
            36,
            37,
            38,
            39,
            40,
            41,
            42,
            43,
            45,
            46,
            47,
            48,
            49,
            50,
            51,
            52,
            53,
            54,
            55,
            56,
            57,
            58,
            59,
            60,
            61,
            62,
            63,
            64,
            65,
            66,
            67,
            68,
            69,
            70,
            71,
            72,
            73,
            87,
            88,
            89,
            90,
            91
          ],
  
          inclusive: true
        },
  
        'INITIAL': {
          rules: [
            29,
            30,
            35,
            36,
            37,
            38,
            39,
            40,
            41,
            42,
            43,
            45,
            46,
            47,
            48,
            49,
            50,
            51,
            52,
            53,
            54,
            55,
            56,
            57,
            58,
            59,
            60,
            61,
            62,
            63,
            64,
            65,
            66,
            67,
            68,
            69,
            70,
            71,
            72,
            73,
            87,
            88,
            89,
            90,
            91
          ],
  
          inclusive: true
        }
      }
    };
  
    var rmCommonWS = helpers.rmCommonWS;
    var dquote = helpers.dquote;
  
    function indent(s, i) {
      var a = s.split('\n');
      var pf = new Array(i + 1).join(' ');
      return pf + a.join('\n' + pf);
    }
  
    // unescape a string value which is wrapped in quotes/doublequotes
    function unescQuote(str) {
      str = '' + str;
      var a = str.split('\\\\');
  
      a = a.map(function(s) {
        return s.replace(/\\'/g, '\'').replace(/\\"/g, '"');
      });
  
      str = a.join('\\\\');
      return str;
    }
  
    lexer.warn = function l_warn() {
      if (this.yy && this.yy.parser && typeof this.yy.parser.warn === 'function') {
        return this.yy.parser.warn.apply(this, arguments);
      } else {
        console.warn.apply(console, arguments);
      }
    };
  
    lexer.log = function l_log() {
      if (this.yy && this.yy.parser && typeof this.yy.parser.log === 'function') {
        return this.yy.parser.log.apply(this, arguments);
      } else {
        console.log.apply(console, arguments);
      }
    };
  
    return lexer;
  }();
  parser.lexer = lexer;
  
  function Parser() {
      this.yy = {};
  }
  Parser.prototype = parser;
  parser.Parser = Parser;
  
  function yyparse() {
      return parser.parse.apply(parser, arguments);
  }
  
  
  
  export default {
      parser,
      Parser,
      parse: yyparse,
      
  };
  
  