diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..10823cf --- /dev/null +++ b/.babelrc @@ -0,0 +1,15 @@ +{ + "ignore": [ + "node_modules/**/*.js" + ], + "compact": false, + "retainLines": false, + "presets": [ + ["env", { + "targets": { + "browsers": ["last 2 versions", "safari >= 7"], + "node": "4.0" + } + }] + ] +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..442aed3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,21 @@ +*.sh text eol=lf +*.bat text eol=crlf +*.php text eol=lf +*.inc text eol=lf +*.html text eol=lf +*.json text eol=lf +*.js text eol=lf +*.css text eol=lf +*.less text eol=lf +*.sass text eol=lf +*.ini text eol=lf +*.txt text eol=lf +*.xml text eol=lf +*.md text eol=lf +*.markdown text eol=lf +*.json5 text eol=lf + +*.pdf binary +*.psd binary +*.pptx binary +*.xlsx binary diff --git a/.gitignore b/.gitignore index 8c32b70..a08585b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ -lex-parser.js +.DS_Store node_modules/ +npm-debug.log # Editor bak files *~ *.bak *.orig + diff --git a/.npmignore b/.npmignore index 7a48940..9fe4b2e 100644 --- a/.npmignore +++ b/.npmignore @@ -1,2 +1,20 @@ +.DS_Store +node_modules/ +npm-debug.log + +# Editor backup files +*.bak +*~ + +# scratch space +/tmp/ + +# Ignore build/publish scripts, etc. +Makefile + +# Sources which are compiled through jison lex.y lex.l + +# misc files which are used during development +__patch_*.js diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f0913fb --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: node_js +sudo: false + +node_js: + - 8 + - 7 + - 6 + - 5 + - 4 + - node + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..e8fcb80 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2009-2017 Zachary Carter + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile index 8e1add5..eb0afbb 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,72 @@ -all: install build test +JISON_VERSION := $(shell node ../../dist/cli-cjs-es5.js -V 2> /dev/null ) -install: +ifndef JISON_VERSION + JISON = sh node_modules/.bin/jison +else + JISON = node ../../dist/cli-cjs-es5.js +endif + +ROLLUP = node_modules/.bin/rollup +BABEL = node_modules/.bin/babel +MOCHA = node_modules/.bin/mocha + + + + +all: build test + +prep: npm-install + +npm-install: npm install +npm-update: + ncu -a --packageFile=package.json + build: - node ./node_modules/.bin/jison lex.y lex.l - mv lex.js lex-parser.js +ifeq ($(wildcard node_modules/.bin/jison),) + $(error "### FAILURE: Make sure you have run 'make prep' before as the jison compiler is unavailable! ###") +endif + $(JISON) -m es -o lex-parser.js lex.y lex.l + -mkdir -p dist + cat lex-parser-prelude.js > lex-parser-base.js + cat lex-parser.js >> lex-parser-base.js + cat lex-parser-base.js > lex-parser.js + -rm lex-parser-base.js + $(ROLLUP) -c + $(BABEL) dist/lex-parser-cjs.js -o dist/lex-parser-cjs-es5.js + $(BABEL) dist/lex-parser-umd.js -o dist/lex-parser-umd-es5.js test: - node tests/all-tests.js + $(MOCHA) --timeout 18000 --check-leaks --globals assert tests/ + + +# increment the XXX number in the package.json file: version ..- +bump: + +git-tag: + +publish: + npm run pub + + clean: + -rm -f lex-parser.js + -rm -rf dist/ + -rm -rf node_modules/ + -rm -f package-lock.json superclean: clean -find . -type d -name 'node_modules' -exec rm -rf "{}" \; + + + +.PHONY: all prep npm-install build test clean superclean bump git-tag publish npm-update + diff --git a/README.md b/README.md index 6913c62..88b99c3 100644 --- a/README.md +++ b/README.md @@ -1,111 +1,581 @@ -# lex-parser +# lex-parser \[OBSOLETED] + + +[![Join the chat at https://gitter.im/jison-parsers-lexers/Lobby](https://badges.gitter.im/jison-parsers-lexers/Lobby.svg)](https://gitter.im/jison-parsers-lexers/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Build Status](https://travis-ci.org/GerHobbelt/lex-parser.svg?branch=master)](https://travis-ci.org/GerHobbelt/lex-parser) +[![NPM version](https://badge.fury.io/js/jison-gho.svg)](https://badge.fury.io/js/jison-gho) +[![Dependency Status](https://img.shields.io/david/GerHobbelt/lex-parser.svg)](https://david-dm.org/GerHobbelt/lex-parser) +[![npm](https://img.shields.io/npm/dm/@gerhobbelt/lex-parser.svg?maxAge=2592000)]() + + + A parser for lexical grammars used by [jison](http://jison.org) and jison-lex. + +> +> # deprecation notice +> +> From today (2017/oct/15) the lex-parser repository is **obsoleted** +> for the `lex-parser` package/codebase: the **primary source** is the +> [jison](https://github.com/GerHobbelt/jison) +> [monorepo](https://medium.com/netscape/the-case-for-monorepos-907c1361708a)'s `packages/lex-parser/` +> directory. See also https://github.com/GerHobbelt/jison/issues/16. +> +> (For a comparable argument, see also ["Why is Babel a monorepo?"](https://github.com/babel/babel/blob/master/doc/design/monorepo.md)) +> +> Issues, pull requests, etc. for `lex-parser` should be filed there; hence +> we do not accept issue reports in this secondary repository any more. +> +> This repository will track the primary source for a while still, but be +> *very aware* that this particular repository will always be lagging behind! +> + + + ## install - npm install lex-parser + npm install @gerhobbelt/lex-parser + ## build -To build the parser yourself, clone the git repo then run: +To build the parser yourself, follow the install & build directions of the [monorepo](https://github.com/GerHobbelt/jison). - make +> +> ### Note about ES6/rollup usage vs. ES5 +> +> All `dist/` library files are 'self-contained': they include all 'local imports' +> from within this jison monorepo in order to deliver a choice of source files +> for your perusal where you only need to worry about importing **external dependencies** +> (such as `recast`). +> +> As such, these `dist/` files **should** be easier to minify and/or use in older +> (ES5) environments. +> +> #### rollup +> +> Iff you use `rollup` or similar tools in an ES6/ES2015/ES2017 setting, then the +> [`package.json::module`](https://github.com/rollup/rollup/wiki/pkg.module) has +> already been set up for you to use the *original sources* instead! +> -This will generate `lex-parser.js`. ## usage - var lexParser = require("lex-parser"); + var lexParser = require("@gerhobbelt/lex-parser"); // parse a lexical grammar and return JSON lexParser.parse("%% ... "); + ## example The parser can parse its own lexical grammar, shown below: - NAME [a-zA-Z_][a-zA-Z0-9_-]* - - %s indented trail rules - %x code start_condition options conditions action - - %% - - [^{}]+ return 'ACTION_BODY' - "{" yy.depth++; return '{' - "}" yy.depth == 0 ? this.begin('trail') : yy.depth--; return '}' - - {NAME} return 'NAME' - ">" this.popState(); return '>' - "," return ',' - "*" return '*' - - \n+ /* */ - \s+ this.begin('indented') - "%%" this.begin('code'); return '%%' - [a-zA-Z0-9_]+ return 'CHARACTER_LIT' - - {NAME} yy.options[yytext] = true - \n+ this.begin('INITIAL') - \s+\n+ this.begin('INITIAL') - \s+ /* empty */ - - {NAME} return 'START_COND' - \n+ this.begin('INITIAL') - \s+\n+ this.begin('INITIAL') - \s+ /* empty */ - - .*\n+ this.begin('rules') - - "{" yy.depth = 0; this.begin('action'); return '{' - "%{"(.|\n)*?"%}" this.begin('trail'); yytext = yytext.substr(2, yytext.length-4);return 'ACTION' - "%{"(.|\n)*?"%}" yytext = yytext.substr(2, yytext.length-4); return 'ACTION' - .+ this.begin('rules'); return 'ACTION' - - "/*"(.|\n|\r)*?"*/" /* ignore */ - "//".* /* ignore */ - - \n+ /* */ - \s+ /* */ - {NAME} return 'NAME' - \"("\\\\"|'\"'|[^"])*\" yytext = yytext.replace(/\\"/g,'"');return 'STRING_LIT' - "'"("\\\\"|"\'"|[^'])*"'" yytext = yytext.replace(/\\'/g,"'");return 'STRING_LIT' - "|" return '|' - "["("\\\\"|"\]"|[^\]])*"]" return 'ANY_GROUP_REGEX' - "(?:" return 'SPECIAL_GROUP' - "(?=" return 'SPECIAL_GROUP' - "(?!" return 'SPECIAL_GROUP' - "(" return '(' - ")" return ')' - "+" return '+' - "*" return '*' - "?" return '?' - "^" return '^' - "," return ',' - "<>" return '$' - "<" this.begin('conditions'); return '<' - "/!" return '/!' - "/" return '/' - "\\"([0-7]{1,3}|[rfntvsSbBwWdD\\*+()${}|[\]\/.^?]|"c"[A-Z]|"x"[0-9A-F]{2}|"u"[a-fA-F0-9]{4}) return 'ESCAPE_CHAR' - "\\". yytext = yytext.replace(/^\\/g,''); return 'ESCAPE_CHAR' - "$" return '$' - "." return '.' - "%options" yy.options = {}; this.begin('options') - "%s" this.begin('start_condition');return 'START_INC' - "%x" this.begin('start_condition');return 'START_EXC' - "%%" this.begin('rules'); return '%%' - "{"\d+(","\s?\d+|",")?"}" return 'RANGE_REGEX' - "{"{NAME}"}" return 'NAME_BRACE' - "{" return '{' - "}" return '}' - . /* ignore bad characters */ - <*><> return 'EOF' - - (.|\n)+ return 'CODE' - - %% +``` +%code imports %{ + import helpers from 'jison-helpers-lib'; +%} + + + +ASCII_LETTER [a-zA-z] +// \p{Alphabetic} already includes [a-zA-z], hence we don't need to merge +// with {UNICODE_LETTER} (though jison has code to optimize if you *did* +// include the `[a-zA-Z]` anyway): +UNICODE_LETTER [\p{Alphabetic}] +ALPHA [{UNICODE_LETTER}_] +DIGIT [\p{Number}] +WHITESPACE [\s\r\n\p{Separator}] +ALNUM [{ALPHA}{DIGIT}] + +NAME [{ALPHA}](?:[{ALNUM}-]*{ALNUM})? +ID [{ALPHA}]{ALNUM}* +DECIMAL_NUMBER [1-9][0-9]* +HEX_NUMBER "0"[xX][0-9a-fA-F]+ +BR \r\n|\n|\r +// WhiteSpace MUST NOT match CR/LF and the regex `\s` DOES, so we cannot use +// that one directly. Instead we define the {WS} macro here: +WS [^\S\r\n] + +// Quoted string content: support *escaped* quotes inside strings: +QUOTED_STRING_CONTENT (?:\\\'|\\[^\']|[^\\\'\r\n])* +DOUBLEQUOTED_STRING_CONTENT (?:\\\"|\\[^\"]|[^\\\"\r\n])* +// backquoted ES6/ES2017 string templates MAY span multiple lines: +ES2017_STRING_CONTENT (?:\\\`|\\[^\`]|[^\\\`])* + +// Accept any non-regex-special character as a direct literal without +// the need to put quotes around it: +ANY_LITERAL_CHAR [^\s\r\n<>\[\](){}.*+?:!=|%\/\\^$,\'\";] + + +%s rules macro named_chunk +%x code start_condition options conditions action path set + + +// Off Topic +// --------- +// +// Do NOT specify the xregexp option as we want the XRegExp \p{...} regex macros converted to +// native regexes and used as such: +// +// %options xregexp + +%options easy_keyword_rules +%options ranges +%options xregexp + + + +%% + +"%{" yy.dept = 0; + yy.include_command_allowed = false; + this.pushState('action'); + this.unput(yytext); + yytext = ''; + return 'ACTION_START'; +"%{"([^]*?)"%}" yytext = this.matches[1]; + yy.include_command_allowed = true; + return 'ACTION'; +"%include" %{ + if (yy.include_command_allowed) { + // This is an include instruction in place of an action: + // + // - one %include per action chunk + // - one %include replaces an entire action chunk + this.pushState('path'); + return 'INCLUDE'; + } else { + // TODO + yyerror('oops!'); + return 'INCLUDE_PLACEMENT_ERROR'; + } + %} +{WS}*"/*"[^]*?"*/" //yy.include_command_allowed = false; -- doesn't impact include-allowed state + return 'ACTION_BODY_C_COMMENT'; +{WS}*"//".* yy.include_command_allowed = false; + return 'ACTION_BODY_CPP_COMMENT'; +{WS}+ return 'ACTION_BODY_WHITESPACE'; + +// make sure to terminate on linefeed before the next rule alternative, +// which is announced by `|`: +"|" if (yy.include_command_allowed) { + this.popState(); + this.unput(yytext); + yytext = ''; + return 'ACTION_END'; + } else { + return 'ACTION_BODY'; + } + +// make sure to terminate on linefeed before the rule section ends, +// which is announced by `%%`: +"%%" if (yy.include_command_allowed) { + this.popState(); + this.unput(yytext); + yytext = ''; + return 'ACTION_END'; + } else { + return 'ACTION_BODY'; + } + +"%" return 'ACTION_BODY'; + +// regexp with braces or quotes (and no spaces, so we don't mistake +// a *division operator* `/` for a regex delimiter here in most circumstances): +"/"[^\s/]*?(?:['"`{}][^\s/]*?)*"/" + yy.include_command_allowed = false; + return 'ACTION_BODY'; +// hack to cope with slashes which MAY be divide operators OR are regex starters: +// we simply gobble the entire line until the end or until we hit a closing brace, +// as we MUST keep track of the curly brace pairs inside an action body. +"/"[^}{BR}]* + yy.include_command_allowed = false; + return 'ACTION_BODY'; +\"{DOUBLEQUOTED_STRING_CONTENT}\" + yy.include_command_allowed = false; + return 'ACTION_BODY'; +\'{QUOTED_STRING_CONTENT}\' yy.include_command_allowed = false; + return 'ACTION_BODY'; +\`{ES2017_STRING_CONTENT}\` yy.include_command_allowed = false; + return 'ACTION_BODY'; +[^{}/"'`|%\{\}{BR}{WS}]+ yy.include_command_allowed = false; + return 'ACTION_BODY'; +"{" yy.depth++; + yy.include_command_allowed = false; + return 'ACTION_BODY'; +"}" %{ + yy.include_command_allowed = false; + if (yy.depth <= 0) { + yyerror(rmCommonWS` + too many closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%\}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + return 'BRACKETS_SURPLUS'; + } else { + yy.depth--; + } + return 'ACTION_BODY'; + %} +// make sure to terminate on linefeed before the next rule alternative, +// which is announced by `|`. +// Note that lexer options & commands should be at the start-of-line, i.e. +// without leading whitespace. The only lexer command which we do accept +// here after the last indent is `%include`, which is considered (part +// of) the rule's action code block. +(?:{BR}{WS}+)+/[^{WS}{BR}|] yy.include_command_allowed = true; + return 'ACTION_BODY_WHITESPACE'; // keep empty lines as-is inside action code blocks. +{BR} if (yy.depth > 0) { + yy.include_command_allowed = true; + return 'ACTION_BODY_WHITESPACE'; // keep empty lines as-is inside action code blocks. + } else { + // end of action code chunk + this.popState(); + this.unput(yytext); + yytext = ''; + return 'ACTION_END'; + } +<> %{ + yy.include_command_allowed = false; + if (yy.depth !== 0) { + yyerror(rmCommonWS` + missing ${yy.depth} closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%\}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + yytext = ''; + return 'BRACKETS_MISSING'; + } + this.popState(); + yytext = ''; + return 'ACTION_END'; + %} + +{NAME} return 'NAME'; +">" this.popState(); return '>'; +"," return ','; +"*" return '*'; + +// Comments should be gobbled and discarded anywhere +// *except* the code/action blocks: +{WS}*"//"[^\r\n]* + /* skip single-line comment */ +{WS}*"/*"[^]*?"*/" + /* skip multi-line comment */ + +{BR}+ /* empty */ +{WS}+{BR}+ /* empty */ +"//"[^\r\n]* + /* skip single-line comment */ +"/*"[^]*?"*/" + /* skip multi-line comment */ +// ACTION code chunks follow rules and are generally indented, but +// never start with characters special to the lex language itself: +// - `%` can start options, commands, etc., e.g. `%include` or `%options` +// - `|` starts a rule alternative, never a chunk of action code. +// - +{WS}+/[^{WS}{BR}|%] yy.depth = 0; + yy.include_command_allowed = true; + this.pushState('action'); + return 'ACTION_START'; +"%%" this.popState(); + this.pushState('code'); + return '%%'; +// Accept any non-regex-special character as a direct literal without +// the need to put quotes around it: +{ANY_LITERAL_CHAR}+ + %{ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 'CHARACTER_LIT'; + %} +{NAME} return 'NAME'; +"=" return '='; +\"{DOUBLEQUOTED_STRING_CONTENT}\" + yytext = unescQuote(this.matches[1], /\\"/g); return 'OPTION_STRING_VALUE'; // value is always a string type +\'{QUOTED_STRING_CONTENT}\' + yytext = unescQuote(this.matches[1], /\\'/g); return 'OPTION_STRING_VALUE'; // value is always a string type +\`{ES2017_STRING_CONTENT}\` + yytext = unescQuote(this.matches[1], /\\`/g); return 'OPTION_STRING_VALUE'; // value is always a string type + +[^\s\r\n]+ return 'OPTION_VALUE'; +{BR}{WS}+(?=\S) /* skip leading whitespace on the next line of input, when followed by more options */ +{BR} this.popState(); return 'OPTIONS_END'; +{WS}+ /* skip whitespace */ + +{ID} return 'START_COND'; +{BR}+ this.popState(); +{WS}+ /* empty */ + +{ID} return 'NAME'; +{ID} this.pushState('macro'); return 'NAME'; +{BR}+ this.popState(); + +// Accept any non-regex-special character as a direct literal without +// the need to put quotes around it: +{ANY_LITERAL_CHAR}+ %{ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 'CHARACTER_LIT'; + %} + +{BR}+ /* empty */ +\s+ /* empty */ + +\"{DOUBLEQUOTED_STRING_CONTENT}\" %{ + yytext = unescQuote(this.matches[1], /\\"/g); + return 'STRING_LIT'; + %} +\'{QUOTED_STRING_CONTENT}\' %{ + yytext = unescQuote(this.matches[1], /\\'/g); + return 'STRING_LIT'; + %} +"[" this.pushState('set'); return 'REGEX_SET_START'; +"|" return '|'; +"(?:" return 'SPECIAL_GROUP'; +"(?=" return 'SPECIAL_GROUP'; +"(?!" return 'SPECIAL_GROUP'; +"(" return '('; +")" return ')'; +"+" return '+'; +"*" return '*'; +"?" return '?'; +"^" return '^'; +"," return ','; +"<>" return '$'; +"<" this.pushState('conditions'); return '<'; +"/!" return '/!'; // treated as `(?!atom)` +"/" return '/'; // treated as `(?=atom)` +"\\"([0-7]{1,3}|[rfntvsSbBwWdD\\*+()${}|[\]\/.^?]|"c"[A-Z]|"x"[0-9A-F]{2}|"u"[a-fA-F0-9]{4}) + return 'ESCAPE_CHAR'; +"\\". yytext = yytext.replace(/^\\/g, ''); return 'ESCAPE_CHAR'; +"$" return '$'; +"." return '.'; +"%options" this.pushState('options'); return 'OPTIONS'; +"%s" this.pushState('start_condition'); return 'START_INC'; +"%x" this.pushState('start_condition'); return 'START_EXC'; + +"%code" this.pushState('named_chunk'); return 'INIT_CODE'; +"%import" this.pushState('named_chunk'); return 'IMPORT'; + +"%include" yy.depth = 0; + yy.include_command_allowed = true; + this.pushState('action'); + this.unput(yytext); + yytext = ''; + return 'ACTION_START'; + +"%include" this.pushState('path'); + return 'INCLUDE'; + +"%"{NAME}([^\r\n]*) + %{ + /* ignore unrecognized decl */ + this.warn(rmCommonWS` + LEX: ignoring unsupported lexer option ${dquote(yytext)} + while lexing in ${dquote(this.topState())} state. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + yytext = [ + this.matches[1], // {NAME} + this.matches[2].trim() // optional value/parameters + ]; + return 'UNKNOWN_DECL'; + %} +"%%" this.pushState('rules'); + return '%%'; +"{"\d+(","\s*\d+|",")?"}" return 'RANGE_REGEX'; +"{"{ID}"}" return 'NAME_BRACE'; +"{"{ID}"}" return 'NAME_BRACE'; +"{" return '{'; +"}" return '}'; + + +(?:"\\\\"|"\\]"|[^\]{])+ return 'REGEX_SET'; +"{" return 'REGEX_SET'; +"]" this.popState(); + return 'REGEX_SET_END'; + + +// in the trailing CODE block, only accept these `%include` macros when +// they appear at the start of a line and make sure the rest of lexer +// regexes account for this one so it'll match that way only: +[^\r\n]*(\r|\n)+ return 'CODE'; +[^\r\n]+ return 'CODE'; // the bit of CODE just before EOF... + + +{BR} this.popState(); this.unput(yytext); + +\"{DOUBLEQUOTED_STRING_CONTENT}\" + yytext = unescQuote(this.matches[1]); + this.popState(); + return 'PATH'; +\'{QUOTED_STRING_CONTENT}\' + yytext = unescQuote(this.matches[1]); + this.popState(); + return 'PATH'; + +{WS}+ // skip whitespace in the line +[^\s\r\n]+ this.popState(); + return 'PATH'; + + +// detect and report unterminated string constants ASAP +// for 'action', 'options', but also for other lexer conditions: +// +// these error catching rules fix https://github.com/GerHobbelt/jison/issues/13 +\" yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + return 'error'; +\' yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + return 'error'; +\` yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + return 'error'; + +\" yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + return 'error'; +\' yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + return 'error'; +\` yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + return 'error'; + +<*>\" var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + yyerror(rmCommonWS` + unterminated string constant encountered while lexing + ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + return 'error'; +<*>\' var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + yyerror(rmCommonWS` + unterminated string constant encountered while lexing + ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + return 'error'; +<*>\` var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + yyerror(rmCommonWS` + unterminated string constant encountered while lexing + ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + return 'error'; + + +. %{ + /* b0rk on bad characters */ + var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + yyerror(rmCommonWS` + unsupported lexer input encountered while lexing + ${rules} (i.e. jison lex regexes). + + NOTE: When you want this input to be interpreted as a LITERAL part + of a lex rule regex, you MUST enclose it in double or + single quotes. + + If not, then know that this input is not accepted as a valid + regex expression here in jison-lex ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + %} + +<*>. %{ + yyerror(rmCommonWS` + unsupported lexer input: ${dquote(yytext)} + while lexing in ${dquote(this.topState())} state. + + Erroneous area: + ` + this.prettyPrintRange(this, yylloc)); + %} + +<*><> return 'EOF'; + +%% + + +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; +} +``` + + ## license MIT + + + +## related repositories + +- [jison / jison-gho](https://github.com/GerHobbelt/jison) @ [NPM](https://www.npmjs.com/package/jison-gho) +- [jison-lex](https://github.com/GerHobbelt/jison/master/packages/jison-lex) @ [NPM](https://www.npmjs.com/package/@gerhobbelt/jison-lex) +- [lex-parser](https://github.com/GerHobbelt/jison/master/packages/lex-parser) @ [NPM](https://www.npmjs.com/package/@gerhobbelt/lex-parser) +- [ebnf-parser](https://github.com/GerHobbelt/jison/master/packages/ebnf-parser) @ [NPM](https://www.npmjs.com/package/@gerhobbelt/ebnf-parser) +- [jison2json](https://github.com/GerHobbelt/jison/master/packages/jison2json) @ [NPM](https://www.npmjs.com/package/@gerhobbelt/jison2json) +- [json2jison](https://github.com/GerHobbelt/jison/master/packages/json2jison) @ [NPM](https://www.npmjs.com/package/@gerhobbelt/json2jison) +- [jison-helpers-lib](https://github.com/GerHobbelt/jison/master/packages/helpers-lib) @ [NPM](https://www.npmjs.com/package/jison-helpers-lib) +- ### secondary source repositories + + [jison-lex](https://github.com/GerHobbelt/jison-lex) + + [lex-parser](https://github.com/GerHobbelt/lex-parser) + + [ebnf-parser](https://github.com/GerHobbelt/ebnf-parser) + + [jison2json](https://github.com/GerHobbelt/jison2json) + + [json2jison](https://github.com/GerHobbelt/json2jison) + + [jison-helpers-lib](https://github.com/GerHobbelt/jison-helpers-lib) + diff --git a/dist/lex-parser-cjs-es5.js b/dist/lex-parser-cjs-es5.js new file mode 100644 index 0000000..4106215 --- /dev/null +++ b/dist/lex-parser-cjs-es5.js @@ -0,0 +1,5714 @@ +'use strict'; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _templateObject = _taggedTemplateLiteral(['\n There\'s an error in your lexer regex rules or epilogue.\n Maybe you did not correctly separate the lexer sections with a \'%%\'\n on an otherwise empty line?\n The lexer spec file should have this structure:\n \n definitions\n %%\n rules\n %% // <-- optional!\n extra_module_code // <-- optional epilogue!\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n There\'s an error in your lexer regex rules or epilogue.\n Maybe you did not correctly separate the lexer sections with a \'%%\'\n on an otherwise empty line?\n The lexer spec file should have this structure:\n \n definitions\n %%\n rules\n %% // <-- optional!\n extra_module_code // <-- optional epilogue!\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject2 = _taggedTemplateLiteral(['\n There\'s probably an error in one or more of your lexer regex rules.\n The lexer rule spec should have this structure:\n \n regex action_code\n \n where \'regex\' is a lex-style regex expression (see the\n jison and jison-lex documentation) which is intended to match a chunk\n of the input to lex, while the \'action_code\' block is the JS code\n which will be invoked when the regex is matched. The \'action_code\' block\n may be any (indented!) set of JS statements, optionally surrounded \n by \'{...}\' curly braces or otherwise enclosed in a \'%{...%}\' block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n There\'s probably an error in one or more of your lexer regex rules.\n The lexer rule spec should have this structure:\n \n regex action_code\n \n where \'regex\' is a lex-style regex expression (see the\n jison and jison-lex documentation) which is intended to match a chunk\n of the input to lex, while the \'action_code\' block is the JS code\n which will be invoked when the regex is matched. The \'action_code\' block\n may be any (indented!) set of JS statements, optionally surrounded \n by \'{...}\' curly braces or otherwise enclosed in a \'%{...%}\' block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject3 = _taggedTemplateLiteral(['\n There\'s an error in your lexer epilogue a.k.a. \'extra_module_code\' block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n There\'s an error in your lexer epilogue a.k.a. \'extra_module_code\' block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject4 = _taggedTemplateLiteral(['\n The \'%{...%}\' lexer setup action code section does not compile: ', '\n \n Erroneous area:\n ', '\n '], ['\n The \'%{...%}\' lexer setup action code section does not compile: ', '\n \n Erroneous area:\n ', '\n ']), + _templateObject5 = _taggedTemplateLiteral(['\n You did not specify a legal file path for the \'%import\' initialization code statement, which must have the format:\n %import qualifier_name file_path\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n You did not specify a legal file path for the \'%import\' initialization code statement, which must have the format:\n %import qualifier_name file_path\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject6 = _taggedTemplateLiteral(['\n %import name or source filename missing maybe?\n \n Note: each \'%import\'-ed initialization code section must be qualified by a name, e.g. \'required\' before the import path itself:\n %import qualifier_name file_path\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n %import name or source filename missing maybe?\n \n Note: each \'%import\'-ed initialization code section must be qualified by a name, e.g. \'required\' before the import path itself:\n %import qualifier_name file_path\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject7 = _taggedTemplateLiteral(['\n The \'%code ', '\' action code section does not compile: ', '\n \n Erroneous area:\n ', '\n '], ['\n The \'%code ', '\' action code section does not compile: ', '\n \n Erroneous area:\n ', '\n ']), + _templateObject8 = _taggedTemplateLiteral(['\n Each \'%code\' initialization code section must be qualified by a name, e.g. \'required\' before the action code itself:\n %code qualifier_name {action code}\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Each \'%code\' initialization code section must be qualified by a name, e.g. \'required\' before the action code itself:\n %code qualifier_name {action code}\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject9 = _taggedTemplateLiteral(['\n Seems you made a mistake while specifying one of the lexer rules inside\n the start condition\n <', '> { rules... }\n block.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you made a mistake while specifying one of the lexer rules inside\n the start condition\n <', '> { rules... }\n block.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject10 = _taggedTemplateLiteral(['\n Seems you did not correctly bracket a lexer rules set inside\n the start condition\n <', '> { rules... }\n as a terminating curly brace \'}\' could not be found.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you did not correctly bracket a lexer rules set inside\n the start condition\n <', '> { rules... }\n as a terminating curly brace \'}\' could not be found.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject11 = _taggedTemplateLiteral(['\n The rule\'s action code section does not compile: ', '\n \n Erroneous area:\n ', '\n '], ['\n The rule\'s action code section does not compile: ', '\n \n Erroneous area:\n ', '\n ']), + _templateObject12 = _taggedTemplateLiteral(['\n Lexer rule regex action code declaration error?\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Lexer rule regex action code declaration error?\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject13 = _taggedTemplateLiteral(['\n Missing curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: \'{ ... }\'.\n \n Offending action body:\n ', '\n '], ['\n Missing curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: \'{ ... }\'.\n \n Offending action body:\n ', '\n ']), + _templateObject14 = _taggedTemplateLiteral(['\n Too many curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: \'{ ... }\'.\n \n Offending action body:\n ', '\n '], ['\n Too many curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: \'{ ... }\'.\n \n Offending action body:\n ', '\n ']), + _templateObject15 = _taggedTemplateLiteral(['\n You may place the \'%include\' instruction only at the start/front of a line.\n \n It\'s use is not permitted at this position:\n ', '\n '], ['\n You may place the \'%include\' instruction only at the start/front of a line.\n \n It\'s use is not permitted at this position:\n ', '\n ']), + _templateObject16 = _taggedTemplateLiteral(['\n Seems you did not correctly match curly braces \'{ ... }\' in a lexer rule action block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you did not correctly match curly braces \'{ ... }\' in a lexer rule action block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject17 = _taggedTemplateLiteral(['\n Seems you did not correctly terminate the start condition set <', ',???> with a terminating \'>\'\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you did not correctly terminate the start condition set <', ',???> with a terminating \'>\'\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject18 = _taggedTemplateLiteral(['\n Seems you did not correctly bracket a lex rule regex part in \'(...)\' braces.\n \n Unterminated regex part:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you did not correctly bracket a lex rule regex part in \'(...)\' braces.\n \n Unterminated regex part:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject19 = _taggedTemplateLiteral(['\n Seems you did not correctly bracket a lex rule regex set in \'[...]\' brackets.\n \n Unterminated regex set:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you did not correctly bracket a lex rule regex set in \'[...]\' brackets.\n \n Unterminated regex set:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject20 = _taggedTemplateLiteral(['\n Internal error: option "', '" value assignment failure.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Internal error: option "', '" value assignment failure.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject21 = _taggedTemplateLiteral(['\n Expected a valid option name (with optional value assignment).\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Expected a valid option name (with optional value assignment).\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject22 = _taggedTemplateLiteral(['\n The extra lexer module code section (a.k.a. \'epilogue\') does not compile: ', '\n \n Erroneous area:\n ', '\n '], ['\n The extra lexer module code section (a.k.a. \'epilogue\') does not compile: ', '\n \n Erroneous area:\n ', '\n ']), + _templateObject23 = _taggedTemplateLiteral(['\n The source code %include-d into the extra lexer module code section (a.k.a. \'epilogue\') does not compile: ', '\n \n Erroneous area:\n ', '\n '], ['\n The source code %include-d into the extra lexer module code section (a.k.a. \'epilogue\') does not compile: ', '\n \n Erroneous area:\n ', '\n ']), + _templateObject24 = _taggedTemplateLiteral(['\n %include MUST be followed by a valid file path.\n \n Erroneous path:\n ', '\n \n Technical error report:\n ', '\n '], ['\n %include MUST be followed by a valid file path.\n \n Erroneous path:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject25 = _taggedTemplateLiteral(['\n Module code declaration error?\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Module code declaration error?\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject26 = _taggedTemplateLiteral(['\n too many closing curly braces in lexer rule action block.\n\n Note: the action code chunk may be too complex for jison to parse\n easily; we suggest you wrap the action code chunk in \'%{...%}\'\n to help jison grok more or less complex action code chunks.\n\n Erroneous area:\n '], ['\n too many closing curly braces in lexer rule action block.\n\n Note: the action code chunk may be too complex for jison to parse\n easily; we suggest you wrap the action code chunk in \'%{...%}\'\n to help jison grok more or less complex action code chunks.\n\n Erroneous area:\n ']), + _templateObject27 = _taggedTemplateLiteral(['\n missing ', ' closing curly braces in lexer rule action block.\n\n Note: the action code chunk may be too complex for jison to parse\n easily; we suggest you wrap the action code chunk in \'%{...%}\'\n to help jison grok more or less complex action code chunks.\n\n Erroneous area:\n '], ['\n missing ', ' closing curly braces in lexer rule action block.\n\n Note: the action code chunk may be too complex for jison to parse\n easily; we suggest you wrap the action code chunk in \'%{...%}\'\n to help jison grok more or less complex action code chunks.\n\n Erroneous area:\n ']), + _templateObject28 = _taggedTemplateLiteral(['\n LEX: ignoring unsupported lexer option ', '\n while lexing in ', ' state.\n\n Erroneous area:\n '], ['\n LEX: ignoring unsupported lexer option ', '\n while lexing in ', ' state.\n\n Erroneous area:\n ']), + _templateObject29 = _taggedTemplateLiteral(['\n unterminated string constant in lexer rule action block.\n\n Erroneous area:\n '], ['\n unterminated string constant in lexer rule action block.\n\n Erroneous area:\n ']), + _templateObject30 = _taggedTemplateLiteral(['\n unterminated string constant in %options entry.\n\n Erroneous area:\n '], ['\n unterminated string constant in %options entry.\n\n Erroneous area:\n ']), + _templateObject31 = _taggedTemplateLiteral(['\n unterminated string constant encountered while lexing\n ', '.\n\n Erroneous area:\n '], ['\n unterminated string constant encountered while lexing\n ', '.\n\n Erroneous area:\n ']), + _templateObject32 = _taggedTemplateLiteral(['\n unsupported lexer input encountered while lexing\n ', ' (i.e. jison lex regexes).\n\n NOTE: When you want this input to be interpreted as a LITERAL part\n of a lex rule regex, you MUST enclose it in double or\n single quotes.\n\n If not, then know that this input is not accepted as a valid\n regex expression here in jison-lex ', '.\n\n Erroneous area:\n '], ['\n unsupported lexer input encountered while lexing\n ', ' (i.e. jison lex regexes).\n\n NOTE: When you want this input to be interpreted as a LITERAL part\n of a lex rule regex, you MUST enclose it in double or\n single quotes.\n\n If not, then know that this input is not accepted as a valid\n regex expression here in jison-lex ', '.\n\n Erroneous area:\n ']), + _templateObject33 = _taggedTemplateLiteral(['\n unsupported lexer input: ', ' \n while lexing in ', ' state.\n\n Erroneous area:\n '], ['\n unsupported lexer input: ', ' \n while lexing in ', ' state.\n\n Erroneous area:\n ']); + +function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +function _interopDefault(ex) { + return ex && (typeof ex === 'undefined' ? 'undefined' : _typeof(ex)) === 'object' && 'default' in ex ? ex['default'] : ex; +} + +var XRegExp = _interopDefault(require('@gerhobbelt/xregexp')); +var helpers = _interopDefault(require('jison-helpers-lib')); +var fs = _interopDefault(require('fs')); + +// 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. + * } + */ + +// 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_: { + "$": 17, + "$accept": 0, + "$end": 1, + "%%": 19, + "(": 10, + ")": 11, + "*": 7, + "+": 12, + ",": 8, + ".": 15, + "/": 14, + "/!": 39, + "<": 5, + "=": 18, + ">": 6, + "?": 13, + "ACTION": 32, + "ACTION_BODY": 33, + "ACTION_BODY_CPP_COMMENT": 35, + "ACTION_BODY_C_COMMENT": 34, + "ACTION_BODY_WHITESPACE": 36, + "ACTION_END": 31, + "ACTION_START": 28, + "BRACKET_MISSING": 29, + "BRACKET_SURPLUS": 30, + "CHARACTER_LIT": 46, + "CODE": 53, + "EOF": 1, + "ESCAPE_CHAR": 44, + "IMPORT": 24, + "INCLUDE": 51, + "INCLUDE_PLACEMENT_ERROR": 37, + "INIT_CODE": 25, + "NAME": 20, + "NAME_BRACE": 40, + "OPTIONS": 47, + "OPTIONS_END": 48, + "OPTION_STRING_VALUE": 49, + "OPTION_VALUE": 50, + "PATH": 52, + "RANGE_REGEX": 45, + "REGEX_SET": 43, + "REGEX_SET_END": 42, + "REGEX_SET_START": 41, + "SPECIAL_GROUP": 38, + "START_COND": 27, + "START_EXC": 22, + "START_INC": 21, + "STRING_LIT": 26, + "UNKNOWN_DECL": 23, + "^": 16, + "action": 68, + "action_body": 69, + "any_group_regex": 78, + "definition": 58, + "definitions": 57, + "error": 2, + "escape_char": 81, + "extra_lexer_module_code": 87, + "import_name": 60, + "import_path": 61, + "include_macro_code": 88, + "init": 56, + "init_code_name": 59, + "lex": 54, + "module_code_chunk": 89, + "name_expansion": 77, + "name_list": 71, + "names_exclusive": 63, + "names_inclusive": 62, + "nonempty_regex_list": 74, + "option": 86, + "option_list": 85, + "optional_module_code_chunk": 90, + "options": 84, + "range_regex": 82, + "regex": 72, + "regex_base": 76, + "regex_concat": 75, + "regex_list": 73, + "regex_set": 79, + "regex_set_atom": 80, + "rule": 67, + "rule_block": 66, + "rules": 64, + "rules_and_epilogue": 55, + "rules_collective": 65, + "start_conditions": 70, + "string": 83, + "{": 3, + "|": 9, + "}": 4 + }, + terminals_: { + 1: "EOF", + 2: "error", + 3: "{", + 4: "}", + 5: "<", + 6: ">", + 7: "*", + 8: ",", + 9: "|", + 10: "(", + 11: ")", + 12: "+", + 13: "?", + 14: "/", + 15: ".", + 16: "^", + 17: "$", + 18: "=", + 19: "%%", + 20: "NAME", + 21: "START_INC", + 22: "START_EXC", + 23: "UNKNOWN_DECL", + 24: "IMPORT", + 25: "INIT_CODE", + 26: "STRING_LIT", + 27: "START_COND", + 28: "ACTION_START", + 29: "BRACKET_MISSING", + 30: "BRACKET_SURPLUS", + 31: "ACTION_END", + 32: "ACTION", + 33: "ACTION_BODY", + 34: "ACTION_BODY_C_COMMENT", + 35: "ACTION_BODY_CPP_COMMENT", + 36: "ACTION_BODY_WHITESPACE", + 37: "INCLUDE_PLACEMENT_ERROR", + 38: "SPECIAL_GROUP", + 39: "/!", + 40: "NAME_BRACE", + 41: "REGEX_SET_START", + 42: "REGEX_SET_END", + 43: "REGEX_SET", + 44: "ESCAPE_CHAR", + 45: "RANGE_REGEX", + 46: "CHARACTER_LIT", + 47: "OPTIONS", + 48: "OPTIONS_END", + 49: "OPTION_STRING_VALUE", + 50: "OPTION_VALUE", + 51: "INCLUDE", + 52: "PATH", + 53: "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([54, 54, s, [55, 6], 56, 57, 57, s, [58, 11], 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64, s, [65, 4], 66, 66, 67, 67, s, [68, 3], s, [69, 9], s, [70, 4], 71, 71, 72, s, [73, 4], s, [74, 4], 75, 75, s, [76, 17], 77, 78, 78, 79, 79, 80, s, [80, 4, 1], 83, 84, 85, 85, s, [86, 6], 87, 87, 88, 88, s, [89, 3], 90, 90]), + rule: u([s, [4, 3], s, [5, 4, -1], 0, 0, 2, 0, s, [2, 3], s, [1, 3], 3, 3, 2, 3, 3, s, [1, 7], 2, 1, 2, c, [23, 3], 4, c, [32, 4], 2, c, [22, 3], 3, s, [2, 8], 0, s, [3, 3], 0, 1, 3, 1, s, [3, 4, -1], c, [21, 3], c, [40, 3], s, [3, 4], s, [2, 5], c, [12, 3], s, [1, 6], c, [16, 3], c, [10, 8], c, [9, 3], s, [3, 4], c, [10, 4], c, [82, 4], 1, 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 : lex $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:: lex : init definitions rules_and_epilogue EOF */ + + // 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 - 1]; + this.$.macros = yyvstack[yysp - 2].macros; + this.$.startConditions = yyvstack[yysp - 2].startConditions; + this.$.unknownDecls = yyvstack[yysp - 2].unknownDecls; + + // if there are any options, add them all, otherwise set options to NULL: + // can't check for 'empty object' by `if (yy.options) ...` so we do it this way: + for (var k in yy.options) { + this.$.options = yy.options; + break; + } + + if (yy.actionInclude) { + var asrc = yy.actionInclude.join('\n\n'); + // Only a non-empty action code chunk should actually make it through: + if (asrc.trim() !== '') { + this.$.actionInclude = asrc; + } + } + + delete yy.options; + delete yy.actionInclude; + return this.$; + break; + + case 2: + /*! Production:: lex : init definitions error EOF */ + + // 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(_templateObject, yylexer.prettyPrintRange(yylstack[yysp - 1]), yyvstack[yysp - 1].errStr)); + break; + + case 3: + /*! Production:: rules_and_epilogue : "%%" rules "%%" extra_lexer_module_code */ + + // 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,-,-) + + + if (yyvstack[yysp].trim() !== '') { + this.$ = { rules: yyvstack[yysp - 2], moduleInclude: yyvstack[yysp] }; + } else { + this.$ = { rules: yyvstack[yysp - 2] }; + } + break; + + case 4: + /*! Production:: rules_and_epilogue : "%%" error rules "%%" extra_lexer_module_code */ + + // 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(_templateObject2, yylexer.prettyPrintRange(yylstack[yysp - 3]), yyvstack[yysp - 3].errStr)); + break; + + case 5: + /*! Production:: rules_and_epilogue : "%%" rules "%%" 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(_templateObject3, yylexer.prettyPrintRange(yylstack[yysp]), yyvstack[yysp].errStr)); + break; + + case 6: + /*! Production:: rules_and_epilogue : "%%" error rules */ + + // 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(_templateObject2, yylexer.prettyPrintRange(yylstack[yysp - 1]), yyvstack[yysp - 1].errStr)); + break; + + case 7: + /*! Production:: rules_and_epilogue : "%%" rules */ + + // 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.$ = { rules: yyvstack[yysp] }; + break; + + case 8: + /*! Production:: rules_and_epilogue : %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.$ = { rules: [] }; + break; + + case 9: + /*! Production:: init : %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,-,-) + + + yy.actionInclude = []; + if (!yy.options) yy.options = {}; + break; + + case 10: + /*! Production:: definitions : definitions definition */ + + // 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] != null) { + if ('length' in yyvstack[yysp]) { + this.$.macros[yyvstack[yysp][0]] = yyvstack[yysp][1]; + } else if (yyvstack[yysp].type === 'names') { + for (var name in yyvstack[yysp].names) { + this.$.startConditions[name] = yyvstack[yysp].names[name]; + } + } else if (yyvstack[yysp].type === 'unknown') { + this.$.unknownDecls.push(yyvstack[yysp].body); + } + } + break; + + case 11: + /*! Production:: definitions : %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.$ = { + macros: {}, // { hash table } + startConditions: {}, // { hash table } + unknownDecls: [] // [ array of [key,value] pairs } + }; + break; + + case 12: + /*! Production:: definition : NAME regex */ + + // 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 13: + /*! Production:: definition : START_INC names_inclusive */ + case 14: + /*! Production:: definition : START_EXC names_exclusive */ + + // 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 15: + /*! Production:: definition : 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(_templateObject4, rv, yylexer.prettyPrintRange(yylstack[yysp]))); + } + yy.actionInclude.push(yyvstack[yysp]); + this.$ = null; + break; + + case 16: + /*! Production:: definition : options */ + case 102: + /*! Production:: option_list : option */ + + // 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.$ = null; + break; + + case 17: + /*! Production:: definition : 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.$ = { type: 'unknown', body: yyvstack[yysp] }; + break; + + case 18: + /*! Production:: definition : 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.$ = { type: 'imports', name: yyvstack[yysp - 1], path: yyvstack[yysp] }; + break; + + case 19: + /*! Production:: definition : 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(_templateObject5, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 20: + /*! Production:: definition : 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,-,-) + + + yyparser.yyError(rmCommonWS(_templateObject6, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1]), yyvstack[yysp].errStr)); + break; + + case 21: + /*! Production:: definition : INIT_CODE init_code_name 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS(_templateObject7, $init_code_name, rv, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]))); + } + this.$ = { + type: 'codesection', + qualifier: yyvstack[yysp - 1], + include: yyvstack[yysp] + }; + break; + + case 22: + /*! Production:: definition : INIT_CODE error action */ + + // 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(_templateObject8, yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2], yylstack[yysp]), yyvstack[yysp - 1].errStr)); + break; + + case 23: + /*! Production:: init_code_name : NAME */ + case 24: + /*! Production:: init_code_name : STRING_LIT */ + case 25: + /*! Production:: import_name : NAME */ + case 26: + /*! Production:: import_name : STRING_LIT */ + case 27: + /*! Production:: import_path : NAME */ + case 28: + /*! Production:: import_path : STRING_LIT */ + case 64: + /*! Production:: regex_list : regex_concat */ + case 69: + /*! Production:: nonempty_regex_list : regex_concat */ + case 71: + /*! Production:: regex_concat : regex_base */ + case 96: + /*! Production:: escape_char : ESCAPE_CHAR */ + case 97: + /*! Production:: range_regex : RANGE_REGEX */ + case 113: + /*! Production:: module_code_chunk : CODE */ + case 116: + /*! 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 29: + /*! Production:: names_inclusive : START_COND */ + + // 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.$ = { type: 'names', names: {} };this.$.names[yyvstack[yysp]] = 0; + break; + + case 30: + /*! Production:: names_inclusive : names_inclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 0; + break; + + case 31: + /*! Production:: names_exclusive : START_COND */ + + // 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.$ = { type: 'names', names: {} };this.$.names[yyvstack[yysp]] = 1; + break; + + case 32: + /*! Production:: names_exclusive : names_exclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 1; + break; + + case 33: + /*! Production:: rules : rules rules_collective */ + + // 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].concat(yyvstack[yysp]); + break; + + case 34: + /*! Production:: rules : %epsilon */ + case 40: + /*! Production:: rule_block : %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 35: + /*! Production:: rules_collective : start_conditions rule */ + + // 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,-,-) + + + if (yyvstack[yysp - 1]) { + yyvstack[yysp].unshift(yyvstack[yysp - 1]); + } + this.$ = [yyvstack[yysp]]; + break; + + case 36: + /*! Production:: rules_collective : start_conditions "{" rule_block "}" */ + + // 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,-,-) + + + if (yyvstack[yysp - 3]) { + yyvstack[yysp - 1].forEach(function (d) { + d.unshift(yyvstack[yysp - 3]); + }); + } + this.$ = yyvstack[yysp - 1]; + break; + + case 37: + /*! Production:: rules_collective : start_conditions "{" 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(_templateObject9, yyvstack[yysp - 3].join(','), yylexer.prettyPrintRange(yylexer.mergeLocationInfo(yysp - 3, yysp), yylstack[yysp - 3]), yyvstack[yysp - 1].errStr)); + break; + + case 38: + /*! Production:: rules_collective : start_conditions "{" 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(_templateObject10, yyvstack[yysp - 2].join(','), yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 39: + /*! Production:: rule_block : rule_block rule */ + + // 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 41: + /*! Production:: rule : regex 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS(_templateObject11, rv, yylexer.prettyPrintRange(yylstack[yysp]))); + } + this.$ = [yyvstack[yysp - 1], yyvstack[yysp]]; + break; + + case 42: + /*! Production:: rule : regex error */ + + // 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]]; + yyparser.yyError(rmCommonWS(_templateObject12, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1]), yyvstack[yysp].errStr)); + break; + + case 43: + /*! Production:: action : ACTION_START action_body BRACKET_MISSING */ + + // 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(_templateObject13, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]))); + break; + + case 44: + /*! Production:: action : ACTION_START action_body BRACKET_SURPLUS */ + + // 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(_templateObject14, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]))); + break; + + case 45: + /*! Production:: action : ACTION_START action_body ACTION_END */ + + // 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 s = yyvstack[yysp - 1].trim(); + // remove outermost set of braces UNLESS there's + // a curly brace in there anywhere: in that case + // we should leave it up to the sophisticated + // code analyzer to simplify the code! + // + // This is a very rough check as it will also look + // inside code comments, which should not have + // any influence. + // + // Nevertheless: this is a *safe* transform! + if (s[0] === '{' && s.indexOf('}') === s.length - 1) { + this.$ = s.substring(1, s.length - 1).trim(); + } else { + this.$ = s; + } + break; + + case 46: + /*! Production:: action_body : action_body ACTION */ + case 51: + /*! Production:: action_body : action_body 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] + '\n\n' + yyvstack[yysp] + '\n\n'; + break; + + case 47: + /*! Production:: action_body : action_body ACTION_BODY */ + case 48: + /*! Production:: action_body : action_body ACTION_BODY_C_COMMENT */ + case 49: + /*! Production:: action_body : action_body ACTION_BODY_CPP_COMMENT */ + case 50: + /*! Production:: action_body : action_body ACTION_BODY_WHITESPACE */ + case 70: + /*! Production:: regex_concat : regex_concat regex_base */ + case 82: + /*! Production:: regex_base : regex_base range_regex */ + case 92: + /*! Production:: regex_set : regex_set regex_set_atom */ + case 114: + /*! 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 52: + /*! Production:: action_body : action_body INCLUDE_PLACEMENT_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(_templateObject15, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1]))); + break; + + case 53: + /*! Production:: action_body : action_body 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(_templateObject16, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1]), yyvstack[yysp].errStr)); + break; + + case 54: + /*! Production:: action_body : %epsilon */ + case 65: + /*! Production:: regex_list : %epsilon */ + case 117: + /*! 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 55: + /*! Production:: start_conditions : "<" name_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 - 1]; + break; + + case 56: + /*! Production:: start_conditions : "<" name_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,-,-) + + + yyparser.yyError(rmCommonWS(_templateObject17, yyvstack[yysp - 1].join(','), yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 57: + /*! Production:: start_conditions : "<" "*" ">" */ + + // 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.$ = ['*']; + break; + + case 58: + /*! Production:: start_conditions : %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 59: + /*! Production:: name_list : 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]]; + break; + + case 60: + /*! Production:: name_list : name_list "," 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];this.$.push(yyvstack[yysp]); + break; + + case 61: + /*! Production:: regex : nonempty_regex_list */ + + // 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,-,-) + + + // Detect if the regex ends with a pure (Unicode) word; + // we *do* consider escaped characters which are 'alphanumeric' + // to be equivalent to their non-escaped version, hence these are + // all valid 'words' for the 'easy keyword rules' option: + // + // - hello_kitty + // - γεια_σου_γατοÏλα + // - \u03B3\u03B5\u03B9\u03B1_\u03C3\u03BF\u03C5_\u03B3\u03B1\u03C4\u03BF\u03CD\u03BB\u03B1 + // + // http://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode#12869914 + // + // As we only check the *tail*, we also accept these as + // 'easy keywords': + // + // - %options + // - %foo-bar + // - +++a:b:c1 + // + // Note the dash in that last example: there the code will consider + // `bar` to be the keyword, which is fine with us as we're only + // interested in the trailing boundary and patching that one for + // the `easy_keyword_rules` option. + this.$ = yyvstack[yysp]; + if (yy.options.easy_keyword_rules) { + // We need to 'protect' `eval` here as keywords are allowed + // to contain double-quotes and other leading cruft. + // `eval` *does* gobble some escapes (such as `\b`) but + // we protect against that through a simple replace regex: + // we're not interested in the special escapes' exact value + // anyway. + // It will also catch escaped escapes (`\\`), which are not + // word characters either, so no need to worry about + // `eval(str)` 'correctly' converting convoluted constructs + // like '\\\\\\\\\\b' in here. + this.$ = this.$.replace(/\\\\/g, '.').replace(/"/g, '.').replace(/\\c[A-Z]/g, '.').replace(/\\[^xu0-9]/g, '.'); + + try { + // Convert Unicode escapes and other escapes to their literal characters + // BEFORE we go and check whether this item is subject to the + // `easy_keyword_rules` option. + this.$ = JSON.parse('"' + this.$ + '"'); + } catch (ex) { + yyparser.warn('easy-keyword-rule FAIL on eval: ', ex); + + // make the next keyword test fail: + this.$ = '.'; + } + // a 'keyword' starts with an alphanumeric character, + // followed by zero or more alphanumerics or digits: + var re = new XRegExp('\\w[\\w\\d]*$'); + if (XRegExp.match(this.$, re)) { + this.$ = yyvstack[yysp] + "\\b"; + } else { + this.$ = yyvstack[yysp]; + } + } + break; + + case 62: + /*! Production:: regex_list : regex_list "|" regex_concat */ + case 66: + /*! Production:: nonempty_regex_list : nonempty_regex_list "|" regex_concat */ + + // 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 63: + /*! Production:: regex_list : regex_list "|" */ + case 67: + /*! Production:: nonempty_regex_list : nonempty_regex_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] + '|'; + break; + + case 68: + /*! Production:: nonempty_regex_list : "|" regex_concat */ + + // 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 72: + /*! Production:: regex_base : "(" regex_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 - 1] + ')'; + break; + + case 73: + /*! Production:: regex_base : SPECIAL_GROUP regex_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 74: + /*! Production:: regex_base : "(" regex_list error */ + case 75: + /*! Production:: regex_base : SPECIAL_GROUP regex_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,-,-) + + + yyparser.yyError(rmCommonWS(_templateObject18, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 76: + /*! Production:: regex_base : regex_base "+" */ + + // 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] + '+'; + break; + + case 77: + /*! Production:: regex_base : regex_base "*" */ + + // 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] + '*'; + break; + + case 78: + /*! Production:: regex_base : regex_base "?" */ + + // 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] + '?'; + break; + + case 79: + /*! Production:: regex_base : "/" regex_base */ + + // 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 80: + /*! Production:: regex_base : "/!" regex_base */ + + // 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 81: + /*! Production:: regex_base : name_expansion */ + case 83: + /*! Production:: regex_base : any_group_regex */ + case 87: + /*! Production:: regex_base : string */ + case 88: + /*! Production:: regex_base : escape_char */ + case 89: + /*! Production:: name_expansion : NAME_BRACE */ + case 93: + /*! Production:: regex_set : regex_set_atom */ + case 94: + /*! Production:: regex_set_atom : REGEX_SET */ + case 99: + /*! Production:: string : CHARACTER_LIT */ + + // 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,-,-) + break; + + case 84: + /*! Production:: regex_base : "." */ + + // 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.$ = '.'; + break; + + case 85: + /*! Production:: regex_base : "^" */ + + // 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.$ = '^'; + break; + + case 86: + /*! Production:: regex_base : "$" */ + + // 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.$ = '$'; + break; + + case 90: + /*! Production:: any_group_regex : REGEX_SET_START regex_set REGEX_SET_END */ + + // 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 91: + /*! Production:: any_group_regex : REGEX_SET_START regex_set 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(_templateObject19, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 95: + /*! Production:: regex_set_atom : name_expansion */ + + // 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,-,-) + + + if (XRegExp._getUnicodeProperty(yyvstack[yysp].replace(/[{}]/g, '')) && yyvstack[yysp].toUpperCase() !== yyvstack[yysp]) { + // treat this as part of an XRegExp `\p{...}` Unicode 'General Category' Property cf. http://unicode.org/reports/tr18/#Categories + this.$ = yyvstack[yysp]; + } else { + this.$ = yyvstack[yysp]; + } + //yyparser.log("name expansion for: ", { name: $name_expansion, redux: $name_expansion.replace(/[{}]/g, ''), output: $$ }); + break; + + case 98: + /*! Production:: string : STRING_LIT */ + + // 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.$ = prepareString(yyvstack[yysp]); + break; + + case 100: + /*! Production:: options : OPTIONS option_list OPTIONS_END */ + + // 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.$ = null; + break; + + case 101: + /*! Production:: option_list : option option_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.$ = null; + break; + + case 103: + /*! Production:: option : NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp]] = true; + break; + + case 104: + /*! Production:: option : NAME "=" OPTION_STRING_VALUE */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = yyvstack[yysp]; + break; + + case 105: + /*! Production:: option : NAME "=" OPTION_VALUE */ + case 106: + /*! Production:: option : NAME "=" NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = parseValue(yyvstack[yysp]); + break; + + case 107: + /*! 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(_templateObject20, $option, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 108: + /*! Production:: option : 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(_templateObject21, yylexer.prettyPrintRange(yylstack[yysp]), yyvstack[yysp].errStr)); + break; + + case 109: + /*! Production:: extra_lexer_module_code : optional_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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS(_templateObject22, rv, yylexer.prettyPrintRange(yylstack[yysp]))); + } + this.$ = yyvstack[yysp]; + break; + + case 110: + /*! Production:: extra_lexer_module_code : extra_lexer_module_code include_macro_code optional_module_code_chunk */ + + // 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,-,-) + + + // Each of the 3 chunks should be parse-able as a JS snippet on its own. + // + // Note: we have already checked the first section in a previous reduction + // of this rule, so we don't need to check that one again! + var rv = checkActionBlock(yyvstack[yysp - 1], yylstack[yysp - 1]); + if (rv) { + yyparser.yyError(rmCommonWS(_templateObject23, rv, yylexer.prettyPrintRange(yylstack[yysp - 1]))); + } + rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS(_templateObject22, rv, yylexer.prettyPrintRange(yylstack[yysp]))); + } + this.$ = yyvstack[yysp - 2] + yyvstack[yysp - 1] + yyvstack[yysp]; + break; + + case 111: + /*! 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' }); + // 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 112: + /*! 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(_templateObject24, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1]), yyvstack[yysp].errStr)); + break; + + case 115: + /*! Production:: module_code_chunk : error CODE */ + + // 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(_templateObject25, yylexer.prettyPrintRange(yylstack[yysp - 1]), yyvstack[yysp - 1].errStr)); + break; + + case 151: + // === 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([13, 1, 12, 15, 1, 1, 11, 19, 21, 2, 2, s, [11, 3], 4, 4, 12, 4, 1, 1, 19, 18, 11, 12, 18, 29, 30, 22, 22, 17, 17, s, [29, 7], 31, 5, s, [29, 3], s, [12, 4], 4, 11, 3, 3, 2, 2, 1, 1, 12, 1, 5, 4, 3, 7, 17, 23, 3, 19, 30, 29, 30, s, [29, 5], 3, 20, 3, 30, 30, 6, s, [4, 3], 12, 12, s, [11, 6], s, [27, 3], s, [11, 8], 2, 11, 1, 4, c, [55, 3], 3, 3, 17, 16, 3, 3, 1, 3, 7, s, [29, 3], 21, s, [29, 4], 4, 13, 13, s, [3, 4], 6, 3, 3, 23, s, [18, 3], 14, 14, 1, 14, 3, 1, 20, 2, 17, 14, 17, 3]), + symbol: u([1, 2, s, [19, 7, 1], 28, 47, 54, 56, 1, c, [14, 11], 57, c, [12, 11], 55, 58, 68, 84, s, [1, 3], c, [17, 10], 1, 2, 3, 5, 9, 10, s, [14, 4, 1], 19, 26, s, [38, 4, 1], 44, 46, 64, c, [15, 6], c, [14, 7], 72, s, [74, 5, 1], 81, 83, 27, 62, 27, 63, c, [55, 13], c, [11, 20], 2, 20, 26, 60, c, [4, 3], 59, 2, s, [29, 9, 1], 51, 69, 2, 20, 85, 86, s, [1, 3], c, [102, 16], 65, 70, c, [19, 17], 64, c, [85, 13], 9, c, [12, 9], c, [143, 12], c, [141, 6], c, [30, 3], c, [58, 6], s, [20, 7, 1], 28, c, [29, 6], 47, c, [29, 7], 7, s, [9, 9, 1], c, [33, 14], 45, 46, 47, 82, c, [58, 3], 11, c, [80, 11], 73, c, [81, 6], c, [22, 22], c, [121, 12], c, [17, 22], c, [108, 29], c, [29, 199], s, [42, 6, 1], 40, 43, 77, 79, 80, c, [123, 89], c, [19, 7], 27, c, [590, 11], c, [12, 27], c, [611, 3], 61, c, [630, 14], c, [3, 3], 28, 68, 28, 68, 28, 28, c, [634, 11], 88, 48, 2, 20, 48, 85, 86, 2, 18, 20, c, [9, 4], 1, 2, 51, 53, 87, 89, 90, c, [629, 17], 3, c, [750, 13], 67, c, [751, 8], 7, 20, 71, c, [691, 20], c, [632, 23], c, [662, 65], c, [526, 145], 2, 9, 11, c, [788, 15], c, [808, 7], 11, c, [201, 59], 82, 2, 40, 42, 43, 77, 80, c, [6, 4], c, [4, 8], c, [495, 33], c, [11, 59], 3, 4, c, [449, 8], c, [401, 15], c, [27, 54], c, [603, 11], c, [11, 78], 52, c, [182, 11], c, [683, 3], 49, 50, 1, 51, 88, 1, 53, 1, 51, 1, 51, c, [5, 3], 53, c, [647, 17], 2, 4, c, [691, 13], 66, 2, 28, 68, 2, 6, 8, 6, c, [4, 3], c, [740, 8], c, [648, 57], c, [531, 31], c, [528, 13], c, [756, 8], c, [668, 115], c, [568, 5], c, [321, 10], 53, c, [13, 13], c, [1004, 3], c, [3, 9], c, [273, 4], c, [272, 3], c, [328, 5], c, [310, 14], c, [1001, 9], 1, c, [496, 10], c, [27, 7], c, [18, 36], c, [1078, 14], c, [14, 14], 20, c, [15, 14], c, [461, 3], 53, c, [843, 20], c, [480, 3], c, [474, 16], c, [163, 14], c, [505, 18], 6, 8]), + type: u([s, [2, 11], 0, 0, 1, c, [14, 12], c, [26, 13], 0, c, [15, 12], s, [2, 20], c, [32, 14], s, [0, 8], c, [23, 3], c, [57, 32], c, [62, 9], c, [113, 13], c, [67, 4], c, [40, 20], c, [21, 18], c, [96, 36], c, [141, 7], c, [30, 28], c, [221, 43], c, [223, 9], c, [22, 34], c, [17, 34], s, [2, 224], c, [239, 141], c, [139, 19], c, [673, 16], c, [14, 5], c, [180, 13], c, [764, 35], c, [751, 9], c, [98, 19], c, [632, 31], c, [662, 75], c, [511, 151], c, [513, 34], c, [231, 35], c, [821, 238], c, [735, 74], c, [43, 27], c, [740, 39], c, [1202, 78], c, [756, 30], c, [696, 140], c, [1001, 31], c, [461, 114], c, [121, 58]]), + state: u([s, [1, 4, 1], 6, 11, 12, 20, 22, 23, 25, 26, 31, 32, 37, 36, 43, 45, 47, 51, 55, 56, 57, 61, 62, 64, 66, c, [16, 5], 67, c, [5, 4], 71, 73, 74, c, [13, 5], 75, c, [7, 6], 76, c, [5, 4], 77, c, [5, 4], 81, 78, 79, 84, 88, 89, 98, 103, 57, 105, 108, 107, 110, 112, c, [67, 7], 113, 61, 62, 117, c, [60, 11], c, [6, 6], 71, 81, 125, 132, 135, 137, 143, 108, 107, c, [15, 5], 145, c, [32, 5], 108, 146, 148, c, [52, 8], 132, c, [23, 5]]), + mode: u([s, [2, 23], s, [1, 12], c, [24, 13], c, [41, 28], c, [44, 15], c, [89, 27], c, [17, 13], c, [88, 11], c, [64, 34], c, [38, 14], c, [123, 15], c, [92, 12], 1, c, [107, 10], c, [27, 6], c, [72, 23], c, [40, 8], c, [45, 7], c, [15, 13], s, [1, 24], s, [2, 234], c, [236, 98], c, [97, 24], c, [24, 15], c, [374, 20], c, [432, 5], c, [409, 15], c, [585, 9], c, [47, 20], c, [45, 25], c, [36, 14], c, [578, 18], c, [602, 53], c, [459, 145], c, [735, 19], c, [797, 33], c, [29, 25], c, [776, 238], c, [813, 51], c, [289, 5], c, [648, 7], c, [298, 21], c, [738, 18], c, [621, 8], c, [376, 7], c, [651, 22], c, [874, 59], c, [1219, 170], c, [960, 9], c, [947, 23], c, [1151, 89], c, [805, 17], s, [2, 53]]), + goto: u([s, [9, 11], s, [11, 11], 8, 5, s, [7, 4, 1], s, [13, 7, 1], s, [10, 11], 34, 21, s, [34, 16], 24, 27, 29, 33, 34, 35, 40, 28, 30, 38, 39, 42, 41, 44, 46, s, [15, 11], s, [16, 11], s, [17, 11], 48, 49, 50, 52, 53, s, [54, 12], 59, 58, 1, 2, 7, 58, 63, s, [58, 6], 60, s, [58, 7], s, [34, 17], s, [12, 11], 61, 61, 65, s, [61, 9], c, [125, 12], s, [69, 3], c, [15, 5], s, [69, 7], 40, 69, c, [23, 7], 71, 71, c, [3, 3], 71, 68, 70, s, [71, 18], 72, 71, 71, 65, 65, 27, 65, c, [68, 11], c, [15, 15], c, [95, 12], c, [12, 12], s, [81, 29], s, [83, 29], s, [84, 29], s, [85, 29], s, [86, 29], s, [87, 29], s, [88, 29], s, [89, 31], 38, 80, s, [98, 29], s, [99, 29], s, [96, 29], s, [13, 9], 82, 13, 13, s, [29, 12], s, [14, 9], 83, 14, 14, s, [31, 12], 85, 86, 87, s, [20, 11], s, [25, 3], s, [26, 3], 16, 16, 23, 24, 100, s, [90, 8, 1], 99, 101, 102, 59, 58, 102, 103, 104, 103, 103, s, [108, 3], 117, 106, 117, 109, s, [33, 17], 111, c, [684, 13], 114, 115, 6, c, [630, 8], 116, s, [58, 7], s, [67, 3], c, [34, 5], s, [67, 7], 40, 67, c, [42, 6], 67, s, [68, 3], c, [24, 5], s, [68, 7], 40, 68, c, [24, 6], 68, 70, 70, 69, s, [70, 3], c, [7, 3], s, [70, 17], 72, 70, 70, s, [76, 29], s, [77, 29], s, [78, 29], s, [82, 29], s, [97, 29], 119, 120, 118, 64, 64, 27, 64, c, [259, 11], 122, 120, 121, 79, 79, 69, s, [79, 3], 68, 70, s, [79, 18], 72, 79, 79, 80, 80, 69, s, [80, 3], 68, 70, s, [80, 18], 72, 80, 80, 124, 38, 123, 80, s, [93, 4], s, [94, 4], s, [95, 4], s, [30, 12], s, [32, 12], s, [18, 11], s, [19, 11], s, [27, 11], s, [28, 11], s, [21, 11], s, [22, 11], s, [43, 27], s, [44, 27], s, [45, 27], s, [46, 11], s, [47, 11], s, [48, 11], s, [49, 11], s, [50, 11], s, [51, 11], s, [52, 11], s, [53, 11], 127, 126, s, [100, 11], 101, 131, 130, 128, 129, 3, 101, 5, 133, 109, 109, 116, 116, 134, s, [113, 3], s, [35, 17], 136, s, [40, 14], 138, 16, 140, 139, 141, 142, s, [59, 3], 117, 144, 117, 109, s, [66, 3], c, [627, 5], s, [66, 7], 40, 66, c, [434, 6], 66, s, [72, 29], s, [74, 29], 63, 63, 27, 63, c, [508, 11], s, [73, 29], s, [75, 29], s, [90, 29], s, [91, 29], s, [92, 4], s, [111, 13], s, [112, 13], s, [104, 3], s, [105, 3], s, [106, 3], s, [107, 3], c, [259, 4], s, [115, 3], s, [114, 3], 147, c, [949, 13], 38, 38, 149, s, [38, 15], s, [41, 18], s, [42, 18], s, [55, 14], s, [56, 14], 150, s, [57, 14], 4, 101, 133, 62, 62, 27, 62, c, [115, 11], 110, 110, s, [36, 17], s, [39, 14], s, [37, 17], s, [60, 3]]) + }), + defaultActions: bda({ + idx: u([0, 2, 6, 11, 12, 13, 16, 18, 19, 21, 22, s, [31, 8, 1], 40, 41, s, [42, 4, 2], 49, 50, 53, 54, 59, 61, s, [68, 5, 1], s, [79, 22, 1], 102, 103, 107, 109, 110, 115, 118, 119, s, [121, 11, 1], 133, 134, s, [137, 4, 1], 142, s, [146, 5, 1]]), + goto: u([9, 11, 10, 15, 16, 17, 54, 1, 2, 34, 12, 81, s, [83, 7, 1], 98, 99, 96, 29, 31, 20, 25, 26, 23, 24, 108, 33, 76, 77, 78, 82, 97, 93, 94, 95, 30, 32, 18, 19, 27, 28, 21, 22, s, [43, 11, 1], 100, 101, 109, 113, 35, 59, 72, 74, 73, 75, 90, 91, 92, 111, 112, s, [104, 4, 1], 115, 114, 41, 42, 55, 56, 57, 110, 36, 39, 37, 60]) + }), + 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 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, 151 /* === 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 === 'undefined' ? 'undefined' : _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 === 'undefined' ? 'undefined' : _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 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 + + var 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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 rmCommonWS = helpers.rmCommonWS; +var checkActionBlock = helpers.checkActionBlock; + +function encodeRE(s) { + return s.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1').replace(/\\\\u([a-fA-F0-9]{4})/g, '\\u$1'); +} + +function prepareString(s) { + // unescape slashes + s = s.replace(/\\\\/g, "\\"); + s = encodeRE(s); + return s; +} + +// 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); +}; + +parser.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse:', arguments); +}; + +parser.yy.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse YY:', arguments); +}; + +parser.yy.post_lex = function p_lex() { + if (parser.yydebug) parser.log('post_lex:', 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 === 'undefined' ? 'undefined' : _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 <> tokens and perform user action code for a <> 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 CONTEXT = 3; + var CONTEXT_TAIL = 1; + var 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; + switch (yyrulenumber) { + case 0: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %\{ */ + yy.depth = 0; + + yy.include_command_allowed = false; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 1: + /*! Conditions:: action */ + /*! Rule:: %\{([^]*?)%\} */ + yy_.yytext = this.matches[1].replace(/%\\\}/g, '%}'); // unescape any literal '%\}' that exists within the action code block + + yy.include_command_allowed = true; + return 32; + break; + + case 2: + /*! Conditions:: action */ + /*! Rule:: %include\b */ + if (yy.include_command_allowed) { + // This is an include instruction in place of an action: + // + // - one %include per action chunk + // - one %include replaces an entire action chunk + this.pushState('path'); + + return 51; + } else { + // TODO + yy_.yyerror('oops!'); + + return 37; + } + + break; + + case 3: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + //yy.include_command_allowed = false; -- doesn't impact include-allowed state + return 34; + + break; + + case 4: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\/.* */ + yy.include_command_allowed = false; + + return 35; + break; + + case 6: + /*! Conditions:: action */ + /*! Rule:: \| */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 7: + /*! Conditions:: action */ + /*! Rule:: %% */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 9: + /*! Conditions:: action */ + /*! Rule:: \/[^\s/]*?(?:['"`{}][^\s/]*?)*\/ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 10: + /*! Conditions:: action */ + /*! Rule:: \/[^}{BR}]* */ + yy.include_command_allowed = false; + + return 33; + break; + + case 11: + /*! Conditions:: action */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy.include_command_allowed = false; + + return 33; + break; + + case 12: + /*! Conditions:: action */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy.include_command_allowed = false; + + return 33; + break; + + case 13: + /*! Conditions:: action */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy.include_command_allowed = false; + + return 33; + break; + + case 14: + /*! Conditions:: action */ + /*! Rule:: [^{}/"'`|%\{\}{BR}{WS}]+ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 15: + /*! Conditions:: action */ + /*! Rule:: \{ */ + yy.depth++; + + yy.include_command_allowed = false; + return 33; + break; + + case 16: + /*! Conditions:: action */ + /*! Rule:: \} */ + yy.include_command_allowed = false; + + if (yy.depth <= 0) { + yy_.yyerror(rmCommonWS(_templateObject26) + this.prettyPrintRange(yy_.yylloc)); + + return 30; + } else { + yy.depth--; + } + + return 33; + break; + + case 17: + /*! Conditions:: action */ + /*! Rule:: (?:{BR}{WS}+)+(?=[^{WS}{BR}|]) */ + yy.include_command_allowed = true; + + return 36; // keep empty lines as-is inside action code blocks. + break; + + case 18: + /*! Conditions:: action */ + /*! Rule:: {BR} */ + if (yy.depth > 0) { + yy.include_command_allowed = true; + return 36; // keep empty lines as-is inside action code blocks. + } else { + // end of action code chunk + this.popState(); + + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } + + break; + + case 19: + /*! Conditions:: action */ + /*! Rule:: $ */ + yy.include_command_allowed = false; + + if (yy.depth !== 0) { + yy_.yyerror(rmCommonWS(_templateObject27, yy.depth) + this.prettyPrintRange(yy_.yylloc)); + + yy_.yytext = ''; + return 29; + } + + this.popState(); + yy_.yytext = ''; + return 31; + break; + + case 21: + /*! Conditions:: conditions */ + /*! Rule:: > */ + this.popState(); + + return 6; + break; + + case 24: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 25: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 26: + /*! Conditions:: rules */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 27: + /*! Conditions:: rules */ + /*! Rule:: {WS}+{BR}+ */ + /* empty */ + break; + + case 28: + /*! Conditions:: rules */ + /*! Rule:: \/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 29: + /*! Conditions:: rules */ + /*! Rule:: \/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 30: + /*! Conditions:: rules */ + /*! Rule:: {WS}+(?=[^{WS}{BR}|%]) */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + return 28; + break; + + case 31: + /*! Conditions:: rules */ + /*! Rule:: %% */ + this.popState(); + + this.pushState('code'); + return 19; + break; + + case 32: + /*! Conditions:: rules */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 35: + /*! Conditions:: options */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 49; // value is always a string type + break; + + case 36: + /*! Conditions:: options */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 49; // value is always a string type + break; + + case 37: + /*! Conditions:: options */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy_.yytext = unescQuote(this.matches[1], /\\`/g); + + return 49; // value is always a string type + break; + + case 39: + /*! Conditions:: options */ + /*! Rule:: {BR}{WS}+(?=\S) */ + /* skip leading whitespace on the next line of input, when followed by more options */ + break; + + case 40: + /*! Conditions:: options */ + /*! Rule:: {BR} */ + this.popState(); + + return 48; + break; + + case 41: + /*! Conditions:: options */ + /*! Rule:: {WS}+ */ + /* skip whitespace */ + break; + + case 43: + /*! Conditions:: start_condition */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 44: + /*! Conditions:: start_condition */ + /*! Rule:: {WS}+ */ + /* empty */ + break; + + case 46: + /*! Conditions:: INITIAL */ + /*! Rule:: {ID} */ + this.pushState('macro'); + + return 20; + break; + + case 47: + /*! Conditions:: macro named_chunk */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 48: + /*! Conditions:: macro */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 49: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 50: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \s+ */ + /* empty */ + break; + + case 51: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 26; + break; + + case 52: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 26; + break; + + case 53: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \[ */ + this.pushState('set'); + + return 41; + break; + + case 66: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: < */ + this.pushState('conditions'); + + return 5; + break; + + case 67: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/! */ + return 39; // treated as `(?!atom)` + + break; + + case 68: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/ */ + return 14; // treated as `(?=atom)` + + break; + + case 70: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\. */ + yy_.yytext = yy_.yytext.replace(/^\\/g, ''); + + return 44; + break; + + case 73: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %options\b */ + this.pushState('options'); + + return 47; + break; + + case 74: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %s\b */ + this.pushState('start_condition'); + + return 21; + break; + + case 75: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %x\b */ + this.pushState('start_condition'); + + return 22; + break; + + case 76: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %code\b */ + this.pushState('named_chunk'); + + return 25; + break; + + case 77: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %import\b */ + this.pushState('named_chunk'); + + return 24; + break; + + case 78: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %include\b */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 79: + /*! Conditions:: code */ + /*! Rule:: %include\b */ + this.pushState('path'); + + return 51; + break; + + case 80: + /*! Conditions:: INITIAL rules code */ + /*! Rule:: %{NAME}([^\r\n]*) */ + /* ignore unrecognized decl */ + this.warn(rmCommonWS(_templateObject28, dquote(yy_.yytext), dquote(this.topState())) + this.prettyPrintRange(yy_.yylloc)); + + yy_.yytext = [this.matches[1], // {NAME} + this.matches[2].trim() // optional value/parameters + ]; + + return 23; + break; + + case 81: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %% */ + this.pushState('rules'); + + return 19; + break; + + case 89: + /*! Conditions:: set */ + /*! Rule:: \] */ + this.popState(); + + return 42; + break; + + case 91: + /*! Conditions:: code */ + /*! Rule:: [^\r\n]+ */ + return 53; // the bit of CODE just before EOF... + + break; + + case 92: + /*! Conditions:: path */ + /*! Rule:: {BR} */ + this.popState(); + + this.unput(yy_.yytext); + break; + + case 93: + /*! Conditions:: path */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 94: + /*! Conditions:: path */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 95: + /*! Conditions:: path */ + /*! Rule:: {WS}+ */ + // skip whitespace in the line + break; + + case 96: + /*! Conditions:: path */ + /*! Rule:: [^\s\r\n]+ */ + this.popState(); + + return 52; + break; + + case 97: + /*! Conditions:: action */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS(_templateObject29) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 98: + /*! Conditions:: action */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS(_templateObject29) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 99: + /*! Conditions:: action */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS(_templateObject29) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 100: + /*! Conditions:: options */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS(_templateObject30) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 101: + /*! Conditions:: options */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS(_templateObject30) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 102: + /*! Conditions:: options */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS(_templateObject30) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 103: + /*! Conditions:: * */ + /*! Rule:: " */ + var rules = this.topState() === 'macro' ? 'macro\'s' : this.topState(); + + yy_.yyerror(rmCommonWS(_templateObject31, rules) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 104: + /*! Conditions:: * */ + /*! Rule:: ' */ + var rules = this.topState() === 'macro' ? 'macro\'s' : this.topState(); + + yy_.yyerror(rmCommonWS(_templateObject31, rules) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 105: + /*! Conditions:: * */ + /*! Rule:: ` */ + var rules = this.topState() === 'macro' ? 'macro\'s' : this.topState(); + + yy_.yyerror(rmCommonWS(_templateObject31, rules) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 106: + /*! Conditions:: macro rules */ + /*! Rule:: . */ + /* b0rk on bad characters */ + var rules = this.topState() === 'macro' ? 'macro\'s' : this.topState(); + + yy_.yyerror(rmCommonWS(_templateObject32, rules, rules) + this.prettyPrintRange(yy_.yylloc)); + + break; + + case 107: + /*! Conditions:: * */ + /*! Rule:: . */ + yy_.yyerror(rmCommonWS(_templateObject33, dquote(yy_.yytext), dquote(this.topState())) + this.prettyPrintRange(yy_.yylloc)); + + break; + + default: + return this.simpleCaseActionClusters[yyrulenumber]; + } + }, + + simpleCaseActionClusters: { + /*! Conditions:: action */ + /*! Rule:: {WS}+ */ + 5: 36, + + /*! Conditions:: action */ + /*! Rule:: % */ + 8: 33, + + /*! Conditions:: conditions */ + /*! Rule:: {NAME} */ + 20: 20, + + /*! Conditions:: conditions */ + /*! Rule:: , */ + 22: 8, + + /*! Conditions:: conditions */ + /*! Rule:: \* */ + 23: 7, + + /*! Conditions:: options */ + /*! Rule:: {NAME} */ + 33: 20, + + /*! Conditions:: options */ + /*! Rule:: = */ + 34: 18, + + /*! Conditions:: options */ + /*! Rule:: [^\s\r\n]+ */ + 38: 50, + + /*! Conditions:: start_condition */ + /*! Rule:: {ID} */ + 42: 27, + + /*! Conditions:: named_chunk */ + /*! Rule:: {ID} */ + 45: 20, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \| */ + 54: 9, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?: */ + 55: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?= */ + 56: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?! */ + 57: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \( */ + 58: 10, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \) */ + 59: 11, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \+ */ + 60: 12, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \* */ + 61: 7, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \? */ + 62: 13, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \^ */ + 63: 16, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: , */ + 64: 8, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: <> */ + 65: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\([0-7]{1,3}|[rfntvsSbBwWdD\\*+()${}|[\]\/.^?]|c[A-Z]|x[0-9A-F]{2}|u[a-fA-F0-9]{4}) */ + 69: 44, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \$ */ + 71: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \. */ + 72: 15, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{\d+(,\s*\d+|,)?\} */ + 82: 45, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{{ID}\} */ + 83: 40, + + /*! Conditions:: set options */ + /*! Rule:: \{{ID}\} */ + 84: 40, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{ */ + 85: 3, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \} */ + 86: 4, + + /*! Conditions:: set */ + /*! Rule:: (?:\\\\|\\\]|[^\]{])+ */ + 87: 43, + + /*! Conditions:: set */ + /*! Rule:: \{ */ + 88: 43, + + /*! Conditions:: code */ + /*! Rule:: [^\r\n]*(\r|\n)+ */ + 90: 53, + + /*! Conditions:: * */ + /*! Rule:: $ */ + 108: 1 + }, + + rules: [ + /* 0: *//^(?:%\{)/, + /* 1: */new XRegExp('^(?:%\\{([^]*?)%\\})', ''), + /* 2: *//^(?:%include\b)/, + /* 3: */new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 4: *//^(?:([^\S\n\r])*\/\/.*)/, + /* 5: *//^(?:([^\S\n\r])+)/, + /* 6: *//^(?:\|)/, + /* 7: *//^(?:%%)/, + /* 8: *//^(?:%)/, + /* 9: *//^(?:\/[^\s\/]*?(?:['"`{}][^\s\/]*?)*\/)/, + /* 10: *//^(?:\/[^\n\r}]*)/, + /* 11: *//^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 12: *//^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 13: *//^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 14: *//^(?:[^\s"%'\/`{-}]+)/, + /* 15: *//^(?:\{)/, + /* 16: *//^(?:\})/, + /* 17: *//^(?:(?:(\r\n|\n|\r)([^\S\n\r])+)+(?=[^\s|]))/, + /* 18: *//^(?:(\r\n|\n|\r))/, + /* 19: *//^(?:$)/, + /* 20: */new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', ''), + /* 21: *//^(?:>)/, + /* 22: *//^(?:,)/, + /* 23: *//^(?:\*)/, + /* 24: *//^(?:([^\S\n\r])*\/\/[^\n\r]*)/, + /* 25: */new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 26: *//^(?:(\r\n|\n|\r)+)/, + /* 27: *//^(?:([^\S\n\r])+(\r\n|\n|\r)+)/, + /* 28: *//^(?:\/\/[^\r\n]*)/, + /* 29: */new XRegExp('^(?:\\/\\*[^]*?\\*\\/)', ''), + /* 30: *//^(?:([^\S\n\r])+(?=[^\s%|]))/, + /* 31: *//^(?:%%)/, + /* 32: *//^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 33: */new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', ''), + /* 34: *//^(?:=)/, + /* 35: *//^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 36: *//^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 37: *//^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 38: *//^(?:\S+)/, + /* 39: *//^(?:(\r\n|\n|\r)([^\S\n\r])+(?=\S))/, + /* 40: *//^(?:(\r\n|\n|\r))/, + /* 41: *//^(?:([^\S\n\r])+)/, + /* 42: */new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 43: *//^(?:(\r\n|\n|\r)+)/, + /* 44: *//^(?:([^\S\n\r])+)/, + /* 45: */new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 46: */new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 47: *//^(?:(\r\n|\n|\r)+)/, + /* 48: *//^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 49: *//^(?:(\r\n|\n|\r)+)/, + /* 50: *//^(?:\s+)/, + /* 51: *//^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 52: *//^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 53: *//^(?:\[)/, + /* 54: *//^(?:\|)/, + /* 55: *//^(?:\(\?:)/, + /* 56: *//^(?:\(\?=)/, + /* 57: *//^(?:\(\?!)/, + /* 58: *//^(?:\()/, + /* 59: *//^(?:\))/, + /* 60: *//^(?:\+)/, + /* 61: *//^(?:\*)/, + /* 62: *//^(?:\?)/, + /* 63: *//^(?:\^)/, + /* 64: *//^(?:,)/, + /* 65: *//^(?:<>)/, + /* 66: *//^(?:<)/, + /* 67: *//^(?:\/!)/, + /* 68: *//^(?:\/)/, + /* 69: *//^(?:\\([0-7]{1,3}|[$(-+.\/?BDSW\[-\^bdfnr-tvw{-}]|c[A-Z]|x[\dA-F]{2}|u[\dA-Fa-f]{4}))/, + /* 70: *//^(?:\\.)/, + /* 71: *//^(?:\$)/, + /* 72: *//^(?:\.)/, + /* 73: *//^(?:%options\b)/, + /* 74: *//^(?:%s\b)/, + /* 75: *//^(?:%x\b)/, + /* 76: *//^(?:%code\b)/, + /* 77: *//^(?:%import\b)/, + /* 78: *//^(?:%include\b)/, + /* 79: *//^(?:%include\b)/, + /* 80: */new XRegExp('^(?:%([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?)([^\\n\\r]*))', ''), + /* 81: *//^(?:%%)/, + /* 82: *//^(?:\{\d+(,\s*\d+|,)?\})/, + /* 83: */new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 84: */new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 85: *//^(?:\{)/, + /* 86: *//^(?:\})/, + /* 87: *//^(?:(?:\\\\|\\\]|[^\]{])+)/, + /* 88: *//^(?:\{)/, + /* 89: *//^(?:\])/, + /* 90: *//^(?:[^\r\n]*(\r|\n)+)/, + /* 91: *//^(?:[^\r\n]+)/, + /* 92: *//^(?:(\r\n|\n|\r))/, + /* 93: *//^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 94: *//^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 95: *//^(?:([^\S\n\r])+)/, + /* 96: *//^(?:\S+)/, + /* 97: *//^(?:")/, + /* 98: *//^(?:')/, + /* 99: *//^(?:`)/, + /* 100: *//^(?:")/, + /* 101: *//^(?:')/, + /* 102: *//^(?:`)/, + /* 103: *//^(?:")/, + /* 104: *//^(?:')/, + /* 105: *//^(?:`)/, + /* 106: *//^(?:.)/, + /* 107: *//^(?:.)/, + /* 108: *//^(?:$)/], + + conditions: { + 'rules': { + rules: [0, 26, 27, 28, 29, 30, 31, 32, 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, 74, 75, 76, 77, 78, 80, 81, 82, 83, 85, 86, 103, 104, 105, 106, 107, 108], + + inclusive: true + }, + + 'macro': { + rules: [0, 24, 25, 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, 74, 75, 76, 77, 78, 81, 82, 83, 85, 86, 103, 104, 105, 106, 107, 108], + + inclusive: true + }, + + 'named_chunk': { + rules: [0, 45, 47, 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, 74, 75, 76, 77, 78, 81, 82, 83, 85, 86, 103, 104, 105, 107, 108], + + inclusive: true + }, + + 'code': { + rules: [79, 80, 90, 91, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'start_condition': { + rules: [24, 25, 42, 43, 44, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'options': { + rules: [24, 25, 33, 34, 35, 36, 37, 38, 39, 40, 41, 84, 100, 101, 102, 103, 104, 105, 107, 108], + + inclusive: false + }, + + 'conditions': { + rules: [20, 21, 22, 23, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'action': { + rules: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 97, 98, 99, 103, 104, 105, 107, 108], + + inclusive: false + }, + + 'path': { + rules: [24, 25, 92, 93, 94, 95, 96, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'set': { + rules: [84, 87, 88, 89, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'INITIAL': { + rules: [0, 24, 25, 46, 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, 74, 75, 76, 77, 78, 80, 81, 82, 83, 85, 86, 103, 104, 105, 107, 108], + + inclusive: true + } + } + }; + + var rmCommonWS = helpers.rmCommonWS; + var dquote = helpers.dquote; + + 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); +} + +var lexParser = { + parser: parser, + Parser: Parser, + parse: yyparse + +}; + +module.exports = lexParser; diff --git a/dist/lex-parser-cjs.js b/dist/lex-parser-cjs.js new file mode 100644 index 0000000..bebaa22 --- /dev/null +++ b/dist/lex-parser-cjs.js @@ -0,0 +1,7963 @@ +'use strict'; + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var XRegExp = _interopDefault(require('@gerhobbelt/xregexp')); +var helpers = _interopDefault(require('jison-helpers-lib')); +var fs = _interopDefault(require('fs')); + +// 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. + * } + */ + + +// 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_: { + "$": 17, + "$accept": 0, + "$end": 1, + "%%": 19, + "(": 10, + ")": 11, + "*": 7, + "+": 12, + ",": 8, + ".": 15, + "/": 14, + "/!": 39, + "<": 5, + "=": 18, + ">": 6, + "?": 13, + "ACTION": 32, + "ACTION_BODY": 33, + "ACTION_BODY_CPP_COMMENT": 35, + "ACTION_BODY_C_COMMENT": 34, + "ACTION_BODY_WHITESPACE": 36, + "ACTION_END": 31, + "ACTION_START": 28, + "BRACKET_MISSING": 29, + "BRACKET_SURPLUS": 30, + "CHARACTER_LIT": 46, + "CODE": 53, + "EOF": 1, + "ESCAPE_CHAR": 44, + "IMPORT": 24, + "INCLUDE": 51, + "INCLUDE_PLACEMENT_ERROR": 37, + "INIT_CODE": 25, + "NAME": 20, + "NAME_BRACE": 40, + "OPTIONS": 47, + "OPTIONS_END": 48, + "OPTION_STRING_VALUE": 49, + "OPTION_VALUE": 50, + "PATH": 52, + "RANGE_REGEX": 45, + "REGEX_SET": 43, + "REGEX_SET_END": 42, + "REGEX_SET_START": 41, + "SPECIAL_GROUP": 38, + "START_COND": 27, + "START_EXC": 22, + "START_INC": 21, + "STRING_LIT": 26, + "UNKNOWN_DECL": 23, + "^": 16, + "action": 68, + "action_body": 69, + "any_group_regex": 78, + "definition": 58, + "definitions": 57, + "error": 2, + "escape_char": 81, + "extra_lexer_module_code": 87, + "import_name": 60, + "import_path": 61, + "include_macro_code": 88, + "init": 56, + "init_code_name": 59, + "lex": 54, + "module_code_chunk": 89, + "name_expansion": 77, + "name_list": 71, + "names_exclusive": 63, + "names_inclusive": 62, + "nonempty_regex_list": 74, + "option": 86, + "option_list": 85, + "optional_module_code_chunk": 90, + "options": 84, + "range_regex": 82, + "regex": 72, + "regex_base": 76, + "regex_concat": 75, + "regex_list": 73, + "regex_set": 79, + "regex_set_atom": 80, + "rule": 67, + "rule_block": 66, + "rules": 64, + "rules_and_epilogue": 55, + "rules_collective": 65, + "start_conditions": 70, + "string": 83, + "{": 3, + "|": 9, + "}": 4 +}, +terminals_: { + 1: "EOF", + 2: "error", + 3: "{", + 4: "}", + 5: "<", + 6: ">", + 7: "*", + 8: ",", + 9: "|", + 10: "(", + 11: ")", + 12: "+", + 13: "?", + 14: "/", + 15: ".", + 16: "^", + 17: "$", + 18: "=", + 19: "%%", + 20: "NAME", + 21: "START_INC", + 22: "START_EXC", + 23: "UNKNOWN_DECL", + 24: "IMPORT", + 25: "INIT_CODE", + 26: "STRING_LIT", + 27: "START_COND", + 28: "ACTION_START", + 29: "BRACKET_MISSING", + 30: "BRACKET_SURPLUS", + 31: "ACTION_END", + 32: "ACTION", + 33: "ACTION_BODY", + 34: "ACTION_BODY_C_COMMENT", + 35: "ACTION_BODY_CPP_COMMENT", + 36: "ACTION_BODY_WHITESPACE", + 37: "INCLUDE_PLACEMENT_ERROR", + 38: "SPECIAL_GROUP", + 39: "/!", + 40: "NAME_BRACE", + 41: "REGEX_SET_START", + 42: "REGEX_SET_END", + 43: "REGEX_SET", + 44: "ESCAPE_CHAR", + 45: "RANGE_REGEX", + 46: "CHARACTER_LIT", + 47: "OPTIONS", + 48: "OPTIONS_END", + 49: "OPTION_STRING_VALUE", + 50: "OPTION_VALUE", + 51: "INCLUDE", + 52: "PATH", + 53: "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([ + 54, + 54, + s, + [55, 6], + 56, + 57, + 57, + s, + [58, 11], + 59, + 59, + 60, + 60, + 61, + 61, + 62, + 62, + 63, + 63, + 64, + 64, + s, + [65, 4], + 66, + 66, + 67, + 67, + s, + [68, 3], + s, + [69, 9], + s, + [70, 4], + 71, + 71, + 72, + s, + [73, 4], + s, + [74, 4], + 75, + 75, + s, + [76, 17], + 77, + 78, + 78, + 79, + 79, + 80, + s, + [80, 4, 1], + 83, + 84, + 85, + 85, + s, + [86, 6], + 87, + 87, + 88, + 88, + s, + [89, 3], + 90, + 90 +]), + rule: u([ + s, + [4, 3], + s, + [5, 4, -1], + 0, + 0, + 2, + 0, + s, + [2, 3], + s, + [1, 3], + 3, + 3, + 2, + 3, + 3, + s, + [1, 7], + 2, + 1, + 2, + c, + [23, 3], + 4, + c, + [32, 4], + 2, + c, + [22, 3], + 3, + s, + [2, 8], + 0, + s, + [3, 3], + 0, + 1, + 3, + 1, + s, + [3, 4, -1], + c, + [21, 3], + c, + [40, 3], + s, + [3, 4], + s, + [2, 5], + c, + [12, 3], + s, + [1, 6], + c, + [16, 3], + c, + [10, 8], + c, + [9, 3], + s, + [3, 4], + c, + [10, 4], + c, + [82, 4], + 1, + 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 : lex $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:: lex : init definitions rules_and_epilogue EOF */ + + // 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 - 1]; + this.$.macros = yyvstack[yysp - 2].macros; + this.$.startConditions = yyvstack[yysp - 2].startConditions; + this.$.unknownDecls = yyvstack[yysp - 2].unknownDecls; + + // if there are any options, add them all, otherwise set options to NULL: + // can't check for 'empty object' by `if (yy.options) ...` so we do it this way: + for (var k in yy.options) { + this.$.options = yy.options; + break; + } + + if (yy.actionInclude) { + var asrc = yy.actionInclude.join('\n\n'); + // Only a non-empty action code chunk should actually make it through: + if (asrc.trim() !== '') { + this.$.actionInclude = asrc; + } + } + + delete yy.options; + delete yy.actionInclude; + return this.$; + break; + +case 2: + /*! Production:: lex : init definitions error EOF */ + + // 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` + There's an error in your lexer regex rules or epilogue. + Maybe you did not correctly separate the lexer sections with a '%%' + on an otherwise empty line? + The lexer spec file should have this structure: + + definitions + %% + rules + %% // <-- optional! + extra_module_code // <-- optional epilogue! + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 3: + /*! Production:: rules_and_epilogue : "%%" rules "%%" extra_lexer_module_code */ + + // 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,-,-) + + + if (yyvstack[yysp].trim() !== '') { + this.$ = { rules: yyvstack[yysp - 2], moduleInclude: yyvstack[yysp] }; + } else { + this.$ = { rules: yyvstack[yysp - 2] }; + } + break; + +case 4: + /*! Production:: rules_and_epilogue : "%%" error rules "%%" extra_lexer_module_code */ + + // 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` + There's probably an error in one or more of your lexer regex rules. + The lexer rule spec should have this structure: + + regex action_code + + where 'regex' is a lex-style regex expression (see the + jison and jison-lex documentation) which is intended to match a chunk + of the input to lex, while the 'action_code' block is the JS code + which will be invoked when the regex is matched. The 'action_code' block + may be any (indented!) set of JS statements, optionally surrounded + by '{...}' curly braces or otherwise enclosed in a '%{...%}' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 3])} + + Technical error report: + ${yyvstack[yysp - 3].errStr} + `); + break; + +case 5: + /*! Production:: rules_and_epilogue : "%%" rules "%%" 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` + There's an error in your lexer epilogue a.k.a. 'extra_module_code' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 6: + /*! Production:: rules_and_epilogue : "%%" error rules */ + + // 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` + There's probably an error in one or more of your lexer regex rules. + The lexer rule spec should have this structure: + + regex action_code + + where 'regex' is a lex-style regex expression (see the + jison and jison-lex documentation) which is intended to match a chunk + of the input to lex, while the 'action_code' block is the JS code + which will be invoked when the regex is matched. The 'action_code' block + may be any (indented!) set of JS statements, optionally surrounded + by '{...}' curly braces or otherwise enclosed in a '%{...%}' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 7: + /*! Production:: rules_and_epilogue : "%%" rules */ + + // 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.$ = { rules: yyvstack[yysp] }; + break; + +case 8: + /*! Production:: rules_and_epilogue : %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.$ = { rules: [] }; + break; + +case 9: + /*! Production:: init : %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,-,-) + + + yy.actionInclude = []; + if (!yy.options) yy.options = {}; + break; + +case 10: + /*! Production:: definitions : definitions definition */ + + // 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] != null) { + if ('length' in yyvstack[yysp]) { + this.$.macros[yyvstack[yysp][0]] = yyvstack[yysp][1]; + } else if (yyvstack[yysp].type === 'names') { + for (var name in yyvstack[yysp].names) { + this.$.startConditions[name] = yyvstack[yysp].names[name]; + } + } else if (yyvstack[yysp].type === 'unknown') { + this.$.unknownDecls.push(yyvstack[yysp].body); + } + } + break; + +case 11: + /*! Production:: definitions : %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.$ = { + macros: {}, // { hash table } + startConditions: {}, // { hash table } + unknownDecls: [] // [ array of [key,value] pairs } + }; + break; + +case 12: + /*! Production:: definition : NAME regex */ + + // 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 13: + /*! Production:: definition : START_INC names_inclusive */ +case 14: + /*! Production:: definition : START_EXC names_exclusive */ + + // 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 15: + /*! Production:: definition : 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` + The '%{...%}' lexer setup action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + yy.actionInclude.push(yyvstack[yysp]); + this.$ = null; + break; + +case 16: + /*! Production:: definition : options */ +case 102: + /*! Production:: option_list : option */ + + // 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.$ = null; + break; + +case 17: + /*! Production:: definition : 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.$ = {type: 'unknown', body: yyvstack[yysp]}; + break; + +case 18: + /*! Production:: definition : 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.$ = {type: 'imports', name: yyvstack[yysp - 1], path: yyvstack[yysp]}; + break; + +case 19: + /*! Production:: definition : 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 20: + /*! Production:: definition : 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,-,-) + + + yyparser.yyError(rmCommonWS` + %import name or source filename missing maybe? + + Note: 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 21: + /*! Production:: definition : INIT_CODE init_code_name 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The '%code ${$init_code_name}' action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + } + this.$ = { + type: 'codesection', + qualifier: yyvstack[yysp - 1], + include: yyvstack[yysp] + }; + break; + +case 22: + /*! Production:: definition : INIT_CODE error action */ + + // 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2], yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 23: + /*! Production:: init_code_name : NAME */ +case 24: + /*! Production:: init_code_name : STRING_LIT */ +case 25: + /*! Production:: import_name : NAME */ +case 26: + /*! Production:: import_name : STRING_LIT */ +case 27: + /*! Production:: import_path : NAME */ +case 28: + /*! Production:: import_path : STRING_LIT */ +case 64: + /*! Production:: regex_list : regex_concat */ +case 69: + /*! Production:: nonempty_regex_list : regex_concat */ +case 71: + /*! Production:: regex_concat : regex_base */ +case 96: + /*! Production:: escape_char : ESCAPE_CHAR */ +case 97: + /*! Production:: range_regex : RANGE_REGEX */ +case 113: + /*! Production:: module_code_chunk : CODE */ +case 116: + /*! 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 29: + /*! Production:: names_inclusive : START_COND */ + + // 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.$ = {type: 'names', names: {}}; this.$.names[yyvstack[yysp]] = 0; + break; + +case 30: + /*! Production:: names_inclusive : names_inclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 0; + break; + +case 31: + /*! Production:: names_exclusive : START_COND */ + + // 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.$ = {type: 'names', names: {}}; this.$.names[yyvstack[yysp]] = 1; + break; + +case 32: + /*! Production:: names_exclusive : names_exclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 1; + break; + +case 33: + /*! Production:: rules : rules rules_collective */ + + // 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].concat(yyvstack[yysp]); + break; + +case 34: + /*! Production:: rules : %epsilon */ +case 40: + /*! Production:: rule_block : %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 35: + /*! Production:: rules_collective : start_conditions rule */ + + // 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,-,-) + + + if (yyvstack[yysp - 1]) { + yyvstack[yysp].unshift(yyvstack[yysp - 1]); + } + this.$ = [yyvstack[yysp]]; + break; + +case 36: + /*! Production:: rules_collective : start_conditions "{" rule_block "}" */ + + // 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,-,-) + + + if (yyvstack[yysp - 3]) { + yyvstack[yysp - 1].forEach(function (d) { + d.unshift(yyvstack[yysp - 3]); + }); + } + this.$ = yyvstack[yysp - 1]; + break; + +case 37: + /*! Production:: rules_collective : start_conditions "{" 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 made a mistake while specifying one of the lexer rules inside + the start condition + <${yyvstack[yysp - 3].join(',')}> { rules... } + block. + + Erroneous area: + ${yylexer.prettyPrintRange(yylexer.mergeLocationInfo((yysp - 3), (yysp)), yylstack[yysp - 3])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 38: + /*! Production:: rules_collective : start_conditions "{" 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 lexer rules set inside + the start condition + <${yyvstack[yysp - 2].join(',')}> { rules... } + as a terminating curly brace '}' could not be found. + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 39: + /*! Production:: rule_block : rule_block rule */ + + // 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 41: + /*! Production:: rule : regex 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The rule's action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = [yyvstack[yysp - 1], yyvstack[yysp]]; + break; + +case 42: + /*! Production:: rule : regex error */ + + // 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]]; + yyparser.yyError(rmCommonWS` + Lexer rule regex action code declaration error? + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 43: + /*! Production:: action : ACTION_START action_body BRACKET_MISSING */ + + // 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` + Missing curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: '{ ... }'. + + Offending action body: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + break; + +case 44: + /*! Production:: action : ACTION_START action_body BRACKET_SURPLUS */ + + // 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` + Too many curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: '{ ... }'. + + Offending action body: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + break; + +case 45: + /*! Production:: action : ACTION_START action_body ACTION_END */ + + // 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 s = yyvstack[yysp - 1].trim(); + // remove outermost set of braces UNLESS there's + // a curly brace in there anywhere: in that case + // we should leave it up to the sophisticated + // code analyzer to simplify the code! + // + // This is a very rough check as it will also look + // inside code comments, which should not have + // any influence. + // + // Nevertheless: this is a *safe* transform! + if (s[0] === '{' && s.indexOf('}') === s.length - 1) { + this.$ = s.substring(1, s.length - 1).trim(); + } else { + this.$ = s; + } + break; + +case 46: + /*! Production:: action_body : action_body ACTION */ +case 51: + /*! Production:: action_body : action_body 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] + '\n\n' + yyvstack[yysp] + '\n\n'; + break; + +case 47: + /*! Production:: action_body : action_body ACTION_BODY */ +case 48: + /*! Production:: action_body : action_body ACTION_BODY_C_COMMENT */ +case 49: + /*! Production:: action_body : action_body ACTION_BODY_CPP_COMMENT */ +case 50: + /*! Production:: action_body : action_body ACTION_BODY_WHITESPACE */ +case 70: + /*! Production:: regex_concat : regex_concat regex_base */ +case 82: + /*! Production:: regex_base : regex_base range_regex */ +case 92: + /*! Production:: regex_set : regex_set regex_set_atom */ +case 114: + /*! 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 52: + /*! Production:: action_body : action_body INCLUDE_PLACEMENT_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` + You may place the '%include' instruction only at the start/front of a line. + + It's use is not permitted at this position: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + `); + break; + +case 53: + /*! Production:: action_body : action_body 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` + Seems you did not correctly match curly braces '{ ... }' in a lexer rule action block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 54: + /*! Production:: action_body : %epsilon */ +case 65: + /*! Production:: regex_list : %epsilon */ +case 117: + /*! 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 55: + /*! Production:: start_conditions : "<" name_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 - 1]; + break; + +case 56: + /*! Production:: start_conditions : "<" name_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,-,-) + + + yyparser.yyError(rmCommonWS` + Seems you did not correctly terminate the start condition set <${yyvstack[yysp - 1].join(',')},???> with a terminating '>' + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 57: + /*! Production:: start_conditions : "<" "*" ">" */ + + // 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.$ = ['*']; + break; + +case 58: + /*! Production:: start_conditions : %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 59: + /*! Production:: name_list : 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]]; + break; + +case 60: + /*! Production:: name_list : name_list "," 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]; this.$.push(yyvstack[yysp]); + break; + +case 61: + /*! Production:: regex : nonempty_regex_list */ + + // 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,-,-) + + + // Detect if the regex ends with a pure (Unicode) word; + // we *do* consider escaped characters which are 'alphanumeric' + // to be equivalent to their non-escaped version, hence these are + // all valid 'words' for the 'easy keyword rules' option: + // + // - hello_kitty + // - γεια_σου_γατοÏλα + // - \u03B3\u03B5\u03B9\u03B1_\u03C3\u03BF\u03C5_\u03B3\u03B1\u03C4\u03BF\u03CD\u03BB\u03B1 + // + // http://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode#12869914 + // + // As we only check the *tail*, we also accept these as + // 'easy keywords': + // + // - %options + // - %foo-bar + // - +++a:b:c1 + // + // Note the dash in that last example: there the code will consider + // `bar` to be the keyword, which is fine with us as we're only + // interested in the trailing boundary and patching that one for + // the `easy_keyword_rules` option. + this.$ = yyvstack[yysp]; + if (yy.options.easy_keyword_rules) { + // We need to 'protect' `eval` here as keywords are allowed + // to contain double-quotes and other leading cruft. + // `eval` *does* gobble some escapes (such as `\b`) but + // we protect against that through a simple replace regex: + // we're not interested in the special escapes' exact value + // anyway. + // It will also catch escaped escapes (`\\`), which are not + // word characters either, so no need to worry about + // `eval(str)` 'correctly' converting convoluted constructs + // like '\\\\\\\\\\b' in here. + this.$ = this.$ + .replace(/\\\\/g, '.') + .replace(/"/g, '.') + .replace(/\\c[A-Z]/g, '.') + .replace(/\\[^xu0-9]/g, '.'); + + try { + // Convert Unicode escapes and other escapes to their literal characters + // BEFORE we go and check whether this item is subject to the + // `easy_keyword_rules` option. + this.$ = JSON.parse('"' + this.$ + '"'); + } + catch (ex) { + yyparser.warn('easy-keyword-rule FAIL on eval: ', ex); + + // make the next keyword test fail: + this.$ = '.'; + } + // a 'keyword' starts with an alphanumeric character, + // followed by zero or more alphanumerics or digits: + var re = new XRegExp('\\w[\\w\\d]*$'); + if (XRegExp.match(this.$, re)) { + this.$ = yyvstack[yysp] + "\\b"; + } else { + this.$ = yyvstack[yysp]; + } + } + break; + +case 62: + /*! Production:: regex_list : regex_list "|" regex_concat */ +case 66: + /*! Production:: nonempty_regex_list : nonempty_regex_list "|" regex_concat */ + + // 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 63: + /*! Production:: regex_list : regex_list "|" */ +case 67: + /*! Production:: nonempty_regex_list : nonempty_regex_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] + '|'; + break; + +case 68: + /*! Production:: nonempty_regex_list : "|" regex_concat */ + + // 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 72: + /*! Production:: regex_base : "(" regex_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 - 1] + ')'; + break; + +case 73: + /*! Production:: regex_base : SPECIAL_GROUP regex_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 74: + /*! Production:: regex_base : "(" regex_list error */ +case 75: + /*! Production:: regex_base : SPECIAL_GROUP regex_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,-,-) + + + yyparser.yyError(rmCommonWS` + Seems you did not correctly bracket a lex rule regex part in '(...)' braces. + + Unterminated regex part: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 76: + /*! Production:: regex_base : regex_base "+" */ + + // 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] + '+'; + break; + +case 77: + /*! Production:: regex_base : regex_base "*" */ + + // 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] + '*'; + break; + +case 78: + /*! Production:: regex_base : regex_base "?" */ + + // 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] + '?'; + break; + +case 79: + /*! Production:: regex_base : "/" regex_base */ + + // 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 80: + /*! Production:: regex_base : "/!" regex_base */ + + // 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 81: + /*! Production:: regex_base : name_expansion */ +case 83: + /*! Production:: regex_base : any_group_regex */ +case 87: + /*! Production:: regex_base : string */ +case 88: + /*! Production:: regex_base : escape_char */ +case 89: + /*! Production:: name_expansion : NAME_BRACE */ +case 93: + /*! Production:: regex_set : regex_set_atom */ +case 94: + /*! Production:: regex_set_atom : REGEX_SET */ +case 99: + /*! Production:: string : CHARACTER_LIT */ + + // 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,-,-) + break; + +case 84: + /*! Production:: regex_base : "." */ + + // 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.$ = '.'; + break; + +case 85: + /*! Production:: regex_base : "^" */ + + // 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.$ = '^'; + break; + +case 86: + /*! Production:: regex_base : "$" */ + + // 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.$ = '$'; + break; + +case 90: + /*! Production:: any_group_regex : REGEX_SET_START regex_set REGEX_SET_END */ + + // 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 91: + /*! Production:: any_group_regex : REGEX_SET_START regex_set 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 lex rule regex set in '[...]' brackets. + + Unterminated regex set: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 95: + /*! Production:: regex_set_atom : name_expansion */ + + // 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,-,-) + + + if (XRegExp._getUnicodeProperty(yyvstack[yysp].replace(/[{}]/g, '')) + && yyvstack[yysp].toUpperCase() !== yyvstack[yysp] + ) { + // treat this as part of an XRegExp `\p{...}` Unicode 'General Category' Property cf. http://unicode.org/reports/tr18/#Categories + this.$ = yyvstack[yysp]; + } else { + this.$ = yyvstack[yysp]; + } + //yyparser.log("name expansion for: ", { name: $name_expansion, redux: $name_expansion.replace(/[{}]/g, ''), output: $$ }); + break; + +case 98: + /*! Production:: string : STRING_LIT */ + + // 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.$ = prepareString(yyvstack[yysp]); + break; + +case 100: + /*! Production:: options : OPTIONS option_list OPTIONS_END */ + + // 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.$ = null; + break; + +case 101: + /*! Production:: option_list : option option_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.$ = null; + break; + +case 103: + /*! Production:: option : NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp]] = true; + break; + +case 104: + /*! Production:: option : NAME "=" OPTION_STRING_VALUE */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = yyvstack[yysp]; + break; + +case 105: + /*! Production:: option : NAME "=" OPTION_VALUE */ +case 106: + /*! Production:: option : NAME "=" NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = parseValue(yyvstack[yysp]); + break; + +case 107: + /*! 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` + Internal error: option "${$option}" value assignment failure. + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 108: + /*! Production:: option : 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` + Expected a valid option name (with optional value assignment). + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 109: + /*! Production:: extra_lexer_module_code : optional_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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = yyvstack[yysp]; + break; + +case 110: + /*! Production:: extra_lexer_module_code : extra_lexer_module_code include_macro_code optional_module_code_chunk */ + + // 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,-,-) + + + // Each of the 3 chunks should be parse-able as a JS snippet on its own. + // + // Note: we have already checked the first section in a previous reduction + // of this rule, so we don't need to check that one again! + var rv = checkActionBlock(yyvstack[yysp - 1], yylstack[yysp - 1]); + if (rv) { + yyparser.yyError(rmCommonWS` + The source code %include-d into the extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + `); + } + rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = yyvstack[yysp - 2] + yyvstack[yysp - 1] + yyvstack[yysp]; + break; + +case 111: + /*! 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' }); + // 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 112: + /*! 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])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 115: + /*! Production:: module_code_chunk : error CODE */ + + // 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` + Module code declaration error? + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 151: // === 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([ + 13, + 1, + 12, + 15, + 1, + 1, + 11, + 19, + 21, + 2, + 2, + s, + [11, 3], + 4, + 4, + 12, + 4, + 1, + 1, + 19, + 18, + 11, + 12, + 18, + 29, + 30, + 22, + 22, + 17, + 17, + s, + [29, 7], + 31, + 5, + s, + [29, 3], + s, + [12, 4], + 4, + 11, + 3, + 3, + 2, + 2, + 1, + 1, + 12, + 1, + 5, + 4, + 3, + 7, + 17, + 23, + 3, + 19, + 30, + 29, + 30, + s, + [29, 5], + 3, + 20, + 3, + 30, + 30, + 6, + s, + [4, 3], + 12, + 12, + s, + [11, 6], + s, + [27, 3], + s, + [11, 8], + 2, + 11, + 1, + 4, + c, + [55, 3], + 3, + 3, + 17, + 16, + 3, + 3, + 1, + 3, + 7, + s, + [29, 3], + 21, + s, + [29, 4], + 4, + 13, + 13, + s, + [3, 4], + 6, + 3, + 3, + 23, + s, + [18, 3], + 14, + 14, + 1, + 14, + 3, + 1, + 20, + 2, + 17, + 14, + 17, + 3 +]), + symbol: u([ + 1, + 2, + s, + [19, 7, 1], + 28, + 47, + 54, + 56, + 1, + c, + [14, 11], + 57, + c, + [12, 11], + 55, + 58, + 68, + 84, + s, + [1, 3], + c, + [17, 10], + 1, + 2, + 3, + 5, + 9, + 10, + s, + [14, 4, 1], + 19, + 26, + s, + [38, 4, 1], + 44, + 46, + 64, + c, + [15, 6], + c, + [14, 7], + 72, + s, + [74, 5, 1], + 81, + 83, + 27, + 62, + 27, + 63, + c, + [55, 13], + c, + [11, 20], + 2, + 20, + 26, + 60, + c, + [4, 3], + 59, + 2, + s, + [29, 9, 1], + 51, + 69, + 2, + 20, + 85, + 86, + s, + [1, 3], + c, + [102, 16], + 65, + 70, + c, + [19, 17], + 64, + c, + [85, 13], + 9, + c, + [12, 9], + c, + [143, 12], + c, + [141, 6], + c, + [30, 3], + c, + [58, 6], + s, + [20, 7, 1], + 28, + c, + [29, 6], + 47, + c, + [29, 7], + 7, + s, + [9, 9, 1], + c, + [33, 14], + 45, + 46, + 47, + 82, + c, + [58, 3], + 11, + c, + [80, 11], + 73, + c, + [81, 6], + c, + [22, 22], + c, + [121, 12], + c, + [17, 22], + c, + [108, 29], + c, + [29, 199], + s, + [42, 6, 1], + 40, + 43, + 77, + 79, + 80, + c, + [123, 89], + c, + [19, 7], + 27, + c, + [590, 11], + c, + [12, 27], + c, + [611, 3], + 61, + c, + [630, 14], + c, + [3, 3], + 28, + 68, + 28, + 68, + 28, + 28, + c, + [634, 11], + 88, + 48, + 2, + 20, + 48, + 85, + 86, + 2, + 18, + 20, + c, + [9, 4], + 1, + 2, + 51, + 53, + 87, + 89, + 90, + c, + [629, 17], + 3, + c, + [750, 13], + 67, + c, + [751, 8], + 7, + 20, + 71, + c, + [691, 20], + c, + [632, 23], + c, + [662, 65], + c, + [526, 145], + 2, + 9, + 11, + c, + [788, 15], + c, + [808, 7], + 11, + c, + [201, 59], + 82, + 2, + 40, + 42, + 43, + 77, + 80, + c, + [6, 4], + c, + [4, 8], + c, + [495, 33], + c, + [11, 59], + 3, + 4, + c, + [449, 8], + c, + [401, 15], + c, + [27, 54], + c, + [603, 11], + c, + [11, 78], + 52, + c, + [182, 11], + c, + [683, 3], + 49, + 50, + 1, + 51, + 88, + 1, + 53, + 1, + 51, + 1, + 51, + c, + [5, 3], + 53, + c, + [647, 17], + 2, + 4, + c, + [691, 13], + 66, + 2, + 28, + 68, + 2, + 6, + 8, + 6, + c, + [4, 3], + c, + [740, 8], + c, + [648, 57], + c, + [531, 31], + c, + [528, 13], + c, + [756, 8], + c, + [668, 115], + c, + [568, 5], + c, + [321, 10], + 53, + c, + [13, 13], + c, + [1004, 3], + c, + [3, 9], + c, + [273, 4], + c, + [272, 3], + c, + [328, 5], + c, + [310, 14], + c, + [1001, 9], + 1, + c, + [496, 10], + c, + [27, 7], + c, + [18, 36], + c, + [1078, 14], + c, + [14, 14], + 20, + c, + [15, 14], + c, + [461, 3], + 53, + c, + [843, 20], + c, + [480, 3], + c, + [474, 16], + c, + [163, 14], + c, + [505, 18], + 6, + 8 +]), + type: u([ + s, + [2, 11], + 0, + 0, + 1, + c, + [14, 12], + c, + [26, 13], + 0, + c, + [15, 12], + s, + [2, 20], + c, + [32, 14], + s, + [0, 8], + c, + [23, 3], + c, + [57, 32], + c, + [62, 9], + c, + [113, 13], + c, + [67, 4], + c, + [40, 20], + c, + [21, 18], + c, + [96, 36], + c, + [141, 7], + c, + [30, 28], + c, + [221, 43], + c, + [223, 9], + c, + [22, 34], + c, + [17, 34], + s, + [2, 224], + c, + [239, 141], + c, + [139, 19], + c, + [673, 16], + c, + [14, 5], + c, + [180, 13], + c, + [764, 35], + c, + [751, 9], + c, + [98, 19], + c, + [632, 31], + c, + [662, 75], + c, + [511, 151], + c, + [513, 34], + c, + [231, 35], + c, + [821, 238], + c, + [735, 74], + c, + [43, 27], + c, + [740, 39], + c, + [1202, 78], + c, + [756, 30], + c, + [696, 140], + c, + [1001, 31], + c, + [461, 114], + c, + [121, 58] +]), + state: u([ + s, + [1, 4, 1], + 6, + 11, + 12, + 20, + 22, + 23, + 25, + 26, + 31, + 32, + 37, + 36, + 43, + 45, + 47, + 51, + 55, + 56, + 57, + 61, + 62, + 64, + 66, + c, + [16, 5], + 67, + c, + [5, 4], + 71, + 73, + 74, + c, + [13, 5], + 75, + c, + [7, 6], + 76, + c, + [5, 4], + 77, + c, + [5, 4], + 81, + 78, + 79, + 84, + 88, + 89, + 98, + 103, + 57, + 105, + 108, + 107, + 110, + 112, + c, + [67, 7], + 113, + 61, + 62, + 117, + c, + [60, 11], + c, + [6, 6], + 71, + 81, + 125, + 132, + 135, + 137, + 143, + 108, + 107, + c, + [15, 5], + 145, + c, + [32, 5], + 108, + 146, + 148, + c, + [52, 8], + 132, + c, + [23, 5] +]), + mode: u([ + s, + [2, 23], + s, + [1, 12], + c, + [24, 13], + c, + [41, 28], + c, + [44, 15], + c, + [89, 27], + c, + [17, 13], + c, + [88, 11], + c, + [64, 34], + c, + [38, 14], + c, + [123, 15], + c, + [92, 12], + 1, + c, + [107, 10], + c, + [27, 6], + c, + [72, 23], + c, + [40, 8], + c, + [45, 7], + c, + [15, 13], + s, + [1, 24], + s, + [2, 234], + c, + [236, 98], + c, + [97, 24], + c, + [24, 15], + c, + [374, 20], + c, + [432, 5], + c, + [409, 15], + c, + [585, 9], + c, + [47, 20], + c, + [45, 25], + c, + [36, 14], + c, + [578, 18], + c, + [602, 53], + c, + [459, 145], + c, + [735, 19], + c, + [797, 33], + c, + [29, 25], + c, + [776, 238], + c, + [813, 51], + c, + [289, 5], + c, + [648, 7], + c, + [298, 21], + c, + [738, 18], + c, + [621, 8], + c, + [376, 7], + c, + [651, 22], + c, + [874, 59], + c, + [1219, 170], + c, + [960, 9], + c, + [947, 23], + c, + [1151, 89], + c, + [805, 17], + s, + [2, 53] +]), + goto: u([ + s, + [9, 11], + s, + [11, 11], + 8, + 5, + s, + [7, 4, 1], + s, + [13, 7, 1], + s, + [10, 11], + 34, + 21, + s, + [34, 16], + 24, + 27, + 29, + 33, + 34, + 35, + 40, + 28, + 30, + 38, + 39, + 42, + 41, + 44, + 46, + s, + [15, 11], + s, + [16, 11], + s, + [17, 11], + 48, + 49, + 50, + 52, + 53, + s, + [54, 12], + 59, + 58, + 1, + 2, + 7, + 58, + 63, + s, + [58, 6], + 60, + s, + [58, 7], + s, + [34, 17], + s, + [12, 11], + 61, + 61, + 65, + s, + [61, 9], + c, + [125, 12], + s, + [69, 3], + c, + [15, 5], + s, + [69, 7], + 40, + 69, + c, + [23, 7], + 71, + 71, + c, + [3, 3], + 71, + 68, + 70, + s, + [71, 18], + 72, + 71, + 71, + 65, + 65, + 27, + 65, + c, + [68, 11], + c, + [15, 15], + c, + [95, 12], + c, + [12, 12], + s, + [81, 29], + s, + [83, 29], + s, + [84, 29], + s, + [85, 29], + s, + [86, 29], + s, + [87, 29], + s, + [88, 29], + s, + [89, 31], + 38, + 80, + s, + [98, 29], + s, + [99, 29], + s, + [96, 29], + s, + [13, 9], + 82, + 13, + 13, + s, + [29, 12], + s, + [14, 9], + 83, + 14, + 14, + s, + [31, 12], + 85, + 86, + 87, + s, + [20, 11], + s, + [25, 3], + s, + [26, 3], + 16, + 16, + 23, + 24, + 100, + s, + [90, 8, 1], + 99, + 101, + 102, + 59, + 58, + 102, + 103, + 104, + 103, + 103, + s, + [108, 3], + 117, + 106, + 117, + 109, + s, + [33, 17], + 111, + c, + [684, 13], + 114, + 115, + 6, + c, + [630, 8], + 116, + s, + [58, 7], + s, + [67, 3], + c, + [34, 5], + s, + [67, 7], + 40, + 67, + c, + [42, 6], + 67, + s, + [68, 3], + c, + [24, 5], + s, + [68, 7], + 40, + 68, + c, + [24, 6], + 68, + 70, + 70, + 69, + s, + [70, 3], + c, + [7, 3], + s, + [70, 17], + 72, + 70, + 70, + s, + [76, 29], + s, + [77, 29], + s, + [78, 29], + s, + [82, 29], + s, + [97, 29], + 119, + 120, + 118, + 64, + 64, + 27, + 64, + c, + [259, 11], + 122, + 120, + 121, + 79, + 79, + 69, + s, + [79, 3], + 68, + 70, + s, + [79, 18], + 72, + 79, + 79, + 80, + 80, + 69, + s, + [80, 3], + 68, + 70, + s, + [80, 18], + 72, + 80, + 80, + 124, + 38, + 123, + 80, + s, + [93, 4], + s, + [94, 4], + s, + [95, 4], + s, + [30, 12], + s, + [32, 12], + s, + [18, 11], + s, + [19, 11], + s, + [27, 11], + s, + [28, 11], + s, + [21, 11], + s, + [22, 11], + s, + [43, 27], + s, + [44, 27], + s, + [45, 27], + s, + [46, 11], + s, + [47, 11], + s, + [48, 11], + s, + [49, 11], + s, + [50, 11], + s, + [51, 11], + s, + [52, 11], + s, + [53, 11], + 127, + 126, + s, + [100, 11], + 101, + 131, + 130, + 128, + 129, + 3, + 101, + 5, + 133, + 109, + 109, + 116, + 116, + 134, + s, + [113, 3], + s, + [35, 17], + 136, + s, + [40, 14], + 138, + 16, + 140, + 139, + 141, + 142, + s, + [59, 3], + 117, + 144, + 117, + 109, + s, + [66, 3], + c, + [627, 5], + s, + [66, 7], + 40, + 66, + c, + [434, 6], + 66, + s, + [72, 29], + s, + [74, 29], + 63, + 63, + 27, + 63, + c, + [508, 11], + s, + [73, 29], + s, + [75, 29], + s, + [90, 29], + s, + [91, 29], + s, + [92, 4], + s, + [111, 13], + s, + [112, 13], + s, + [104, 3], + s, + [105, 3], + s, + [106, 3], + s, + [107, 3], + c, + [259, 4], + s, + [115, 3], + s, + [114, 3], + 147, + c, + [949, 13], + 38, + 38, + 149, + s, + [38, 15], + s, + [41, 18], + s, + [42, 18], + s, + [55, 14], + s, + [56, 14], + 150, + s, + [57, 14], + 4, + 101, + 133, + 62, + 62, + 27, + 62, + c, + [115, 11], + 110, + 110, + s, + [36, 17], + s, + [39, 14], + s, + [37, 17], + s, + [60, 3] +]) +}), +defaultActions: bda({ + idx: u([ + 0, + 2, + 6, + 11, + 12, + 13, + 16, + 18, + 19, + 21, + 22, + s, + [31, 8, 1], + 40, + 41, + s, + [42, 4, 2], + 49, + 50, + 53, + 54, + 59, + 61, + s, + [68, 5, 1], + s, + [79, 22, 1], + 102, + 103, + 107, + 109, + 110, + 115, + 118, + 119, + s, + [121, 11, 1], + 133, + 134, + s, + [137, 4, 1], + 142, + s, + [146, 5, 1] +]), + goto: u([ + 9, + 11, + 10, + 15, + 16, + 17, + 54, + 1, + 2, + 34, + 12, + 81, + s, + [83, 7, 1], + 98, + 99, + 96, + 29, + 31, + 20, + 25, + 26, + 23, + 24, + 108, + 33, + 76, + 77, + 78, + 82, + 97, + 93, + 94, + 95, + 30, + 32, + 18, + 19, + 27, + 28, + 21, + 22, + s, + [43, 11, 1], + 100, + 101, + 109, + 113, + 35, + 59, + 72, + 74, + 73, + 75, + 90, + 91, + 92, + 111, + 112, + s, + [104, 4, 1], + 115, + 114, + 41, + 42, + 55, + 56, + 57, + 110, + 36, + 39, + 37, + 60 +]) +}), +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 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, 151 /* === 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 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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 rmCommonWS = helpers.rmCommonWS; +var checkActionBlock = helpers.checkActionBlock; + + +function encodeRE(s) { + return s.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1').replace(/\\\\u([a-fA-F0-9]{4})/g, '\\u$1'); +} + +function prepareString(s) { + // unescape slashes + s = s.replace(/\\\\/g, "\\"); + s = encodeRE(s); + return s; +} + +// 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); +}; + +parser.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse:', arguments); +}; + +parser.yy.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse YY:', arguments); +}; + +parser.yy.post_lex = function p_lex() { + if (parser.yydebug) parser.log('post_lex:', 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 <> tokens and perform user action code for a <> 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) { + 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; + switch (yyrulenumber) { + case 0: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %\{ */ + yy.depth = 0; + + yy.include_command_allowed = false; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 1: + /*! Conditions:: action */ + /*! Rule:: %\{([^]*?)%\} */ + yy_.yytext = this.matches[1].replace(/%\\\}/g, '%}'); // unescape any literal '%\}' that exists within the action code block + + yy.include_command_allowed = true; + return 32; + break; + + case 2: + /*! Conditions:: action */ + /*! Rule:: %include\b */ + if (yy.include_command_allowed) { + // This is an include instruction in place of an action: + // + // - one %include per action chunk + // - one %include replaces an entire action chunk + this.pushState('path'); + + return 51; + } else { + // TODO + yy_.yyerror('oops!'); + + return 37; + } + + break; + + case 3: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + //yy.include_command_allowed = false; -- doesn't impact include-allowed state + return 34; + + break; + + case 4: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\/.* */ + yy.include_command_allowed = false; + + return 35; + break; + + case 6: + /*! Conditions:: action */ + /*! Rule:: \| */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 7: + /*! Conditions:: action */ + /*! Rule:: %% */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 9: + /*! Conditions:: action */ + /*! Rule:: \/[^\s/]*?(?:['"`{}][^\s/]*?)*\/ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 10: + /*! Conditions:: action */ + /*! Rule:: \/[^}{BR}]* */ + yy.include_command_allowed = false; + + return 33; + break; + + case 11: + /*! Conditions:: action */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy.include_command_allowed = false; + + return 33; + break; + + case 12: + /*! Conditions:: action */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy.include_command_allowed = false; + + return 33; + break; + + case 13: + /*! Conditions:: action */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy.include_command_allowed = false; + + return 33; + break; + + case 14: + /*! Conditions:: action */ + /*! Rule:: [^{}/"'`|%\{\}{BR}{WS}]+ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 15: + /*! Conditions:: action */ + /*! Rule:: \{ */ + yy.depth++; + + yy.include_command_allowed = false; + return 33; + break; + + case 16: + /*! Conditions:: action */ + /*! Rule:: \} */ + yy.include_command_allowed = false; + + if (yy.depth <= 0) { + yy_.yyerror(rmCommonWS` + too many closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 30; + } else { + yy.depth--; + } + + return 33; + break; + + case 17: + /*! Conditions:: action */ + /*! Rule:: (?:{BR}{WS}+)+(?=[^{WS}{BR}|]) */ + yy.include_command_allowed = true; + + return 36; // keep empty lines as-is inside action code blocks. + break; + + case 18: + /*! Conditions:: action */ + /*! Rule:: {BR} */ + if (yy.depth > 0) { + yy.include_command_allowed = true; + return 36; // keep empty lines as-is inside action code blocks. + } else { + // end of action code chunk + this.popState(); + + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } + + break; + + case 19: + /*! Conditions:: action */ + /*! Rule:: $ */ + yy.include_command_allowed = false; + + if (yy.depth !== 0) { + yy_.yyerror(rmCommonWS` + missing ${yy.depth} closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + yy_.yytext = ''; + return 29; + } + + this.popState(); + yy_.yytext = ''; + return 31; + break; + + case 21: + /*! Conditions:: conditions */ + /*! Rule:: > */ + this.popState(); + + return 6; + break; + + case 24: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 25: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 26: + /*! Conditions:: rules */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 27: + /*! Conditions:: rules */ + /*! Rule:: {WS}+{BR}+ */ + /* empty */ + break; + + case 28: + /*! Conditions:: rules */ + /*! Rule:: \/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 29: + /*! Conditions:: rules */ + /*! Rule:: \/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 30: + /*! Conditions:: rules */ + /*! Rule:: {WS}+(?=[^{WS}{BR}|%]) */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + return 28; + break; + + case 31: + /*! Conditions:: rules */ + /*! Rule:: %% */ + this.popState(); + + this.pushState('code'); + return 19; + break; + + case 32: + /*! Conditions:: rules */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 35: + /*! Conditions:: options */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 49; // value is always a string type + break; + + case 36: + /*! Conditions:: options */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 49; // value is always a string type + break; + + case 37: + /*! Conditions:: options */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy_.yytext = unescQuote(this.matches[1], /\\`/g); + + return 49; // value is always a string type + break; + + case 39: + /*! Conditions:: options */ + /*! Rule:: {BR}{WS}+(?=\S) */ + /* skip leading whitespace on the next line of input, when followed by more options */ + break; + + case 40: + /*! Conditions:: options */ + /*! Rule:: {BR} */ + this.popState(); + + return 48; + break; + + case 41: + /*! Conditions:: options */ + /*! Rule:: {WS}+ */ + /* skip whitespace */ + break; + + case 43: + /*! Conditions:: start_condition */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 44: + /*! Conditions:: start_condition */ + /*! Rule:: {WS}+ */ + /* empty */ + break; + + case 46: + /*! Conditions:: INITIAL */ + /*! Rule:: {ID} */ + this.pushState('macro'); + + return 20; + break; + + case 47: + /*! Conditions:: macro named_chunk */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 48: + /*! Conditions:: macro */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 49: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 50: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \s+ */ + /* empty */ + break; + + case 51: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 26; + break; + + case 52: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 26; + break; + + case 53: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \[ */ + this.pushState('set'); + + return 41; + break; + + case 66: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: < */ + this.pushState('conditions'); + + return 5; + break; + + case 67: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/! */ + return 39; // treated as `(?!atom)` + + break; + + case 68: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/ */ + return 14; // treated as `(?=atom)` + + break; + + case 70: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\. */ + yy_.yytext = yy_.yytext.replace(/^\\/g, ''); + + return 44; + break; + + case 73: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %options\b */ + this.pushState('options'); + + return 47; + break; + + case 74: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %s\b */ + this.pushState('start_condition'); + + return 21; + break; + + case 75: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %x\b */ + this.pushState('start_condition'); + + return 22; + break; + + case 76: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %code\b */ + this.pushState('named_chunk'); + + return 25; + break; + + case 77: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %import\b */ + this.pushState('named_chunk'); + + return 24; + break; + + case 78: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %include\b */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 79: + /*! Conditions:: code */ + /*! Rule:: %include\b */ + this.pushState('path'); + + return 51; + break; + + case 80: + /*! Conditions:: INITIAL rules code */ + /*! Rule:: %{NAME}([^\r\n]*) */ + /* ignore unrecognized decl */ + this.warn(rmCommonWS` + LEX: ignoring unsupported lexer 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 23; + break; + + case 81: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %% */ + this.pushState('rules'); + + return 19; + break; + + case 89: + /*! Conditions:: set */ + /*! Rule:: \] */ + this.popState(); + + return 42; + break; + + case 91: + /*! Conditions:: code */ + /*! Rule:: [^\r\n]+ */ + return 53; // the bit of CODE just before EOF... + + break; + + case 92: + /*! Conditions:: path */ + /*! Rule:: {BR} */ + this.popState(); + + this.unput(yy_.yytext); + break; + + case 93: + /*! Conditions:: path */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 94: + /*! Conditions:: path */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 95: + /*! Conditions:: path */ + /*! Rule:: {WS}+ */ + // skip whitespace in the line + break; + + case 96: + /*! Conditions:: path */ + /*! Rule:: [^\s\r\n]+ */ + this.popState(); + + return 52; + break; + + case 97: + /*! Conditions:: action */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 98: + /*! Conditions:: action */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 99: + /*! Conditions:: action */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 100: + /*! Conditions:: options */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 101: + /*! Conditions:: options */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 102: + /*! Conditions:: options */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 103: + /*! 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 104: + /*! 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 105: + /*! 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 106: + /*! Conditions:: macro rules */ + /*! Rule:: . */ + /* b0rk on bad characters */ + var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + + yy_.yyerror(rmCommonWS` + unsupported lexer input encountered while lexing + ${rules} (i.e. jison lex regexes). + + NOTE: When you want this input to be interpreted as a LITERAL part + of a lex rule regex, you MUST enclose it in double or + single quotes. + + If not, then know that this input is not accepted as a valid + regex expression here in jison-lex ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + break; + + case 107: + /*! Conditions:: * */ + /*! Rule:: . */ + yy_.yyerror(rmCommonWS` + unsupported lexer 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:: {WS}+ */ + 5: 36, + + /*! Conditions:: action */ + /*! Rule:: % */ + 8: 33, + + /*! Conditions:: conditions */ + /*! Rule:: {NAME} */ + 20: 20, + + /*! Conditions:: conditions */ + /*! Rule:: , */ + 22: 8, + + /*! Conditions:: conditions */ + /*! Rule:: \* */ + 23: 7, + + /*! Conditions:: options */ + /*! Rule:: {NAME} */ + 33: 20, + + /*! Conditions:: options */ + /*! Rule:: = */ + 34: 18, + + /*! Conditions:: options */ + /*! Rule:: [^\s\r\n]+ */ + 38: 50, + + /*! Conditions:: start_condition */ + /*! Rule:: {ID} */ + 42: 27, + + /*! Conditions:: named_chunk */ + /*! Rule:: {ID} */ + 45: 20, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \| */ + 54: 9, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?: */ + 55: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?= */ + 56: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?! */ + 57: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \( */ + 58: 10, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \) */ + 59: 11, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \+ */ + 60: 12, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \* */ + 61: 7, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \? */ + 62: 13, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \^ */ + 63: 16, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: , */ + 64: 8, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: <> */ + 65: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\([0-7]{1,3}|[rfntvsSbBwWdD\\*+()${}|[\]\/.^?]|c[A-Z]|x[0-9A-F]{2}|u[a-fA-F0-9]{4}) */ + 69: 44, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \$ */ + 71: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \. */ + 72: 15, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{\d+(,\s*\d+|,)?\} */ + 82: 45, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{{ID}\} */ + 83: 40, + + /*! Conditions:: set options */ + /*! Rule:: \{{ID}\} */ + 84: 40, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{ */ + 85: 3, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \} */ + 86: 4, + + /*! Conditions:: set */ + /*! Rule:: (?:\\\\|\\\]|[^\]{])+ */ + 87: 43, + + /*! Conditions:: set */ + /*! Rule:: \{ */ + 88: 43, + + /*! Conditions:: code */ + /*! Rule:: [^\r\n]*(\r|\n)+ */ + 90: 53, + + /*! Conditions:: * */ + /*! Rule:: $ */ + 108: 1 + }, + + rules: [ + /* 0: */ /^(?:%\{)/, + /* 1: */ new XRegExp('^(?:%\\{([^]*?)%\\})', ''), + /* 2: */ /^(?:%include\b)/, + /* 3: */ new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 4: */ /^(?:([^\S\n\r])*\/\/.*)/, + /* 5: */ /^(?:([^\S\n\r])+)/, + /* 6: */ /^(?:\|)/, + /* 7: */ /^(?:%%)/, + /* 8: */ /^(?:%)/, + /* 9: */ /^(?:\/[^\s\/]*?(?:['"`{}][^\s\/]*?)*\/)/, + /* 10: */ /^(?:\/[^\n\r}]*)/, + /* 11: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 12: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 13: */ /^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 14: */ /^(?:[^\s"%'\/`{-}]+)/, + /* 15: */ /^(?:\{)/, + /* 16: */ /^(?:\})/, + /* 17: */ /^(?:(?:(\r\n|\n|\r)([^\S\n\r])+)+(?=[^\s|]))/, + /* 18: */ /^(?:(\r\n|\n|\r))/, + /* 19: */ /^(?:$)/, + /* 20: */ new XRegExp( + '^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', + '' + ), + /* 21: */ /^(?:>)/, + /* 22: */ /^(?:,)/, + /* 23: */ /^(?:\*)/, + /* 24: */ /^(?:([^\S\n\r])*\/\/[^\n\r]*)/, + /* 25: */ new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 26: */ /^(?:(\r\n|\n|\r)+)/, + /* 27: */ /^(?:([^\S\n\r])+(\r\n|\n|\r)+)/, + /* 28: */ /^(?:\/\/[^\r\n]*)/, + /* 29: */ new XRegExp('^(?:\\/\\*[^]*?\\*\\/)', ''), + /* 30: */ /^(?:([^\S\n\r])+(?=[^\s%|]))/, + /* 31: */ /^(?:%%)/, + /* 32: */ /^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 33: */ new XRegExp( + '^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', + '' + ), + /* 34: */ /^(?:=)/, + /* 35: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 36: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 37: */ /^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 38: */ /^(?:\S+)/, + /* 39: */ /^(?:(\r\n|\n|\r)([^\S\n\r])+(?=\S))/, + /* 40: */ /^(?:(\r\n|\n|\r))/, + /* 41: */ /^(?:([^\S\n\r])+)/, + /* 42: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 43: */ /^(?:(\r\n|\n|\r)+)/, + /* 44: */ /^(?:([^\S\n\r])+)/, + /* 45: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 46: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 47: */ /^(?:(\r\n|\n|\r)+)/, + /* 48: */ /^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 49: */ /^(?:(\r\n|\n|\r)+)/, + /* 50: */ /^(?:\s+)/, + /* 51: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 52: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 53: */ /^(?:\[)/, + /* 54: */ /^(?:\|)/, + /* 55: */ /^(?:\(\?:)/, + /* 56: */ /^(?:\(\?=)/, + /* 57: */ /^(?:\(\?!)/, + /* 58: */ /^(?:\()/, + /* 59: */ /^(?:\))/, + /* 60: */ /^(?:\+)/, + /* 61: */ /^(?:\*)/, + /* 62: */ /^(?:\?)/, + /* 63: */ /^(?:\^)/, + /* 64: */ /^(?:,)/, + /* 65: */ /^(?:<>)/, + /* 66: */ /^(?:<)/, + /* 67: */ /^(?:\/!)/, + /* 68: */ /^(?:\/)/, + /* 69: */ /^(?:\\([0-7]{1,3}|[$(-+.\/?BDSW\[-\^bdfnr-tvw{-}]|c[A-Z]|x[\dA-F]{2}|u[\dA-Fa-f]{4}))/, + /* 70: */ /^(?:\\.)/, + /* 71: */ /^(?:\$)/, + /* 72: */ /^(?:\.)/, + /* 73: */ /^(?:%options\b)/, + /* 74: */ /^(?:%s\b)/, + /* 75: */ /^(?:%x\b)/, + /* 76: */ /^(?:%code\b)/, + /* 77: */ /^(?:%import\b)/, + /* 78: */ /^(?:%include\b)/, + /* 79: */ /^(?:%include\b)/, + /* 80: */ new XRegExp( + '^(?:%([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?)([^\\n\\r]*))', + '' + ), + /* 81: */ /^(?:%%)/, + /* 82: */ /^(?:\{\d+(,\s*\d+|,)?\})/, + /* 83: */ new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 84: */ new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 85: */ /^(?:\{)/, + /* 86: */ /^(?:\})/, + /* 87: */ /^(?:(?:\\\\|\\\]|[^\]{])+)/, + /* 88: */ /^(?:\{)/, + /* 89: */ /^(?:\])/, + /* 90: */ /^(?:[^\r\n]*(\r|\n)+)/, + /* 91: */ /^(?:[^\r\n]+)/, + /* 92: */ /^(?:(\r\n|\n|\r))/, + /* 93: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 94: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 95: */ /^(?:([^\S\n\r])+)/, + /* 96: */ /^(?:\S+)/, + /* 97: */ /^(?:")/, + /* 98: */ /^(?:')/, + /* 99: */ /^(?:`)/, + /* 100: */ /^(?:")/, + /* 101: */ /^(?:')/, + /* 102: */ /^(?:`)/, + /* 103: */ /^(?:")/, + /* 104: */ /^(?:')/, + /* 105: */ /^(?:`)/, + /* 106: */ /^(?:.)/, + /* 107: */ /^(?:.)/, + /* 108: */ /^(?:$)/ + ], + + conditions: { + 'rules': { + rules: [ + 0, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 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, + 74, + 75, + 76, + 77, + 78, + 80, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 106, + 107, + 108 + ], + + inclusive: true + }, + + 'macro': { + rules: [ + 0, + 24, + 25, + 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, + 74, + 75, + 76, + 77, + 78, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 106, + 107, + 108 + ], + + inclusive: true + }, + + 'named_chunk': { + rules: [ + 0, + 45, + 47, + 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, + 74, + 75, + 76, + 77, + 78, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: true + }, + + 'code': { + rules: [79, 80, 90, 91, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'start_condition': { + rules: [24, 25, 42, 43, 44, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'options': { + rules: [ + 24, + 25, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 84, + 100, + 101, + 102, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: false + }, + + 'conditions': { + rules: [20, 21, 22, 23, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'action': { + rules: [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 97, + 98, + 99, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: false + }, + + 'path': { + rules: [24, 25, 92, 93, 94, 95, 96, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'set': { + rules: [84, 87, 88, 89, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'INITIAL': { + rules: [ + 0, + 24, + 25, + 46, + 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, + 74, + 75, + 76, + 77, + 78, + 80, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: true + } + } + }; + + var rmCommonWS = helpers.rmCommonWS; + var dquote = helpers.dquote; + + 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); +} + + + +var lexParser = { + parser, + Parser, + parse: yyparse, + +}; + +module.exports = lexParser; diff --git a/dist/lex-parser-es6.js b/dist/lex-parser-es6.js new file mode 100644 index 0000000..543d5d9 --- /dev/null +++ b/dist/lex-parser-es6.js @@ -0,0 +1,7959 @@ +import XRegExp from '@gerhobbelt/xregexp'; +import helpers from 'jison-helpers-lib'; +import fs from 'fs'; + +// 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. + * } + */ + + +// 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_: { + "$": 17, + "$accept": 0, + "$end": 1, + "%%": 19, + "(": 10, + ")": 11, + "*": 7, + "+": 12, + ",": 8, + ".": 15, + "/": 14, + "/!": 39, + "<": 5, + "=": 18, + ">": 6, + "?": 13, + "ACTION": 32, + "ACTION_BODY": 33, + "ACTION_BODY_CPP_COMMENT": 35, + "ACTION_BODY_C_COMMENT": 34, + "ACTION_BODY_WHITESPACE": 36, + "ACTION_END": 31, + "ACTION_START": 28, + "BRACKET_MISSING": 29, + "BRACKET_SURPLUS": 30, + "CHARACTER_LIT": 46, + "CODE": 53, + "EOF": 1, + "ESCAPE_CHAR": 44, + "IMPORT": 24, + "INCLUDE": 51, + "INCLUDE_PLACEMENT_ERROR": 37, + "INIT_CODE": 25, + "NAME": 20, + "NAME_BRACE": 40, + "OPTIONS": 47, + "OPTIONS_END": 48, + "OPTION_STRING_VALUE": 49, + "OPTION_VALUE": 50, + "PATH": 52, + "RANGE_REGEX": 45, + "REGEX_SET": 43, + "REGEX_SET_END": 42, + "REGEX_SET_START": 41, + "SPECIAL_GROUP": 38, + "START_COND": 27, + "START_EXC": 22, + "START_INC": 21, + "STRING_LIT": 26, + "UNKNOWN_DECL": 23, + "^": 16, + "action": 68, + "action_body": 69, + "any_group_regex": 78, + "definition": 58, + "definitions": 57, + "error": 2, + "escape_char": 81, + "extra_lexer_module_code": 87, + "import_name": 60, + "import_path": 61, + "include_macro_code": 88, + "init": 56, + "init_code_name": 59, + "lex": 54, + "module_code_chunk": 89, + "name_expansion": 77, + "name_list": 71, + "names_exclusive": 63, + "names_inclusive": 62, + "nonempty_regex_list": 74, + "option": 86, + "option_list": 85, + "optional_module_code_chunk": 90, + "options": 84, + "range_regex": 82, + "regex": 72, + "regex_base": 76, + "regex_concat": 75, + "regex_list": 73, + "regex_set": 79, + "regex_set_atom": 80, + "rule": 67, + "rule_block": 66, + "rules": 64, + "rules_and_epilogue": 55, + "rules_collective": 65, + "start_conditions": 70, + "string": 83, + "{": 3, + "|": 9, + "}": 4 +}, +terminals_: { + 1: "EOF", + 2: "error", + 3: "{", + 4: "}", + 5: "<", + 6: ">", + 7: "*", + 8: ",", + 9: "|", + 10: "(", + 11: ")", + 12: "+", + 13: "?", + 14: "/", + 15: ".", + 16: "^", + 17: "$", + 18: "=", + 19: "%%", + 20: "NAME", + 21: "START_INC", + 22: "START_EXC", + 23: "UNKNOWN_DECL", + 24: "IMPORT", + 25: "INIT_CODE", + 26: "STRING_LIT", + 27: "START_COND", + 28: "ACTION_START", + 29: "BRACKET_MISSING", + 30: "BRACKET_SURPLUS", + 31: "ACTION_END", + 32: "ACTION", + 33: "ACTION_BODY", + 34: "ACTION_BODY_C_COMMENT", + 35: "ACTION_BODY_CPP_COMMENT", + 36: "ACTION_BODY_WHITESPACE", + 37: "INCLUDE_PLACEMENT_ERROR", + 38: "SPECIAL_GROUP", + 39: "/!", + 40: "NAME_BRACE", + 41: "REGEX_SET_START", + 42: "REGEX_SET_END", + 43: "REGEX_SET", + 44: "ESCAPE_CHAR", + 45: "RANGE_REGEX", + 46: "CHARACTER_LIT", + 47: "OPTIONS", + 48: "OPTIONS_END", + 49: "OPTION_STRING_VALUE", + 50: "OPTION_VALUE", + 51: "INCLUDE", + 52: "PATH", + 53: "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([ + 54, + 54, + s, + [55, 6], + 56, + 57, + 57, + s, + [58, 11], + 59, + 59, + 60, + 60, + 61, + 61, + 62, + 62, + 63, + 63, + 64, + 64, + s, + [65, 4], + 66, + 66, + 67, + 67, + s, + [68, 3], + s, + [69, 9], + s, + [70, 4], + 71, + 71, + 72, + s, + [73, 4], + s, + [74, 4], + 75, + 75, + s, + [76, 17], + 77, + 78, + 78, + 79, + 79, + 80, + s, + [80, 4, 1], + 83, + 84, + 85, + 85, + s, + [86, 6], + 87, + 87, + 88, + 88, + s, + [89, 3], + 90, + 90 +]), + rule: u([ + s, + [4, 3], + s, + [5, 4, -1], + 0, + 0, + 2, + 0, + s, + [2, 3], + s, + [1, 3], + 3, + 3, + 2, + 3, + 3, + s, + [1, 7], + 2, + 1, + 2, + c, + [23, 3], + 4, + c, + [32, 4], + 2, + c, + [22, 3], + 3, + s, + [2, 8], + 0, + s, + [3, 3], + 0, + 1, + 3, + 1, + s, + [3, 4, -1], + c, + [21, 3], + c, + [40, 3], + s, + [3, 4], + s, + [2, 5], + c, + [12, 3], + s, + [1, 6], + c, + [16, 3], + c, + [10, 8], + c, + [9, 3], + s, + [3, 4], + c, + [10, 4], + c, + [82, 4], + 1, + 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 : lex $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:: lex : init definitions rules_and_epilogue EOF */ + + // 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 - 1]; + this.$.macros = yyvstack[yysp - 2].macros; + this.$.startConditions = yyvstack[yysp - 2].startConditions; + this.$.unknownDecls = yyvstack[yysp - 2].unknownDecls; + + // if there are any options, add them all, otherwise set options to NULL: + // can't check for 'empty object' by `if (yy.options) ...` so we do it this way: + for (var k in yy.options) { + this.$.options = yy.options; + break; + } + + if (yy.actionInclude) { + var asrc = yy.actionInclude.join('\n\n'); + // Only a non-empty action code chunk should actually make it through: + if (asrc.trim() !== '') { + this.$.actionInclude = asrc; + } + } + + delete yy.options; + delete yy.actionInclude; + return this.$; + break; + +case 2: + /*! Production:: lex : init definitions error EOF */ + + // 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` + There's an error in your lexer regex rules or epilogue. + Maybe you did not correctly separate the lexer sections with a '%%' + on an otherwise empty line? + The lexer spec file should have this structure: + + definitions + %% + rules + %% // <-- optional! + extra_module_code // <-- optional epilogue! + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 3: + /*! Production:: rules_and_epilogue : "%%" rules "%%" extra_lexer_module_code */ + + // 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,-,-) + + + if (yyvstack[yysp].trim() !== '') { + this.$ = { rules: yyvstack[yysp - 2], moduleInclude: yyvstack[yysp] }; + } else { + this.$ = { rules: yyvstack[yysp - 2] }; + } + break; + +case 4: + /*! Production:: rules_and_epilogue : "%%" error rules "%%" extra_lexer_module_code */ + + // 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` + There's probably an error in one or more of your lexer regex rules. + The lexer rule spec should have this structure: + + regex action_code + + where 'regex' is a lex-style regex expression (see the + jison and jison-lex documentation) which is intended to match a chunk + of the input to lex, while the 'action_code' block is the JS code + which will be invoked when the regex is matched. The 'action_code' block + may be any (indented!) set of JS statements, optionally surrounded + by '{...}' curly braces or otherwise enclosed in a '%{...%}' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 3])} + + Technical error report: + ${yyvstack[yysp - 3].errStr} + `); + break; + +case 5: + /*! Production:: rules_and_epilogue : "%%" rules "%%" 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` + There's an error in your lexer epilogue a.k.a. 'extra_module_code' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 6: + /*! Production:: rules_and_epilogue : "%%" error rules */ + + // 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` + There's probably an error in one or more of your lexer regex rules. + The lexer rule spec should have this structure: + + regex action_code + + where 'regex' is a lex-style regex expression (see the + jison and jison-lex documentation) which is intended to match a chunk + of the input to lex, while the 'action_code' block is the JS code + which will be invoked when the regex is matched. The 'action_code' block + may be any (indented!) set of JS statements, optionally surrounded + by '{...}' curly braces or otherwise enclosed in a '%{...%}' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 7: + /*! Production:: rules_and_epilogue : "%%" rules */ + + // 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.$ = { rules: yyvstack[yysp] }; + break; + +case 8: + /*! Production:: rules_and_epilogue : %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.$ = { rules: [] }; + break; + +case 9: + /*! Production:: init : %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,-,-) + + + yy.actionInclude = []; + if (!yy.options) yy.options = {}; + break; + +case 10: + /*! Production:: definitions : definitions definition */ + + // 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] != null) { + if ('length' in yyvstack[yysp]) { + this.$.macros[yyvstack[yysp][0]] = yyvstack[yysp][1]; + } else if (yyvstack[yysp].type === 'names') { + for (var name in yyvstack[yysp].names) { + this.$.startConditions[name] = yyvstack[yysp].names[name]; + } + } else if (yyvstack[yysp].type === 'unknown') { + this.$.unknownDecls.push(yyvstack[yysp].body); + } + } + break; + +case 11: + /*! Production:: definitions : %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.$ = { + macros: {}, // { hash table } + startConditions: {}, // { hash table } + unknownDecls: [] // [ array of [key,value] pairs } + }; + break; + +case 12: + /*! Production:: definition : NAME regex */ + + // 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 13: + /*! Production:: definition : START_INC names_inclusive */ +case 14: + /*! Production:: definition : START_EXC names_exclusive */ + + // 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 15: + /*! Production:: definition : 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` + The '%{...%}' lexer setup action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + yy.actionInclude.push(yyvstack[yysp]); + this.$ = null; + break; + +case 16: + /*! Production:: definition : options */ +case 102: + /*! Production:: option_list : option */ + + // 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.$ = null; + break; + +case 17: + /*! Production:: definition : 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.$ = {type: 'unknown', body: yyvstack[yysp]}; + break; + +case 18: + /*! Production:: definition : 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.$ = {type: 'imports', name: yyvstack[yysp - 1], path: yyvstack[yysp]}; + break; + +case 19: + /*! Production:: definition : 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 20: + /*! Production:: definition : 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,-,-) + + + yyparser.yyError(rmCommonWS` + %import name or source filename missing maybe? + + Note: 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 21: + /*! Production:: definition : INIT_CODE init_code_name 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The '%code ${$init_code_name}' action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + } + this.$ = { + type: 'codesection', + qualifier: yyvstack[yysp - 1], + include: yyvstack[yysp] + }; + break; + +case 22: + /*! Production:: definition : INIT_CODE error action */ + + // 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2], yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 23: + /*! Production:: init_code_name : NAME */ +case 24: + /*! Production:: init_code_name : STRING_LIT */ +case 25: + /*! Production:: import_name : NAME */ +case 26: + /*! Production:: import_name : STRING_LIT */ +case 27: + /*! Production:: import_path : NAME */ +case 28: + /*! Production:: import_path : STRING_LIT */ +case 64: + /*! Production:: regex_list : regex_concat */ +case 69: + /*! Production:: nonempty_regex_list : regex_concat */ +case 71: + /*! Production:: regex_concat : regex_base */ +case 96: + /*! Production:: escape_char : ESCAPE_CHAR */ +case 97: + /*! Production:: range_regex : RANGE_REGEX */ +case 113: + /*! Production:: module_code_chunk : CODE */ +case 116: + /*! 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 29: + /*! Production:: names_inclusive : START_COND */ + + // 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.$ = {type: 'names', names: {}}; this.$.names[yyvstack[yysp]] = 0; + break; + +case 30: + /*! Production:: names_inclusive : names_inclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 0; + break; + +case 31: + /*! Production:: names_exclusive : START_COND */ + + // 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.$ = {type: 'names', names: {}}; this.$.names[yyvstack[yysp]] = 1; + break; + +case 32: + /*! Production:: names_exclusive : names_exclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 1; + break; + +case 33: + /*! Production:: rules : rules rules_collective */ + + // 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].concat(yyvstack[yysp]); + break; + +case 34: + /*! Production:: rules : %epsilon */ +case 40: + /*! Production:: rule_block : %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 35: + /*! Production:: rules_collective : start_conditions rule */ + + // 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,-,-) + + + if (yyvstack[yysp - 1]) { + yyvstack[yysp].unshift(yyvstack[yysp - 1]); + } + this.$ = [yyvstack[yysp]]; + break; + +case 36: + /*! Production:: rules_collective : start_conditions "{" rule_block "}" */ + + // 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,-,-) + + + if (yyvstack[yysp - 3]) { + yyvstack[yysp - 1].forEach(function (d) { + d.unshift(yyvstack[yysp - 3]); + }); + } + this.$ = yyvstack[yysp - 1]; + break; + +case 37: + /*! Production:: rules_collective : start_conditions "{" 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 made a mistake while specifying one of the lexer rules inside + the start condition + <${yyvstack[yysp - 3].join(',')}> { rules... } + block. + + Erroneous area: + ${yylexer.prettyPrintRange(yylexer.mergeLocationInfo((yysp - 3), (yysp)), yylstack[yysp - 3])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 38: + /*! Production:: rules_collective : start_conditions "{" 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 lexer rules set inside + the start condition + <${yyvstack[yysp - 2].join(',')}> { rules... } + as a terminating curly brace '}' could not be found. + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 39: + /*! Production:: rule_block : rule_block rule */ + + // 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 41: + /*! Production:: rule : regex 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The rule's action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = [yyvstack[yysp - 1], yyvstack[yysp]]; + break; + +case 42: + /*! Production:: rule : regex error */ + + // 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]]; + yyparser.yyError(rmCommonWS` + Lexer rule regex action code declaration error? + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 43: + /*! Production:: action : ACTION_START action_body BRACKET_MISSING */ + + // 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` + Missing curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: '{ ... }'. + + Offending action body: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + break; + +case 44: + /*! Production:: action : ACTION_START action_body BRACKET_SURPLUS */ + + // 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` + Too many curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: '{ ... }'. + + Offending action body: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + break; + +case 45: + /*! Production:: action : ACTION_START action_body ACTION_END */ + + // 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 s = yyvstack[yysp - 1].trim(); + // remove outermost set of braces UNLESS there's + // a curly brace in there anywhere: in that case + // we should leave it up to the sophisticated + // code analyzer to simplify the code! + // + // This is a very rough check as it will also look + // inside code comments, which should not have + // any influence. + // + // Nevertheless: this is a *safe* transform! + if (s[0] === '{' && s.indexOf('}') === s.length - 1) { + this.$ = s.substring(1, s.length - 1).trim(); + } else { + this.$ = s; + } + break; + +case 46: + /*! Production:: action_body : action_body ACTION */ +case 51: + /*! Production:: action_body : action_body 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] + '\n\n' + yyvstack[yysp] + '\n\n'; + break; + +case 47: + /*! Production:: action_body : action_body ACTION_BODY */ +case 48: + /*! Production:: action_body : action_body ACTION_BODY_C_COMMENT */ +case 49: + /*! Production:: action_body : action_body ACTION_BODY_CPP_COMMENT */ +case 50: + /*! Production:: action_body : action_body ACTION_BODY_WHITESPACE */ +case 70: + /*! Production:: regex_concat : regex_concat regex_base */ +case 82: + /*! Production:: regex_base : regex_base range_regex */ +case 92: + /*! Production:: regex_set : regex_set regex_set_atom */ +case 114: + /*! 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 52: + /*! Production:: action_body : action_body INCLUDE_PLACEMENT_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` + You may place the '%include' instruction only at the start/front of a line. + + It's use is not permitted at this position: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + `); + break; + +case 53: + /*! Production:: action_body : action_body 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` + Seems you did not correctly match curly braces '{ ... }' in a lexer rule action block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 54: + /*! Production:: action_body : %epsilon */ +case 65: + /*! Production:: regex_list : %epsilon */ +case 117: + /*! 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 55: + /*! Production:: start_conditions : "<" name_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 - 1]; + break; + +case 56: + /*! Production:: start_conditions : "<" name_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,-,-) + + + yyparser.yyError(rmCommonWS` + Seems you did not correctly terminate the start condition set <${yyvstack[yysp - 1].join(',')},???> with a terminating '>' + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 57: + /*! Production:: start_conditions : "<" "*" ">" */ + + // 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.$ = ['*']; + break; + +case 58: + /*! Production:: start_conditions : %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 59: + /*! Production:: name_list : 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]]; + break; + +case 60: + /*! Production:: name_list : name_list "," 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]; this.$.push(yyvstack[yysp]); + break; + +case 61: + /*! Production:: regex : nonempty_regex_list */ + + // 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,-,-) + + + // Detect if the regex ends with a pure (Unicode) word; + // we *do* consider escaped characters which are 'alphanumeric' + // to be equivalent to their non-escaped version, hence these are + // all valid 'words' for the 'easy keyword rules' option: + // + // - hello_kitty + // - γεια_σου_γατοÏλα + // - \u03B3\u03B5\u03B9\u03B1_\u03C3\u03BF\u03C5_\u03B3\u03B1\u03C4\u03BF\u03CD\u03BB\u03B1 + // + // http://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode#12869914 + // + // As we only check the *tail*, we also accept these as + // 'easy keywords': + // + // - %options + // - %foo-bar + // - +++a:b:c1 + // + // Note the dash in that last example: there the code will consider + // `bar` to be the keyword, which is fine with us as we're only + // interested in the trailing boundary and patching that one for + // the `easy_keyword_rules` option. + this.$ = yyvstack[yysp]; + if (yy.options.easy_keyword_rules) { + // We need to 'protect' `eval` here as keywords are allowed + // to contain double-quotes and other leading cruft. + // `eval` *does* gobble some escapes (such as `\b`) but + // we protect against that through a simple replace regex: + // we're not interested in the special escapes' exact value + // anyway. + // It will also catch escaped escapes (`\\`), which are not + // word characters either, so no need to worry about + // `eval(str)` 'correctly' converting convoluted constructs + // like '\\\\\\\\\\b' in here. + this.$ = this.$ + .replace(/\\\\/g, '.') + .replace(/"/g, '.') + .replace(/\\c[A-Z]/g, '.') + .replace(/\\[^xu0-9]/g, '.'); + + try { + // Convert Unicode escapes and other escapes to their literal characters + // BEFORE we go and check whether this item is subject to the + // `easy_keyword_rules` option. + this.$ = JSON.parse('"' + this.$ + '"'); + } + catch (ex) { + yyparser.warn('easy-keyword-rule FAIL on eval: ', ex); + + // make the next keyword test fail: + this.$ = '.'; + } + // a 'keyword' starts with an alphanumeric character, + // followed by zero or more alphanumerics or digits: + var re = new XRegExp('\\w[\\w\\d]*$'); + if (XRegExp.match(this.$, re)) { + this.$ = yyvstack[yysp] + "\\b"; + } else { + this.$ = yyvstack[yysp]; + } + } + break; + +case 62: + /*! Production:: regex_list : regex_list "|" regex_concat */ +case 66: + /*! Production:: nonempty_regex_list : nonempty_regex_list "|" regex_concat */ + + // 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 63: + /*! Production:: regex_list : regex_list "|" */ +case 67: + /*! Production:: nonempty_regex_list : nonempty_regex_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] + '|'; + break; + +case 68: + /*! Production:: nonempty_regex_list : "|" regex_concat */ + + // 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 72: + /*! Production:: regex_base : "(" regex_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 - 1] + ')'; + break; + +case 73: + /*! Production:: regex_base : SPECIAL_GROUP regex_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 74: + /*! Production:: regex_base : "(" regex_list error */ +case 75: + /*! Production:: regex_base : SPECIAL_GROUP regex_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,-,-) + + + yyparser.yyError(rmCommonWS` + Seems you did not correctly bracket a lex rule regex part in '(...)' braces. + + Unterminated regex part: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 76: + /*! Production:: regex_base : regex_base "+" */ + + // 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] + '+'; + break; + +case 77: + /*! Production:: regex_base : regex_base "*" */ + + // 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] + '*'; + break; + +case 78: + /*! Production:: regex_base : regex_base "?" */ + + // 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] + '?'; + break; + +case 79: + /*! Production:: regex_base : "/" regex_base */ + + // 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 80: + /*! Production:: regex_base : "/!" regex_base */ + + // 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 81: + /*! Production:: regex_base : name_expansion */ +case 83: + /*! Production:: regex_base : any_group_regex */ +case 87: + /*! Production:: regex_base : string */ +case 88: + /*! Production:: regex_base : escape_char */ +case 89: + /*! Production:: name_expansion : NAME_BRACE */ +case 93: + /*! Production:: regex_set : regex_set_atom */ +case 94: + /*! Production:: regex_set_atom : REGEX_SET */ +case 99: + /*! Production:: string : CHARACTER_LIT */ + + // 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,-,-) + break; + +case 84: + /*! Production:: regex_base : "." */ + + // 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.$ = '.'; + break; + +case 85: + /*! Production:: regex_base : "^" */ + + // 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.$ = '^'; + break; + +case 86: + /*! Production:: regex_base : "$" */ + + // 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.$ = '$'; + break; + +case 90: + /*! Production:: any_group_regex : REGEX_SET_START regex_set REGEX_SET_END */ + + // 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 91: + /*! Production:: any_group_regex : REGEX_SET_START regex_set 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 lex rule regex set in '[...]' brackets. + + Unterminated regex set: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 95: + /*! Production:: regex_set_atom : name_expansion */ + + // 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,-,-) + + + if (XRegExp._getUnicodeProperty(yyvstack[yysp].replace(/[{}]/g, '')) + && yyvstack[yysp].toUpperCase() !== yyvstack[yysp] + ) { + // treat this as part of an XRegExp `\p{...}` Unicode 'General Category' Property cf. http://unicode.org/reports/tr18/#Categories + this.$ = yyvstack[yysp]; + } else { + this.$ = yyvstack[yysp]; + } + //yyparser.log("name expansion for: ", { name: $name_expansion, redux: $name_expansion.replace(/[{}]/g, ''), output: $$ }); + break; + +case 98: + /*! Production:: string : STRING_LIT */ + + // 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.$ = prepareString(yyvstack[yysp]); + break; + +case 100: + /*! Production:: options : OPTIONS option_list OPTIONS_END */ + + // 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.$ = null; + break; + +case 101: + /*! Production:: option_list : option option_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.$ = null; + break; + +case 103: + /*! Production:: option : NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp]] = true; + break; + +case 104: + /*! Production:: option : NAME "=" OPTION_STRING_VALUE */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = yyvstack[yysp]; + break; + +case 105: + /*! Production:: option : NAME "=" OPTION_VALUE */ +case 106: + /*! Production:: option : NAME "=" NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = parseValue(yyvstack[yysp]); + break; + +case 107: + /*! 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` + Internal error: option "${$option}" value assignment failure. + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 108: + /*! Production:: option : 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` + Expected a valid option name (with optional value assignment). + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 109: + /*! Production:: extra_lexer_module_code : optional_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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = yyvstack[yysp]; + break; + +case 110: + /*! Production:: extra_lexer_module_code : extra_lexer_module_code include_macro_code optional_module_code_chunk */ + + // 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,-,-) + + + // Each of the 3 chunks should be parse-able as a JS snippet on its own. + // + // Note: we have already checked the first section in a previous reduction + // of this rule, so we don't need to check that one again! + var rv = checkActionBlock(yyvstack[yysp - 1], yylstack[yysp - 1]); + if (rv) { + yyparser.yyError(rmCommonWS` + The source code %include-d into the extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + `); + } + rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = yyvstack[yysp - 2] + yyvstack[yysp - 1] + yyvstack[yysp]; + break; + +case 111: + /*! 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' }); + // 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 112: + /*! 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])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 115: + /*! Production:: module_code_chunk : error CODE */ + + // 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` + Module code declaration error? + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 151: // === 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([ + 13, + 1, + 12, + 15, + 1, + 1, + 11, + 19, + 21, + 2, + 2, + s, + [11, 3], + 4, + 4, + 12, + 4, + 1, + 1, + 19, + 18, + 11, + 12, + 18, + 29, + 30, + 22, + 22, + 17, + 17, + s, + [29, 7], + 31, + 5, + s, + [29, 3], + s, + [12, 4], + 4, + 11, + 3, + 3, + 2, + 2, + 1, + 1, + 12, + 1, + 5, + 4, + 3, + 7, + 17, + 23, + 3, + 19, + 30, + 29, + 30, + s, + [29, 5], + 3, + 20, + 3, + 30, + 30, + 6, + s, + [4, 3], + 12, + 12, + s, + [11, 6], + s, + [27, 3], + s, + [11, 8], + 2, + 11, + 1, + 4, + c, + [55, 3], + 3, + 3, + 17, + 16, + 3, + 3, + 1, + 3, + 7, + s, + [29, 3], + 21, + s, + [29, 4], + 4, + 13, + 13, + s, + [3, 4], + 6, + 3, + 3, + 23, + s, + [18, 3], + 14, + 14, + 1, + 14, + 3, + 1, + 20, + 2, + 17, + 14, + 17, + 3 +]), + symbol: u([ + 1, + 2, + s, + [19, 7, 1], + 28, + 47, + 54, + 56, + 1, + c, + [14, 11], + 57, + c, + [12, 11], + 55, + 58, + 68, + 84, + s, + [1, 3], + c, + [17, 10], + 1, + 2, + 3, + 5, + 9, + 10, + s, + [14, 4, 1], + 19, + 26, + s, + [38, 4, 1], + 44, + 46, + 64, + c, + [15, 6], + c, + [14, 7], + 72, + s, + [74, 5, 1], + 81, + 83, + 27, + 62, + 27, + 63, + c, + [55, 13], + c, + [11, 20], + 2, + 20, + 26, + 60, + c, + [4, 3], + 59, + 2, + s, + [29, 9, 1], + 51, + 69, + 2, + 20, + 85, + 86, + s, + [1, 3], + c, + [102, 16], + 65, + 70, + c, + [19, 17], + 64, + c, + [85, 13], + 9, + c, + [12, 9], + c, + [143, 12], + c, + [141, 6], + c, + [30, 3], + c, + [58, 6], + s, + [20, 7, 1], + 28, + c, + [29, 6], + 47, + c, + [29, 7], + 7, + s, + [9, 9, 1], + c, + [33, 14], + 45, + 46, + 47, + 82, + c, + [58, 3], + 11, + c, + [80, 11], + 73, + c, + [81, 6], + c, + [22, 22], + c, + [121, 12], + c, + [17, 22], + c, + [108, 29], + c, + [29, 199], + s, + [42, 6, 1], + 40, + 43, + 77, + 79, + 80, + c, + [123, 89], + c, + [19, 7], + 27, + c, + [590, 11], + c, + [12, 27], + c, + [611, 3], + 61, + c, + [630, 14], + c, + [3, 3], + 28, + 68, + 28, + 68, + 28, + 28, + c, + [634, 11], + 88, + 48, + 2, + 20, + 48, + 85, + 86, + 2, + 18, + 20, + c, + [9, 4], + 1, + 2, + 51, + 53, + 87, + 89, + 90, + c, + [629, 17], + 3, + c, + [750, 13], + 67, + c, + [751, 8], + 7, + 20, + 71, + c, + [691, 20], + c, + [632, 23], + c, + [662, 65], + c, + [526, 145], + 2, + 9, + 11, + c, + [788, 15], + c, + [808, 7], + 11, + c, + [201, 59], + 82, + 2, + 40, + 42, + 43, + 77, + 80, + c, + [6, 4], + c, + [4, 8], + c, + [495, 33], + c, + [11, 59], + 3, + 4, + c, + [449, 8], + c, + [401, 15], + c, + [27, 54], + c, + [603, 11], + c, + [11, 78], + 52, + c, + [182, 11], + c, + [683, 3], + 49, + 50, + 1, + 51, + 88, + 1, + 53, + 1, + 51, + 1, + 51, + c, + [5, 3], + 53, + c, + [647, 17], + 2, + 4, + c, + [691, 13], + 66, + 2, + 28, + 68, + 2, + 6, + 8, + 6, + c, + [4, 3], + c, + [740, 8], + c, + [648, 57], + c, + [531, 31], + c, + [528, 13], + c, + [756, 8], + c, + [668, 115], + c, + [568, 5], + c, + [321, 10], + 53, + c, + [13, 13], + c, + [1004, 3], + c, + [3, 9], + c, + [273, 4], + c, + [272, 3], + c, + [328, 5], + c, + [310, 14], + c, + [1001, 9], + 1, + c, + [496, 10], + c, + [27, 7], + c, + [18, 36], + c, + [1078, 14], + c, + [14, 14], + 20, + c, + [15, 14], + c, + [461, 3], + 53, + c, + [843, 20], + c, + [480, 3], + c, + [474, 16], + c, + [163, 14], + c, + [505, 18], + 6, + 8 +]), + type: u([ + s, + [2, 11], + 0, + 0, + 1, + c, + [14, 12], + c, + [26, 13], + 0, + c, + [15, 12], + s, + [2, 20], + c, + [32, 14], + s, + [0, 8], + c, + [23, 3], + c, + [57, 32], + c, + [62, 9], + c, + [113, 13], + c, + [67, 4], + c, + [40, 20], + c, + [21, 18], + c, + [96, 36], + c, + [141, 7], + c, + [30, 28], + c, + [221, 43], + c, + [223, 9], + c, + [22, 34], + c, + [17, 34], + s, + [2, 224], + c, + [239, 141], + c, + [139, 19], + c, + [673, 16], + c, + [14, 5], + c, + [180, 13], + c, + [764, 35], + c, + [751, 9], + c, + [98, 19], + c, + [632, 31], + c, + [662, 75], + c, + [511, 151], + c, + [513, 34], + c, + [231, 35], + c, + [821, 238], + c, + [735, 74], + c, + [43, 27], + c, + [740, 39], + c, + [1202, 78], + c, + [756, 30], + c, + [696, 140], + c, + [1001, 31], + c, + [461, 114], + c, + [121, 58] +]), + state: u([ + s, + [1, 4, 1], + 6, + 11, + 12, + 20, + 22, + 23, + 25, + 26, + 31, + 32, + 37, + 36, + 43, + 45, + 47, + 51, + 55, + 56, + 57, + 61, + 62, + 64, + 66, + c, + [16, 5], + 67, + c, + [5, 4], + 71, + 73, + 74, + c, + [13, 5], + 75, + c, + [7, 6], + 76, + c, + [5, 4], + 77, + c, + [5, 4], + 81, + 78, + 79, + 84, + 88, + 89, + 98, + 103, + 57, + 105, + 108, + 107, + 110, + 112, + c, + [67, 7], + 113, + 61, + 62, + 117, + c, + [60, 11], + c, + [6, 6], + 71, + 81, + 125, + 132, + 135, + 137, + 143, + 108, + 107, + c, + [15, 5], + 145, + c, + [32, 5], + 108, + 146, + 148, + c, + [52, 8], + 132, + c, + [23, 5] +]), + mode: u([ + s, + [2, 23], + s, + [1, 12], + c, + [24, 13], + c, + [41, 28], + c, + [44, 15], + c, + [89, 27], + c, + [17, 13], + c, + [88, 11], + c, + [64, 34], + c, + [38, 14], + c, + [123, 15], + c, + [92, 12], + 1, + c, + [107, 10], + c, + [27, 6], + c, + [72, 23], + c, + [40, 8], + c, + [45, 7], + c, + [15, 13], + s, + [1, 24], + s, + [2, 234], + c, + [236, 98], + c, + [97, 24], + c, + [24, 15], + c, + [374, 20], + c, + [432, 5], + c, + [409, 15], + c, + [585, 9], + c, + [47, 20], + c, + [45, 25], + c, + [36, 14], + c, + [578, 18], + c, + [602, 53], + c, + [459, 145], + c, + [735, 19], + c, + [797, 33], + c, + [29, 25], + c, + [776, 238], + c, + [813, 51], + c, + [289, 5], + c, + [648, 7], + c, + [298, 21], + c, + [738, 18], + c, + [621, 8], + c, + [376, 7], + c, + [651, 22], + c, + [874, 59], + c, + [1219, 170], + c, + [960, 9], + c, + [947, 23], + c, + [1151, 89], + c, + [805, 17], + s, + [2, 53] +]), + goto: u([ + s, + [9, 11], + s, + [11, 11], + 8, + 5, + s, + [7, 4, 1], + s, + [13, 7, 1], + s, + [10, 11], + 34, + 21, + s, + [34, 16], + 24, + 27, + 29, + 33, + 34, + 35, + 40, + 28, + 30, + 38, + 39, + 42, + 41, + 44, + 46, + s, + [15, 11], + s, + [16, 11], + s, + [17, 11], + 48, + 49, + 50, + 52, + 53, + s, + [54, 12], + 59, + 58, + 1, + 2, + 7, + 58, + 63, + s, + [58, 6], + 60, + s, + [58, 7], + s, + [34, 17], + s, + [12, 11], + 61, + 61, + 65, + s, + [61, 9], + c, + [125, 12], + s, + [69, 3], + c, + [15, 5], + s, + [69, 7], + 40, + 69, + c, + [23, 7], + 71, + 71, + c, + [3, 3], + 71, + 68, + 70, + s, + [71, 18], + 72, + 71, + 71, + 65, + 65, + 27, + 65, + c, + [68, 11], + c, + [15, 15], + c, + [95, 12], + c, + [12, 12], + s, + [81, 29], + s, + [83, 29], + s, + [84, 29], + s, + [85, 29], + s, + [86, 29], + s, + [87, 29], + s, + [88, 29], + s, + [89, 31], + 38, + 80, + s, + [98, 29], + s, + [99, 29], + s, + [96, 29], + s, + [13, 9], + 82, + 13, + 13, + s, + [29, 12], + s, + [14, 9], + 83, + 14, + 14, + s, + [31, 12], + 85, + 86, + 87, + s, + [20, 11], + s, + [25, 3], + s, + [26, 3], + 16, + 16, + 23, + 24, + 100, + s, + [90, 8, 1], + 99, + 101, + 102, + 59, + 58, + 102, + 103, + 104, + 103, + 103, + s, + [108, 3], + 117, + 106, + 117, + 109, + s, + [33, 17], + 111, + c, + [684, 13], + 114, + 115, + 6, + c, + [630, 8], + 116, + s, + [58, 7], + s, + [67, 3], + c, + [34, 5], + s, + [67, 7], + 40, + 67, + c, + [42, 6], + 67, + s, + [68, 3], + c, + [24, 5], + s, + [68, 7], + 40, + 68, + c, + [24, 6], + 68, + 70, + 70, + 69, + s, + [70, 3], + c, + [7, 3], + s, + [70, 17], + 72, + 70, + 70, + s, + [76, 29], + s, + [77, 29], + s, + [78, 29], + s, + [82, 29], + s, + [97, 29], + 119, + 120, + 118, + 64, + 64, + 27, + 64, + c, + [259, 11], + 122, + 120, + 121, + 79, + 79, + 69, + s, + [79, 3], + 68, + 70, + s, + [79, 18], + 72, + 79, + 79, + 80, + 80, + 69, + s, + [80, 3], + 68, + 70, + s, + [80, 18], + 72, + 80, + 80, + 124, + 38, + 123, + 80, + s, + [93, 4], + s, + [94, 4], + s, + [95, 4], + s, + [30, 12], + s, + [32, 12], + s, + [18, 11], + s, + [19, 11], + s, + [27, 11], + s, + [28, 11], + s, + [21, 11], + s, + [22, 11], + s, + [43, 27], + s, + [44, 27], + s, + [45, 27], + s, + [46, 11], + s, + [47, 11], + s, + [48, 11], + s, + [49, 11], + s, + [50, 11], + s, + [51, 11], + s, + [52, 11], + s, + [53, 11], + 127, + 126, + s, + [100, 11], + 101, + 131, + 130, + 128, + 129, + 3, + 101, + 5, + 133, + 109, + 109, + 116, + 116, + 134, + s, + [113, 3], + s, + [35, 17], + 136, + s, + [40, 14], + 138, + 16, + 140, + 139, + 141, + 142, + s, + [59, 3], + 117, + 144, + 117, + 109, + s, + [66, 3], + c, + [627, 5], + s, + [66, 7], + 40, + 66, + c, + [434, 6], + 66, + s, + [72, 29], + s, + [74, 29], + 63, + 63, + 27, + 63, + c, + [508, 11], + s, + [73, 29], + s, + [75, 29], + s, + [90, 29], + s, + [91, 29], + s, + [92, 4], + s, + [111, 13], + s, + [112, 13], + s, + [104, 3], + s, + [105, 3], + s, + [106, 3], + s, + [107, 3], + c, + [259, 4], + s, + [115, 3], + s, + [114, 3], + 147, + c, + [949, 13], + 38, + 38, + 149, + s, + [38, 15], + s, + [41, 18], + s, + [42, 18], + s, + [55, 14], + s, + [56, 14], + 150, + s, + [57, 14], + 4, + 101, + 133, + 62, + 62, + 27, + 62, + c, + [115, 11], + 110, + 110, + s, + [36, 17], + s, + [39, 14], + s, + [37, 17], + s, + [60, 3] +]) +}), +defaultActions: bda({ + idx: u([ + 0, + 2, + 6, + 11, + 12, + 13, + 16, + 18, + 19, + 21, + 22, + s, + [31, 8, 1], + 40, + 41, + s, + [42, 4, 2], + 49, + 50, + 53, + 54, + 59, + 61, + s, + [68, 5, 1], + s, + [79, 22, 1], + 102, + 103, + 107, + 109, + 110, + 115, + 118, + 119, + s, + [121, 11, 1], + 133, + 134, + s, + [137, 4, 1], + 142, + s, + [146, 5, 1] +]), + goto: u([ + 9, + 11, + 10, + 15, + 16, + 17, + 54, + 1, + 2, + 34, + 12, + 81, + s, + [83, 7, 1], + 98, + 99, + 96, + 29, + 31, + 20, + 25, + 26, + 23, + 24, + 108, + 33, + 76, + 77, + 78, + 82, + 97, + 93, + 94, + 95, + 30, + 32, + 18, + 19, + 27, + 28, + 21, + 22, + s, + [43, 11, 1], + 100, + 101, + 109, + 113, + 35, + 59, + 72, + 74, + 73, + 75, + 90, + 91, + 92, + 111, + 112, + s, + [104, 4, 1], + 115, + 114, + 41, + 42, + 55, + 56, + 57, + 110, + 36, + 39, + 37, + 60 +]) +}), +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 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, 151 /* === 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 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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 rmCommonWS = helpers.rmCommonWS; +var checkActionBlock = helpers.checkActionBlock; + + +function encodeRE(s) { + return s.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1').replace(/\\\\u([a-fA-F0-9]{4})/g, '\\u$1'); +} + +function prepareString(s) { + // unescape slashes + s = s.replace(/\\\\/g, "\\"); + s = encodeRE(s); + return s; +} + +// 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); +}; + +parser.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse:', arguments); +}; + +parser.yy.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse YY:', arguments); +}; + +parser.yy.post_lex = function p_lex() { + if (parser.yydebug) parser.log('post_lex:', 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 <> tokens and perform user action code for a <> 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) { + 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; + switch (yyrulenumber) { + case 0: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %\{ */ + yy.depth = 0; + + yy.include_command_allowed = false; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 1: + /*! Conditions:: action */ + /*! Rule:: %\{([^]*?)%\} */ + yy_.yytext = this.matches[1].replace(/%\\\}/g, '%}'); // unescape any literal '%\}' that exists within the action code block + + yy.include_command_allowed = true; + return 32; + break; + + case 2: + /*! Conditions:: action */ + /*! Rule:: %include\b */ + if (yy.include_command_allowed) { + // This is an include instruction in place of an action: + // + // - one %include per action chunk + // - one %include replaces an entire action chunk + this.pushState('path'); + + return 51; + } else { + // TODO + yy_.yyerror('oops!'); + + return 37; + } + + break; + + case 3: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + //yy.include_command_allowed = false; -- doesn't impact include-allowed state + return 34; + + break; + + case 4: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\/.* */ + yy.include_command_allowed = false; + + return 35; + break; + + case 6: + /*! Conditions:: action */ + /*! Rule:: \| */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 7: + /*! Conditions:: action */ + /*! Rule:: %% */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 9: + /*! Conditions:: action */ + /*! Rule:: \/[^\s/]*?(?:['"`{}][^\s/]*?)*\/ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 10: + /*! Conditions:: action */ + /*! Rule:: \/[^}{BR}]* */ + yy.include_command_allowed = false; + + return 33; + break; + + case 11: + /*! Conditions:: action */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy.include_command_allowed = false; + + return 33; + break; + + case 12: + /*! Conditions:: action */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy.include_command_allowed = false; + + return 33; + break; + + case 13: + /*! Conditions:: action */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy.include_command_allowed = false; + + return 33; + break; + + case 14: + /*! Conditions:: action */ + /*! Rule:: [^{}/"'`|%\{\}{BR}{WS}]+ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 15: + /*! Conditions:: action */ + /*! Rule:: \{ */ + yy.depth++; + + yy.include_command_allowed = false; + return 33; + break; + + case 16: + /*! Conditions:: action */ + /*! Rule:: \} */ + yy.include_command_allowed = false; + + if (yy.depth <= 0) { + yy_.yyerror(rmCommonWS` + too many closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 30; + } else { + yy.depth--; + } + + return 33; + break; + + case 17: + /*! Conditions:: action */ + /*! Rule:: (?:{BR}{WS}+)+(?=[^{WS}{BR}|]) */ + yy.include_command_allowed = true; + + return 36; // keep empty lines as-is inside action code blocks. + break; + + case 18: + /*! Conditions:: action */ + /*! Rule:: {BR} */ + if (yy.depth > 0) { + yy.include_command_allowed = true; + return 36; // keep empty lines as-is inside action code blocks. + } else { + // end of action code chunk + this.popState(); + + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } + + break; + + case 19: + /*! Conditions:: action */ + /*! Rule:: $ */ + yy.include_command_allowed = false; + + if (yy.depth !== 0) { + yy_.yyerror(rmCommonWS` + missing ${yy.depth} closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + yy_.yytext = ''; + return 29; + } + + this.popState(); + yy_.yytext = ''; + return 31; + break; + + case 21: + /*! Conditions:: conditions */ + /*! Rule:: > */ + this.popState(); + + return 6; + break; + + case 24: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 25: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 26: + /*! Conditions:: rules */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 27: + /*! Conditions:: rules */ + /*! Rule:: {WS}+{BR}+ */ + /* empty */ + break; + + case 28: + /*! Conditions:: rules */ + /*! Rule:: \/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 29: + /*! Conditions:: rules */ + /*! Rule:: \/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 30: + /*! Conditions:: rules */ + /*! Rule:: {WS}+(?=[^{WS}{BR}|%]) */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + return 28; + break; + + case 31: + /*! Conditions:: rules */ + /*! Rule:: %% */ + this.popState(); + + this.pushState('code'); + return 19; + break; + + case 32: + /*! Conditions:: rules */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 35: + /*! Conditions:: options */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 49; // value is always a string type + break; + + case 36: + /*! Conditions:: options */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 49; // value is always a string type + break; + + case 37: + /*! Conditions:: options */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy_.yytext = unescQuote(this.matches[1], /\\`/g); + + return 49; // value is always a string type + break; + + case 39: + /*! Conditions:: options */ + /*! Rule:: {BR}{WS}+(?=\S) */ + /* skip leading whitespace on the next line of input, when followed by more options */ + break; + + case 40: + /*! Conditions:: options */ + /*! Rule:: {BR} */ + this.popState(); + + return 48; + break; + + case 41: + /*! Conditions:: options */ + /*! Rule:: {WS}+ */ + /* skip whitespace */ + break; + + case 43: + /*! Conditions:: start_condition */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 44: + /*! Conditions:: start_condition */ + /*! Rule:: {WS}+ */ + /* empty */ + break; + + case 46: + /*! Conditions:: INITIAL */ + /*! Rule:: {ID} */ + this.pushState('macro'); + + return 20; + break; + + case 47: + /*! Conditions:: macro named_chunk */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 48: + /*! Conditions:: macro */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 49: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 50: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \s+ */ + /* empty */ + break; + + case 51: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 26; + break; + + case 52: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 26; + break; + + case 53: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \[ */ + this.pushState('set'); + + return 41; + break; + + case 66: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: < */ + this.pushState('conditions'); + + return 5; + break; + + case 67: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/! */ + return 39; // treated as `(?!atom)` + + break; + + case 68: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/ */ + return 14; // treated as `(?=atom)` + + break; + + case 70: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\. */ + yy_.yytext = yy_.yytext.replace(/^\\/g, ''); + + return 44; + break; + + case 73: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %options\b */ + this.pushState('options'); + + return 47; + break; + + case 74: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %s\b */ + this.pushState('start_condition'); + + return 21; + break; + + case 75: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %x\b */ + this.pushState('start_condition'); + + return 22; + break; + + case 76: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %code\b */ + this.pushState('named_chunk'); + + return 25; + break; + + case 77: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %import\b */ + this.pushState('named_chunk'); + + return 24; + break; + + case 78: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %include\b */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 79: + /*! Conditions:: code */ + /*! Rule:: %include\b */ + this.pushState('path'); + + return 51; + break; + + case 80: + /*! Conditions:: INITIAL rules code */ + /*! Rule:: %{NAME}([^\r\n]*) */ + /* ignore unrecognized decl */ + this.warn(rmCommonWS` + LEX: ignoring unsupported lexer 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 23; + break; + + case 81: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %% */ + this.pushState('rules'); + + return 19; + break; + + case 89: + /*! Conditions:: set */ + /*! Rule:: \] */ + this.popState(); + + return 42; + break; + + case 91: + /*! Conditions:: code */ + /*! Rule:: [^\r\n]+ */ + return 53; // the bit of CODE just before EOF... + + break; + + case 92: + /*! Conditions:: path */ + /*! Rule:: {BR} */ + this.popState(); + + this.unput(yy_.yytext); + break; + + case 93: + /*! Conditions:: path */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 94: + /*! Conditions:: path */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 95: + /*! Conditions:: path */ + /*! Rule:: {WS}+ */ + // skip whitespace in the line + break; + + case 96: + /*! Conditions:: path */ + /*! Rule:: [^\s\r\n]+ */ + this.popState(); + + return 52; + break; + + case 97: + /*! Conditions:: action */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 98: + /*! Conditions:: action */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 99: + /*! Conditions:: action */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 100: + /*! Conditions:: options */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 101: + /*! Conditions:: options */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 102: + /*! Conditions:: options */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 103: + /*! 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 104: + /*! 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 105: + /*! 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 106: + /*! Conditions:: macro rules */ + /*! Rule:: . */ + /* b0rk on bad characters */ + var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + + yy_.yyerror(rmCommonWS` + unsupported lexer input encountered while lexing + ${rules} (i.e. jison lex regexes). + + NOTE: When you want this input to be interpreted as a LITERAL part + of a lex rule regex, you MUST enclose it in double or + single quotes. + + If not, then know that this input is not accepted as a valid + regex expression here in jison-lex ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + break; + + case 107: + /*! Conditions:: * */ + /*! Rule:: . */ + yy_.yyerror(rmCommonWS` + unsupported lexer 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:: {WS}+ */ + 5: 36, + + /*! Conditions:: action */ + /*! Rule:: % */ + 8: 33, + + /*! Conditions:: conditions */ + /*! Rule:: {NAME} */ + 20: 20, + + /*! Conditions:: conditions */ + /*! Rule:: , */ + 22: 8, + + /*! Conditions:: conditions */ + /*! Rule:: \* */ + 23: 7, + + /*! Conditions:: options */ + /*! Rule:: {NAME} */ + 33: 20, + + /*! Conditions:: options */ + /*! Rule:: = */ + 34: 18, + + /*! Conditions:: options */ + /*! Rule:: [^\s\r\n]+ */ + 38: 50, + + /*! Conditions:: start_condition */ + /*! Rule:: {ID} */ + 42: 27, + + /*! Conditions:: named_chunk */ + /*! Rule:: {ID} */ + 45: 20, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \| */ + 54: 9, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?: */ + 55: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?= */ + 56: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?! */ + 57: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \( */ + 58: 10, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \) */ + 59: 11, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \+ */ + 60: 12, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \* */ + 61: 7, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \? */ + 62: 13, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \^ */ + 63: 16, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: , */ + 64: 8, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: <> */ + 65: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\([0-7]{1,3}|[rfntvsSbBwWdD\\*+()${}|[\]\/.^?]|c[A-Z]|x[0-9A-F]{2}|u[a-fA-F0-9]{4}) */ + 69: 44, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \$ */ + 71: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \. */ + 72: 15, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{\d+(,\s*\d+|,)?\} */ + 82: 45, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{{ID}\} */ + 83: 40, + + /*! Conditions:: set options */ + /*! Rule:: \{{ID}\} */ + 84: 40, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{ */ + 85: 3, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \} */ + 86: 4, + + /*! Conditions:: set */ + /*! Rule:: (?:\\\\|\\\]|[^\]{])+ */ + 87: 43, + + /*! Conditions:: set */ + /*! Rule:: \{ */ + 88: 43, + + /*! Conditions:: code */ + /*! Rule:: [^\r\n]*(\r|\n)+ */ + 90: 53, + + /*! Conditions:: * */ + /*! Rule:: $ */ + 108: 1 + }, + + rules: [ + /* 0: */ /^(?:%\{)/, + /* 1: */ new XRegExp('^(?:%\\{([^]*?)%\\})', ''), + /* 2: */ /^(?:%include\b)/, + /* 3: */ new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 4: */ /^(?:([^\S\n\r])*\/\/.*)/, + /* 5: */ /^(?:([^\S\n\r])+)/, + /* 6: */ /^(?:\|)/, + /* 7: */ /^(?:%%)/, + /* 8: */ /^(?:%)/, + /* 9: */ /^(?:\/[^\s\/]*?(?:['"`{}][^\s\/]*?)*\/)/, + /* 10: */ /^(?:\/[^\n\r}]*)/, + /* 11: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 12: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 13: */ /^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 14: */ /^(?:[^\s"%'\/`{-}]+)/, + /* 15: */ /^(?:\{)/, + /* 16: */ /^(?:\})/, + /* 17: */ /^(?:(?:(\r\n|\n|\r)([^\S\n\r])+)+(?=[^\s|]))/, + /* 18: */ /^(?:(\r\n|\n|\r))/, + /* 19: */ /^(?:$)/, + /* 20: */ new XRegExp( + '^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', + '' + ), + /* 21: */ /^(?:>)/, + /* 22: */ /^(?:,)/, + /* 23: */ /^(?:\*)/, + /* 24: */ /^(?:([^\S\n\r])*\/\/[^\n\r]*)/, + /* 25: */ new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 26: */ /^(?:(\r\n|\n|\r)+)/, + /* 27: */ /^(?:([^\S\n\r])+(\r\n|\n|\r)+)/, + /* 28: */ /^(?:\/\/[^\r\n]*)/, + /* 29: */ new XRegExp('^(?:\\/\\*[^]*?\\*\\/)', ''), + /* 30: */ /^(?:([^\S\n\r])+(?=[^\s%|]))/, + /* 31: */ /^(?:%%)/, + /* 32: */ /^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 33: */ new XRegExp( + '^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', + '' + ), + /* 34: */ /^(?:=)/, + /* 35: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 36: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 37: */ /^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 38: */ /^(?:\S+)/, + /* 39: */ /^(?:(\r\n|\n|\r)([^\S\n\r])+(?=\S))/, + /* 40: */ /^(?:(\r\n|\n|\r))/, + /* 41: */ /^(?:([^\S\n\r])+)/, + /* 42: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 43: */ /^(?:(\r\n|\n|\r)+)/, + /* 44: */ /^(?:([^\S\n\r])+)/, + /* 45: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 46: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 47: */ /^(?:(\r\n|\n|\r)+)/, + /* 48: */ /^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 49: */ /^(?:(\r\n|\n|\r)+)/, + /* 50: */ /^(?:\s+)/, + /* 51: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 52: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 53: */ /^(?:\[)/, + /* 54: */ /^(?:\|)/, + /* 55: */ /^(?:\(\?:)/, + /* 56: */ /^(?:\(\?=)/, + /* 57: */ /^(?:\(\?!)/, + /* 58: */ /^(?:\()/, + /* 59: */ /^(?:\))/, + /* 60: */ /^(?:\+)/, + /* 61: */ /^(?:\*)/, + /* 62: */ /^(?:\?)/, + /* 63: */ /^(?:\^)/, + /* 64: */ /^(?:,)/, + /* 65: */ /^(?:<>)/, + /* 66: */ /^(?:<)/, + /* 67: */ /^(?:\/!)/, + /* 68: */ /^(?:\/)/, + /* 69: */ /^(?:\\([0-7]{1,3}|[$(-+.\/?BDSW\[-\^bdfnr-tvw{-}]|c[A-Z]|x[\dA-F]{2}|u[\dA-Fa-f]{4}))/, + /* 70: */ /^(?:\\.)/, + /* 71: */ /^(?:\$)/, + /* 72: */ /^(?:\.)/, + /* 73: */ /^(?:%options\b)/, + /* 74: */ /^(?:%s\b)/, + /* 75: */ /^(?:%x\b)/, + /* 76: */ /^(?:%code\b)/, + /* 77: */ /^(?:%import\b)/, + /* 78: */ /^(?:%include\b)/, + /* 79: */ /^(?:%include\b)/, + /* 80: */ new XRegExp( + '^(?:%([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?)([^\\n\\r]*))', + '' + ), + /* 81: */ /^(?:%%)/, + /* 82: */ /^(?:\{\d+(,\s*\d+|,)?\})/, + /* 83: */ new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 84: */ new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 85: */ /^(?:\{)/, + /* 86: */ /^(?:\})/, + /* 87: */ /^(?:(?:\\\\|\\\]|[^\]{])+)/, + /* 88: */ /^(?:\{)/, + /* 89: */ /^(?:\])/, + /* 90: */ /^(?:[^\r\n]*(\r|\n)+)/, + /* 91: */ /^(?:[^\r\n]+)/, + /* 92: */ /^(?:(\r\n|\n|\r))/, + /* 93: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 94: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 95: */ /^(?:([^\S\n\r])+)/, + /* 96: */ /^(?:\S+)/, + /* 97: */ /^(?:")/, + /* 98: */ /^(?:')/, + /* 99: */ /^(?:`)/, + /* 100: */ /^(?:")/, + /* 101: */ /^(?:')/, + /* 102: */ /^(?:`)/, + /* 103: */ /^(?:")/, + /* 104: */ /^(?:')/, + /* 105: */ /^(?:`)/, + /* 106: */ /^(?:.)/, + /* 107: */ /^(?:.)/, + /* 108: */ /^(?:$)/ + ], + + conditions: { + 'rules': { + rules: [ + 0, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 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, + 74, + 75, + 76, + 77, + 78, + 80, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 106, + 107, + 108 + ], + + inclusive: true + }, + + 'macro': { + rules: [ + 0, + 24, + 25, + 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, + 74, + 75, + 76, + 77, + 78, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 106, + 107, + 108 + ], + + inclusive: true + }, + + 'named_chunk': { + rules: [ + 0, + 45, + 47, + 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, + 74, + 75, + 76, + 77, + 78, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: true + }, + + 'code': { + rules: [79, 80, 90, 91, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'start_condition': { + rules: [24, 25, 42, 43, 44, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'options': { + rules: [ + 24, + 25, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 84, + 100, + 101, + 102, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: false + }, + + 'conditions': { + rules: [20, 21, 22, 23, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'action': { + rules: [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 97, + 98, + 99, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: false + }, + + 'path': { + rules: [24, 25, 92, 93, 94, 95, 96, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'set': { + rules: [84, 87, 88, 89, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'INITIAL': { + rules: [ + 0, + 24, + 25, + 46, + 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, + 74, + 75, + 76, + 77, + 78, + 80, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: true + } + } + }; + + var rmCommonWS = helpers.rmCommonWS; + var dquote = helpers.dquote; + + 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); +} + + + +var lexParser = { + parser, + Parser, + parse: yyparse, + +}; + +export default lexParser; diff --git a/dist/lex-parser-umd-es5.js b/dist/lex-parser-umd-es5.js new file mode 100644 index 0000000..8a1d26d --- /dev/null +++ b/dist/lex-parser-umd-es5.js @@ -0,0 +1,5716 @@ +'use strict'; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _templateObject = _taggedTemplateLiteral(['\n There\'s an error in your lexer regex rules or epilogue.\n Maybe you did not correctly separate the lexer sections with a \'%%\'\n on an otherwise empty line?\n The lexer spec file should have this structure:\n \n definitions\n %%\n rules\n %% // <-- optional!\n extra_module_code // <-- optional epilogue!\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n There\'s an error in your lexer regex rules or epilogue.\n Maybe you did not correctly separate the lexer sections with a \'%%\'\n on an otherwise empty line?\n The lexer spec file should have this structure:\n \n definitions\n %%\n rules\n %% // <-- optional!\n extra_module_code // <-- optional epilogue!\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject2 = _taggedTemplateLiteral(['\n There\'s probably an error in one or more of your lexer regex rules.\n The lexer rule spec should have this structure:\n \n regex action_code\n \n where \'regex\' is a lex-style regex expression (see the\n jison and jison-lex documentation) which is intended to match a chunk\n of the input to lex, while the \'action_code\' block is the JS code\n which will be invoked when the regex is matched. The \'action_code\' block\n may be any (indented!) set of JS statements, optionally surrounded \n by \'{...}\' curly braces or otherwise enclosed in a \'%{...%}\' block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n There\'s probably an error in one or more of your lexer regex rules.\n The lexer rule spec should have this structure:\n \n regex action_code\n \n where \'regex\' is a lex-style regex expression (see the\n jison and jison-lex documentation) which is intended to match a chunk\n of the input to lex, while the \'action_code\' block is the JS code\n which will be invoked when the regex is matched. The \'action_code\' block\n may be any (indented!) set of JS statements, optionally surrounded \n by \'{...}\' curly braces or otherwise enclosed in a \'%{...%}\' block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject3 = _taggedTemplateLiteral(['\n There\'s an error in your lexer epilogue a.k.a. \'extra_module_code\' block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n There\'s an error in your lexer epilogue a.k.a. \'extra_module_code\' block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject4 = _taggedTemplateLiteral(['\n The \'%{...%}\' lexer setup action code section does not compile: ', '\n \n Erroneous area:\n ', '\n '], ['\n The \'%{...%}\' lexer setup action code section does not compile: ', '\n \n Erroneous area:\n ', '\n ']), + _templateObject5 = _taggedTemplateLiteral(['\n You did not specify a legal file path for the \'%import\' initialization code statement, which must have the format:\n %import qualifier_name file_path\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n You did not specify a legal file path for the \'%import\' initialization code statement, which must have the format:\n %import qualifier_name file_path\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject6 = _taggedTemplateLiteral(['\n %import name or source filename missing maybe?\n \n Note: each \'%import\'-ed initialization code section must be qualified by a name, e.g. \'required\' before the import path itself:\n %import qualifier_name file_path\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n %import name or source filename missing maybe?\n \n Note: each \'%import\'-ed initialization code section must be qualified by a name, e.g. \'required\' before the import path itself:\n %import qualifier_name file_path\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject7 = _taggedTemplateLiteral(['\n The \'%code ', '\' action code section does not compile: ', '\n \n Erroneous area:\n ', '\n '], ['\n The \'%code ', '\' action code section does not compile: ', '\n \n Erroneous area:\n ', '\n ']), + _templateObject8 = _taggedTemplateLiteral(['\n Each \'%code\' initialization code section must be qualified by a name, e.g. \'required\' before the action code itself:\n %code qualifier_name {action code}\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Each \'%code\' initialization code section must be qualified by a name, e.g. \'required\' before the action code itself:\n %code qualifier_name {action code}\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject9 = _taggedTemplateLiteral(['\n Seems you made a mistake while specifying one of the lexer rules inside\n the start condition\n <', '> { rules... }\n block.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you made a mistake while specifying one of the lexer rules inside\n the start condition\n <', '> { rules... }\n block.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject10 = _taggedTemplateLiteral(['\n Seems you did not correctly bracket a lexer rules set inside\n the start condition\n <', '> { rules... }\n as a terminating curly brace \'}\' could not be found.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you did not correctly bracket a lexer rules set inside\n the start condition\n <', '> { rules... }\n as a terminating curly brace \'}\' could not be found.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject11 = _taggedTemplateLiteral(['\n The rule\'s action code section does not compile: ', '\n \n Erroneous area:\n ', '\n '], ['\n The rule\'s action code section does not compile: ', '\n \n Erroneous area:\n ', '\n ']), + _templateObject12 = _taggedTemplateLiteral(['\n Lexer rule regex action code declaration error?\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Lexer rule regex action code declaration error?\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject13 = _taggedTemplateLiteral(['\n Missing curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: \'{ ... }\'.\n \n Offending action body:\n ', '\n '], ['\n Missing curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: \'{ ... }\'.\n \n Offending action body:\n ', '\n ']), + _templateObject14 = _taggedTemplateLiteral(['\n Too many curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: \'{ ... }\'.\n \n Offending action body:\n ', '\n '], ['\n Too many curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: \'{ ... }\'.\n \n Offending action body:\n ', '\n ']), + _templateObject15 = _taggedTemplateLiteral(['\n You may place the \'%include\' instruction only at the start/front of a line.\n \n It\'s use is not permitted at this position:\n ', '\n '], ['\n You may place the \'%include\' instruction only at the start/front of a line.\n \n It\'s use is not permitted at this position:\n ', '\n ']), + _templateObject16 = _taggedTemplateLiteral(['\n Seems you did not correctly match curly braces \'{ ... }\' in a lexer rule action block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you did not correctly match curly braces \'{ ... }\' in a lexer rule action block.\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject17 = _taggedTemplateLiteral(['\n Seems you did not correctly terminate the start condition set <', ',???> with a terminating \'>\'\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you did not correctly terminate the start condition set <', ',???> with a terminating \'>\'\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject18 = _taggedTemplateLiteral(['\n Seems you did not correctly bracket a lex rule regex part in \'(...)\' braces.\n \n Unterminated regex part:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you did not correctly bracket a lex rule regex part in \'(...)\' braces.\n \n Unterminated regex part:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject19 = _taggedTemplateLiteral(['\n Seems you did not correctly bracket a lex rule regex set in \'[...]\' brackets.\n \n Unterminated regex set:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Seems you did not correctly bracket a lex rule regex set in \'[...]\' brackets.\n \n Unterminated regex set:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject20 = _taggedTemplateLiteral(['\n Internal error: option "', '" value assignment failure.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Internal error: option "', '" value assignment failure.\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject21 = _taggedTemplateLiteral(['\n Expected a valid option name (with optional value assignment).\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Expected a valid option name (with optional value assignment).\n \n Erroneous area:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject22 = _taggedTemplateLiteral(['\n The extra lexer module code section (a.k.a. \'epilogue\') does not compile: ', '\n \n Erroneous area:\n ', '\n '], ['\n The extra lexer module code section (a.k.a. \'epilogue\') does not compile: ', '\n \n Erroneous area:\n ', '\n ']), + _templateObject23 = _taggedTemplateLiteral(['\n The source code %include-d into the extra lexer module code section (a.k.a. \'epilogue\') does not compile: ', '\n \n Erroneous area:\n ', '\n '], ['\n The source code %include-d into the extra lexer module code section (a.k.a. \'epilogue\') does not compile: ', '\n \n Erroneous area:\n ', '\n ']), + _templateObject24 = _taggedTemplateLiteral(['\n %include MUST be followed by a valid file path.\n \n Erroneous path:\n ', '\n \n Technical error report:\n ', '\n '], ['\n %include MUST be followed by a valid file path.\n \n Erroneous path:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject25 = _taggedTemplateLiteral(['\n Module code declaration error?\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n '], ['\n Module code declaration error?\n \n Erroneous code:\n ', '\n \n Technical error report:\n ', '\n ']), + _templateObject26 = _taggedTemplateLiteral(['\n too many closing curly braces in lexer rule action block.\n\n Note: the action code chunk may be too complex for jison to parse\n easily; we suggest you wrap the action code chunk in \'%{...%}\'\n to help jison grok more or less complex action code chunks.\n\n Erroneous area:\n '], ['\n too many closing curly braces in lexer rule action block.\n\n Note: the action code chunk may be too complex for jison to parse\n easily; we suggest you wrap the action code chunk in \'%{...%}\'\n to help jison grok more or less complex action code chunks.\n\n Erroneous area:\n ']), + _templateObject27 = _taggedTemplateLiteral(['\n missing ', ' closing curly braces in lexer rule action block.\n\n Note: the action code chunk may be too complex for jison to parse\n easily; we suggest you wrap the action code chunk in \'%{...%}\'\n to help jison grok more or less complex action code chunks.\n\n Erroneous area:\n '], ['\n missing ', ' closing curly braces in lexer rule action block.\n\n Note: the action code chunk may be too complex for jison to parse\n easily; we suggest you wrap the action code chunk in \'%{...%}\'\n to help jison grok more or less complex action code chunks.\n\n Erroneous area:\n ']), + _templateObject28 = _taggedTemplateLiteral(['\n LEX: ignoring unsupported lexer option ', '\n while lexing in ', ' state.\n\n Erroneous area:\n '], ['\n LEX: ignoring unsupported lexer option ', '\n while lexing in ', ' state.\n\n Erroneous area:\n ']), + _templateObject29 = _taggedTemplateLiteral(['\n unterminated string constant in lexer rule action block.\n\n Erroneous area:\n '], ['\n unterminated string constant in lexer rule action block.\n\n Erroneous area:\n ']), + _templateObject30 = _taggedTemplateLiteral(['\n unterminated string constant in %options entry.\n\n Erroneous area:\n '], ['\n unterminated string constant in %options entry.\n\n Erroneous area:\n ']), + _templateObject31 = _taggedTemplateLiteral(['\n unterminated string constant encountered while lexing\n ', '.\n\n Erroneous area:\n '], ['\n unterminated string constant encountered while lexing\n ', '.\n\n Erroneous area:\n ']), + _templateObject32 = _taggedTemplateLiteral(['\n unsupported lexer input encountered while lexing\n ', ' (i.e. jison lex regexes).\n\n NOTE: When you want this input to be interpreted as a LITERAL part\n of a lex rule regex, you MUST enclose it in double or\n single quotes.\n\n If not, then know that this input is not accepted as a valid\n regex expression here in jison-lex ', '.\n\n Erroneous area:\n '], ['\n unsupported lexer input encountered while lexing\n ', ' (i.e. jison lex regexes).\n\n NOTE: When you want this input to be interpreted as a LITERAL part\n of a lex rule regex, you MUST enclose it in double or\n single quotes.\n\n If not, then know that this input is not accepted as a valid\n regex expression here in jison-lex ', '.\n\n Erroneous area:\n ']), + _templateObject33 = _taggedTemplateLiteral(['\n unsupported lexer input: ', ' \n while lexing in ', ' state.\n\n Erroneous area:\n '], ['\n unsupported lexer input: ', ' \n while lexing in ', ' state.\n\n Erroneous area:\n ']); + +function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +(function (global, factory) { + (typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@gerhobbelt/xregexp'), require('jison-helpers-lib'), require('fs')) : typeof define === 'function' && define.amd ? define(['@gerhobbelt/xregexp', 'jison-helpers-lib', 'fs'], factory) : global['lex-parser'] = factory(global.XRegExp, global.helpers, global.fs); +})(undefined, function (XRegExp, helpers, fs) { + 'use strict'; + + XRegExp = XRegExp && XRegExp.hasOwnProperty('default') ? XRegExp['default'] : XRegExp; + helpers = helpers && helpers.hasOwnProperty('default') ? helpers['default'] : helpers; + fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; + + // 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. + * } + */ + + // 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_: { + "$": 17, + "$accept": 0, + "$end": 1, + "%%": 19, + "(": 10, + ")": 11, + "*": 7, + "+": 12, + ",": 8, + ".": 15, + "/": 14, + "/!": 39, + "<": 5, + "=": 18, + ">": 6, + "?": 13, + "ACTION": 32, + "ACTION_BODY": 33, + "ACTION_BODY_CPP_COMMENT": 35, + "ACTION_BODY_C_COMMENT": 34, + "ACTION_BODY_WHITESPACE": 36, + "ACTION_END": 31, + "ACTION_START": 28, + "BRACKET_MISSING": 29, + "BRACKET_SURPLUS": 30, + "CHARACTER_LIT": 46, + "CODE": 53, + "EOF": 1, + "ESCAPE_CHAR": 44, + "IMPORT": 24, + "INCLUDE": 51, + "INCLUDE_PLACEMENT_ERROR": 37, + "INIT_CODE": 25, + "NAME": 20, + "NAME_BRACE": 40, + "OPTIONS": 47, + "OPTIONS_END": 48, + "OPTION_STRING_VALUE": 49, + "OPTION_VALUE": 50, + "PATH": 52, + "RANGE_REGEX": 45, + "REGEX_SET": 43, + "REGEX_SET_END": 42, + "REGEX_SET_START": 41, + "SPECIAL_GROUP": 38, + "START_COND": 27, + "START_EXC": 22, + "START_INC": 21, + "STRING_LIT": 26, + "UNKNOWN_DECL": 23, + "^": 16, + "action": 68, + "action_body": 69, + "any_group_regex": 78, + "definition": 58, + "definitions": 57, + "error": 2, + "escape_char": 81, + "extra_lexer_module_code": 87, + "import_name": 60, + "import_path": 61, + "include_macro_code": 88, + "init": 56, + "init_code_name": 59, + "lex": 54, + "module_code_chunk": 89, + "name_expansion": 77, + "name_list": 71, + "names_exclusive": 63, + "names_inclusive": 62, + "nonempty_regex_list": 74, + "option": 86, + "option_list": 85, + "optional_module_code_chunk": 90, + "options": 84, + "range_regex": 82, + "regex": 72, + "regex_base": 76, + "regex_concat": 75, + "regex_list": 73, + "regex_set": 79, + "regex_set_atom": 80, + "rule": 67, + "rule_block": 66, + "rules": 64, + "rules_and_epilogue": 55, + "rules_collective": 65, + "start_conditions": 70, + "string": 83, + "{": 3, + "|": 9, + "}": 4 + }, + terminals_: { + 1: "EOF", + 2: "error", + 3: "{", + 4: "}", + 5: "<", + 6: ">", + 7: "*", + 8: ",", + 9: "|", + 10: "(", + 11: ")", + 12: "+", + 13: "?", + 14: "/", + 15: ".", + 16: "^", + 17: "$", + 18: "=", + 19: "%%", + 20: "NAME", + 21: "START_INC", + 22: "START_EXC", + 23: "UNKNOWN_DECL", + 24: "IMPORT", + 25: "INIT_CODE", + 26: "STRING_LIT", + 27: "START_COND", + 28: "ACTION_START", + 29: "BRACKET_MISSING", + 30: "BRACKET_SURPLUS", + 31: "ACTION_END", + 32: "ACTION", + 33: "ACTION_BODY", + 34: "ACTION_BODY_C_COMMENT", + 35: "ACTION_BODY_CPP_COMMENT", + 36: "ACTION_BODY_WHITESPACE", + 37: "INCLUDE_PLACEMENT_ERROR", + 38: "SPECIAL_GROUP", + 39: "/!", + 40: "NAME_BRACE", + 41: "REGEX_SET_START", + 42: "REGEX_SET_END", + 43: "REGEX_SET", + 44: "ESCAPE_CHAR", + 45: "RANGE_REGEX", + 46: "CHARACTER_LIT", + 47: "OPTIONS", + 48: "OPTIONS_END", + 49: "OPTION_STRING_VALUE", + 50: "OPTION_VALUE", + 51: "INCLUDE", + 52: "PATH", + 53: "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([54, 54, s, [55, 6], 56, 57, 57, s, [58, 11], 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64, s, [65, 4], 66, 66, 67, 67, s, [68, 3], s, [69, 9], s, [70, 4], 71, 71, 72, s, [73, 4], s, [74, 4], 75, 75, s, [76, 17], 77, 78, 78, 79, 79, 80, s, [80, 4, 1], 83, 84, 85, 85, s, [86, 6], 87, 87, 88, 88, s, [89, 3], 90, 90]), + rule: u([s, [4, 3], s, [5, 4, -1], 0, 0, 2, 0, s, [2, 3], s, [1, 3], 3, 3, 2, 3, 3, s, [1, 7], 2, 1, 2, c, [23, 3], 4, c, [32, 4], 2, c, [22, 3], 3, s, [2, 8], 0, s, [3, 3], 0, 1, 3, 1, s, [3, 4, -1], c, [21, 3], c, [40, 3], s, [3, 4], s, [2, 5], c, [12, 3], s, [1, 6], c, [16, 3], c, [10, 8], c, [9, 3], s, [3, 4], c, [10, 4], c, [82, 4], 1, 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 : lex $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:: lex : init definitions rules_and_epilogue EOF */ + + // 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 - 1]; + this.$.macros = yyvstack[yysp - 2].macros; + this.$.startConditions = yyvstack[yysp - 2].startConditions; + this.$.unknownDecls = yyvstack[yysp - 2].unknownDecls; + + // if there are any options, add them all, otherwise set options to NULL: + // can't check for 'empty object' by `if (yy.options) ...` so we do it this way: + for (var k in yy.options) { + this.$.options = yy.options; + break; + } + + if (yy.actionInclude) { + var asrc = yy.actionInclude.join('\n\n'); + // Only a non-empty action code chunk should actually make it through: + if (asrc.trim() !== '') { + this.$.actionInclude = asrc; + } + } + + delete yy.options; + delete yy.actionInclude; + return this.$; + break; + + case 2: + /*! Production:: lex : init definitions error EOF */ + + // 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(_templateObject, yylexer.prettyPrintRange(yylstack[yysp - 1]), yyvstack[yysp - 1].errStr)); + break; + + case 3: + /*! Production:: rules_and_epilogue : "%%" rules "%%" extra_lexer_module_code */ + + // 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,-,-) + + + if (yyvstack[yysp].trim() !== '') { + this.$ = { rules: yyvstack[yysp - 2], moduleInclude: yyvstack[yysp] }; + } else { + this.$ = { rules: yyvstack[yysp - 2] }; + } + break; + + case 4: + /*! Production:: rules_and_epilogue : "%%" error rules "%%" extra_lexer_module_code */ + + // 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(_templateObject2, yylexer.prettyPrintRange(yylstack[yysp - 3]), yyvstack[yysp - 3].errStr)); + break; + + case 5: + /*! Production:: rules_and_epilogue : "%%" rules "%%" 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(_templateObject3, yylexer.prettyPrintRange(yylstack[yysp]), yyvstack[yysp].errStr)); + break; + + case 6: + /*! Production:: rules_and_epilogue : "%%" error rules */ + + // 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(_templateObject2, yylexer.prettyPrintRange(yylstack[yysp - 1]), yyvstack[yysp - 1].errStr)); + break; + + case 7: + /*! Production:: rules_and_epilogue : "%%" rules */ + + // 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.$ = { rules: yyvstack[yysp] }; + break; + + case 8: + /*! Production:: rules_and_epilogue : %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.$ = { rules: [] }; + break; + + case 9: + /*! Production:: init : %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,-,-) + + + yy.actionInclude = []; + if (!yy.options) yy.options = {}; + break; + + case 10: + /*! Production:: definitions : definitions definition */ + + // 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] != null) { + if ('length' in yyvstack[yysp]) { + this.$.macros[yyvstack[yysp][0]] = yyvstack[yysp][1]; + } else if (yyvstack[yysp].type === 'names') { + for (var name in yyvstack[yysp].names) { + this.$.startConditions[name] = yyvstack[yysp].names[name]; + } + } else if (yyvstack[yysp].type === 'unknown') { + this.$.unknownDecls.push(yyvstack[yysp].body); + } + } + break; + + case 11: + /*! Production:: definitions : %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.$ = { + macros: {}, // { hash table } + startConditions: {}, // { hash table } + unknownDecls: [] // [ array of [key,value] pairs } + }; + break; + + case 12: + /*! Production:: definition : NAME regex */ + + // 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 13: + /*! Production:: definition : START_INC names_inclusive */ + case 14: + /*! Production:: definition : START_EXC names_exclusive */ + + // 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 15: + /*! Production:: definition : 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(_templateObject4, rv, yylexer.prettyPrintRange(yylstack[yysp]))); + } + yy.actionInclude.push(yyvstack[yysp]); + this.$ = null; + break; + + case 16: + /*! Production:: definition : options */ + case 102: + /*! Production:: option_list : option */ + + // 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.$ = null; + break; + + case 17: + /*! Production:: definition : 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.$ = { type: 'unknown', body: yyvstack[yysp] }; + break; + + case 18: + /*! Production:: definition : 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.$ = { type: 'imports', name: yyvstack[yysp - 1], path: yyvstack[yysp] }; + break; + + case 19: + /*! Production:: definition : 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(_templateObject5, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 20: + /*! Production:: definition : 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,-,-) + + + yyparser.yyError(rmCommonWS(_templateObject6, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1]), yyvstack[yysp].errStr)); + break; + + case 21: + /*! Production:: definition : INIT_CODE init_code_name 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS(_templateObject7, $init_code_name, rv, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]))); + } + this.$ = { + type: 'codesection', + qualifier: yyvstack[yysp - 1], + include: yyvstack[yysp] + }; + break; + + case 22: + /*! Production:: definition : INIT_CODE error action */ + + // 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(_templateObject8, yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2], yylstack[yysp]), yyvstack[yysp - 1].errStr)); + break; + + case 23: + /*! Production:: init_code_name : NAME */ + case 24: + /*! Production:: init_code_name : STRING_LIT */ + case 25: + /*! Production:: import_name : NAME */ + case 26: + /*! Production:: import_name : STRING_LIT */ + case 27: + /*! Production:: import_path : NAME */ + case 28: + /*! Production:: import_path : STRING_LIT */ + case 64: + /*! Production:: regex_list : regex_concat */ + case 69: + /*! Production:: nonempty_regex_list : regex_concat */ + case 71: + /*! Production:: regex_concat : regex_base */ + case 96: + /*! Production:: escape_char : ESCAPE_CHAR */ + case 97: + /*! Production:: range_regex : RANGE_REGEX */ + case 113: + /*! Production:: module_code_chunk : CODE */ + case 116: + /*! 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 29: + /*! Production:: names_inclusive : START_COND */ + + // 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.$ = { type: 'names', names: {} };this.$.names[yyvstack[yysp]] = 0; + break; + + case 30: + /*! Production:: names_inclusive : names_inclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 0; + break; + + case 31: + /*! Production:: names_exclusive : START_COND */ + + // 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.$ = { type: 'names', names: {} };this.$.names[yyvstack[yysp]] = 1; + break; + + case 32: + /*! Production:: names_exclusive : names_exclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 1; + break; + + case 33: + /*! Production:: rules : rules rules_collective */ + + // 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].concat(yyvstack[yysp]); + break; + + case 34: + /*! Production:: rules : %epsilon */ + case 40: + /*! Production:: rule_block : %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 35: + /*! Production:: rules_collective : start_conditions rule */ + + // 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,-,-) + + + if (yyvstack[yysp - 1]) { + yyvstack[yysp].unshift(yyvstack[yysp - 1]); + } + this.$ = [yyvstack[yysp]]; + break; + + case 36: + /*! Production:: rules_collective : start_conditions "{" rule_block "}" */ + + // 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,-,-) + + + if (yyvstack[yysp - 3]) { + yyvstack[yysp - 1].forEach(function (d) { + d.unshift(yyvstack[yysp - 3]); + }); + } + this.$ = yyvstack[yysp - 1]; + break; + + case 37: + /*! Production:: rules_collective : start_conditions "{" 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(_templateObject9, yyvstack[yysp - 3].join(','), yylexer.prettyPrintRange(yylexer.mergeLocationInfo(yysp - 3, yysp), yylstack[yysp - 3]), yyvstack[yysp - 1].errStr)); + break; + + case 38: + /*! Production:: rules_collective : start_conditions "{" 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(_templateObject10, yyvstack[yysp - 2].join(','), yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 39: + /*! Production:: rule_block : rule_block rule */ + + // 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 41: + /*! Production:: rule : regex 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS(_templateObject11, rv, yylexer.prettyPrintRange(yylstack[yysp]))); + } + this.$ = [yyvstack[yysp - 1], yyvstack[yysp]]; + break; + + case 42: + /*! Production:: rule : regex error */ + + // 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]]; + yyparser.yyError(rmCommonWS(_templateObject12, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1]), yyvstack[yysp].errStr)); + break; + + case 43: + /*! Production:: action : ACTION_START action_body BRACKET_MISSING */ + + // 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(_templateObject13, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]))); + break; + + case 44: + /*! Production:: action : ACTION_START action_body BRACKET_SURPLUS */ + + // 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(_templateObject14, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]))); + break; + + case 45: + /*! Production:: action : ACTION_START action_body ACTION_END */ + + // 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 s = yyvstack[yysp - 1].trim(); + // remove outermost set of braces UNLESS there's + // a curly brace in there anywhere: in that case + // we should leave it up to the sophisticated + // code analyzer to simplify the code! + // + // This is a very rough check as it will also look + // inside code comments, which should not have + // any influence. + // + // Nevertheless: this is a *safe* transform! + if (s[0] === '{' && s.indexOf('}') === s.length - 1) { + this.$ = s.substring(1, s.length - 1).trim(); + } else { + this.$ = s; + } + break; + + case 46: + /*! Production:: action_body : action_body ACTION */ + case 51: + /*! Production:: action_body : action_body 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] + '\n\n' + yyvstack[yysp] + '\n\n'; + break; + + case 47: + /*! Production:: action_body : action_body ACTION_BODY */ + case 48: + /*! Production:: action_body : action_body ACTION_BODY_C_COMMENT */ + case 49: + /*! Production:: action_body : action_body ACTION_BODY_CPP_COMMENT */ + case 50: + /*! Production:: action_body : action_body ACTION_BODY_WHITESPACE */ + case 70: + /*! Production:: regex_concat : regex_concat regex_base */ + case 82: + /*! Production:: regex_base : regex_base range_regex */ + case 92: + /*! Production:: regex_set : regex_set regex_set_atom */ + case 114: + /*! 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 52: + /*! Production:: action_body : action_body INCLUDE_PLACEMENT_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(_templateObject15, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1]))); + break; + + case 53: + /*! Production:: action_body : action_body 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(_templateObject16, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1]), yyvstack[yysp].errStr)); + break; + + case 54: + /*! Production:: action_body : %epsilon */ + case 65: + /*! Production:: regex_list : %epsilon */ + case 117: + /*! 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 55: + /*! Production:: start_conditions : "<" name_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 - 1]; + break; + + case 56: + /*! Production:: start_conditions : "<" name_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,-,-) + + + yyparser.yyError(rmCommonWS(_templateObject17, yyvstack[yysp - 1].join(','), yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 57: + /*! Production:: start_conditions : "<" "*" ">" */ + + // 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.$ = ['*']; + break; + + case 58: + /*! Production:: start_conditions : %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 59: + /*! Production:: name_list : 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]]; + break; + + case 60: + /*! Production:: name_list : name_list "," 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];this.$.push(yyvstack[yysp]); + break; + + case 61: + /*! Production:: regex : nonempty_regex_list */ + + // 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,-,-) + + + // Detect if the regex ends with a pure (Unicode) word; + // we *do* consider escaped characters which are 'alphanumeric' + // to be equivalent to their non-escaped version, hence these are + // all valid 'words' for the 'easy keyword rules' option: + // + // - hello_kitty + // - γεια_σου_γατοÏλα + // - \u03B3\u03B5\u03B9\u03B1_\u03C3\u03BF\u03C5_\u03B3\u03B1\u03C4\u03BF\u03CD\u03BB\u03B1 + // + // http://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode#12869914 + // + // As we only check the *tail*, we also accept these as + // 'easy keywords': + // + // - %options + // - %foo-bar + // - +++a:b:c1 + // + // Note the dash in that last example: there the code will consider + // `bar` to be the keyword, which is fine with us as we're only + // interested in the trailing boundary and patching that one for + // the `easy_keyword_rules` option. + this.$ = yyvstack[yysp]; + if (yy.options.easy_keyword_rules) { + // We need to 'protect' `eval` here as keywords are allowed + // to contain double-quotes and other leading cruft. + // `eval` *does* gobble some escapes (such as `\b`) but + // we protect against that through a simple replace regex: + // we're not interested in the special escapes' exact value + // anyway. + // It will also catch escaped escapes (`\\`), which are not + // word characters either, so no need to worry about + // `eval(str)` 'correctly' converting convoluted constructs + // like '\\\\\\\\\\b' in here. + this.$ = this.$.replace(/\\\\/g, '.').replace(/"/g, '.').replace(/\\c[A-Z]/g, '.').replace(/\\[^xu0-9]/g, '.'); + + try { + // Convert Unicode escapes and other escapes to their literal characters + // BEFORE we go and check whether this item is subject to the + // `easy_keyword_rules` option. + this.$ = JSON.parse('"' + this.$ + '"'); + } catch (ex) { + yyparser.warn('easy-keyword-rule FAIL on eval: ', ex); + + // make the next keyword test fail: + this.$ = '.'; + } + // a 'keyword' starts with an alphanumeric character, + // followed by zero or more alphanumerics or digits: + var re = new XRegExp('\\w[\\w\\d]*$'); + if (XRegExp.match(this.$, re)) { + this.$ = yyvstack[yysp] + "\\b"; + } else { + this.$ = yyvstack[yysp]; + } + } + break; + + case 62: + /*! Production:: regex_list : regex_list "|" regex_concat */ + case 66: + /*! Production:: nonempty_regex_list : nonempty_regex_list "|" regex_concat */ + + // 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 63: + /*! Production:: regex_list : regex_list "|" */ + case 67: + /*! Production:: nonempty_regex_list : nonempty_regex_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] + '|'; + break; + + case 68: + /*! Production:: nonempty_regex_list : "|" regex_concat */ + + // 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 72: + /*! Production:: regex_base : "(" regex_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 - 1] + ')'; + break; + + case 73: + /*! Production:: regex_base : SPECIAL_GROUP regex_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 74: + /*! Production:: regex_base : "(" regex_list error */ + case 75: + /*! Production:: regex_base : SPECIAL_GROUP regex_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,-,-) + + + yyparser.yyError(rmCommonWS(_templateObject18, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 76: + /*! Production:: regex_base : regex_base "+" */ + + // 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] + '+'; + break; + + case 77: + /*! Production:: regex_base : regex_base "*" */ + + // 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] + '*'; + break; + + case 78: + /*! Production:: regex_base : regex_base "?" */ + + // 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] + '?'; + break; + + case 79: + /*! Production:: regex_base : "/" regex_base */ + + // 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 80: + /*! Production:: regex_base : "/!" regex_base */ + + // 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 81: + /*! Production:: regex_base : name_expansion */ + case 83: + /*! Production:: regex_base : any_group_regex */ + case 87: + /*! Production:: regex_base : string */ + case 88: + /*! Production:: regex_base : escape_char */ + case 89: + /*! Production:: name_expansion : NAME_BRACE */ + case 93: + /*! Production:: regex_set : regex_set_atom */ + case 94: + /*! Production:: regex_set_atom : REGEX_SET */ + case 99: + /*! Production:: string : CHARACTER_LIT */ + + // 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,-,-) + break; + + case 84: + /*! Production:: regex_base : "." */ + + // 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.$ = '.'; + break; + + case 85: + /*! Production:: regex_base : "^" */ + + // 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.$ = '^'; + break; + + case 86: + /*! Production:: regex_base : "$" */ + + // 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.$ = '$'; + break; + + case 90: + /*! Production:: any_group_regex : REGEX_SET_START regex_set REGEX_SET_END */ + + // 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 91: + /*! Production:: any_group_regex : REGEX_SET_START regex_set 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(_templateObject19, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 95: + /*! Production:: regex_set_atom : name_expansion */ + + // 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,-,-) + + + if (XRegExp._getUnicodeProperty(yyvstack[yysp].replace(/[{}]/g, '')) && yyvstack[yysp].toUpperCase() !== yyvstack[yysp]) { + // treat this as part of an XRegExp `\p{...}` Unicode 'General Category' Property cf. http://unicode.org/reports/tr18/#Categories + this.$ = yyvstack[yysp]; + } else { + this.$ = yyvstack[yysp]; + } + //yyparser.log("name expansion for: ", { name: $name_expansion, redux: $name_expansion.replace(/[{}]/g, ''), output: $$ }); + break; + + case 98: + /*! Production:: string : STRING_LIT */ + + // 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.$ = prepareString(yyvstack[yysp]); + break; + + case 100: + /*! Production:: options : OPTIONS option_list OPTIONS_END */ + + // 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.$ = null; + break; + + case 101: + /*! Production:: option_list : option option_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.$ = null; + break; + + case 103: + /*! Production:: option : NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp]] = true; + break; + + case 104: + /*! Production:: option : NAME "=" OPTION_STRING_VALUE */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = yyvstack[yysp]; + break; + + case 105: + /*! Production:: option : NAME "=" OPTION_VALUE */ + case 106: + /*! Production:: option : NAME "=" NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = parseValue(yyvstack[yysp]); + break; + + case 107: + /*! 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(_templateObject20, $option, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2]), yyvstack[yysp].errStr)); + break; + + case 108: + /*! Production:: option : 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(_templateObject21, yylexer.prettyPrintRange(yylstack[yysp]), yyvstack[yysp].errStr)); + break; + + case 109: + /*! Production:: extra_lexer_module_code : optional_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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS(_templateObject22, rv, yylexer.prettyPrintRange(yylstack[yysp]))); + } + this.$ = yyvstack[yysp]; + break; + + case 110: + /*! Production:: extra_lexer_module_code : extra_lexer_module_code include_macro_code optional_module_code_chunk */ + + // 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,-,-) + + + // Each of the 3 chunks should be parse-able as a JS snippet on its own. + // + // Note: we have already checked the first section in a previous reduction + // of this rule, so we don't need to check that one again! + var rv = checkActionBlock(yyvstack[yysp - 1], yylstack[yysp - 1]); + if (rv) { + yyparser.yyError(rmCommonWS(_templateObject23, rv, yylexer.prettyPrintRange(yylstack[yysp - 1]))); + } + rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS(_templateObject22, rv, yylexer.prettyPrintRange(yylstack[yysp]))); + } + this.$ = yyvstack[yysp - 2] + yyvstack[yysp - 1] + yyvstack[yysp]; + break; + + case 111: + /*! 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' }); + // 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 112: + /*! 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(_templateObject24, yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1]), yyvstack[yysp].errStr)); + break; + + case 115: + /*! Production:: module_code_chunk : error CODE */ + + // 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(_templateObject25, yylexer.prettyPrintRange(yylstack[yysp - 1]), yyvstack[yysp - 1].errStr)); + break; + + case 151: + // === 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([13, 1, 12, 15, 1, 1, 11, 19, 21, 2, 2, s, [11, 3], 4, 4, 12, 4, 1, 1, 19, 18, 11, 12, 18, 29, 30, 22, 22, 17, 17, s, [29, 7], 31, 5, s, [29, 3], s, [12, 4], 4, 11, 3, 3, 2, 2, 1, 1, 12, 1, 5, 4, 3, 7, 17, 23, 3, 19, 30, 29, 30, s, [29, 5], 3, 20, 3, 30, 30, 6, s, [4, 3], 12, 12, s, [11, 6], s, [27, 3], s, [11, 8], 2, 11, 1, 4, c, [55, 3], 3, 3, 17, 16, 3, 3, 1, 3, 7, s, [29, 3], 21, s, [29, 4], 4, 13, 13, s, [3, 4], 6, 3, 3, 23, s, [18, 3], 14, 14, 1, 14, 3, 1, 20, 2, 17, 14, 17, 3]), + symbol: u([1, 2, s, [19, 7, 1], 28, 47, 54, 56, 1, c, [14, 11], 57, c, [12, 11], 55, 58, 68, 84, s, [1, 3], c, [17, 10], 1, 2, 3, 5, 9, 10, s, [14, 4, 1], 19, 26, s, [38, 4, 1], 44, 46, 64, c, [15, 6], c, [14, 7], 72, s, [74, 5, 1], 81, 83, 27, 62, 27, 63, c, [55, 13], c, [11, 20], 2, 20, 26, 60, c, [4, 3], 59, 2, s, [29, 9, 1], 51, 69, 2, 20, 85, 86, s, [1, 3], c, [102, 16], 65, 70, c, [19, 17], 64, c, [85, 13], 9, c, [12, 9], c, [143, 12], c, [141, 6], c, [30, 3], c, [58, 6], s, [20, 7, 1], 28, c, [29, 6], 47, c, [29, 7], 7, s, [9, 9, 1], c, [33, 14], 45, 46, 47, 82, c, [58, 3], 11, c, [80, 11], 73, c, [81, 6], c, [22, 22], c, [121, 12], c, [17, 22], c, [108, 29], c, [29, 199], s, [42, 6, 1], 40, 43, 77, 79, 80, c, [123, 89], c, [19, 7], 27, c, [590, 11], c, [12, 27], c, [611, 3], 61, c, [630, 14], c, [3, 3], 28, 68, 28, 68, 28, 28, c, [634, 11], 88, 48, 2, 20, 48, 85, 86, 2, 18, 20, c, [9, 4], 1, 2, 51, 53, 87, 89, 90, c, [629, 17], 3, c, [750, 13], 67, c, [751, 8], 7, 20, 71, c, [691, 20], c, [632, 23], c, [662, 65], c, [526, 145], 2, 9, 11, c, [788, 15], c, [808, 7], 11, c, [201, 59], 82, 2, 40, 42, 43, 77, 80, c, [6, 4], c, [4, 8], c, [495, 33], c, [11, 59], 3, 4, c, [449, 8], c, [401, 15], c, [27, 54], c, [603, 11], c, [11, 78], 52, c, [182, 11], c, [683, 3], 49, 50, 1, 51, 88, 1, 53, 1, 51, 1, 51, c, [5, 3], 53, c, [647, 17], 2, 4, c, [691, 13], 66, 2, 28, 68, 2, 6, 8, 6, c, [4, 3], c, [740, 8], c, [648, 57], c, [531, 31], c, [528, 13], c, [756, 8], c, [668, 115], c, [568, 5], c, [321, 10], 53, c, [13, 13], c, [1004, 3], c, [3, 9], c, [273, 4], c, [272, 3], c, [328, 5], c, [310, 14], c, [1001, 9], 1, c, [496, 10], c, [27, 7], c, [18, 36], c, [1078, 14], c, [14, 14], 20, c, [15, 14], c, [461, 3], 53, c, [843, 20], c, [480, 3], c, [474, 16], c, [163, 14], c, [505, 18], 6, 8]), + type: u([s, [2, 11], 0, 0, 1, c, [14, 12], c, [26, 13], 0, c, [15, 12], s, [2, 20], c, [32, 14], s, [0, 8], c, [23, 3], c, [57, 32], c, [62, 9], c, [113, 13], c, [67, 4], c, [40, 20], c, [21, 18], c, [96, 36], c, [141, 7], c, [30, 28], c, [221, 43], c, [223, 9], c, [22, 34], c, [17, 34], s, [2, 224], c, [239, 141], c, [139, 19], c, [673, 16], c, [14, 5], c, [180, 13], c, [764, 35], c, [751, 9], c, [98, 19], c, [632, 31], c, [662, 75], c, [511, 151], c, [513, 34], c, [231, 35], c, [821, 238], c, [735, 74], c, [43, 27], c, [740, 39], c, [1202, 78], c, [756, 30], c, [696, 140], c, [1001, 31], c, [461, 114], c, [121, 58]]), + state: u([s, [1, 4, 1], 6, 11, 12, 20, 22, 23, 25, 26, 31, 32, 37, 36, 43, 45, 47, 51, 55, 56, 57, 61, 62, 64, 66, c, [16, 5], 67, c, [5, 4], 71, 73, 74, c, [13, 5], 75, c, [7, 6], 76, c, [5, 4], 77, c, [5, 4], 81, 78, 79, 84, 88, 89, 98, 103, 57, 105, 108, 107, 110, 112, c, [67, 7], 113, 61, 62, 117, c, [60, 11], c, [6, 6], 71, 81, 125, 132, 135, 137, 143, 108, 107, c, [15, 5], 145, c, [32, 5], 108, 146, 148, c, [52, 8], 132, c, [23, 5]]), + mode: u([s, [2, 23], s, [1, 12], c, [24, 13], c, [41, 28], c, [44, 15], c, [89, 27], c, [17, 13], c, [88, 11], c, [64, 34], c, [38, 14], c, [123, 15], c, [92, 12], 1, c, [107, 10], c, [27, 6], c, [72, 23], c, [40, 8], c, [45, 7], c, [15, 13], s, [1, 24], s, [2, 234], c, [236, 98], c, [97, 24], c, [24, 15], c, [374, 20], c, [432, 5], c, [409, 15], c, [585, 9], c, [47, 20], c, [45, 25], c, [36, 14], c, [578, 18], c, [602, 53], c, [459, 145], c, [735, 19], c, [797, 33], c, [29, 25], c, [776, 238], c, [813, 51], c, [289, 5], c, [648, 7], c, [298, 21], c, [738, 18], c, [621, 8], c, [376, 7], c, [651, 22], c, [874, 59], c, [1219, 170], c, [960, 9], c, [947, 23], c, [1151, 89], c, [805, 17], s, [2, 53]]), + goto: u([s, [9, 11], s, [11, 11], 8, 5, s, [7, 4, 1], s, [13, 7, 1], s, [10, 11], 34, 21, s, [34, 16], 24, 27, 29, 33, 34, 35, 40, 28, 30, 38, 39, 42, 41, 44, 46, s, [15, 11], s, [16, 11], s, [17, 11], 48, 49, 50, 52, 53, s, [54, 12], 59, 58, 1, 2, 7, 58, 63, s, [58, 6], 60, s, [58, 7], s, [34, 17], s, [12, 11], 61, 61, 65, s, [61, 9], c, [125, 12], s, [69, 3], c, [15, 5], s, [69, 7], 40, 69, c, [23, 7], 71, 71, c, [3, 3], 71, 68, 70, s, [71, 18], 72, 71, 71, 65, 65, 27, 65, c, [68, 11], c, [15, 15], c, [95, 12], c, [12, 12], s, [81, 29], s, [83, 29], s, [84, 29], s, [85, 29], s, [86, 29], s, [87, 29], s, [88, 29], s, [89, 31], 38, 80, s, [98, 29], s, [99, 29], s, [96, 29], s, [13, 9], 82, 13, 13, s, [29, 12], s, [14, 9], 83, 14, 14, s, [31, 12], 85, 86, 87, s, [20, 11], s, [25, 3], s, [26, 3], 16, 16, 23, 24, 100, s, [90, 8, 1], 99, 101, 102, 59, 58, 102, 103, 104, 103, 103, s, [108, 3], 117, 106, 117, 109, s, [33, 17], 111, c, [684, 13], 114, 115, 6, c, [630, 8], 116, s, [58, 7], s, [67, 3], c, [34, 5], s, [67, 7], 40, 67, c, [42, 6], 67, s, [68, 3], c, [24, 5], s, [68, 7], 40, 68, c, [24, 6], 68, 70, 70, 69, s, [70, 3], c, [7, 3], s, [70, 17], 72, 70, 70, s, [76, 29], s, [77, 29], s, [78, 29], s, [82, 29], s, [97, 29], 119, 120, 118, 64, 64, 27, 64, c, [259, 11], 122, 120, 121, 79, 79, 69, s, [79, 3], 68, 70, s, [79, 18], 72, 79, 79, 80, 80, 69, s, [80, 3], 68, 70, s, [80, 18], 72, 80, 80, 124, 38, 123, 80, s, [93, 4], s, [94, 4], s, [95, 4], s, [30, 12], s, [32, 12], s, [18, 11], s, [19, 11], s, [27, 11], s, [28, 11], s, [21, 11], s, [22, 11], s, [43, 27], s, [44, 27], s, [45, 27], s, [46, 11], s, [47, 11], s, [48, 11], s, [49, 11], s, [50, 11], s, [51, 11], s, [52, 11], s, [53, 11], 127, 126, s, [100, 11], 101, 131, 130, 128, 129, 3, 101, 5, 133, 109, 109, 116, 116, 134, s, [113, 3], s, [35, 17], 136, s, [40, 14], 138, 16, 140, 139, 141, 142, s, [59, 3], 117, 144, 117, 109, s, [66, 3], c, [627, 5], s, [66, 7], 40, 66, c, [434, 6], 66, s, [72, 29], s, [74, 29], 63, 63, 27, 63, c, [508, 11], s, [73, 29], s, [75, 29], s, [90, 29], s, [91, 29], s, [92, 4], s, [111, 13], s, [112, 13], s, [104, 3], s, [105, 3], s, [106, 3], s, [107, 3], c, [259, 4], s, [115, 3], s, [114, 3], 147, c, [949, 13], 38, 38, 149, s, [38, 15], s, [41, 18], s, [42, 18], s, [55, 14], s, [56, 14], 150, s, [57, 14], 4, 101, 133, 62, 62, 27, 62, c, [115, 11], 110, 110, s, [36, 17], s, [39, 14], s, [37, 17], s, [60, 3]]) + }), + defaultActions: bda({ + idx: u([0, 2, 6, 11, 12, 13, 16, 18, 19, 21, 22, s, [31, 8, 1], 40, 41, s, [42, 4, 2], 49, 50, 53, 54, 59, 61, s, [68, 5, 1], s, [79, 22, 1], 102, 103, 107, 109, 110, 115, 118, 119, s, [121, 11, 1], 133, 134, s, [137, 4, 1], 142, s, [146, 5, 1]]), + goto: u([9, 11, 10, 15, 16, 17, 54, 1, 2, 34, 12, 81, s, [83, 7, 1], 98, 99, 96, 29, 31, 20, 25, 26, 23, 24, 108, 33, 76, 77, 78, 82, 97, 93, 94, 95, 30, 32, 18, 19, 27, 28, 21, 22, s, [43, 11, 1], 100, 101, 109, 113, 35, 59, 72, 74, 73, 75, 90, 91, 92, 111, 112, s, [104, 4, 1], 115, 114, 41, 42, 55, 56, 57, 110, 36, 39, 37, 60]) + }), + 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 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, 151 /* === 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 === 'undefined' ? 'undefined' : _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 === 'undefined' ? 'undefined' : _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 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 + + var 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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 rmCommonWS = helpers.rmCommonWS; + var checkActionBlock = helpers.checkActionBlock; + + function encodeRE(s) { + return s.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1').replace(/\\\\u([a-fA-F0-9]{4})/g, '\\u$1'); + } + + function prepareString(s) { + // unescape slashes + s = s.replace(/\\\\/g, "\\"); + s = encodeRE(s); + return s; + } + + // 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); + }; + + parser.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse:', arguments); + }; + + parser.yy.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse YY:', arguments); + }; + + parser.yy.post_lex = function p_lex() { + if (parser.yydebug) parser.log('post_lex:', 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 === 'undefined' ? 'undefined' : _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 <> tokens and perform user action code for a <> 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 CONTEXT = 3; + var CONTEXT_TAIL = 1; + var 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; + switch (yyrulenumber) { + case 0: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %\{ */ + yy.depth = 0; + + yy.include_command_allowed = false; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 1: + /*! Conditions:: action */ + /*! Rule:: %\{([^]*?)%\} */ + yy_.yytext = this.matches[1].replace(/%\\\}/g, '%}'); // unescape any literal '%\}' that exists within the action code block + + yy.include_command_allowed = true; + return 32; + break; + + case 2: + /*! Conditions:: action */ + /*! Rule:: %include\b */ + if (yy.include_command_allowed) { + // This is an include instruction in place of an action: + // + // - one %include per action chunk + // - one %include replaces an entire action chunk + this.pushState('path'); + + return 51; + } else { + // TODO + yy_.yyerror('oops!'); + + return 37; + } + + break; + + case 3: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + //yy.include_command_allowed = false; -- doesn't impact include-allowed state + return 34; + + break; + + case 4: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\/.* */ + yy.include_command_allowed = false; + + return 35; + break; + + case 6: + /*! Conditions:: action */ + /*! Rule:: \| */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 7: + /*! Conditions:: action */ + /*! Rule:: %% */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 9: + /*! Conditions:: action */ + /*! Rule:: \/[^\s/]*?(?:['"`{}][^\s/]*?)*\/ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 10: + /*! Conditions:: action */ + /*! Rule:: \/[^}{BR}]* */ + yy.include_command_allowed = false; + + return 33; + break; + + case 11: + /*! Conditions:: action */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy.include_command_allowed = false; + + return 33; + break; + + case 12: + /*! Conditions:: action */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy.include_command_allowed = false; + + return 33; + break; + + case 13: + /*! Conditions:: action */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy.include_command_allowed = false; + + return 33; + break; + + case 14: + /*! Conditions:: action */ + /*! Rule:: [^{}/"'`|%\{\}{BR}{WS}]+ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 15: + /*! Conditions:: action */ + /*! Rule:: \{ */ + yy.depth++; + + yy.include_command_allowed = false; + return 33; + break; + + case 16: + /*! Conditions:: action */ + /*! Rule:: \} */ + yy.include_command_allowed = false; + + if (yy.depth <= 0) { + yy_.yyerror(rmCommonWS(_templateObject26) + this.prettyPrintRange(yy_.yylloc)); + + return 30; + } else { + yy.depth--; + } + + return 33; + break; + + case 17: + /*! Conditions:: action */ + /*! Rule:: (?:{BR}{WS}+)+(?=[^{WS}{BR}|]) */ + yy.include_command_allowed = true; + + return 36; // keep empty lines as-is inside action code blocks. + break; + + case 18: + /*! Conditions:: action */ + /*! Rule:: {BR} */ + if (yy.depth > 0) { + yy.include_command_allowed = true; + return 36; // keep empty lines as-is inside action code blocks. + } else { + // end of action code chunk + this.popState(); + + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } + + break; + + case 19: + /*! Conditions:: action */ + /*! Rule:: $ */ + yy.include_command_allowed = false; + + if (yy.depth !== 0) { + yy_.yyerror(rmCommonWS(_templateObject27, yy.depth) + this.prettyPrintRange(yy_.yylloc)); + + yy_.yytext = ''; + return 29; + } + + this.popState(); + yy_.yytext = ''; + return 31; + break; + + case 21: + /*! Conditions:: conditions */ + /*! Rule:: > */ + this.popState(); + + return 6; + break; + + case 24: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 25: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 26: + /*! Conditions:: rules */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 27: + /*! Conditions:: rules */ + /*! Rule:: {WS}+{BR}+ */ + /* empty */ + break; + + case 28: + /*! Conditions:: rules */ + /*! Rule:: \/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 29: + /*! Conditions:: rules */ + /*! Rule:: \/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 30: + /*! Conditions:: rules */ + /*! Rule:: {WS}+(?=[^{WS}{BR}|%]) */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + return 28; + break; + + case 31: + /*! Conditions:: rules */ + /*! Rule:: %% */ + this.popState(); + + this.pushState('code'); + return 19; + break; + + case 32: + /*! Conditions:: rules */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 35: + /*! Conditions:: options */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 49; // value is always a string type + break; + + case 36: + /*! Conditions:: options */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 49; // value is always a string type + break; + + case 37: + /*! Conditions:: options */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy_.yytext = unescQuote(this.matches[1], /\\`/g); + + return 49; // value is always a string type + break; + + case 39: + /*! Conditions:: options */ + /*! Rule:: {BR}{WS}+(?=\S) */ + /* skip leading whitespace on the next line of input, when followed by more options */ + break; + + case 40: + /*! Conditions:: options */ + /*! Rule:: {BR} */ + this.popState(); + + return 48; + break; + + case 41: + /*! Conditions:: options */ + /*! Rule:: {WS}+ */ + /* skip whitespace */ + break; + + case 43: + /*! Conditions:: start_condition */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 44: + /*! Conditions:: start_condition */ + /*! Rule:: {WS}+ */ + /* empty */ + break; + + case 46: + /*! Conditions:: INITIAL */ + /*! Rule:: {ID} */ + this.pushState('macro'); + + return 20; + break; + + case 47: + /*! Conditions:: macro named_chunk */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 48: + /*! Conditions:: macro */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 49: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 50: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \s+ */ + /* empty */ + break; + + case 51: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 26; + break; + + case 52: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 26; + break; + + case 53: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \[ */ + this.pushState('set'); + + return 41; + break; + + case 66: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: < */ + this.pushState('conditions'); + + return 5; + break; + + case 67: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/! */ + return 39; // treated as `(?!atom)` + + break; + + case 68: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/ */ + return 14; // treated as `(?=atom)` + + break; + + case 70: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\. */ + yy_.yytext = yy_.yytext.replace(/^\\/g, ''); + + return 44; + break; + + case 73: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %options\b */ + this.pushState('options'); + + return 47; + break; + + case 74: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %s\b */ + this.pushState('start_condition'); + + return 21; + break; + + case 75: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %x\b */ + this.pushState('start_condition'); + + return 22; + break; + + case 76: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %code\b */ + this.pushState('named_chunk'); + + return 25; + break; + + case 77: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %import\b */ + this.pushState('named_chunk'); + + return 24; + break; + + case 78: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %include\b */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 79: + /*! Conditions:: code */ + /*! Rule:: %include\b */ + this.pushState('path'); + + return 51; + break; + + case 80: + /*! Conditions:: INITIAL rules code */ + /*! Rule:: %{NAME}([^\r\n]*) */ + /* ignore unrecognized decl */ + this.warn(rmCommonWS(_templateObject28, dquote(yy_.yytext), dquote(this.topState())) + this.prettyPrintRange(yy_.yylloc)); + + yy_.yytext = [this.matches[1], // {NAME} + this.matches[2].trim() // optional value/parameters + ]; + + return 23; + break; + + case 81: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %% */ + this.pushState('rules'); + + return 19; + break; + + case 89: + /*! Conditions:: set */ + /*! Rule:: \] */ + this.popState(); + + return 42; + break; + + case 91: + /*! Conditions:: code */ + /*! Rule:: [^\r\n]+ */ + return 53; // the bit of CODE just before EOF... + + break; + + case 92: + /*! Conditions:: path */ + /*! Rule:: {BR} */ + this.popState(); + + this.unput(yy_.yytext); + break; + + case 93: + /*! Conditions:: path */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 94: + /*! Conditions:: path */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 95: + /*! Conditions:: path */ + /*! Rule:: {WS}+ */ + // skip whitespace in the line + break; + + case 96: + /*! Conditions:: path */ + /*! Rule:: [^\s\r\n]+ */ + this.popState(); + + return 52; + break; + + case 97: + /*! Conditions:: action */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS(_templateObject29) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 98: + /*! Conditions:: action */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS(_templateObject29) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 99: + /*! Conditions:: action */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS(_templateObject29) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 100: + /*! Conditions:: options */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS(_templateObject30) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 101: + /*! Conditions:: options */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS(_templateObject30) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 102: + /*! Conditions:: options */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS(_templateObject30) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 103: + /*! Conditions:: * */ + /*! Rule:: " */ + var rules = this.topState() === 'macro' ? 'macro\'s' : this.topState(); + + yy_.yyerror(rmCommonWS(_templateObject31, rules) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 104: + /*! Conditions:: * */ + /*! Rule:: ' */ + var rules = this.topState() === 'macro' ? 'macro\'s' : this.topState(); + + yy_.yyerror(rmCommonWS(_templateObject31, rules) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 105: + /*! Conditions:: * */ + /*! Rule:: ` */ + var rules = this.topState() === 'macro' ? 'macro\'s' : this.topState(); + + yy_.yyerror(rmCommonWS(_templateObject31, rules) + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 106: + /*! Conditions:: macro rules */ + /*! Rule:: . */ + /* b0rk on bad characters */ + var rules = this.topState() === 'macro' ? 'macro\'s' : this.topState(); + + yy_.yyerror(rmCommonWS(_templateObject32, rules, rules) + this.prettyPrintRange(yy_.yylloc)); + + break; + + case 107: + /*! Conditions:: * */ + /*! Rule:: . */ + yy_.yyerror(rmCommonWS(_templateObject33, dquote(yy_.yytext), dquote(this.topState())) + this.prettyPrintRange(yy_.yylloc)); + + break; + + default: + return this.simpleCaseActionClusters[yyrulenumber]; + } + }, + + simpleCaseActionClusters: { + /*! Conditions:: action */ + /*! Rule:: {WS}+ */ + 5: 36, + + /*! Conditions:: action */ + /*! Rule:: % */ + 8: 33, + + /*! Conditions:: conditions */ + /*! Rule:: {NAME} */ + 20: 20, + + /*! Conditions:: conditions */ + /*! Rule:: , */ + 22: 8, + + /*! Conditions:: conditions */ + /*! Rule:: \* */ + 23: 7, + + /*! Conditions:: options */ + /*! Rule:: {NAME} */ + 33: 20, + + /*! Conditions:: options */ + /*! Rule:: = */ + 34: 18, + + /*! Conditions:: options */ + /*! Rule:: [^\s\r\n]+ */ + 38: 50, + + /*! Conditions:: start_condition */ + /*! Rule:: {ID} */ + 42: 27, + + /*! Conditions:: named_chunk */ + /*! Rule:: {ID} */ + 45: 20, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \| */ + 54: 9, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?: */ + 55: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?= */ + 56: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?! */ + 57: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \( */ + 58: 10, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \) */ + 59: 11, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \+ */ + 60: 12, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \* */ + 61: 7, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \? */ + 62: 13, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \^ */ + 63: 16, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: , */ + 64: 8, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: <> */ + 65: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\([0-7]{1,3}|[rfntvsSbBwWdD\\*+()${}|[\]\/.^?]|c[A-Z]|x[0-9A-F]{2}|u[a-fA-F0-9]{4}) */ + 69: 44, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \$ */ + 71: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \. */ + 72: 15, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{\d+(,\s*\d+|,)?\} */ + 82: 45, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{{ID}\} */ + 83: 40, + + /*! Conditions:: set options */ + /*! Rule:: \{{ID}\} */ + 84: 40, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{ */ + 85: 3, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \} */ + 86: 4, + + /*! Conditions:: set */ + /*! Rule:: (?:\\\\|\\\]|[^\]{])+ */ + 87: 43, + + /*! Conditions:: set */ + /*! Rule:: \{ */ + 88: 43, + + /*! Conditions:: code */ + /*! Rule:: [^\r\n]*(\r|\n)+ */ + 90: 53, + + /*! Conditions:: * */ + /*! Rule:: $ */ + 108: 1 + }, + + rules: [ + /* 0: *//^(?:%\{)/, + /* 1: */new XRegExp('^(?:%\\{([^]*?)%\\})', ''), + /* 2: *//^(?:%include\b)/, + /* 3: */new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 4: *//^(?:([^\S\n\r])*\/\/.*)/, + /* 5: *//^(?:([^\S\n\r])+)/, + /* 6: *//^(?:\|)/, + /* 7: *//^(?:%%)/, + /* 8: *//^(?:%)/, + /* 9: *//^(?:\/[^\s\/]*?(?:['"`{}][^\s\/]*?)*\/)/, + /* 10: *//^(?:\/[^\n\r}]*)/, + /* 11: *//^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 12: *//^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 13: *//^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 14: *//^(?:[^\s"%'\/`{-}]+)/, + /* 15: *//^(?:\{)/, + /* 16: *//^(?:\})/, + /* 17: *//^(?:(?:(\r\n|\n|\r)([^\S\n\r])+)+(?=[^\s|]))/, + /* 18: *//^(?:(\r\n|\n|\r))/, + /* 19: *//^(?:$)/, + /* 20: */new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', ''), + /* 21: *//^(?:>)/, + /* 22: *//^(?:,)/, + /* 23: *//^(?:\*)/, + /* 24: *//^(?:([^\S\n\r])*\/\/[^\n\r]*)/, + /* 25: */new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 26: *//^(?:(\r\n|\n|\r)+)/, + /* 27: *//^(?:([^\S\n\r])+(\r\n|\n|\r)+)/, + /* 28: *//^(?:\/\/[^\r\n]*)/, + /* 29: */new XRegExp('^(?:\\/\\*[^]*?\\*\\/)', ''), + /* 30: *//^(?:([^\S\n\r])+(?=[^\s%|]))/, + /* 31: *//^(?:%%)/, + /* 32: *//^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 33: */new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', ''), + /* 34: *//^(?:=)/, + /* 35: *//^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 36: *//^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 37: *//^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 38: *//^(?:\S+)/, + /* 39: *//^(?:(\r\n|\n|\r)([^\S\n\r])+(?=\S))/, + /* 40: *//^(?:(\r\n|\n|\r))/, + /* 41: *//^(?:([^\S\n\r])+)/, + /* 42: */new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 43: *//^(?:(\r\n|\n|\r)+)/, + /* 44: *//^(?:([^\S\n\r])+)/, + /* 45: */new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 46: */new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 47: *//^(?:(\r\n|\n|\r)+)/, + /* 48: *//^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 49: *//^(?:(\r\n|\n|\r)+)/, + /* 50: *//^(?:\s+)/, + /* 51: *//^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 52: *//^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 53: *//^(?:\[)/, + /* 54: *//^(?:\|)/, + /* 55: *//^(?:\(\?:)/, + /* 56: *//^(?:\(\?=)/, + /* 57: *//^(?:\(\?!)/, + /* 58: *//^(?:\()/, + /* 59: *//^(?:\))/, + /* 60: *//^(?:\+)/, + /* 61: *//^(?:\*)/, + /* 62: *//^(?:\?)/, + /* 63: *//^(?:\^)/, + /* 64: *//^(?:,)/, + /* 65: *//^(?:<>)/, + /* 66: *//^(?:<)/, + /* 67: *//^(?:\/!)/, + /* 68: *//^(?:\/)/, + /* 69: *//^(?:\\([0-7]{1,3}|[$(-+.\/?BDSW\[-\^bdfnr-tvw{-}]|c[A-Z]|x[\dA-F]{2}|u[\dA-Fa-f]{4}))/, + /* 70: *//^(?:\\.)/, + /* 71: *//^(?:\$)/, + /* 72: *//^(?:\.)/, + /* 73: *//^(?:%options\b)/, + /* 74: *//^(?:%s\b)/, + /* 75: *//^(?:%x\b)/, + /* 76: *//^(?:%code\b)/, + /* 77: *//^(?:%import\b)/, + /* 78: *//^(?:%include\b)/, + /* 79: *//^(?:%include\b)/, + /* 80: */new XRegExp('^(?:%([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?)([^\\n\\r]*))', ''), + /* 81: *//^(?:%%)/, + /* 82: *//^(?:\{\d+(,\s*\d+|,)?\})/, + /* 83: */new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 84: */new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 85: *//^(?:\{)/, + /* 86: *//^(?:\})/, + /* 87: *//^(?:(?:\\\\|\\\]|[^\]{])+)/, + /* 88: *//^(?:\{)/, + /* 89: *//^(?:\])/, + /* 90: *//^(?:[^\r\n]*(\r|\n)+)/, + /* 91: *//^(?:[^\r\n]+)/, + /* 92: *//^(?:(\r\n|\n|\r))/, + /* 93: *//^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 94: *//^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 95: *//^(?:([^\S\n\r])+)/, + /* 96: *//^(?:\S+)/, + /* 97: *//^(?:")/, + /* 98: *//^(?:')/, + /* 99: *//^(?:`)/, + /* 100: *//^(?:")/, + /* 101: *//^(?:')/, + /* 102: *//^(?:`)/, + /* 103: *//^(?:")/, + /* 104: *//^(?:')/, + /* 105: *//^(?:`)/, + /* 106: *//^(?:.)/, + /* 107: *//^(?:.)/, + /* 108: *//^(?:$)/], + + conditions: { + 'rules': { + rules: [0, 26, 27, 28, 29, 30, 31, 32, 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, 74, 75, 76, 77, 78, 80, 81, 82, 83, 85, 86, 103, 104, 105, 106, 107, 108], + + inclusive: true + }, + + 'macro': { + rules: [0, 24, 25, 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, 74, 75, 76, 77, 78, 81, 82, 83, 85, 86, 103, 104, 105, 106, 107, 108], + + inclusive: true + }, + + 'named_chunk': { + rules: [0, 45, 47, 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, 74, 75, 76, 77, 78, 81, 82, 83, 85, 86, 103, 104, 105, 107, 108], + + inclusive: true + }, + + 'code': { + rules: [79, 80, 90, 91, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'start_condition': { + rules: [24, 25, 42, 43, 44, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'options': { + rules: [24, 25, 33, 34, 35, 36, 37, 38, 39, 40, 41, 84, 100, 101, 102, 103, 104, 105, 107, 108], + + inclusive: false + }, + + 'conditions': { + rules: [20, 21, 22, 23, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'action': { + rules: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 97, 98, 99, 103, 104, 105, 107, 108], + + inclusive: false + }, + + 'path': { + rules: [24, 25, 92, 93, 94, 95, 96, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'set': { + rules: [84, 87, 88, 89, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'INITIAL': { + rules: [0, 24, 25, 46, 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, 74, 75, 76, 77, 78, 80, 81, 82, 83, 85, 86, 103, 104, 105, 107, 108], + + inclusive: true + } + } + }; + + var rmCommonWS = helpers.rmCommonWS; + var dquote = helpers.dquote; + + 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); + } + + var lexParser = { + parser: parser, + Parser: Parser, + parse: yyparse + + }; + + return lexParser; +}); diff --git a/dist/lex-parser-umd.js b/dist/lex-parser-umd.js new file mode 100644 index 0000000..3f6266e --- /dev/null +++ b/dist/lex-parser-umd.js @@ -0,0 +1,7967 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@gerhobbelt/xregexp'), require('jison-helpers-lib'), require('fs')) : + typeof define === 'function' && define.amd ? define(['@gerhobbelt/xregexp', 'jison-helpers-lib', 'fs'], factory) : + (global['lex-parser'] = factory(global.XRegExp,global.helpers,global.fs)); +}(this, (function (XRegExp,helpers,fs) { 'use strict'; + +XRegExp = XRegExp && XRegExp.hasOwnProperty('default') ? XRegExp['default'] : XRegExp; +helpers = helpers && helpers.hasOwnProperty('default') ? helpers['default'] : helpers; +fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; + +// 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. + * } + */ + + +// 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_: { + "$": 17, + "$accept": 0, + "$end": 1, + "%%": 19, + "(": 10, + ")": 11, + "*": 7, + "+": 12, + ",": 8, + ".": 15, + "/": 14, + "/!": 39, + "<": 5, + "=": 18, + ">": 6, + "?": 13, + "ACTION": 32, + "ACTION_BODY": 33, + "ACTION_BODY_CPP_COMMENT": 35, + "ACTION_BODY_C_COMMENT": 34, + "ACTION_BODY_WHITESPACE": 36, + "ACTION_END": 31, + "ACTION_START": 28, + "BRACKET_MISSING": 29, + "BRACKET_SURPLUS": 30, + "CHARACTER_LIT": 46, + "CODE": 53, + "EOF": 1, + "ESCAPE_CHAR": 44, + "IMPORT": 24, + "INCLUDE": 51, + "INCLUDE_PLACEMENT_ERROR": 37, + "INIT_CODE": 25, + "NAME": 20, + "NAME_BRACE": 40, + "OPTIONS": 47, + "OPTIONS_END": 48, + "OPTION_STRING_VALUE": 49, + "OPTION_VALUE": 50, + "PATH": 52, + "RANGE_REGEX": 45, + "REGEX_SET": 43, + "REGEX_SET_END": 42, + "REGEX_SET_START": 41, + "SPECIAL_GROUP": 38, + "START_COND": 27, + "START_EXC": 22, + "START_INC": 21, + "STRING_LIT": 26, + "UNKNOWN_DECL": 23, + "^": 16, + "action": 68, + "action_body": 69, + "any_group_regex": 78, + "definition": 58, + "definitions": 57, + "error": 2, + "escape_char": 81, + "extra_lexer_module_code": 87, + "import_name": 60, + "import_path": 61, + "include_macro_code": 88, + "init": 56, + "init_code_name": 59, + "lex": 54, + "module_code_chunk": 89, + "name_expansion": 77, + "name_list": 71, + "names_exclusive": 63, + "names_inclusive": 62, + "nonempty_regex_list": 74, + "option": 86, + "option_list": 85, + "optional_module_code_chunk": 90, + "options": 84, + "range_regex": 82, + "regex": 72, + "regex_base": 76, + "regex_concat": 75, + "regex_list": 73, + "regex_set": 79, + "regex_set_atom": 80, + "rule": 67, + "rule_block": 66, + "rules": 64, + "rules_and_epilogue": 55, + "rules_collective": 65, + "start_conditions": 70, + "string": 83, + "{": 3, + "|": 9, + "}": 4 +}, +terminals_: { + 1: "EOF", + 2: "error", + 3: "{", + 4: "}", + 5: "<", + 6: ">", + 7: "*", + 8: ",", + 9: "|", + 10: "(", + 11: ")", + 12: "+", + 13: "?", + 14: "/", + 15: ".", + 16: "^", + 17: "$", + 18: "=", + 19: "%%", + 20: "NAME", + 21: "START_INC", + 22: "START_EXC", + 23: "UNKNOWN_DECL", + 24: "IMPORT", + 25: "INIT_CODE", + 26: "STRING_LIT", + 27: "START_COND", + 28: "ACTION_START", + 29: "BRACKET_MISSING", + 30: "BRACKET_SURPLUS", + 31: "ACTION_END", + 32: "ACTION", + 33: "ACTION_BODY", + 34: "ACTION_BODY_C_COMMENT", + 35: "ACTION_BODY_CPP_COMMENT", + 36: "ACTION_BODY_WHITESPACE", + 37: "INCLUDE_PLACEMENT_ERROR", + 38: "SPECIAL_GROUP", + 39: "/!", + 40: "NAME_BRACE", + 41: "REGEX_SET_START", + 42: "REGEX_SET_END", + 43: "REGEX_SET", + 44: "ESCAPE_CHAR", + 45: "RANGE_REGEX", + 46: "CHARACTER_LIT", + 47: "OPTIONS", + 48: "OPTIONS_END", + 49: "OPTION_STRING_VALUE", + 50: "OPTION_VALUE", + 51: "INCLUDE", + 52: "PATH", + 53: "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([ + 54, + 54, + s, + [55, 6], + 56, + 57, + 57, + s, + [58, 11], + 59, + 59, + 60, + 60, + 61, + 61, + 62, + 62, + 63, + 63, + 64, + 64, + s, + [65, 4], + 66, + 66, + 67, + 67, + s, + [68, 3], + s, + [69, 9], + s, + [70, 4], + 71, + 71, + 72, + s, + [73, 4], + s, + [74, 4], + 75, + 75, + s, + [76, 17], + 77, + 78, + 78, + 79, + 79, + 80, + s, + [80, 4, 1], + 83, + 84, + 85, + 85, + s, + [86, 6], + 87, + 87, + 88, + 88, + s, + [89, 3], + 90, + 90 +]), + rule: u([ + s, + [4, 3], + s, + [5, 4, -1], + 0, + 0, + 2, + 0, + s, + [2, 3], + s, + [1, 3], + 3, + 3, + 2, + 3, + 3, + s, + [1, 7], + 2, + 1, + 2, + c, + [23, 3], + 4, + c, + [32, 4], + 2, + c, + [22, 3], + 3, + s, + [2, 8], + 0, + s, + [3, 3], + 0, + 1, + 3, + 1, + s, + [3, 4, -1], + c, + [21, 3], + c, + [40, 3], + s, + [3, 4], + s, + [2, 5], + c, + [12, 3], + s, + [1, 6], + c, + [16, 3], + c, + [10, 8], + c, + [9, 3], + s, + [3, 4], + c, + [10, 4], + c, + [82, 4], + 1, + 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 : lex $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:: lex : init definitions rules_and_epilogue EOF */ + + // 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 - 1]; + this.$.macros = yyvstack[yysp - 2].macros; + this.$.startConditions = yyvstack[yysp - 2].startConditions; + this.$.unknownDecls = yyvstack[yysp - 2].unknownDecls; + + // if there are any options, add them all, otherwise set options to NULL: + // can't check for 'empty object' by `if (yy.options) ...` so we do it this way: + for (var k in yy.options) { + this.$.options = yy.options; + break; + } + + if (yy.actionInclude) { + var asrc = yy.actionInclude.join('\n\n'); + // Only a non-empty action code chunk should actually make it through: + if (asrc.trim() !== '') { + this.$.actionInclude = asrc; + } + } + + delete yy.options; + delete yy.actionInclude; + return this.$; + break; + +case 2: + /*! Production:: lex : init definitions error EOF */ + + // 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` + There's an error in your lexer regex rules or epilogue. + Maybe you did not correctly separate the lexer sections with a '%%' + on an otherwise empty line? + The lexer spec file should have this structure: + + definitions + %% + rules + %% // <-- optional! + extra_module_code // <-- optional epilogue! + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 3: + /*! Production:: rules_and_epilogue : "%%" rules "%%" extra_lexer_module_code */ + + // 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,-,-) + + + if (yyvstack[yysp].trim() !== '') { + this.$ = { rules: yyvstack[yysp - 2], moduleInclude: yyvstack[yysp] }; + } else { + this.$ = { rules: yyvstack[yysp - 2] }; + } + break; + +case 4: + /*! Production:: rules_and_epilogue : "%%" error rules "%%" extra_lexer_module_code */ + + // 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` + There's probably an error in one or more of your lexer regex rules. + The lexer rule spec should have this structure: + + regex action_code + + where 'regex' is a lex-style regex expression (see the + jison and jison-lex documentation) which is intended to match a chunk + of the input to lex, while the 'action_code' block is the JS code + which will be invoked when the regex is matched. The 'action_code' block + may be any (indented!) set of JS statements, optionally surrounded + by '{...}' curly braces or otherwise enclosed in a '%{...%}' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 3])} + + Technical error report: + ${yyvstack[yysp - 3].errStr} + `); + break; + +case 5: + /*! Production:: rules_and_epilogue : "%%" rules "%%" 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` + There's an error in your lexer epilogue a.k.a. 'extra_module_code' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 6: + /*! Production:: rules_and_epilogue : "%%" error rules */ + + // 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` + There's probably an error in one or more of your lexer regex rules. + The lexer rule spec should have this structure: + + regex action_code + + where 'regex' is a lex-style regex expression (see the + jison and jison-lex documentation) which is intended to match a chunk + of the input to lex, while the 'action_code' block is the JS code + which will be invoked when the regex is matched. The 'action_code' block + may be any (indented!) set of JS statements, optionally surrounded + by '{...}' curly braces or otherwise enclosed in a '%{...%}' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 7: + /*! Production:: rules_and_epilogue : "%%" rules */ + + // 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.$ = { rules: yyvstack[yysp] }; + break; + +case 8: + /*! Production:: rules_and_epilogue : %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.$ = { rules: [] }; + break; + +case 9: + /*! Production:: init : %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,-,-) + + + yy.actionInclude = []; + if (!yy.options) yy.options = {}; + break; + +case 10: + /*! Production:: definitions : definitions definition */ + + // 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] != null) { + if ('length' in yyvstack[yysp]) { + this.$.macros[yyvstack[yysp][0]] = yyvstack[yysp][1]; + } else if (yyvstack[yysp].type === 'names') { + for (var name in yyvstack[yysp].names) { + this.$.startConditions[name] = yyvstack[yysp].names[name]; + } + } else if (yyvstack[yysp].type === 'unknown') { + this.$.unknownDecls.push(yyvstack[yysp].body); + } + } + break; + +case 11: + /*! Production:: definitions : %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.$ = { + macros: {}, // { hash table } + startConditions: {}, // { hash table } + unknownDecls: [] // [ array of [key,value] pairs } + }; + break; + +case 12: + /*! Production:: definition : NAME regex */ + + // 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 13: + /*! Production:: definition : START_INC names_inclusive */ +case 14: + /*! Production:: definition : START_EXC names_exclusive */ + + // 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 15: + /*! Production:: definition : 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` + The '%{...%}' lexer setup action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + yy.actionInclude.push(yyvstack[yysp]); + this.$ = null; + break; + +case 16: + /*! Production:: definition : options */ +case 102: + /*! Production:: option_list : option */ + + // 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.$ = null; + break; + +case 17: + /*! Production:: definition : 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.$ = {type: 'unknown', body: yyvstack[yysp]}; + break; + +case 18: + /*! Production:: definition : 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.$ = {type: 'imports', name: yyvstack[yysp - 1], path: yyvstack[yysp]}; + break; + +case 19: + /*! Production:: definition : 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 20: + /*! Production:: definition : 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,-,-) + + + yyparser.yyError(rmCommonWS` + %import name or source filename missing maybe? + + Note: 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 21: + /*! Production:: definition : INIT_CODE init_code_name 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The '%code ${$init_code_name}' action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + } + this.$ = { + type: 'codesection', + qualifier: yyvstack[yysp - 1], + include: yyvstack[yysp] + }; + break; + +case 22: + /*! Production:: definition : INIT_CODE error action */ + + // 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2], yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 23: + /*! Production:: init_code_name : NAME */ +case 24: + /*! Production:: init_code_name : STRING_LIT */ +case 25: + /*! Production:: import_name : NAME */ +case 26: + /*! Production:: import_name : STRING_LIT */ +case 27: + /*! Production:: import_path : NAME */ +case 28: + /*! Production:: import_path : STRING_LIT */ +case 64: + /*! Production:: regex_list : regex_concat */ +case 69: + /*! Production:: nonempty_regex_list : regex_concat */ +case 71: + /*! Production:: regex_concat : regex_base */ +case 96: + /*! Production:: escape_char : ESCAPE_CHAR */ +case 97: + /*! Production:: range_regex : RANGE_REGEX */ +case 113: + /*! Production:: module_code_chunk : CODE */ +case 116: + /*! 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 29: + /*! Production:: names_inclusive : START_COND */ + + // 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.$ = {type: 'names', names: {}}; this.$.names[yyvstack[yysp]] = 0; + break; + +case 30: + /*! Production:: names_inclusive : names_inclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 0; + break; + +case 31: + /*! Production:: names_exclusive : START_COND */ + + // 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.$ = {type: 'names', names: {}}; this.$.names[yyvstack[yysp]] = 1; + break; + +case 32: + /*! Production:: names_exclusive : names_exclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 1; + break; + +case 33: + /*! Production:: rules : rules rules_collective */ + + // 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].concat(yyvstack[yysp]); + break; + +case 34: + /*! Production:: rules : %epsilon */ +case 40: + /*! Production:: rule_block : %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 35: + /*! Production:: rules_collective : start_conditions rule */ + + // 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,-,-) + + + if (yyvstack[yysp - 1]) { + yyvstack[yysp].unshift(yyvstack[yysp - 1]); + } + this.$ = [yyvstack[yysp]]; + break; + +case 36: + /*! Production:: rules_collective : start_conditions "{" rule_block "}" */ + + // 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,-,-) + + + if (yyvstack[yysp - 3]) { + yyvstack[yysp - 1].forEach(function (d) { + d.unshift(yyvstack[yysp - 3]); + }); + } + this.$ = yyvstack[yysp - 1]; + break; + +case 37: + /*! Production:: rules_collective : start_conditions "{" 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 made a mistake while specifying one of the lexer rules inside + the start condition + <${yyvstack[yysp - 3].join(',')}> { rules... } + block. + + Erroneous area: + ${yylexer.prettyPrintRange(yylexer.mergeLocationInfo((yysp - 3), (yysp)), yylstack[yysp - 3])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 38: + /*! Production:: rules_collective : start_conditions "{" 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 lexer rules set inside + the start condition + <${yyvstack[yysp - 2].join(',')}> { rules... } + as a terminating curly brace '}' could not be found. + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 39: + /*! Production:: rule_block : rule_block rule */ + + // 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 41: + /*! Production:: rule : regex 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The rule's action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = [yyvstack[yysp - 1], yyvstack[yysp]]; + break; + +case 42: + /*! Production:: rule : regex error */ + + // 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]]; + yyparser.yyError(rmCommonWS` + Lexer rule regex action code declaration error? + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 43: + /*! Production:: action : ACTION_START action_body BRACKET_MISSING */ + + // 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` + Missing curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: '{ ... }'. + + Offending action body: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + break; + +case 44: + /*! Production:: action : ACTION_START action_body BRACKET_SURPLUS */ + + // 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` + Too many curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: '{ ... }'. + + Offending action body: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + break; + +case 45: + /*! Production:: action : ACTION_START action_body ACTION_END */ + + // 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 s = yyvstack[yysp - 1].trim(); + // remove outermost set of braces UNLESS there's + // a curly brace in there anywhere: in that case + // we should leave it up to the sophisticated + // code analyzer to simplify the code! + // + // This is a very rough check as it will also look + // inside code comments, which should not have + // any influence. + // + // Nevertheless: this is a *safe* transform! + if (s[0] === '{' && s.indexOf('}') === s.length - 1) { + this.$ = s.substring(1, s.length - 1).trim(); + } else { + this.$ = s; + } + break; + +case 46: + /*! Production:: action_body : action_body ACTION */ +case 51: + /*! Production:: action_body : action_body 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] + '\n\n' + yyvstack[yysp] + '\n\n'; + break; + +case 47: + /*! Production:: action_body : action_body ACTION_BODY */ +case 48: + /*! Production:: action_body : action_body ACTION_BODY_C_COMMENT */ +case 49: + /*! Production:: action_body : action_body ACTION_BODY_CPP_COMMENT */ +case 50: + /*! Production:: action_body : action_body ACTION_BODY_WHITESPACE */ +case 70: + /*! Production:: regex_concat : regex_concat regex_base */ +case 82: + /*! Production:: regex_base : regex_base range_regex */ +case 92: + /*! Production:: regex_set : regex_set regex_set_atom */ +case 114: + /*! 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 52: + /*! Production:: action_body : action_body INCLUDE_PLACEMENT_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` + You may place the '%include' instruction only at the start/front of a line. + + It's use is not permitted at this position: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + `); + break; + +case 53: + /*! Production:: action_body : action_body 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` + Seems you did not correctly match curly braces '{ ... }' in a lexer rule action block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 54: + /*! Production:: action_body : %epsilon */ +case 65: + /*! Production:: regex_list : %epsilon */ +case 117: + /*! 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 55: + /*! Production:: start_conditions : "<" name_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 - 1]; + break; + +case 56: + /*! Production:: start_conditions : "<" name_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,-,-) + + + yyparser.yyError(rmCommonWS` + Seems you did not correctly terminate the start condition set <${yyvstack[yysp - 1].join(',')},???> with a terminating '>' + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 57: + /*! Production:: start_conditions : "<" "*" ">" */ + + // 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.$ = ['*']; + break; + +case 58: + /*! Production:: start_conditions : %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 59: + /*! Production:: name_list : 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]]; + break; + +case 60: + /*! Production:: name_list : name_list "," 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]; this.$.push(yyvstack[yysp]); + break; + +case 61: + /*! Production:: regex : nonempty_regex_list */ + + // 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,-,-) + + + // Detect if the regex ends with a pure (Unicode) word; + // we *do* consider escaped characters which are 'alphanumeric' + // to be equivalent to their non-escaped version, hence these are + // all valid 'words' for the 'easy keyword rules' option: + // + // - hello_kitty + // - γεια_σου_γατοÏλα + // - \u03B3\u03B5\u03B9\u03B1_\u03C3\u03BF\u03C5_\u03B3\u03B1\u03C4\u03BF\u03CD\u03BB\u03B1 + // + // http://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode#12869914 + // + // As we only check the *tail*, we also accept these as + // 'easy keywords': + // + // - %options + // - %foo-bar + // - +++a:b:c1 + // + // Note the dash in that last example: there the code will consider + // `bar` to be the keyword, which is fine with us as we're only + // interested in the trailing boundary and patching that one for + // the `easy_keyword_rules` option. + this.$ = yyvstack[yysp]; + if (yy.options.easy_keyword_rules) { + // We need to 'protect' `eval` here as keywords are allowed + // to contain double-quotes and other leading cruft. + // `eval` *does* gobble some escapes (such as `\b`) but + // we protect against that through a simple replace regex: + // we're not interested in the special escapes' exact value + // anyway. + // It will also catch escaped escapes (`\\`), which are not + // word characters either, so no need to worry about + // `eval(str)` 'correctly' converting convoluted constructs + // like '\\\\\\\\\\b' in here. + this.$ = this.$ + .replace(/\\\\/g, '.') + .replace(/"/g, '.') + .replace(/\\c[A-Z]/g, '.') + .replace(/\\[^xu0-9]/g, '.'); + + try { + // Convert Unicode escapes and other escapes to their literal characters + // BEFORE we go and check whether this item is subject to the + // `easy_keyword_rules` option. + this.$ = JSON.parse('"' + this.$ + '"'); + } + catch (ex) { + yyparser.warn('easy-keyword-rule FAIL on eval: ', ex); + + // make the next keyword test fail: + this.$ = '.'; + } + // a 'keyword' starts with an alphanumeric character, + // followed by zero or more alphanumerics or digits: + var re = new XRegExp('\\w[\\w\\d]*$'); + if (XRegExp.match(this.$, re)) { + this.$ = yyvstack[yysp] + "\\b"; + } else { + this.$ = yyvstack[yysp]; + } + } + break; + +case 62: + /*! Production:: regex_list : regex_list "|" regex_concat */ +case 66: + /*! Production:: nonempty_regex_list : nonempty_regex_list "|" regex_concat */ + + // 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 63: + /*! Production:: regex_list : regex_list "|" */ +case 67: + /*! Production:: nonempty_regex_list : nonempty_regex_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] + '|'; + break; + +case 68: + /*! Production:: nonempty_regex_list : "|" regex_concat */ + + // 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 72: + /*! Production:: regex_base : "(" regex_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 - 1] + ')'; + break; + +case 73: + /*! Production:: regex_base : SPECIAL_GROUP regex_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 74: + /*! Production:: regex_base : "(" regex_list error */ +case 75: + /*! Production:: regex_base : SPECIAL_GROUP regex_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,-,-) + + + yyparser.yyError(rmCommonWS` + Seems you did not correctly bracket a lex rule regex part in '(...)' braces. + + Unterminated regex part: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 76: + /*! Production:: regex_base : regex_base "+" */ + + // 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] + '+'; + break; + +case 77: + /*! Production:: regex_base : regex_base "*" */ + + // 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] + '*'; + break; + +case 78: + /*! Production:: regex_base : regex_base "?" */ + + // 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] + '?'; + break; + +case 79: + /*! Production:: regex_base : "/" regex_base */ + + // 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 80: + /*! Production:: regex_base : "/!" regex_base */ + + // 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 81: + /*! Production:: regex_base : name_expansion */ +case 83: + /*! Production:: regex_base : any_group_regex */ +case 87: + /*! Production:: regex_base : string */ +case 88: + /*! Production:: regex_base : escape_char */ +case 89: + /*! Production:: name_expansion : NAME_BRACE */ +case 93: + /*! Production:: regex_set : regex_set_atom */ +case 94: + /*! Production:: regex_set_atom : REGEX_SET */ +case 99: + /*! Production:: string : CHARACTER_LIT */ + + // 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,-,-) + break; + +case 84: + /*! Production:: regex_base : "." */ + + // 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.$ = '.'; + break; + +case 85: + /*! Production:: regex_base : "^" */ + + // 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.$ = '^'; + break; + +case 86: + /*! Production:: regex_base : "$" */ + + // 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.$ = '$'; + break; + +case 90: + /*! Production:: any_group_regex : REGEX_SET_START regex_set REGEX_SET_END */ + + // 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 91: + /*! Production:: any_group_regex : REGEX_SET_START regex_set 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 lex rule regex set in '[...]' brackets. + + Unterminated regex set: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 95: + /*! Production:: regex_set_atom : name_expansion */ + + // 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,-,-) + + + if (XRegExp._getUnicodeProperty(yyvstack[yysp].replace(/[{}]/g, '')) + && yyvstack[yysp].toUpperCase() !== yyvstack[yysp] + ) { + // treat this as part of an XRegExp `\p{...}` Unicode 'General Category' Property cf. http://unicode.org/reports/tr18/#Categories + this.$ = yyvstack[yysp]; + } else { + this.$ = yyvstack[yysp]; + } + //yyparser.log("name expansion for: ", { name: $name_expansion, redux: $name_expansion.replace(/[{}]/g, ''), output: $$ }); + break; + +case 98: + /*! Production:: string : STRING_LIT */ + + // 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.$ = prepareString(yyvstack[yysp]); + break; + +case 100: + /*! Production:: options : OPTIONS option_list OPTIONS_END */ + + // 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.$ = null; + break; + +case 101: + /*! Production:: option_list : option option_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.$ = null; + break; + +case 103: + /*! Production:: option : NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp]] = true; + break; + +case 104: + /*! Production:: option : NAME "=" OPTION_STRING_VALUE */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = yyvstack[yysp]; + break; + +case 105: + /*! Production:: option : NAME "=" OPTION_VALUE */ +case 106: + /*! Production:: option : NAME "=" NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = parseValue(yyvstack[yysp]); + break; + +case 107: + /*! 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` + Internal error: option "${$option}" value assignment failure. + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 108: + /*! Production:: option : 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` + Expected a valid option name (with optional value assignment). + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 109: + /*! Production:: extra_lexer_module_code : optional_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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = yyvstack[yysp]; + break; + +case 110: + /*! Production:: extra_lexer_module_code : extra_lexer_module_code include_macro_code optional_module_code_chunk */ + + // 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,-,-) + + + // Each of the 3 chunks should be parse-able as a JS snippet on its own. + // + // Note: we have already checked the first section in a previous reduction + // of this rule, so we don't need to check that one again! + var rv = checkActionBlock(yyvstack[yysp - 1], yylstack[yysp - 1]); + if (rv) { + yyparser.yyError(rmCommonWS` + The source code %include-d into the extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + `); + } + rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = yyvstack[yysp - 2] + yyvstack[yysp - 1] + yyvstack[yysp]; + break; + +case 111: + /*! 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' }); + // 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 112: + /*! 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])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 115: + /*! Production:: module_code_chunk : error CODE */ + + // 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` + Module code declaration error? + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 151: // === 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([ + 13, + 1, + 12, + 15, + 1, + 1, + 11, + 19, + 21, + 2, + 2, + s, + [11, 3], + 4, + 4, + 12, + 4, + 1, + 1, + 19, + 18, + 11, + 12, + 18, + 29, + 30, + 22, + 22, + 17, + 17, + s, + [29, 7], + 31, + 5, + s, + [29, 3], + s, + [12, 4], + 4, + 11, + 3, + 3, + 2, + 2, + 1, + 1, + 12, + 1, + 5, + 4, + 3, + 7, + 17, + 23, + 3, + 19, + 30, + 29, + 30, + s, + [29, 5], + 3, + 20, + 3, + 30, + 30, + 6, + s, + [4, 3], + 12, + 12, + s, + [11, 6], + s, + [27, 3], + s, + [11, 8], + 2, + 11, + 1, + 4, + c, + [55, 3], + 3, + 3, + 17, + 16, + 3, + 3, + 1, + 3, + 7, + s, + [29, 3], + 21, + s, + [29, 4], + 4, + 13, + 13, + s, + [3, 4], + 6, + 3, + 3, + 23, + s, + [18, 3], + 14, + 14, + 1, + 14, + 3, + 1, + 20, + 2, + 17, + 14, + 17, + 3 +]), + symbol: u([ + 1, + 2, + s, + [19, 7, 1], + 28, + 47, + 54, + 56, + 1, + c, + [14, 11], + 57, + c, + [12, 11], + 55, + 58, + 68, + 84, + s, + [1, 3], + c, + [17, 10], + 1, + 2, + 3, + 5, + 9, + 10, + s, + [14, 4, 1], + 19, + 26, + s, + [38, 4, 1], + 44, + 46, + 64, + c, + [15, 6], + c, + [14, 7], + 72, + s, + [74, 5, 1], + 81, + 83, + 27, + 62, + 27, + 63, + c, + [55, 13], + c, + [11, 20], + 2, + 20, + 26, + 60, + c, + [4, 3], + 59, + 2, + s, + [29, 9, 1], + 51, + 69, + 2, + 20, + 85, + 86, + s, + [1, 3], + c, + [102, 16], + 65, + 70, + c, + [19, 17], + 64, + c, + [85, 13], + 9, + c, + [12, 9], + c, + [143, 12], + c, + [141, 6], + c, + [30, 3], + c, + [58, 6], + s, + [20, 7, 1], + 28, + c, + [29, 6], + 47, + c, + [29, 7], + 7, + s, + [9, 9, 1], + c, + [33, 14], + 45, + 46, + 47, + 82, + c, + [58, 3], + 11, + c, + [80, 11], + 73, + c, + [81, 6], + c, + [22, 22], + c, + [121, 12], + c, + [17, 22], + c, + [108, 29], + c, + [29, 199], + s, + [42, 6, 1], + 40, + 43, + 77, + 79, + 80, + c, + [123, 89], + c, + [19, 7], + 27, + c, + [590, 11], + c, + [12, 27], + c, + [611, 3], + 61, + c, + [630, 14], + c, + [3, 3], + 28, + 68, + 28, + 68, + 28, + 28, + c, + [634, 11], + 88, + 48, + 2, + 20, + 48, + 85, + 86, + 2, + 18, + 20, + c, + [9, 4], + 1, + 2, + 51, + 53, + 87, + 89, + 90, + c, + [629, 17], + 3, + c, + [750, 13], + 67, + c, + [751, 8], + 7, + 20, + 71, + c, + [691, 20], + c, + [632, 23], + c, + [662, 65], + c, + [526, 145], + 2, + 9, + 11, + c, + [788, 15], + c, + [808, 7], + 11, + c, + [201, 59], + 82, + 2, + 40, + 42, + 43, + 77, + 80, + c, + [6, 4], + c, + [4, 8], + c, + [495, 33], + c, + [11, 59], + 3, + 4, + c, + [449, 8], + c, + [401, 15], + c, + [27, 54], + c, + [603, 11], + c, + [11, 78], + 52, + c, + [182, 11], + c, + [683, 3], + 49, + 50, + 1, + 51, + 88, + 1, + 53, + 1, + 51, + 1, + 51, + c, + [5, 3], + 53, + c, + [647, 17], + 2, + 4, + c, + [691, 13], + 66, + 2, + 28, + 68, + 2, + 6, + 8, + 6, + c, + [4, 3], + c, + [740, 8], + c, + [648, 57], + c, + [531, 31], + c, + [528, 13], + c, + [756, 8], + c, + [668, 115], + c, + [568, 5], + c, + [321, 10], + 53, + c, + [13, 13], + c, + [1004, 3], + c, + [3, 9], + c, + [273, 4], + c, + [272, 3], + c, + [328, 5], + c, + [310, 14], + c, + [1001, 9], + 1, + c, + [496, 10], + c, + [27, 7], + c, + [18, 36], + c, + [1078, 14], + c, + [14, 14], + 20, + c, + [15, 14], + c, + [461, 3], + 53, + c, + [843, 20], + c, + [480, 3], + c, + [474, 16], + c, + [163, 14], + c, + [505, 18], + 6, + 8 +]), + type: u([ + s, + [2, 11], + 0, + 0, + 1, + c, + [14, 12], + c, + [26, 13], + 0, + c, + [15, 12], + s, + [2, 20], + c, + [32, 14], + s, + [0, 8], + c, + [23, 3], + c, + [57, 32], + c, + [62, 9], + c, + [113, 13], + c, + [67, 4], + c, + [40, 20], + c, + [21, 18], + c, + [96, 36], + c, + [141, 7], + c, + [30, 28], + c, + [221, 43], + c, + [223, 9], + c, + [22, 34], + c, + [17, 34], + s, + [2, 224], + c, + [239, 141], + c, + [139, 19], + c, + [673, 16], + c, + [14, 5], + c, + [180, 13], + c, + [764, 35], + c, + [751, 9], + c, + [98, 19], + c, + [632, 31], + c, + [662, 75], + c, + [511, 151], + c, + [513, 34], + c, + [231, 35], + c, + [821, 238], + c, + [735, 74], + c, + [43, 27], + c, + [740, 39], + c, + [1202, 78], + c, + [756, 30], + c, + [696, 140], + c, + [1001, 31], + c, + [461, 114], + c, + [121, 58] +]), + state: u([ + s, + [1, 4, 1], + 6, + 11, + 12, + 20, + 22, + 23, + 25, + 26, + 31, + 32, + 37, + 36, + 43, + 45, + 47, + 51, + 55, + 56, + 57, + 61, + 62, + 64, + 66, + c, + [16, 5], + 67, + c, + [5, 4], + 71, + 73, + 74, + c, + [13, 5], + 75, + c, + [7, 6], + 76, + c, + [5, 4], + 77, + c, + [5, 4], + 81, + 78, + 79, + 84, + 88, + 89, + 98, + 103, + 57, + 105, + 108, + 107, + 110, + 112, + c, + [67, 7], + 113, + 61, + 62, + 117, + c, + [60, 11], + c, + [6, 6], + 71, + 81, + 125, + 132, + 135, + 137, + 143, + 108, + 107, + c, + [15, 5], + 145, + c, + [32, 5], + 108, + 146, + 148, + c, + [52, 8], + 132, + c, + [23, 5] +]), + mode: u([ + s, + [2, 23], + s, + [1, 12], + c, + [24, 13], + c, + [41, 28], + c, + [44, 15], + c, + [89, 27], + c, + [17, 13], + c, + [88, 11], + c, + [64, 34], + c, + [38, 14], + c, + [123, 15], + c, + [92, 12], + 1, + c, + [107, 10], + c, + [27, 6], + c, + [72, 23], + c, + [40, 8], + c, + [45, 7], + c, + [15, 13], + s, + [1, 24], + s, + [2, 234], + c, + [236, 98], + c, + [97, 24], + c, + [24, 15], + c, + [374, 20], + c, + [432, 5], + c, + [409, 15], + c, + [585, 9], + c, + [47, 20], + c, + [45, 25], + c, + [36, 14], + c, + [578, 18], + c, + [602, 53], + c, + [459, 145], + c, + [735, 19], + c, + [797, 33], + c, + [29, 25], + c, + [776, 238], + c, + [813, 51], + c, + [289, 5], + c, + [648, 7], + c, + [298, 21], + c, + [738, 18], + c, + [621, 8], + c, + [376, 7], + c, + [651, 22], + c, + [874, 59], + c, + [1219, 170], + c, + [960, 9], + c, + [947, 23], + c, + [1151, 89], + c, + [805, 17], + s, + [2, 53] +]), + goto: u([ + s, + [9, 11], + s, + [11, 11], + 8, + 5, + s, + [7, 4, 1], + s, + [13, 7, 1], + s, + [10, 11], + 34, + 21, + s, + [34, 16], + 24, + 27, + 29, + 33, + 34, + 35, + 40, + 28, + 30, + 38, + 39, + 42, + 41, + 44, + 46, + s, + [15, 11], + s, + [16, 11], + s, + [17, 11], + 48, + 49, + 50, + 52, + 53, + s, + [54, 12], + 59, + 58, + 1, + 2, + 7, + 58, + 63, + s, + [58, 6], + 60, + s, + [58, 7], + s, + [34, 17], + s, + [12, 11], + 61, + 61, + 65, + s, + [61, 9], + c, + [125, 12], + s, + [69, 3], + c, + [15, 5], + s, + [69, 7], + 40, + 69, + c, + [23, 7], + 71, + 71, + c, + [3, 3], + 71, + 68, + 70, + s, + [71, 18], + 72, + 71, + 71, + 65, + 65, + 27, + 65, + c, + [68, 11], + c, + [15, 15], + c, + [95, 12], + c, + [12, 12], + s, + [81, 29], + s, + [83, 29], + s, + [84, 29], + s, + [85, 29], + s, + [86, 29], + s, + [87, 29], + s, + [88, 29], + s, + [89, 31], + 38, + 80, + s, + [98, 29], + s, + [99, 29], + s, + [96, 29], + s, + [13, 9], + 82, + 13, + 13, + s, + [29, 12], + s, + [14, 9], + 83, + 14, + 14, + s, + [31, 12], + 85, + 86, + 87, + s, + [20, 11], + s, + [25, 3], + s, + [26, 3], + 16, + 16, + 23, + 24, + 100, + s, + [90, 8, 1], + 99, + 101, + 102, + 59, + 58, + 102, + 103, + 104, + 103, + 103, + s, + [108, 3], + 117, + 106, + 117, + 109, + s, + [33, 17], + 111, + c, + [684, 13], + 114, + 115, + 6, + c, + [630, 8], + 116, + s, + [58, 7], + s, + [67, 3], + c, + [34, 5], + s, + [67, 7], + 40, + 67, + c, + [42, 6], + 67, + s, + [68, 3], + c, + [24, 5], + s, + [68, 7], + 40, + 68, + c, + [24, 6], + 68, + 70, + 70, + 69, + s, + [70, 3], + c, + [7, 3], + s, + [70, 17], + 72, + 70, + 70, + s, + [76, 29], + s, + [77, 29], + s, + [78, 29], + s, + [82, 29], + s, + [97, 29], + 119, + 120, + 118, + 64, + 64, + 27, + 64, + c, + [259, 11], + 122, + 120, + 121, + 79, + 79, + 69, + s, + [79, 3], + 68, + 70, + s, + [79, 18], + 72, + 79, + 79, + 80, + 80, + 69, + s, + [80, 3], + 68, + 70, + s, + [80, 18], + 72, + 80, + 80, + 124, + 38, + 123, + 80, + s, + [93, 4], + s, + [94, 4], + s, + [95, 4], + s, + [30, 12], + s, + [32, 12], + s, + [18, 11], + s, + [19, 11], + s, + [27, 11], + s, + [28, 11], + s, + [21, 11], + s, + [22, 11], + s, + [43, 27], + s, + [44, 27], + s, + [45, 27], + s, + [46, 11], + s, + [47, 11], + s, + [48, 11], + s, + [49, 11], + s, + [50, 11], + s, + [51, 11], + s, + [52, 11], + s, + [53, 11], + 127, + 126, + s, + [100, 11], + 101, + 131, + 130, + 128, + 129, + 3, + 101, + 5, + 133, + 109, + 109, + 116, + 116, + 134, + s, + [113, 3], + s, + [35, 17], + 136, + s, + [40, 14], + 138, + 16, + 140, + 139, + 141, + 142, + s, + [59, 3], + 117, + 144, + 117, + 109, + s, + [66, 3], + c, + [627, 5], + s, + [66, 7], + 40, + 66, + c, + [434, 6], + 66, + s, + [72, 29], + s, + [74, 29], + 63, + 63, + 27, + 63, + c, + [508, 11], + s, + [73, 29], + s, + [75, 29], + s, + [90, 29], + s, + [91, 29], + s, + [92, 4], + s, + [111, 13], + s, + [112, 13], + s, + [104, 3], + s, + [105, 3], + s, + [106, 3], + s, + [107, 3], + c, + [259, 4], + s, + [115, 3], + s, + [114, 3], + 147, + c, + [949, 13], + 38, + 38, + 149, + s, + [38, 15], + s, + [41, 18], + s, + [42, 18], + s, + [55, 14], + s, + [56, 14], + 150, + s, + [57, 14], + 4, + 101, + 133, + 62, + 62, + 27, + 62, + c, + [115, 11], + 110, + 110, + s, + [36, 17], + s, + [39, 14], + s, + [37, 17], + s, + [60, 3] +]) +}), +defaultActions: bda({ + idx: u([ + 0, + 2, + 6, + 11, + 12, + 13, + 16, + 18, + 19, + 21, + 22, + s, + [31, 8, 1], + 40, + 41, + s, + [42, 4, 2], + 49, + 50, + 53, + 54, + 59, + 61, + s, + [68, 5, 1], + s, + [79, 22, 1], + 102, + 103, + 107, + 109, + 110, + 115, + 118, + 119, + s, + [121, 11, 1], + 133, + 134, + s, + [137, 4, 1], + 142, + s, + [146, 5, 1] +]), + goto: u([ + 9, + 11, + 10, + 15, + 16, + 17, + 54, + 1, + 2, + 34, + 12, + 81, + s, + [83, 7, 1], + 98, + 99, + 96, + 29, + 31, + 20, + 25, + 26, + 23, + 24, + 108, + 33, + 76, + 77, + 78, + 82, + 97, + 93, + 94, + 95, + 30, + 32, + 18, + 19, + 27, + 28, + 21, + 22, + s, + [43, 11, 1], + 100, + 101, + 109, + 113, + 35, + 59, + 72, + 74, + 73, + 75, + 90, + 91, + 92, + 111, + 112, + s, + [104, 4, 1], + 115, + 114, + 41, + 42, + 55, + 56, + 57, + 110, + 36, + 39, + 37, + 60 +]) +}), +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 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, 151 /* === 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 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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 rmCommonWS = helpers.rmCommonWS; +var checkActionBlock = helpers.checkActionBlock; + + +function encodeRE(s) { + return s.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1').replace(/\\\\u([a-fA-F0-9]{4})/g, '\\u$1'); +} + +function prepareString(s) { + // unescape slashes + s = s.replace(/\\\\/g, "\\"); + s = encodeRE(s); + return s; +} + +// 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); +}; + +parser.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse:', arguments); +}; + +parser.yy.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse YY:', arguments); +}; + +parser.yy.post_lex = function p_lex() { + if (parser.yydebug) parser.log('post_lex:', 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 <> tokens and perform user action code for a <> 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) { + 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; + switch (yyrulenumber) { + case 0: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %\{ */ + yy.depth = 0; + + yy.include_command_allowed = false; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 1: + /*! Conditions:: action */ + /*! Rule:: %\{([^]*?)%\} */ + yy_.yytext = this.matches[1].replace(/%\\\}/g, '%}'); // unescape any literal '%\}' that exists within the action code block + + yy.include_command_allowed = true; + return 32; + break; + + case 2: + /*! Conditions:: action */ + /*! Rule:: %include\b */ + if (yy.include_command_allowed) { + // This is an include instruction in place of an action: + // + // - one %include per action chunk + // - one %include replaces an entire action chunk + this.pushState('path'); + + return 51; + } else { + // TODO + yy_.yyerror('oops!'); + + return 37; + } + + break; + + case 3: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + //yy.include_command_allowed = false; -- doesn't impact include-allowed state + return 34; + + break; + + case 4: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\/.* */ + yy.include_command_allowed = false; + + return 35; + break; + + case 6: + /*! Conditions:: action */ + /*! Rule:: \| */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 7: + /*! Conditions:: action */ + /*! Rule:: %% */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 9: + /*! Conditions:: action */ + /*! Rule:: \/[^\s/]*?(?:['"`{}][^\s/]*?)*\/ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 10: + /*! Conditions:: action */ + /*! Rule:: \/[^}{BR}]* */ + yy.include_command_allowed = false; + + return 33; + break; + + case 11: + /*! Conditions:: action */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy.include_command_allowed = false; + + return 33; + break; + + case 12: + /*! Conditions:: action */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy.include_command_allowed = false; + + return 33; + break; + + case 13: + /*! Conditions:: action */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy.include_command_allowed = false; + + return 33; + break; + + case 14: + /*! Conditions:: action */ + /*! Rule:: [^{}/"'`|%\{\}{BR}{WS}]+ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 15: + /*! Conditions:: action */ + /*! Rule:: \{ */ + yy.depth++; + + yy.include_command_allowed = false; + return 33; + break; + + case 16: + /*! Conditions:: action */ + /*! Rule:: \} */ + yy.include_command_allowed = false; + + if (yy.depth <= 0) { + yy_.yyerror(rmCommonWS` + too many closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 30; + } else { + yy.depth--; + } + + return 33; + break; + + case 17: + /*! Conditions:: action */ + /*! Rule:: (?:{BR}{WS}+)+(?=[^{WS}{BR}|]) */ + yy.include_command_allowed = true; + + return 36; // keep empty lines as-is inside action code blocks. + break; + + case 18: + /*! Conditions:: action */ + /*! Rule:: {BR} */ + if (yy.depth > 0) { + yy.include_command_allowed = true; + return 36; // keep empty lines as-is inside action code blocks. + } else { + // end of action code chunk + this.popState(); + + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } + + break; + + case 19: + /*! Conditions:: action */ + /*! Rule:: $ */ + yy.include_command_allowed = false; + + if (yy.depth !== 0) { + yy_.yyerror(rmCommonWS` + missing ${yy.depth} closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + yy_.yytext = ''; + return 29; + } + + this.popState(); + yy_.yytext = ''; + return 31; + break; + + case 21: + /*! Conditions:: conditions */ + /*! Rule:: > */ + this.popState(); + + return 6; + break; + + case 24: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 25: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 26: + /*! Conditions:: rules */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 27: + /*! Conditions:: rules */ + /*! Rule:: {WS}+{BR}+ */ + /* empty */ + break; + + case 28: + /*! Conditions:: rules */ + /*! Rule:: \/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 29: + /*! Conditions:: rules */ + /*! Rule:: \/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 30: + /*! Conditions:: rules */ + /*! Rule:: {WS}+(?=[^{WS}{BR}|%]) */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + return 28; + break; + + case 31: + /*! Conditions:: rules */ + /*! Rule:: %% */ + this.popState(); + + this.pushState('code'); + return 19; + break; + + case 32: + /*! Conditions:: rules */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 35: + /*! Conditions:: options */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 49; // value is always a string type + break; + + case 36: + /*! Conditions:: options */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 49; // value is always a string type + break; + + case 37: + /*! Conditions:: options */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy_.yytext = unescQuote(this.matches[1], /\\`/g); + + return 49; // value is always a string type + break; + + case 39: + /*! Conditions:: options */ + /*! Rule:: {BR}{WS}+(?=\S) */ + /* skip leading whitespace on the next line of input, when followed by more options */ + break; + + case 40: + /*! Conditions:: options */ + /*! Rule:: {BR} */ + this.popState(); + + return 48; + break; + + case 41: + /*! Conditions:: options */ + /*! Rule:: {WS}+ */ + /* skip whitespace */ + break; + + case 43: + /*! Conditions:: start_condition */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 44: + /*! Conditions:: start_condition */ + /*! Rule:: {WS}+ */ + /* empty */ + break; + + case 46: + /*! Conditions:: INITIAL */ + /*! Rule:: {ID} */ + this.pushState('macro'); + + return 20; + break; + + case 47: + /*! Conditions:: macro named_chunk */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 48: + /*! Conditions:: macro */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 49: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 50: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \s+ */ + /* empty */ + break; + + case 51: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 26; + break; + + case 52: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 26; + break; + + case 53: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \[ */ + this.pushState('set'); + + return 41; + break; + + case 66: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: < */ + this.pushState('conditions'); + + return 5; + break; + + case 67: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/! */ + return 39; // treated as `(?!atom)` + + break; + + case 68: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/ */ + return 14; // treated as `(?=atom)` + + break; + + case 70: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\. */ + yy_.yytext = yy_.yytext.replace(/^\\/g, ''); + + return 44; + break; + + case 73: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %options\b */ + this.pushState('options'); + + return 47; + break; + + case 74: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %s\b */ + this.pushState('start_condition'); + + return 21; + break; + + case 75: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %x\b */ + this.pushState('start_condition'); + + return 22; + break; + + case 76: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %code\b */ + this.pushState('named_chunk'); + + return 25; + break; + + case 77: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %import\b */ + this.pushState('named_chunk'); + + return 24; + break; + + case 78: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %include\b */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 79: + /*! Conditions:: code */ + /*! Rule:: %include\b */ + this.pushState('path'); + + return 51; + break; + + case 80: + /*! Conditions:: INITIAL rules code */ + /*! Rule:: %{NAME}([^\r\n]*) */ + /* ignore unrecognized decl */ + this.warn(rmCommonWS` + LEX: ignoring unsupported lexer 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 23; + break; + + case 81: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %% */ + this.pushState('rules'); + + return 19; + break; + + case 89: + /*! Conditions:: set */ + /*! Rule:: \] */ + this.popState(); + + return 42; + break; + + case 91: + /*! Conditions:: code */ + /*! Rule:: [^\r\n]+ */ + return 53; // the bit of CODE just before EOF... + + break; + + case 92: + /*! Conditions:: path */ + /*! Rule:: {BR} */ + this.popState(); + + this.unput(yy_.yytext); + break; + + case 93: + /*! Conditions:: path */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 94: + /*! Conditions:: path */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 95: + /*! Conditions:: path */ + /*! Rule:: {WS}+ */ + // skip whitespace in the line + break; + + case 96: + /*! Conditions:: path */ + /*! Rule:: [^\s\r\n]+ */ + this.popState(); + + return 52; + break; + + case 97: + /*! Conditions:: action */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 98: + /*! Conditions:: action */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 99: + /*! Conditions:: action */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 100: + /*! Conditions:: options */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 101: + /*! Conditions:: options */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 102: + /*! Conditions:: options */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 103: + /*! 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 104: + /*! 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 105: + /*! 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 106: + /*! Conditions:: macro rules */ + /*! Rule:: . */ + /* b0rk on bad characters */ + var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + + yy_.yyerror(rmCommonWS` + unsupported lexer input encountered while lexing + ${rules} (i.e. jison lex regexes). + + NOTE: When you want this input to be interpreted as a LITERAL part + of a lex rule regex, you MUST enclose it in double or + single quotes. + + If not, then know that this input is not accepted as a valid + regex expression here in jison-lex ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + break; + + case 107: + /*! Conditions:: * */ + /*! Rule:: . */ + yy_.yyerror(rmCommonWS` + unsupported lexer 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:: {WS}+ */ + 5: 36, + + /*! Conditions:: action */ + /*! Rule:: % */ + 8: 33, + + /*! Conditions:: conditions */ + /*! Rule:: {NAME} */ + 20: 20, + + /*! Conditions:: conditions */ + /*! Rule:: , */ + 22: 8, + + /*! Conditions:: conditions */ + /*! Rule:: \* */ + 23: 7, + + /*! Conditions:: options */ + /*! Rule:: {NAME} */ + 33: 20, + + /*! Conditions:: options */ + /*! Rule:: = */ + 34: 18, + + /*! Conditions:: options */ + /*! Rule:: [^\s\r\n]+ */ + 38: 50, + + /*! Conditions:: start_condition */ + /*! Rule:: {ID} */ + 42: 27, + + /*! Conditions:: named_chunk */ + /*! Rule:: {ID} */ + 45: 20, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \| */ + 54: 9, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?: */ + 55: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?= */ + 56: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?! */ + 57: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \( */ + 58: 10, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \) */ + 59: 11, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \+ */ + 60: 12, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \* */ + 61: 7, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \? */ + 62: 13, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \^ */ + 63: 16, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: , */ + 64: 8, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: <> */ + 65: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\([0-7]{1,3}|[rfntvsSbBwWdD\\*+()${}|[\]\/.^?]|c[A-Z]|x[0-9A-F]{2}|u[a-fA-F0-9]{4}) */ + 69: 44, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \$ */ + 71: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \. */ + 72: 15, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{\d+(,\s*\d+|,)?\} */ + 82: 45, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{{ID}\} */ + 83: 40, + + /*! Conditions:: set options */ + /*! Rule:: \{{ID}\} */ + 84: 40, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{ */ + 85: 3, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \} */ + 86: 4, + + /*! Conditions:: set */ + /*! Rule:: (?:\\\\|\\\]|[^\]{])+ */ + 87: 43, + + /*! Conditions:: set */ + /*! Rule:: \{ */ + 88: 43, + + /*! Conditions:: code */ + /*! Rule:: [^\r\n]*(\r|\n)+ */ + 90: 53, + + /*! Conditions:: * */ + /*! Rule:: $ */ + 108: 1 + }, + + rules: [ + /* 0: */ /^(?:%\{)/, + /* 1: */ new XRegExp('^(?:%\\{([^]*?)%\\})', ''), + /* 2: */ /^(?:%include\b)/, + /* 3: */ new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 4: */ /^(?:([^\S\n\r])*\/\/.*)/, + /* 5: */ /^(?:([^\S\n\r])+)/, + /* 6: */ /^(?:\|)/, + /* 7: */ /^(?:%%)/, + /* 8: */ /^(?:%)/, + /* 9: */ /^(?:\/[^\s\/]*?(?:['"`{}][^\s\/]*?)*\/)/, + /* 10: */ /^(?:\/[^\n\r}]*)/, + /* 11: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 12: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 13: */ /^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 14: */ /^(?:[^\s"%'\/`{-}]+)/, + /* 15: */ /^(?:\{)/, + /* 16: */ /^(?:\})/, + /* 17: */ /^(?:(?:(\r\n|\n|\r)([^\S\n\r])+)+(?=[^\s|]))/, + /* 18: */ /^(?:(\r\n|\n|\r))/, + /* 19: */ /^(?:$)/, + /* 20: */ new XRegExp( + '^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', + '' + ), + /* 21: */ /^(?:>)/, + /* 22: */ /^(?:,)/, + /* 23: */ /^(?:\*)/, + /* 24: */ /^(?:([^\S\n\r])*\/\/[^\n\r]*)/, + /* 25: */ new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 26: */ /^(?:(\r\n|\n|\r)+)/, + /* 27: */ /^(?:([^\S\n\r])+(\r\n|\n|\r)+)/, + /* 28: */ /^(?:\/\/[^\r\n]*)/, + /* 29: */ new XRegExp('^(?:\\/\\*[^]*?\\*\\/)', ''), + /* 30: */ /^(?:([^\S\n\r])+(?=[^\s%|]))/, + /* 31: */ /^(?:%%)/, + /* 32: */ /^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 33: */ new XRegExp( + '^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', + '' + ), + /* 34: */ /^(?:=)/, + /* 35: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 36: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 37: */ /^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 38: */ /^(?:\S+)/, + /* 39: */ /^(?:(\r\n|\n|\r)([^\S\n\r])+(?=\S))/, + /* 40: */ /^(?:(\r\n|\n|\r))/, + /* 41: */ /^(?:([^\S\n\r])+)/, + /* 42: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 43: */ /^(?:(\r\n|\n|\r)+)/, + /* 44: */ /^(?:([^\S\n\r])+)/, + /* 45: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 46: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 47: */ /^(?:(\r\n|\n|\r)+)/, + /* 48: */ /^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 49: */ /^(?:(\r\n|\n|\r)+)/, + /* 50: */ /^(?:\s+)/, + /* 51: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 52: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 53: */ /^(?:\[)/, + /* 54: */ /^(?:\|)/, + /* 55: */ /^(?:\(\?:)/, + /* 56: */ /^(?:\(\?=)/, + /* 57: */ /^(?:\(\?!)/, + /* 58: */ /^(?:\()/, + /* 59: */ /^(?:\))/, + /* 60: */ /^(?:\+)/, + /* 61: */ /^(?:\*)/, + /* 62: */ /^(?:\?)/, + /* 63: */ /^(?:\^)/, + /* 64: */ /^(?:,)/, + /* 65: */ /^(?:<>)/, + /* 66: */ /^(?:<)/, + /* 67: */ /^(?:\/!)/, + /* 68: */ /^(?:\/)/, + /* 69: */ /^(?:\\([0-7]{1,3}|[$(-+.\/?BDSW\[-\^bdfnr-tvw{-}]|c[A-Z]|x[\dA-F]{2}|u[\dA-Fa-f]{4}))/, + /* 70: */ /^(?:\\.)/, + /* 71: */ /^(?:\$)/, + /* 72: */ /^(?:\.)/, + /* 73: */ /^(?:%options\b)/, + /* 74: */ /^(?:%s\b)/, + /* 75: */ /^(?:%x\b)/, + /* 76: */ /^(?:%code\b)/, + /* 77: */ /^(?:%import\b)/, + /* 78: */ /^(?:%include\b)/, + /* 79: */ /^(?:%include\b)/, + /* 80: */ new XRegExp( + '^(?:%([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?)([^\\n\\r]*))', + '' + ), + /* 81: */ /^(?:%%)/, + /* 82: */ /^(?:\{\d+(,\s*\d+|,)?\})/, + /* 83: */ new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 84: */ new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 85: */ /^(?:\{)/, + /* 86: */ /^(?:\})/, + /* 87: */ /^(?:(?:\\\\|\\\]|[^\]{])+)/, + /* 88: */ /^(?:\{)/, + /* 89: */ /^(?:\])/, + /* 90: */ /^(?:[^\r\n]*(\r|\n)+)/, + /* 91: */ /^(?:[^\r\n]+)/, + /* 92: */ /^(?:(\r\n|\n|\r))/, + /* 93: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 94: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 95: */ /^(?:([^\S\n\r])+)/, + /* 96: */ /^(?:\S+)/, + /* 97: */ /^(?:")/, + /* 98: */ /^(?:')/, + /* 99: */ /^(?:`)/, + /* 100: */ /^(?:")/, + /* 101: */ /^(?:')/, + /* 102: */ /^(?:`)/, + /* 103: */ /^(?:")/, + /* 104: */ /^(?:')/, + /* 105: */ /^(?:`)/, + /* 106: */ /^(?:.)/, + /* 107: */ /^(?:.)/, + /* 108: */ /^(?:$)/ + ], + + conditions: { + 'rules': { + rules: [ + 0, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 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, + 74, + 75, + 76, + 77, + 78, + 80, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 106, + 107, + 108 + ], + + inclusive: true + }, + + 'macro': { + rules: [ + 0, + 24, + 25, + 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, + 74, + 75, + 76, + 77, + 78, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 106, + 107, + 108 + ], + + inclusive: true + }, + + 'named_chunk': { + rules: [ + 0, + 45, + 47, + 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, + 74, + 75, + 76, + 77, + 78, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: true + }, + + 'code': { + rules: [79, 80, 90, 91, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'start_condition': { + rules: [24, 25, 42, 43, 44, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'options': { + rules: [ + 24, + 25, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 84, + 100, + 101, + 102, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: false + }, + + 'conditions': { + rules: [20, 21, 22, 23, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'action': { + rules: [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 97, + 98, + 99, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: false + }, + + 'path': { + rules: [24, 25, 92, 93, 94, 95, 96, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'set': { + rules: [84, 87, 88, 89, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'INITIAL': { + rules: [ + 0, + 24, + 25, + 46, + 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, + 74, + 75, + 76, + 77, + 78, + 80, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: true + } + } + }; + + var rmCommonWS = helpers.rmCommonWS; + var dquote = helpers.dquote; + + 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); +} + + + +var lexParser = { + parser, + Parser, + parse: yyparse, + +}; + +return lexParser; + +}))); diff --git a/lex-parser-prelude.js b/lex-parser-prelude.js new file mode 100644 index 0000000..075ac5f --- /dev/null +++ b/lex-parser-prelude.js @@ -0,0 +1,3 @@ + +// hack: +var assert; diff --git a/lex-parser.js b/lex-parser.js new file mode 100644 index 0000000..a568521 --- /dev/null +++ b/lex-parser.js @@ -0,0 +1,7981 @@ + +// 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'; + +// 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_: { + "$": 17, + "$accept": 0, + "$end": 1, + "%%": 19, + "(": 10, + ")": 11, + "*": 7, + "+": 12, + ",": 8, + ".": 15, + "/": 14, + "/!": 39, + "<": 5, + "=": 18, + ">": 6, + "?": 13, + "ACTION": 32, + "ACTION_BODY": 33, + "ACTION_BODY_CPP_COMMENT": 35, + "ACTION_BODY_C_COMMENT": 34, + "ACTION_BODY_WHITESPACE": 36, + "ACTION_END": 31, + "ACTION_START": 28, + "BRACKET_MISSING": 29, + "BRACKET_SURPLUS": 30, + "CHARACTER_LIT": 46, + "CODE": 53, + "EOF": 1, + "ESCAPE_CHAR": 44, + "IMPORT": 24, + "INCLUDE": 51, + "INCLUDE_PLACEMENT_ERROR": 37, + "INIT_CODE": 25, + "NAME": 20, + "NAME_BRACE": 40, + "OPTIONS": 47, + "OPTIONS_END": 48, + "OPTION_STRING_VALUE": 49, + "OPTION_VALUE": 50, + "PATH": 52, + "RANGE_REGEX": 45, + "REGEX_SET": 43, + "REGEX_SET_END": 42, + "REGEX_SET_START": 41, + "SPECIAL_GROUP": 38, + "START_COND": 27, + "START_EXC": 22, + "START_INC": 21, + "STRING_LIT": 26, + "UNKNOWN_DECL": 23, + "^": 16, + "action": 68, + "action_body": 69, + "any_group_regex": 78, + "definition": 58, + "definitions": 57, + "error": 2, + "escape_char": 81, + "extra_lexer_module_code": 87, + "import_name": 60, + "import_path": 61, + "include_macro_code": 88, + "init": 56, + "init_code_name": 59, + "lex": 54, + "module_code_chunk": 89, + "name_expansion": 77, + "name_list": 71, + "names_exclusive": 63, + "names_inclusive": 62, + "nonempty_regex_list": 74, + "option": 86, + "option_list": 85, + "optional_module_code_chunk": 90, + "options": 84, + "range_regex": 82, + "regex": 72, + "regex_base": 76, + "regex_concat": 75, + "regex_list": 73, + "regex_set": 79, + "regex_set_atom": 80, + "rule": 67, + "rule_block": 66, + "rules": 64, + "rules_and_epilogue": 55, + "rules_collective": 65, + "start_conditions": 70, + "string": 83, + "{": 3, + "|": 9, + "}": 4 +}, +terminals_: { + 1: "EOF", + 2: "error", + 3: "{", + 4: "}", + 5: "<", + 6: ">", + 7: "*", + 8: ",", + 9: "|", + 10: "(", + 11: ")", + 12: "+", + 13: "?", + 14: "/", + 15: ".", + 16: "^", + 17: "$", + 18: "=", + 19: "%%", + 20: "NAME", + 21: "START_INC", + 22: "START_EXC", + 23: "UNKNOWN_DECL", + 24: "IMPORT", + 25: "INIT_CODE", + 26: "STRING_LIT", + 27: "START_COND", + 28: "ACTION_START", + 29: "BRACKET_MISSING", + 30: "BRACKET_SURPLUS", + 31: "ACTION_END", + 32: "ACTION", + 33: "ACTION_BODY", + 34: "ACTION_BODY_C_COMMENT", + 35: "ACTION_BODY_CPP_COMMENT", + 36: "ACTION_BODY_WHITESPACE", + 37: "INCLUDE_PLACEMENT_ERROR", + 38: "SPECIAL_GROUP", + 39: "/!", + 40: "NAME_BRACE", + 41: "REGEX_SET_START", + 42: "REGEX_SET_END", + 43: "REGEX_SET", + 44: "ESCAPE_CHAR", + 45: "RANGE_REGEX", + 46: "CHARACTER_LIT", + 47: "OPTIONS", + 48: "OPTIONS_END", + 49: "OPTION_STRING_VALUE", + 50: "OPTION_VALUE", + 51: "INCLUDE", + 52: "PATH", + 53: "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([ + 54, + 54, + s, + [55, 6], + 56, + 57, + 57, + s, + [58, 11], + 59, + 59, + 60, + 60, + 61, + 61, + 62, + 62, + 63, + 63, + 64, + 64, + s, + [65, 4], + 66, + 66, + 67, + 67, + s, + [68, 3], + s, + [69, 9], + s, + [70, 4], + 71, + 71, + 72, + s, + [73, 4], + s, + [74, 4], + 75, + 75, + s, + [76, 17], + 77, + 78, + 78, + 79, + 79, + 80, + s, + [80, 4, 1], + 83, + 84, + 85, + 85, + s, + [86, 6], + 87, + 87, + 88, + 88, + s, + [89, 3], + 90, + 90 +]), + rule: u([ + s, + [4, 3], + s, + [5, 4, -1], + 0, + 0, + 2, + 0, + s, + [2, 3], + s, + [1, 3], + 3, + 3, + 2, + 3, + 3, + s, + [1, 7], + 2, + 1, + 2, + c, + [23, 3], + 4, + c, + [32, 4], + 2, + c, + [22, 3], + 3, + s, + [2, 8], + 0, + s, + [3, 3], + 0, + 1, + 3, + 1, + s, + [3, 4, -1], + c, + [21, 3], + c, + [40, 3], + s, + [3, 4], + s, + [2, 5], + c, + [12, 3], + s, + [1, 6], + c, + [16, 3], + c, + [10, 8], + c, + [9, 3], + s, + [3, 4], + c, + [10, 4], + c, + [82, 4], + 1, + 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 : lex $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:: lex : init definitions rules_and_epilogue EOF */ + + // 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 - 1]; + this.$.macros = yyvstack[yysp - 2].macros; + this.$.startConditions = yyvstack[yysp - 2].startConditions; + this.$.unknownDecls = yyvstack[yysp - 2].unknownDecls; + + // if there are any options, add them all, otherwise set options to NULL: + // can't check for 'empty object' by `if (yy.options) ...` so we do it this way: + for (var k in yy.options) { + this.$.options = yy.options; + break; + } + + if (yy.actionInclude) { + var asrc = yy.actionInclude.join('\n\n'); + // Only a non-empty action code chunk should actually make it through: + if (asrc.trim() !== '') { + this.$.actionInclude = asrc; + } + } + + delete yy.options; + delete yy.actionInclude; + return this.$; + break; + +case 2: + /*! Production:: lex : init definitions error EOF */ + + // 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` + There's an error in your lexer regex rules or epilogue. + Maybe you did not correctly separate the lexer sections with a '%%' + on an otherwise empty line? + The lexer spec file should have this structure: + + definitions + %% + rules + %% // <-- optional! + extra_module_code // <-- optional epilogue! + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 3: + /*! Production:: rules_and_epilogue : "%%" rules "%%" extra_lexer_module_code */ + + // 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,-,-) + + + if (yyvstack[yysp].trim() !== '') { + this.$ = { rules: yyvstack[yysp - 2], moduleInclude: yyvstack[yysp] }; + } else { + this.$ = { rules: yyvstack[yysp - 2] }; + } + break; + +case 4: + /*! Production:: rules_and_epilogue : "%%" error rules "%%" extra_lexer_module_code */ + + // 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` + There's probably an error in one or more of your lexer regex rules. + The lexer rule spec should have this structure: + + regex action_code + + where 'regex' is a lex-style regex expression (see the + jison and jison-lex documentation) which is intended to match a chunk + of the input to lex, while the 'action_code' block is the JS code + which will be invoked when the regex is matched. The 'action_code' block + may be any (indented!) set of JS statements, optionally surrounded + by '{...}' curly braces or otherwise enclosed in a '%{...%}' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 3])} + + Technical error report: + ${yyvstack[yysp - 3].errStr} + `); + break; + +case 5: + /*! Production:: rules_and_epilogue : "%%" rules "%%" 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` + There's an error in your lexer epilogue a.k.a. 'extra_module_code' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 6: + /*! Production:: rules_and_epilogue : "%%" error rules */ + + // 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` + There's probably an error in one or more of your lexer regex rules. + The lexer rule spec should have this structure: + + regex action_code + + where 'regex' is a lex-style regex expression (see the + jison and jison-lex documentation) which is intended to match a chunk + of the input to lex, while the 'action_code' block is the JS code + which will be invoked when the regex is matched. The 'action_code' block + may be any (indented!) set of JS statements, optionally surrounded + by '{...}' curly braces or otherwise enclosed in a '%{...%}' block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 7: + /*! Production:: rules_and_epilogue : "%%" rules */ + + // 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.$ = { rules: yyvstack[yysp] }; + break; + +case 8: + /*! Production:: rules_and_epilogue : %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.$ = { rules: [] }; + break; + +case 9: + /*! Production:: init : %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,-,-) + + + yy.actionInclude = []; + if (!yy.options) yy.options = {}; + break; + +case 10: + /*! Production:: definitions : definitions definition */ + + // 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] != null) { + if ('length' in yyvstack[yysp]) { + this.$.macros[yyvstack[yysp][0]] = yyvstack[yysp][1]; + } else if (yyvstack[yysp].type === 'names') { + for (var name in yyvstack[yysp].names) { + this.$.startConditions[name] = yyvstack[yysp].names[name]; + } + } else if (yyvstack[yysp].type === 'unknown') { + this.$.unknownDecls.push(yyvstack[yysp].body); + } + } + break; + +case 11: + /*! Production:: definitions : %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.$ = { + macros: {}, // { hash table } + startConditions: {}, // { hash table } + unknownDecls: [] // [ array of [key,value] pairs } + }; + break; + +case 12: + /*! Production:: definition : NAME regex */ + + // 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 13: + /*! Production:: definition : START_INC names_inclusive */ +case 14: + /*! Production:: definition : START_EXC names_exclusive */ + + // 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 15: + /*! Production:: definition : 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` + The '%{...%}' lexer setup action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + yy.actionInclude.push(yyvstack[yysp]); + this.$ = null; + break; + +case 16: + /*! Production:: definition : options */ +case 102: + /*! Production:: option_list : option */ + + // 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.$ = null; + break; + +case 17: + /*! Production:: definition : 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.$ = {type: 'unknown', body: yyvstack[yysp]}; + break; + +case 18: + /*! Production:: definition : 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.$ = {type: 'imports', name: yyvstack[yysp - 1], path: yyvstack[yysp]}; + break; + +case 19: + /*! Production:: definition : 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 20: + /*! Production:: definition : 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,-,-) + + + yyparser.yyError(rmCommonWS` + %import name or source filename missing maybe? + + Note: 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 21: + /*! Production:: definition : INIT_CODE init_code_name 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The '%code ${$init_code_name}' action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + } + this.$ = { + type: 'codesection', + qualifier: yyvstack[yysp - 1], + include: yyvstack[yysp] + }; + break; + +case 22: + /*! Production:: definition : INIT_CODE error action */ + + // 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 code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1], yylstack[yysp - 2], yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 23: + /*! Production:: init_code_name : NAME */ +case 24: + /*! Production:: init_code_name : STRING_LIT */ +case 25: + /*! Production:: import_name : NAME */ +case 26: + /*! Production:: import_name : STRING_LIT */ +case 27: + /*! Production:: import_path : NAME */ +case 28: + /*! Production:: import_path : STRING_LIT */ +case 64: + /*! Production:: regex_list : regex_concat */ +case 69: + /*! Production:: nonempty_regex_list : regex_concat */ +case 71: + /*! Production:: regex_concat : regex_base */ +case 96: + /*! Production:: escape_char : ESCAPE_CHAR */ +case 97: + /*! Production:: range_regex : RANGE_REGEX */ +case 113: + /*! Production:: module_code_chunk : CODE */ +case 116: + /*! 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 29: + /*! Production:: names_inclusive : START_COND */ + + // 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.$ = {type: 'names', names: {}}; this.$.names[yyvstack[yysp]] = 0; + break; + +case 30: + /*! Production:: names_inclusive : names_inclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 0; + break; + +case 31: + /*! Production:: names_exclusive : START_COND */ + + // 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.$ = {type: 'names', names: {}}; this.$.names[yyvstack[yysp]] = 1; + break; + +case 32: + /*! Production:: names_exclusive : names_exclusive START_COND */ + + // 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.$.names[yyvstack[yysp]] = 1; + break; + +case 33: + /*! Production:: rules : rules rules_collective */ + + // 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].concat(yyvstack[yysp]); + break; + +case 34: + /*! Production:: rules : %epsilon */ +case 40: + /*! Production:: rule_block : %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 35: + /*! Production:: rules_collective : start_conditions rule */ + + // 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,-,-) + + + if (yyvstack[yysp - 1]) { + yyvstack[yysp].unshift(yyvstack[yysp - 1]); + } + this.$ = [yyvstack[yysp]]; + break; + +case 36: + /*! Production:: rules_collective : start_conditions "{" rule_block "}" */ + + // 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,-,-) + + + if (yyvstack[yysp - 3]) { + yyvstack[yysp - 1].forEach(function (d) { + d.unshift(yyvstack[yysp - 3]); + }); + } + this.$ = yyvstack[yysp - 1]; + break; + +case 37: + /*! Production:: rules_collective : start_conditions "{" 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 made a mistake while specifying one of the lexer rules inside + the start condition + <${yyvstack[yysp - 3].join(',')}> { rules... } + block. + + Erroneous area: + ${yylexer.prettyPrintRange(yylexer.mergeLocationInfo((yysp - 3), (yysp)), yylstack[yysp - 3])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 38: + /*! Production:: rules_collective : start_conditions "{" 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 lexer rules set inside + the start condition + <${yyvstack[yysp - 2].join(',')}> { rules... } + as a terminating curly brace '}' could not be found. + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 39: + /*! Production:: rule_block : rule_block rule */ + + // 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 41: + /*! Production:: rule : regex 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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The rule's action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = [yyvstack[yysp - 1], yyvstack[yysp]]; + break; + +case 42: + /*! Production:: rule : regex error */ + + // 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]]; + yyparser.yyError(rmCommonWS` + Lexer rule regex action code declaration error? + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 43: + /*! Production:: action : ACTION_START action_body BRACKET_MISSING */ + + // 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` + Missing curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: '{ ... }'. + + Offending action body: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + break; + +case 44: + /*! Production:: action : ACTION_START action_body BRACKET_SURPLUS */ + + // 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` + Too many curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: '{ ... }'. + + Offending action body: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + `); + break; + +case 45: + /*! Production:: action : ACTION_START action_body ACTION_END */ + + // 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 s = yyvstack[yysp - 1].trim(); + // remove outermost set of braces UNLESS there's + // a curly brace in there anywhere: in that case + // we should leave it up to the sophisticated + // code analyzer to simplify the code! + // + // This is a very rough check as it will also look + // inside code comments, which should not have + // any influence. + // + // Nevertheless: this is a *safe* transform! + if (s[0] === '{' && s.indexOf('}') === s.length - 1) { + this.$ = s.substring(1, s.length - 1).trim(); + } else { + this.$ = s; + } + break; + +case 46: + /*! Production:: action_body : action_body ACTION */ +case 51: + /*! Production:: action_body : action_body 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] + '\n\n' + yyvstack[yysp] + '\n\n'; + break; + +case 47: + /*! Production:: action_body : action_body ACTION_BODY */ +case 48: + /*! Production:: action_body : action_body ACTION_BODY_C_COMMENT */ +case 49: + /*! Production:: action_body : action_body ACTION_BODY_CPP_COMMENT */ +case 50: + /*! Production:: action_body : action_body ACTION_BODY_WHITESPACE */ +case 70: + /*! Production:: regex_concat : regex_concat regex_base */ +case 82: + /*! Production:: regex_base : regex_base range_regex */ +case 92: + /*! Production:: regex_set : regex_set regex_set_atom */ +case 114: + /*! 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 52: + /*! Production:: action_body : action_body INCLUDE_PLACEMENT_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` + You may place the '%include' instruction only at the start/front of a line. + + It's use is not permitted at this position: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + `); + break; + +case 53: + /*! Production:: action_body : action_body 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` + Seems you did not correctly match curly braces '{ ... }' in a lexer rule action block. + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 54: + /*! Production:: action_body : %epsilon */ +case 65: + /*! Production:: regex_list : %epsilon */ +case 117: + /*! 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 55: + /*! Production:: start_conditions : "<" name_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 - 1]; + break; + +case 56: + /*! Production:: start_conditions : "<" name_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,-,-) + + + yyparser.yyError(rmCommonWS` + Seems you did not correctly terminate the start condition set <${yyvstack[yysp - 1].join(',')},???> with a terminating '>' + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 57: + /*! Production:: start_conditions : "<" "*" ">" */ + + // 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.$ = ['*']; + break; + +case 58: + /*! Production:: start_conditions : %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 59: + /*! Production:: name_list : 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]]; + break; + +case 60: + /*! Production:: name_list : name_list "," 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]; this.$.push(yyvstack[yysp]); + break; + +case 61: + /*! Production:: regex : nonempty_regex_list */ + + // 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,-,-) + + + // Detect if the regex ends with a pure (Unicode) word; + // we *do* consider escaped characters which are 'alphanumeric' + // to be equivalent to their non-escaped version, hence these are + // all valid 'words' for the 'easy keyword rules' option: + // + // - hello_kitty + // - γεια_σου_γατοÏλα + // - \u03B3\u03B5\u03B9\u03B1_\u03C3\u03BF\u03C5_\u03B3\u03B1\u03C4\u03BF\u03CD\u03BB\u03B1 + // + // http://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode#12869914 + // + // As we only check the *tail*, we also accept these as + // 'easy keywords': + // + // - %options + // - %foo-bar + // - +++a:b:c1 + // + // Note the dash in that last example: there the code will consider + // `bar` to be the keyword, which is fine with us as we're only + // interested in the trailing boundary and patching that one for + // the `easy_keyword_rules` option. + this.$ = yyvstack[yysp]; + if (yy.options.easy_keyword_rules) { + // We need to 'protect' `eval` here as keywords are allowed + // to contain double-quotes and other leading cruft. + // `eval` *does* gobble some escapes (such as `\b`) but + // we protect against that through a simple replace regex: + // we're not interested in the special escapes' exact value + // anyway. + // It will also catch escaped escapes (`\\`), which are not + // word characters either, so no need to worry about + // `eval(str)` 'correctly' converting convoluted constructs + // like '\\\\\\\\\\b' in here. + this.$ = this.$ + .replace(/\\\\/g, '.') + .replace(/"/g, '.') + .replace(/\\c[A-Z]/g, '.') + .replace(/\\[^xu0-9]/g, '.'); + + try { + // Convert Unicode escapes and other escapes to their literal characters + // BEFORE we go and check whether this item is subject to the + // `easy_keyword_rules` option. + this.$ = JSON.parse('"' + this.$ + '"'); + } + catch (ex) { + yyparser.warn('easy-keyword-rule FAIL on eval: ', ex); + + // make the next keyword test fail: + this.$ = '.'; + } + // a 'keyword' starts with an alphanumeric character, + // followed by zero or more alphanumerics or digits: + var re = new XRegExp('\\w[\\w\\d]*$'); + if (XRegExp.match(this.$, re)) { + this.$ = yyvstack[yysp] + "\\b"; + } else { + this.$ = yyvstack[yysp]; + } + } + break; + +case 62: + /*! Production:: regex_list : regex_list "|" regex_concat */ +case 66: + /*! Production:: nonempty_regex_list : nonempty_regex_list "|" regex_concat */ + + // 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 63: + /*! Production:: regex_list : regex_list "|" */ +case 67: + /*! Production:: nonempty_regex_list : nonempty_regex_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] + '|'; + break; + +case 68: + /*! Production:: nonempty_regex_list : "|" regex_concat */ + + // 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 72: + /*! Production:: regex_base : "(" regex_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 - 1] + ')'; + break; + +case 73: + /*! Production:: regex_base : SPECIAL_GROUP regex_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 74: + /*! Production:: regex_base : "(" regex_list error */ +case 75: + /*! Production:: regex_base : SPECIAL_GROUP regex_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,-,-) + + + yyparser.yyError(rmCommonWS` + Seems you did not correctly bracket a lex rule regex part in '(...)' braces. + + Unterminated regex part: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 76: + /*! Production:: regex_base : regex_base "+" */ + + // 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] + '+'; + break; + +case 77: + /*! Production:: regex_base : regex_base "*" */ + + // 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] + '*'; + break; + +case 78: + /*! Production:: regex_base : regex_base "?" */ + + // 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] + '?'; + break; + +case 79: + /*! Production:: regex_base : "/" regex_base */ + + // 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 80: + /*! Production:: regex_base : "/!" regex_base */ + + // 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 81: + /*! Production:: regex_base : name_expansion */ +case 83: + /*! Production:: regex_base : any_group_regex */ +case 87: + /*! Production:: regex_base : string */ +case 88: + /*! Production:: regex_base : escape_char */ +case 89: + /*! Production:: name_expansion : NAME_BRACE */ +case 93: + /*! Production:: regex_set : regex_set_atom */ +case 94: + /*! Production:: regex_set_atom : REGEX_SET */ +case 99: + /*! Production:: string : CHARACTER_LIT */ + + // 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,-,-) + break; + +case 84: + /*! Production:: regex_base : "." */ + + // 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.$ = '.'; + break; + +case 85: + /*! Production:: regex_base : "^" */ + + // 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.$ = '^'; + break; + +case 86: + /*! Production:: regex_base : "$" */ + + // 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.$ = '$'; + break; + +case 90: + /*! Production:: any_group_regex : REGEX_SET_START regex_set REGEX_SET_END */ + + // 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 91: + /*! Production:: any_group_regex : REGEX_SET_START regex_set 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 lex rule regex set in '[...]' brackets. + + Unterminated regex set: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 95: + /*! Production:: regex_set_atom : name_expansion */ + + // 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,-,-) + + + if (XRegExp._getUnicodeProperty(yyvstack[yysp].replace(/[{}]/g, '')) + && yyvstack[yysp].toUpperCase() !== yyvstack[yysp] + ) { + // treat this as part of an XRegExp `\p{...}` Unicode 'General Category' Property cf. http://unicode.org/reports/tr18/#Categories + this.$ = yyvstack[yysp]; + } else { + this.$ = yyvstack[yysp]; + } + //yyparser.log("name expansion for: ", { name: $name_expansion, redux: $name_expansion.replace(/[{}]/g, ''), output: $$ }); + break; + +case 98: + /*! Production:: string : STRING_LIT */ + + // 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.$ = prepareString(yyvstack[yysp]); + break; + +case 100: + /*! Production:: options : OPTIONS option_list OPTIONS_END */ + + // 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.$ = null; + break; + +case 101: + /*! Production:: option_list : option option_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.$ = null; + break; + +case 103: + /*! Production:: option : NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp]] = true; + break; + +case 104: + /*! Production:: option : NAME "=" OPTION_STRING_VALUE */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = yyvstack[yysp]; + break; + +case 105: + /*! Production:: option : NAME "=" OPTION_VALUE */ +case 106: + /*! Production:: option : NAME "=" NAME */ + + // 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,-,-) + + + yy.options[yyvstack[yysp - 2]] = parseValue(yyvstack[yysp]); + break; + +case 107: + /*! 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` + Internal error: option "${$option}" value assignment failure. + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp], yylstack[yysp - 2])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 108: + /*! Production:: option : 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` + Expected a valid option name (with optional value assignment). + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 109: + /*! Production:: extra_lexer_module_code : optional_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,-,-) + + + var rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = yyvstack[yysp]; + break; + +case 110: + /*! Production:: extra_lexer_module_code : extra_lexer_module_code include_macro_code optional_module_code_chunk */ + + // 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,-,-) + + + // Each of the 3 chunks should be parse-able as a JS snippet on its own. + // + // Note: we have already checked the first section in a previous reduction + // of this rule, so we don't need to check that one again! + var rv = checkActionBlock(yyvstack[yysp - 1], yylstack[yysp - 1]); + if (rv) { + yyparser.yyError(rmCommonWS` + The source code %include-d into the extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + `); + } + rv = checkActionBlock(yyvstack[yysp], yylstack[yysp]); + if (rv) { + yyparser.yyError(rmCommonWS` + The extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(yylstack[yysp])} + `); + } + this.$ = yyvstack[yysp - 2] + yyvstack[yysp - 1] + yyvstack[yysp]; + break; + +case 111: + /*! 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' }); + // 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 112: + /*! 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])} + + Technical error report: + ${yyvstack[yysp].errStr} + `); + break; + +case 115: + /*! Production:: module_code_chunk : error CODE */ + + // 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` + Module code declaration error? + + Erroneous code: + ${yylexer.prettyPrintRange(yylstack[yysp - 1])} + + Technical error report: + ${yyvstack[yysp - 1].errStr} + `); + break; + +case 151: // === 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([ + 13, + 1, + 12, + 15, + 1, + 1, + 11, + 19, + 21, + 2, + 2, + s, + [11, 3], + 4, + 4, + 12, + 4, + 1, + 1, + 19, + 18, + 11, + 12, + 18, + 29, + 30, + 22, + 22, + 17, + 17, + s, + [29, 7], + 31, + 5, + s, + [29, 3], + s, + [12, 4], + 4, + 11, + 3, + 3, + 2, + 2, + 1, + 1, + 12, + 1, + 5, + 4, + 3, + 7, + 17, + 23, + 3, + 19, + 30, + 29, + 30, + s, + [29, 5], + 3, + 20, + 3, + 30, + 30, + 6, + s, + [4, 3], + 12, + 12, + s, + [11, 6], + s, + [27, 3], + s, + [11, 8], + 2, + 11, + 1, + 4, + c, + [55, 3], + 3, + 3, + 17, + 16, + 3, + 3, + 1, + 3, + 7, + s, + [29, 3], + 21, + s, + [29, 4], + 4, + 13, + 13, + s, + [3, 4], + 6, + 3, + 3, + 23, + s, + [18, 3], + 14, + 14, + 1, + 14, + 3, + 1, + 20, + 2, + 17, + 14, + 17, + 3 +]), + symbol: u([ + 1, + 2, + s, + [19, 7, 1], + 28, + 47, + 54, + 56, + 1, + c, + [14, 11], + 57, + c, + [12, 11], + 55, + 58, + 68, + 84, + s, + [1, 3], + c, + [17, 10], + 1, + 2, + 3, + 5, + 9, + 10, + s, + [14, 4, 1], + 19, + 26, + s, + [38, 4, 1], + 44, + 46, + 64, + c, + [15, 6], + c, + [14, 7], + 72, + s, + [74, 5, 1], + 81, + 83, + 27, + 62, + 27, + 63, + c, + [55, 13], + c, + [11, 20], + 2, + 20, + 26, + 60, + c, + [4, 3], + 59, + 2, + s, + [29, 9, 1], + 51, + 69, + 2, + 20, + 85, + 86, + s, + [1, 3], + c, + [102, 16], + 65, + 70, + c, + [19, 17], + 64, + c, + [85, 13], + 9, + c, + [12, 9], + c, + [143, 12], + c, + [141, 6], + c, + [30, 3], + c, + [58, 6], + s, + [20, 7, 1], + 28, + c, + [29, 6], + 47, + c, + [29, 7], + 7, + s, + [9, 9, 1], + c, + [33, 14], + 45, + 46, + 47, + 82, + c, + [58, 3], + 11, + c, + [80, 11], + 73, + c, + [81, 6], + c, + [22, 22], + c, + [121, 12], + c, + [17, 22], + c, + [108, 29], + c, + [29, 199], + s, + [42, 6, 1], + 40, + 43, + 77, + 79, + 80, + c, + [123, 89], + c, + [19, 7], + 27, + c, + [590, 11], + c, + [12, 27], + c, + [611, 3], + 61, + c, + [630, 14], + c, + [3, 3], + 28, + 68, + 28, + 68, + 28, + 28, + c, + [634, 11], + 88, + 48, + 2, + 20, + 48, + 85, + 86, + 2, + 18, + 20, + c, + [9, 4], + 1, + 2, + 51, + 53, + 87, + 89, + 90, + c, + [629, 17], + 3, + c, + [750, 13], + 67, + c, + [751, 8], + 7, + 20, + 71, + c, + [691, 20], + c, + [632, 23], + c, + [662, 65], + c, + [526, 145], + 2, + 9, + 11, + c, + [788, 15], + c, + [808, 7], + 11, + c, + [201, 59], + 82, + 2, + 40, + 42, + 43, + 77, + 80, + c, + [6, 4], + c, + [4, 8], + c, + [495, 33], + c, + [11, 59], + 3, + 4, + c, + [449, 8], + c, + [401, 15], + c, + [27, 54], + c, + [603, 11], + c, + [11, 78], + 52, + c, + [182, 11], + c, + [683, 3], + 49, + 50, + 1, + 51, + 88, + 1, + 53, + 1, + 51, + 1, + 51, + c, + [5, 3], + 53, + c, + [647, 17], + 2, + 4, + c, + [691, 13], + 66, + 2, + 28, + 68, + 2, + 6, + 8, + 6, + c, + [4, 3], + c, + [740, 8], + c, + [648, 57], + c, + [531, 31], + c, + [528, 13], + c, + [756, 8], + c, + [668, 115], + c, + [568, 5], + c, + [321, 10], + 53, + c, + [13, 13], + c, + [1004, 3], + c, + [3, 9], + c, + [273, 4], + c, + [272, 3], + c, + [328, 5], + c, + [310, 14], + c, + [1001, 9], + 1, + c, + [496, 10], + c, + [27, 7], + c, + [18, 36], + c, + [1078, 14], + c, + [14, 14], + 20, + c, + [15, 14], + c, + [461, 3], + 53, + c, + [843, 20], + c, + [480, 3], + c, + [474, 16], + c, + [163, 14], + c, + [505, 18], + 6, + 8 +]), + type: u([ + s, + [2, 11], + 0, + 0, + 1, + c, + [14, 12], + c, + [26, 13], + 0, + c, + [15, 12], + s, + [2, 20], + c, + [32, 14], + s, + [0, 8], + c, + [23, 3], + c, + [57, 32], + c, + [62, 9], + c, + [113, 13], + c, + [67, 4], + c, + [40, 20], + c, + [21, 18], + c, + [96, 36], + c, + [141, 7], + c, + [30, 28], + c, + [221, 43], + c, + [223, 9], + c, + [22, 34], + c, + [17, 34], + s, + [2, 224], + c, + [239, 141], + c, + [139, 19], + c, + [673, 16], + c, + [14, 5], + c, + [180, 13], + c, + [764, 35], + c, + [751, 9], + c, + [98, 19], + c, + [632, 31], + c, + [662, 75], + c, + [511, 151], + c, + [513, 34], + c, + [231, 35], + c, + [821, 238], + c, + [735, 74], + c, + [43, 27], + c, + [740, 39], + c, + [1202, 78], + c, + [756, 30], + c, + [696, 140], + c, + [1001, 31], + c, + [461, 114], + c, + [121, 58] +]), + state: u([ + s, + [1, 4, 1], + 6, + 11, + 12, + 20, + 22, + 23, + 25, + 26, + 31, + 32, + 37, + 36, + 43, + 45, + 47, + 51, + 55, + 56, + 57, + 61, + 62, + 64, + 66, + c, + [16, 5], + 67, + c, + [5, 4], + 71, + 73, + 74, + c, + [13, 5], + 75, + c, + [7, 6], + 76, + c, + [5, 4], + 77, + c, + [5, 4], + 81, + 78, + 79, + 84, + 88, + 89, + 98, + 103, + 57, + 105, + 108, + 107, + 110, + 112, + c, + [67, 7], + 113, + 61, + 62, + 117, + c, + [60, 11], + c, + [6, 6], + 71, + 81, + 125, + 132, + 135, + 137, + 143, + 108, + 107, + c, + [15, 5], + 145, + c, + [32, 5], + 108, + 146, + 148, + c, + [52, 8], + 132, + c, + [23, 5] +]), + mode: u([ + s, + [2, 23], + s, + [1, 12], + c, + [24, 13], + c, + [41, 28], + c, + [44, 15], + c, + [89, 27], + c, + [17, 13], + c, + [88, 11], + c, + [64, 34], + c, + [38, 14], + c, + [123, 15], + c, + [92, 12], + 1, + c, + [107, 10], + c, + [27, 6], + c, + [72, 23], + c, + [40, 8], + c, + [45, 7], + c, + [15, 13], + s, + [1, 24], + s, + [2, 234], + c, + [236, 98], + c, + [97, 24], + c, + [24, 15], + c, + [374, 20], + c, + [432, 5], + c, + [409, 15], + c, + [585, 9], + c, + [47, 20], + c, + [45, 25], + c, + [36, 14], + c, + [578, 18], + c, + [602, 53], + c, + [459, 145], + c, + [735, 19], + c, + [797, 33], + c, + [29, 25], + c, + [776, 238], + c, + [813, 51], + c, + [289, 5], + c, + [648, 7], + c, + [298, 21], + c, + [738, 18], + c, + [621, 8], + c, + [376, 7], + c, + [651, 22], + c, + [874, 59], + c, + [1219, 170], + c, + [960, 9], + c, + [947, 23], + c, + [1151, 89], + c, + [805, 17], + s, + [2, 53] +]), + goto: u([ + s, + [9, 11], + s, + [11, 11], + 8, + 5, + s, + [7, 4, 1], + s, + [13, 7, 1], + s, + [10, 11], + 34, + 21, + s, + [34, 16], + 24, + 27, + 29, + 33, + 34, + 35, + 40, + 28, + 30, + 38, + 39, + 42, + 41, + 44, + 46, + s, + [15, 11], + s, + [16, 11], + s, + [17, 11], + 48, + 49, + 50, + 52, + 53, + s, + [54, 12], + 59, + 58, + 1, + 2, + 7, + 58, + 63, + s, + [58, 6], + 60, + s, + [58, 7], + s, + [34, 17], + s, + [12, 11], + 61, + 61, + 65, + s, + [61, 9], + c, + [125, 12], + s, + [69, 3], + c, + [15, 5], + s, + [69, 7], + 40, + 69, + c, + [23, 7], + 71, + 71, + c, + [3, 3], + 71, + 68, + 70, + s, + [71, 18], + 72, + 71, + 71, + 65, + 65, + 27, + 65, + c, + [68, 11], + c, + [15, 15], + c, + [95, 12], + c, + [12, 12], + s, + [81, 29], + s, + [83, 29], + s, + [84, 29], + s, + [85, 29], + s, + [86, 29], + s, + [87, 29], + s, + [88, 29], + s, + [89, 31], + 38, + 80, + s, + [98, 29], + s, + [99, 29], + s, + [96, 29], + s, + [13, 9], + 82, + 13, + 13, + s, + [29, 12], + s, + [14, 9], + 83, + 14, + 14, + s, + [31, 12], + 85, + 86, + 87, + s, + [20, 11], + s, + [25, 3], + s, + [26, 3], + 16, + 16, + 23, + 24, + 100, + s, + [90, 8, 1], + 99, + 101, + 102, + 59, + 58, + 102, + 103, + 104, + 103, + 103, + s, + [108, 3], + 117, + 106, + 117, + 109, + s, + [33, 17], + 111, + c, + [684, 13], + 114, + 115, + 6, + c, + [630, 8], + 116, + s, + [58, 7], + s, + [67, 3], + c, + [34, 5], + s, + [67, 7], + 40, + 67, + c, + [42, 6], + 67, + s, + [68, 3], + c, + [24, 5], + s, + [68, 7], + 40, + 68, + c, + [24, 6], + 68, + 70, + 70, + 69, + s, + [70, 3], + c, + [7, 3], + s, + [70, 17], + 72, + 70, + 70, + s, + [76, 29], + s, + [77, 29], + s, + [78, 29], + s, + [82, 29], + s, + [97, 29], + 119, + 120, + 118, + 64, + 64, + 27, + 64, + c, + [259, 11], + 122, + 120, + 121, + 79, + 79, + 69, + s, + [79, 3], + 68, + 70, + s, + [79, 18], + 72, + 79, + 79, + 80, + 80, + 69, + s, + [80, 3], + 68, + 70, + s, + [80, 18], + 72, + 80, + 80, + 124, + 38, + 123, + 80, + s, + [93, 4], + s, + [94, 4], + s, + [95, 4], + s, + [30, 12], + s, + [32, 12], + s, + [18, 11], + s, + [19, 11], + s, + [27, 11], + s, + [28, 11], + s, + [21, 11], + s, + [22, 11], + s, + [43, 27], + s, + [44, 27], + s, + [45, 27], + s, + [46, 11], + s, + [47, 11], + s, + [48, 11], + s, + [49, 11], + s, + [50, 11], + s, + [51, 11], + s, + [52, 11], + s, + [53, 11], + 127, + 126, + s, + [100, 11], + 101, + 131, + 130, + 128, + 129, + 3, + 101, + 5, + 133, + 109, + 109, + 116, + 116, + 134, + s, + [113, 3], + s, + [35, 17], + 136, + s, + [40, 14], + 138, + 16, + 140, + 139, + 141, + 142, + s, + [59, 3], + 117, + 144, + 117, + 109, + s, + [66, 3], + c, + [627, 5], + s, + [66, 7], + 40, + 66, + c, + [434, 6], + 66, + s, + [72, 29], + s, + [74, 29], + 63, + 63, + 27, + 63, + c, + [508, 11], + s, + [73, 29], + s, + [75, 29], + s, + [90, 29], + s, + [91, 29], + s, + [92, 4], + s, + [111, 13], + s, + [112, 13], + s, + [104, 3], + s, + [105, 3], + s, + [106, 3], + s, + [107, 3], + c, + [259, 4], + s, + [115, 3], + s, + [114, 3], + 147, + c, + [949, 13], + 38, + 38, + 149, + s, + [38, 15], + s, + [41, 18], + s, + [42, 18], + s, + [55, 14], + s, + [56, 14], + 150, + s, + [57, 14], + 4, + 101, + 133, + 62, + 62, + 27, + 62, + c, + [115, 11], + 110, + 110, + s, + [36, 17], + s, + [39, 14], + s, + [37, 17], + s, + [60, 3] +]) +}), +defaultActions: bda({ + idx: u([ + 0, + 2, + 6, + 11, + 12, + 13, + 16, + 18, + 19, + 21, + 22, + s, + [31, 8, 1], + 40, + 41, + s, + [42, 4, 2], + 49, + 50, + 53, + 54, + 59, + 61, + s, + [68, 5, 1], + s, + [79, 22, 1], + 102, + 103, + 107, + 109, + 110, + 115, + 118, + 119, + s, + [121, 11, 1], + 133, + 134, + s, + [137, 4, 1], + 142, + s, + [146, 5, 1] +]), + goto: u([ + 9, + 11, + 10, + 15, + 16, + 17, + 54, + 1, + 2, + 34, + 12, + 81, + s, + [83, 7, 1], + 98, + 99, + 96, + 29, + 31, + 20, + 25, + 26, + 23, + 24, + 108, + 33, + 76, + 77, + 78, + 82, + 97, + 93, + 94, + 95, + 30, + 32, + 18, + 19, + 27, + 28, + 21, + 22, + s, + [43, 11, 1], + 100, + 101, + 109, + 113, + 35, + 59, + 72, + 74, + 73, + 75, + 90, + 91, + 92, + 111, + 112, + s, + [104, 4, 1], + 115, + 114, + 41, + 42, + 55, + 56, + 57, + 110, + 36, + 39, + 37, + 60 +]) +}), +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, 151 /* === 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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: $end + // %{ $$ = $1; @$ = @1; %} + // + // which, combined with the parse kernel's `$accept` state behaviour coded below, + // will produce the `$$` value output of the 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 rmCommonWS = helpers.rmCommonWS; +var checkActionBlock = helpers.checkActionBlock; + + +function encodeRE(s) { + return s.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1').replace(/\\\\u([a-fA-F0-9]{4})/g, '\\u$1'); +} + +function prepareString(s) { + // unescape slashes + s = s.replace(/\\\\/g, "\\"); + s = encodeRE(s); + return s; +} + +// 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); +}; + +parser.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse:', arguments); +}; + +parser.yy.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse YY:', arguments); +}; + +parser.yy.post_lex = function p_lex() { + if (parser.yydebug) parser.log('post_lex:', 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 <> tokens and perform user action code for a <> 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 0: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %\{ */ + yy.depth = 0; + + yy.include_command_allowed = false; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 1: + /*! Conditions:: action */ + /*! Rule:: %\{([^]*?)%\} */ + yy_.yytext = this.matches[1].replace(/%\\\}/g, '%}'); // unescape any literal '%\}' that exists within the action code block + + yy.include_command_allowed = true; + return 32; + break; + + case 2: + /*! Conditions:: action */ + /*! Rule:: %include\b */ + if (yy.include_command_allowed) { + // This is an include instruction in place of an action: + // + // - one %include per action chunk + // - one %include replaces an entire action chunk + this.pushState('path'); + + return 51; + } else { + // TODO + yy_.yyerror('oops!'); + + return 37; + } + + break; + + case 3: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + //yy.include_command_allowed = false; -- doesn't impact include-allowed state + return 34; + + break; + + case 4: + /*! Conditions:: action */ + /*! Rule:: {WS}*\/\/.* */ + yy.include_command_allowed = false; + + return 35; + break; + + case 6: + /*! Conditions:: action */ + /*! Rule:: \| */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 7: + /*! Conditions:: action */ + /*! Rule:: %% */ + if (yy.include_command_allowed) { + this.popState(); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } else { + return 33; + } + + break; + + case 9: + /*! Conditions:: action */ + /*! Rule:: \/[^\s/]*?(?:['"`{}][^\s/]*?)*\/ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 10: + /*! Conditions:: action */ + /*! Rule:: \/[^}{BR}]* */ + yy.include_command_allowed = false; + + return 33; + break; + + case 11: + /*! Conditions:: action */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy.include_command_allowed = false; + + return 33; + break; + + case 12: + /*! Conditions:: action */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy.include_command_allowed = false; + + return 33; + break; + + case 13: + /*! Conditions:: action */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy.include_command_allowed = false; + + return 33; + break; + + case 14: + /*! Conditions:: action */ + /*! Rule:: [^{}/"'`|%\{\}{BR}{WS}]+ */ + yy.include_command_allowed = false; + + return 33; + break; + + case 15: + /*! Conditions:: action */ + /*! Rule:: \{ */ + yy.depth++; + + yy.include_command_allowed = false; + return 33; + break; + + case 16: + /*! Conditions:: action */ + /*! Rule:: \} */ + yy.include_command_allowed = false; + + if (yy.depth <= 0) { + yy_.yyerror(rmCommonWS` + too many closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 30; + } else { + yy.depth--; + } + + return 33; + break; + + case 17: + /*! Conditions:: action */ + /*! Rule:: (?:{BR}{WS}+)+(?=[^{WS}{BR}|]) */ + yy.include_command_allowed = true; + + return 36; // keep empty lines as-is inside action code blocks. + break; + + case 18: + /*! Conditions:: action */ + /*! Rule:: {BR} */ + if (yy.depth > 0) { + yy.include_command_allowed = true; + return 36; // keep empty lines as-is inside action code blocks. + } else { + // end of action code chunk + this.popState(); + + this.unput(yy_.yytext); + yy_.yytext = ''; + return 31; + } + + break; + + case 19: + /*! Conditions:: action */ + /*! Rule:: $ */ + yy.include_command_allowed = false; + + if (yy.depth !== 0) { + yy_.yyerror(rmCommonWS` + missing ${yy.depth} closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + yy_.yytext = ''; + return 29; + } + + this.popState(); + yy_.yytext = ''; + return 31; + break; + + case 21: + /*! Conditions:: conditions */ + /*! Rule:: > */ + this.popState(); + + return 6; + break; + + case 24: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 25: + /*! Conditions:: INITIAL start_condition macro path options */ + /*! Rule:: {WS}*\/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 26: + /*! Conditions:: rules */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 27: + /*! Conditions:: rules */ + /*! Rule:: {WS}+{BR}+ */ + /* empty */ + break; + + case 28: + /*! Conditions:: rules */ + /*! Rule:: \/\/[^\r\n]* */ + /* skip single-line comment */ + break; + + case 29: + /*! Conditions:: rules */ + /*! Rule:: \/\*[^]*?\*\/ */ + /* skip multi-line comment */ + break; + + case 30: + /*! Conditions:: rules */ + /*! Rule:: {WS}+(?=[^{WS}{BR}|%]) */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + return 28; + break; + + case 31: + /*! Conditions:: rules */ + /*! Rule:: %% */ + this.popState(); + + this.pushState('code'); + return 19; + break; + + case 32: + /*! Conditions:: rules */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 35: + /*! Conditions:: options */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 49; // value is always a string type + break; + + case 36: + /*! Conditions:: options */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 49; // value is always a string type + break; + + case 37: + /*! Conditions:: options */ + /*! Rule:: `{ES2017_STRING_CONTENT}` */ + yy_.yytext = unescQuote(this.matches[1], /\\`/g); + + return 49; // value is always a string type + break; + + case 39: + /*! Conditions:: options */ + /*! Rule:: {BR}{WS}+(?=\S) */ + /* skip leading whitespace on the next line of input, when followed by more options */ + break; + + case 40: + /*! Conditions:: options */ + /*! Rule:: {BR} */ + this.popState(); + + return 48; + break; + + case 41: + /*! Conditions:: options */ + /*! Rule:: {WS}+ */ + /* skip whitespace */ + break; + + case 43: + /*! Conditions:: start_condition */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 44: + /*! Conditions:: start_condition */ + /*! Rule:: {WS}+ */ + /* empty */ + break; + + case 46: + /*! Conditions:: INITIAL */ + /*! Rule:: {ID} */ + this.pushState('macro'); + + return 20; + break; + + case 47: + /*! Conditions:: macro named_chunk */ + /*! Rule:: {BR}+ */ + this.popState(); + + break; + + case 48: + /*! Conditions:: macro */ + /*! Rule:: {ANY_LITERAL_CHAR}+ */ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 46; + + break; + + case 49: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: {BR}+ */ + /* empty */ + break; + + case 50: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \s+ */ + /* empty */ + break; + + case 51: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1], /\\"/g); + + return 26; + break; + + case 52: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1], /\\'/g); + + return 26; + break; + + case 53: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \[ */ + this.pushState('set'); + + return 41; + break; + + case 66: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: < */ + this.pushState('conditions'); + + return 5; + break; + + case 67: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/! */ + return 39; // treated as `(?!atom)` + + break; + + case 68: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \/ */ + return 14; // treated as `(?=atom)` + + break; + + case 70: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\. */ + yy_.yytext = yy_.yytext.replace(/^\\/g, ''); + + return 44; + break; + + case 73: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %options\b */ + this.pushState('options'); + + return 47; + break; + + case 74: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %s\b */ + this.pushState('start_condition'); + + return 21; + break; + + case 75: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %x\b */ + this.pushState('start_condition'); + + return 22; + break; + + case 76: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %code\b */ + this.pushState('named_chunk'); + + return 25; + break; + + case 77: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %import\b */ + this.pushState('named_chunk'); + + return 24; + break; + + case 78: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %include\b */ + yy.depth = 0; + + yy.include_command_allowed = true; + this.pushState('action'); + this.unput(yy_.yytext); + yy_.yytext = ''; + return 28; + break; + + case 79: + /*! Conditions:: code */ + /*! Rule:: %include\b */ + this.pushState('path'); + + return 51; + break; + + case 80: + /*! Conditions:: INITIAL rules code */ + /*! Rule:: %{NAME}([^\r\n]*) */ + /* ignore unrecognized decl */ + this.warn(rmCommonWS` + LEX: ignoring unsupported lexer 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 23; + break; + + case 81: + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: %% */ + this.pushState('rules'); + + return 19; + break; + + case 89: + /*! Conditions:: set */ + /*! Rule:: \] */ + this.popState(); + + return 42; + break; + + case 91: + /*! Conditions:: code */ + /*! Rule:: [^\r\n]+ */ + return 53; // the bit of CODE just before EOF... + + break; + + case 92: + /*! Conditions:: path */ + /*! Rule:: {BR} */ + this.popState(); + + this.unput(yy_.yytext); + break; + + case 93: + /*! Conditions:: path */ + /*! Rule:: "{DOUBLEQUOTED_STRING_CONTENT}" */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 94: + /*! Conditions:: path */ + /*! Rule:: '{QUOTED_STRING_CONTENT}' */ + yy_.yytext = unescQuote(this.matches[1]); + + this.popState(); + return 52; + break; + + case 95: + /*! Conditions:: path */ + /*! Rule:: {WS}+ */ + // skip whitespace in the line + break; + + case 96: + /*! Conditions:: path */ + /*! Rule:: [^\s\r\n]+ */ + this.popState(); + + return 52; + break; + + case 97: + /*! Conditions:: action */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 98: + /*! Conditions:: action */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 99: + /*! Conditions:: action */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 100: + /*! Conditions:: options */ + /*! Rule:: " */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 101: + /*! Conditions:: options */ + /*! Rule:: ' */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 102: + /*! Conditions:: options */ + /*! Rule:: ` */ + yy_.yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + return 2; + break; + + case 103: + /*! 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 104: + /*! 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 105: + /*! 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 106: + /*! Conditions:: macro rules */ + /*! Rule:: . */ + /* b0rk on bad characters */ + var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + + yy_.yyerror(rmCommonWS` + unsupported lexer input encountered while lexing + ${rules} (i.e. jison lex regexes). + + NOTE: When you want this input to be interpreted as a LITERAL part + of a lex rule regex, you MUST enclose it in double or + single quotes. + + If not, then know that this input is not accepted as a valid + regex expression here in jison-lex ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(yy_.yylloc)); + + break; + + case 107: + /*! Conditions:: * */ + /*! Rule:: . */ + yy_.yyerror(rmCommonWS` + unsupported lexer 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:: {WS}+ */ + 5: 36, + + /*! Conditions:: action */ + /*! Rule:: % */ + 8: 33, + + /*! Conditions:: conditions */ + /*! Rule:: {NAME} */ + 20: 20, + + /*! Conditions:: conditions */ + /*! Rule:: , */ + 22: 8, + + /*! Conditions:: conditions */ + /*! Rule:: \* */ + 23: 7, + + /*! Conditions:: options */ + /*! Rule:: {NAME} */ + 33: 20, + + /*! Conditions:: options */ + /*! Rule:: = */ + 34: 18, + + /*! Conditions:: options */ + /*! Rule:: [^\s\r\n]+ */ + 38: 50, + + /*! Conditions:: start_condition */ + /*! Rule:: {ID} */ + 42: 27, + + /*! Conditions:: named_chunk */ + /*! Rule:: {ID} */ + 45: 20, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \| */ + 54: 9, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?: */ + 55: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?= */ + 56: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \(\?! */ + 57: 38, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \( */ + 58: 10, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \) */ + 59: 11, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \+ */ + 60: 12, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \* */ + 61: 7, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \? */ + 62: 13, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \^ */ + 63: 16, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: , */ + 64: 8, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: <> */ + 65: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \\([0-7]{1,3}|[rfntvsSbBwWdD\\*+()${}|[\]\/.^?]|c[A-Z]|x[0-9A-F]{2}|u[a-fA-F0-9]{4}) */ + 69: 44, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \$ */ + 71: 17, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \. */ + 72: 15, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{\d+(,\s*\d+|,)?\} */ + 82: 45, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{{ID}\} */ + 83: 40, + + /*! Conditions:: set options */ + /*! Rule:: \{{ID}\} */ + 84: 40, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \{ */ + 85: 3, + + /*! Conditions:: rules macro named_chunk INITIAL */ + /*! Rule:: \} */ + 86: 4, + + /*! Conditions:: set */ + /*! Rule:: (?:\\\\|\\\]|[^\]{])+ */ + 87: 43, + + /*! Conditions:: set */ + /*! Rule:: \{ */ + 88: 43, + + /*! Conditions:: code */ + /*! Rule:: [^\r\n]*(\r|\n)+ */ + 90: 53, + + /*! Conditions:: * */ + /*! Rule:: $ */ + 108: 1 + }, + + rules: [ + /* 0: */ /^(?:%\{)/, + /* 1: */ new XRegExp('^(?:%\\{([^]*?)%\\})', ''), + /* 2: */ /^(?:%include\b)/, + /* 3: */ new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 4: */ /^(?:([^\S\n\r])*\/\/.*)/, + /* 5: */ /^(?:([^\S\n\r])+)/, + /* 6: */ /^(?:\|)/, + /* 7: */ /^(?:%%)/, + /* 8: */ /^(?:%)/, + /* 9: */ /^(?:\/[^\s\/]*?(?:['"`{}][^\s\/]*?)*\/)/, + /* 10: */ /^(?:\/[^\n\r}]*)/, + /* 11: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 12: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 13: */ /^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 14: */ /^(?:[^\s"%'\/`{-}]+)/, + /* 15: */ /^(?:\{)/, + /* 16: */ /^(?:\})/, + /* 17: */ /^(?:(?:(\r\n|\n|\r)([^\S\n\r])+)+(?=[^\s|]))/, + /* 18: */ /^(?:(\r\n|\n|\r))/, + /* 19: */ /^(?:$)/, + /* 20: */ new XRegExp( + '^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', + '' + ), + /* 21: */ /^(?:>)/, + /* 22: */ /^(?:,)/, + /* 23: */ /^(?:\*)/, + /* 24: */ /^(?:([^\S\n\r])*\/\/[^\n\r]*)/, + /* 25: */ new XRegExp('^(?:([^\\S\\n\\r])*\\/\\*[^]*?\\*\\/)', ''), + /* 26: */ /^(?:(\r\n|\n|\r)+)/, + /* 27: */ /^(?:([^\S\n\r])+(\r\n|\n|\r)+)/, + /* 28: */ /^(?:\/\/[^\r\n]*)/, + /* 29: */ new XRegExp('^(?:\\/\\*[^]*?\\*\\/)', ''), + /* 30: */ /^(?:([^\S\n\r])+(?=[^\s%|]))/, + /* 31: */ /^(?:%%)/, + /* 32: */ /^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 33: */ new XRegExp( + '^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?))', + '' + ), + /* 34: */ /^(?:=)/, + /* 35: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 36: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 37: */ /^(?:`((?:\\`|\\[^`]|[^\\`])*)`)/, + /* 38: */ /^(?:\S+)/, + /* 39: */ /^(?:(\r\n|\n|\r)([^\S\n\r])+(?=\S))/, + /* 40: */ /^(?:(\r\n|\n|\r))/, + /* 41: */ /^(?:([^\S\n\r])+)/, + /* 42: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 43: */ /^(?:(\r\n|\n|\r)+)/, + /* 44: */ /^(?:([^\S\n\r])+)/, + /* 45: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 46: */ new XRegExp('^(?:([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*))', ''), + /* 47: */ /^(?:(\r\n|\n|\r)+)/, + /* 48: */ /^(?:([^\s!"$%'-,.\/:-?\[-\^{-}])+)/, + /* 49: */ /^(?:(\r\n|\n|\r)+)/, + /* 50: */ /^(?:\s+)/, + /* 51: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 52: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 53: */ /^(?:\[)/, + /* 54: */ /^(?:\|)/, + /* 55: */ /^(?:\(\?:)/, + /* 56: */ /^(?:\(\?=)/, + /* 57: */ /^(?:\(\?!)/, + /* 58: */ /^(?:\()/, + /* 59: */ /^(?:\))/, + /* 60: */ /^(?:\+)/, + /* 61: */ /^(?:\*)/, + /* 62: */ /^(?:\?)/, + /* 63: */ /^(?:\^)/, + /* 64: */ /^(?:,)/, + /* 65: */ /^(?:<>)/, + /* 66: */ /^(?:<)/, + /* 67: */ /^(?:\/!)/, + /* 68: */ /^(?:\/)/, + /* 69: */ /^(?:\\([0-7]{1,3}|[$(-+.\/?BDSW\[-\^bdfnr-tvw{-}]|c[A-Z]|x[\dA-F]{2}|u[\dA-Fa-f]{4}))/, + /* 70: */ /^(?:\\.)/, + /* 71: */ /^(?:\$)/, + /* 72: */ /^(?:\.)/, + /* 73: */ /^(?:%options\b)/, + /* 74: */ /^(?:%s\b)/, + /* 75: */ /^(?:%x\b)/, + /* 76: */ /^(?:%code\b)/, + /* 77: */ /^(?:%import\b)/, + /* 78: */ /^(?:%include\b)/, + /* 79: */ /^(?:%include\b)/, + /* 80: */ new XRegExp( + '^(?:%([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}\\-_]*(?:[\\p{Alphabetic}\\p{Number}_]))?)([^\\n\\r]*))', + '' + ), + /* 81: */ /^(?:%%)/, + /* 82: */ /^(?:\{\d+(,\s*\d+|,)?\})/, + /* 83: */ new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 84: */ new XRegExp('^(?:\\{([\\p{Alphabetic}_](?:[\\p{Alphabetic}\\p{Number}_])*)\\})', ''), + /* 85: */ /^(?:\{)/, + /* 86: */ /^(?:\})/, + /* 87: */ /^(?:(?:\\\\|\\\]|[^\]{])+)/, + /* 88: */ /^(?:\{)/, + /* 89: */ /^(?:\])/, + /* 90: */ /^(?:[^\r\n]*(\r|\n)+)/, + /* 91: */ /^(?:[^\r\n]+)/, + /* 92: */ /^(?:(\r\n|\n|\r))/, + /* 93: */ /^(?:"((?:\\"|\\[^"]|[^\n\r"\\])*)")/, + /* 94: */ /^(?:'((?:\\'|\\[^']|[^\n\r'\\])*)')/, + /* 95: */ /^(?:([^\S\n\r])+)/, + /* 96: */ /^(?:\S+)/, + /* 97: */ /^(?:")/, + /* 98: */ /^(?:')/, + /* 99: */ /^(?:`)/, + /* 100: */ /^(?:")/, + /* 101: */ /^(?:')/, + /* 102: */ /^(?:`)/, + /* 103: */ /^(?:")/, + /* 104: */ /^(?:')/, + /* 105: */ /^(?:`)/, + /* 106: */ /^(?:.)/, + /* 107: */ /^(?:.)/, + /* 108: */ /^(?:$)/ + ], + + conditions: { + 'rules': { + rules: [ + 0, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 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, + 74, + 75, + 76, + 77, + 78, + 80, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 106, + 107, + 108 + ], + + inclusive: true + }, + + 'macro': { + rules: [ + 0, + 24, + 25, + 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, + 74, + 75, + 76, + 77, + 78, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 106, + 107, + 108 + ], + + inclusive: true + }, + + 'named_chunk': { + rules: [ + 0, + 45, + 47, + 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, + 74, + 75, + 76, + 77, + 78, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: true + }, + + 'code': { + rules: [79, 80, 90, 91, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'start_condition': { + rules: [24, 25, 42, 43, 44, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'options': { + rules: [ + 24, + 25, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 84, + 100, + 101, + 102, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: false + }, + + 'conditions': { + rules: [20, 21, 22, 23, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'action': { + rules: [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 97, + 98, + 99, + 103, + 104, + 105, + 107, + 108 + ], + + inclusive: false + }, + + 'path': { + rules: [24, 25, 92, 93, 94, 95, 96, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'set': { + rules: [84, 87, 88, 89, 103, 104, 105, 107, 108], + inclusive: false + }, + + 'INITIAL': { + rules: [ + 0, + 24, + 25, + 46, + 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, + 74, + 75, + 76, + 77, + 78, + 80, + 81, + 82, + 83, + 85, + 86, + 103, + 104, + 105, + 107, + 108 + ], + + 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, + +}; + diff --git a/lex.l b/lex.l index 515984d..1bf5685 100644 --- a/lex.l +++ b/lex.l @@ -1,90 +1,489 @@ -NAME [a-zA-Z_][a-zA-Z0-9_-]* -BR \r\n|\n|\r +%code imports %{ + import helpers from 'jison-helpers-lib'; +%} + + + +ASCII_LETTER [a-zA-z] +// \p{Alphabetic} already includes [a-zA-z], hence we don't need to merge +// with {UNICODE_LETTER} (though jison has code to optimize if you *did* +// include the `[a-zA-Z]` anyway): +UNICODE_LETTER [\p{Alphabetic}] +ALPHA [{UNICODE_LETTER}_] +DIGIT [\p{Number}] +WHITESPACE [\s\r\n\p{Separator}] +ALNUM [{ALPHA}{DIGIT}] + +NAME [{ALPHA}](?:[{ALNUM}-]*{ALNUM})? +ID [{ALPHA}]{ALNUM}* +DECIMAL_NUMBER [1-9][0-9]* +HEX_NUMBER "0"[xX][0-9a-fA-F]+ +BR \r\n|\n|\r +// WhiteSpace MUST NOT match CR/LF and the regex `\s` DOES, so we cannot use +// that one directly. Instead we define the {WS} macro here: +WS [^\S\r\n] + +// Quoted string content: support *escaped* quotes inside strings: +QUOTED_STRING_CONTENT (?:\\\'|\\[^\']|[^\\\'\r\n])* +DOUBLEQUOTED_STRING_CONTENT (?:\\\"|\\[^\"]|[^\\\"\r\n])* +// backquoted ES6/ES2017 string templates MAY span multiple lines: +ES2017_STRING_CONTENT (?:\\\`|\\[^\`]|[^\\\`])* + +// Accept any non-regex-special character as a direct literal without +// the need to put quotes around it: +ANY_LITERAL_CHAR [^\s\r\n<>\[\](){}.*+?:!=|%\/\\^$,\'\";] + + +%s rules macro named_chunk +%x code start_condition options conditions action path set + + +%options easy_keyword_rules +%options ranges +%options xregexp + -%s indented trail rules -%x code start_condition options conditions action %% -"/*"(.|\n|\r)*?"*/" return 'ACTION_BODY'; -"//".* return 'ACTION_BODY'; -"/"[^ /]*?['"{}'][^ ]*?"/" return 'ACTION_BODY'; // regexp with braces or quotes (and no spaces) -\"("\\\\"|'\"'|[^"])*\" return 'ACTION_BODY'; -"'"("\\\\"|"\'"|[^'])*"'" return 'ACTION_BODY'; -[/"'][^{}/"']+ return 'ACTION_BODY'; -[^{}/"']+ return 'ACTION_BODY'; -"{" yy.depth++; return '{' -"}" yy.depth == 0 ? this.begin('trail') : yy.depth--; return '}' - -{NAME} return 'NAME'; -">" this.popState(); return '>'; -"," return ','; -"*" return '*'; - -{BR}+ /* */ -\s+{BR}+ /* */ -\s+ this.begin('indented') -"%%" this.begin('code'); return '%%' -[a-zA-Z0-9_]+ return 'CHARACTER_LIT' - -{NAME} yy.options[yytext] = true -{BR}+ this.begin('INITIAL') -\s+{BR}+ this.begin('INITIAL') -\s+ /* empty */ - -{NAME} return 'START_COND' -{BR}+ this.begin('INITIAL') -\s+{BR}+ this.begin('INITIAL') -\s+ /* empty */ - -.*{BR}+ this.begin('rules') - -"{" yy.depth = 0; this.begin('action'); return '{' -"%{"(.|{BR})*?"%}" this.begin('trail'); yytext = yytext.substr(2, yytext.length-4);return 'ACTION' -"%{"(.|{BR})*?"%}" yytext = yytext.substr(2, yytext.length-4); return 'ACTION' -.+ this.begin('rules'); return 'ACTION' - -"/*"(.|\n|\r)*?"*/" /* ignore */ -"//".* /* ignore */ - -{BR}+ /* */ -\s+ /* */ -{NAME} return 'NAME'; -\"("\\\\"|'\"'|[^"])*\" yytext = yytext.replace(/\\"/g,'"'); return 'STRING_LIT'; -"'"("\\\\"|"\'"|[^'])*"'" yytext = yytext.replace(/\\'/g,"'"); return 'STRING_LIT'; -"|" return '|'; -"["("\\\\"|"\]"|[^\]])*"]" return 'ANY_GROUP_REGEX'; -"(?:" return 'SPECIAL_GROUP'; -"(?=" return 'SPECIAL_GROUP'; -"(?!" return 'SPECIAL_GROUP'; -"(" return '('; -")" return ')'; -"+" return '+'; -"*" return '*'; -"?" return '?'; -"^" return '^'; -"," return ','; -"<>" return '$'; -"<" this.begin('conditions'); return '<'; -"/!" return '/!'; -"/" return '/'; -"\\"([0-7]{1,3}|[rfntvsSbBwWdD\\*+()${}|[\]\/.^?]|"c"[A-Z]|"x"[0-9A-F]{2}|"u"[a-fA-F0-9]{4}) return 'ESCAPE_CHAR'; -"\\". yytext = yytext.replace(/^\\/g,''); return 'ESCAPE_CHAR'; -"$" return '$'; -"." return '.'; -"%options" yy.options = {}; this.begin('options'); -"%s" this.begin('start_condition'); return 'START_INC'; -"%x" this.begin('start_condition'); return 'START_EXC'; -"%%" this.begin('rules'); return '%%'; -"{"\d+(","\s?\d+|",")?"}" return 'RANGE_REGEX'; -"{"{NAME}"}" return 'NAME_BRACE'; -"{" return '{'; -"}" return '}'; -. /* ignore bad characters */ -<*><> return 'EOF'; - -(.|{BR})+ return 'CODE'; +"%{" yy.depth = 0; + yy.include_command_allowed = false; + this.pushState('action'); + this.unput(yytext); + yytext = ''; + return 'ACTION_START'; +"%{"([^]*?)"%}" yytext = this.matches[1].replace(/%\\\}/g, '%}'); // unescape any literal '%\}' that exists within the action code block + yy.include_command_allowed = true; + return 'ACTION'; +"%include" %{ + if (yy.include_command_allowed) { + // This is an include instruction in place of an action: + // + // - one %include per action chunk + // - one %include replaces an entire action chunk + this.pushState('path'); + return 'INCLUDE'; + } else { + // TODO + yyerror('oops!'); + return 'INCLUDE_PLACEMENT_ERROR'; + } + %} +{WS}*"/*"[^]*?"*/" //yy.include_command_allowed = false; -- doesn't impact include-allowed state + return 'ACTION_BODY_C_COMMENT'; +{WS}*"//".* yy.include_command_allowed = false; + return 'ACTION_BODY_CPP_COMMENT'; +{WS}+ return 'ACTION_BODY_WHITESPACE'; + +// make sure to terminate on linefeed before the next rule alternative, +// which is announced by `|`: +"|" if (yy.include_command_allowed) { + this.popState(); + this.unput(yytext); + yytext = ''; + return 'ACTION_END'; + } else { + return 'ACTION_BODY'; + } + +// make sure to terminate on linefeed before the rule section ends, +// which is announced by `%%`: +"%%" if (yy.include_command_allowed) { + this.popState(); + this.unput(yytext); + yytext = ''; + return 'ACTION_END'; + } else { + return 'ACTION_BODY'; + } + +"%" return 'ACTION_BODY'; + +// regexp with braces or quotes (and no spaces, so we don't mistake +// a *division operator* `/` for a regex delimiter here in most circumstances): +"/"[^\s/]*?(?:['"`{}][^\s/]*?)*"/" + yy.include_command_allowed = false; + return 'ACTION_BODY'; +// hack to cope with slashes which MAY be divide operators OR are regex starters: +// we simply gobble the entire line until the end or until we hit a closing brace, +// as we MUST keep track of the curly brace pairs inside an action body. +"/"[^}{BR}]* + yy.include_command_allowed = false; + return 'ACTION_BODY'; +\"{DOUBLEQUOTED_STRING_CONTENT}\" + yy.include_command_allowed = false; + return 'ACTION_BODY'; +\'{QUOTED_STRING_CONTENT}\' yy.include_command_allowed = false; + return 'ACTION_BODY'; +\`{ES2017_STRING_CONTENT}\` yy.include_command_allowed = false; + return 'ACTION_BODY'; +[^{}/"'`|%\{\}{BR}{WS}]+ yy.include_command_allowed = false; + return 'ACTION_BODY'; +"{" yy.depth++; + yy.include_command_allowed = false; + return 'ACTION_BODY'; +"}" %{ + yy.include_command_allowed = false; + if (yy.depth <= 0) { + yyerror(rmCommonWS` + too many closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%\}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + return 'BRACKET_SURPLUS'; + } else { + yy.depth--; + } + return 'ACTION_BODY'; + %} +// make sure to terminate on linefeed before the next rule alternative, +// which is announced by `|`. +// Note that lexer options & commands should be at the start-of-line, i.e. +// without leading whitespace. The only lexer command which we do accept +// here after the last indent is `%include`, which is considered (part +// of) the rule's action code block. +(?:{BR}{WS}+)+/[^{WS}{BR}|] yy.include_command_allowed = true; + return 'ACTION_BODY_WHITESPACE'; // keep empty lines as-is inside action code blocks. +{BR} if (yy.depth > 0) { + yy.include_command_allowed = true; + return 'ACTION_BODY_WHITESPACE'; // keep empty lines as-is inside action code blocks. + } else { + // end of action code chunk + this.popState(); + this.unput(yytext); + yytext = ''; + return 'ACTION_END'; + } +<> %{ + yy.include_command_allowed = false; + if (yy.depth !== 0) { + yyerror(rmCommonWS` + missing ${yy.depth} closing curly braces in lexer rule action block. + + Note: the action code chunk may be too complex for jison to parse + easily; we suggest you wrap the action code chunk in '%{...%\}' + to help jison grok more or less complex action code chunks. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + yytext = ''; + return 'BRACKET_MISSING'; + } + this.popState(); + yytext = ''; + return 'ACTION_END'; + %} + +{NAME} return 'NAME'; +">" this.popState(); return '>'; +"," return ','; +"*" return '*'; + +// Comments should be gobbled and discarded anywhere +// *except* the code/action blocks: +{WS}*"//"[^\r\n]* + /* skip single-line comment */ +{WS}*"/*"[^]*?"*/" + /* skip multi-line comment */ + +{BR}+ /* empty */ +{WS}+{BR}+ /* empty */ + +"//"[^\r\n]* /* skip single-line comment */ +"/*"[^]*?"*/" /* skip multi-line comment */ + +// ACTION code chunks follow rules and are generally indented, but +// never start with characters special to the lex language itself: +// - `%` can start options, commands, etc., e.g. `%include` or `%options` +// - `|` starts a rule alternative, never a chunk of action code. +// - +{WS}+/[^{WS}{BR}|%] yy.depth = 0; + yy.include_command_allowed = true; + this.pushState('action'); + return 'ACTION_START'; + +"%%" this.popState(); + this.pushState('code'); + return '%%'; + +// Accept any non-regex-special character as a direct literal without +// the need to put quotes around it: +{ANY_LITERAL_CHAR}+ %{ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 'CHARACTER_LIT'; + %} +{NAME} return 'NAME'; +"=" return '='; +\"{DOUBLEQUOTED_STRING_CONTENT}\" + yytext = unescQuote(this.matches[1], /\\"/g); return 'OPTION_STRING_VALUE'; // value is always a string type +\'{QUOTED_STRING_CONTENT}\' + yytext = unescQuote(this.matches[1], /\\'/g); return 'OPTION_STRING_VALUE'; // value is always a string type +\`{ES2017_STRING_CONTENT}\` + yytext = unescQuote(this.matches[1], /\\`/g); return 'OPTION_STRING_VALUE'; // value is always a string type + +[^\s\r\n]+ return 'OPTION_VALUE'; +{BR}{WS}+(?=\S) /* skip leading whitespace on the next line of input, when followed by more options */ +{BR} this.popState(); return 'OPTIONS_END'; +{WS}+ /* skip whitespace */ + +{ID} return 'START_COND'; +{BR}+ this.popState(); +{WS}+ /* empty */ + +{ID} return 'NAME'; +{ID} this.pushState('macro'); return 'NAME'; +{BR}+ this.popState(); + +// Accept any non-regex-special character as a direct literal without +// the need to put quotes around it: +{ANY_LITERAL_CHAR}+ %{ + // accept any non-regex, non-lex, non-string-delim, + // non-escape-starter, non-space character as-is + return 'CHARACTER_LIT'; + %} + +{BR}+ /* empty */ +\s+ /* empty */ + +\"{DOUBLEQUOTED_STRING_CONTENT}\" %{ + yytext = unescQuote(this.matches[1], /\\"/g); + return 'STRING_LIT'; + %} +\'{QUOTED_STRING_CONTENT}\' %{ + yytext = unescQuote(this.matches[1], /\\'/g); + return 'STRING_LIT'; + %} +"[" this.pushState('set'); return 'REGEX_SET_START'; +"|" return '|'; +"(?:" return 'SPECIAL_GROUP'; +"(?=" return 'SPECIAL_GROUP'; +"(?!" return 'SPECIAL_GROUP'; +"(" return '('; +")" return ')'; +"+" return '+'; +"*" return '*'; +"?" return '?'; +"^" return '^'; +"," return ','; +"<>" return '$'; +"<" this.pushState('conditions'); return '<'; +"/!" return '/!'; // treated as `(?!atom)` +"/" return '/'; // treated as `(?=atom)` +"\\"([0-7]{1,3}|[rfntvsSbBwWdD\\*+()${}|[\]\/.^?]|"c"[A-Z]|"x"[0-9A-F]{2}|"u"[a-fA-F0-9]{4}) + return 'ESCAPE_CHAR'; +"\\". yytext = yytext.replace(/^\\/g, ''); return 'ESCAPE_CHAR'; +"$" return '$'; +"." return '.'; +"%options" this.pushState('options'); return 'OPTIONS'; +"%s" this.pushState('start_condition'); return 'START_INC'; +"%x" this.pushState('start_condition'); return 'START_EXC'; + +"%code" this.pushState('named_chunk'); return 'INIT_CODE'; +"%import" this.pushState('named_chunk'); return 'IMPORT'; + +"%include" yy.depth = 0; + yy.include_command_allowed = true; + this.pushState('action'); + this.unput(yytext); + yytext = ''; + return 'ACTION_START'; + +"%include" this.pushState('path'); + return 'INCLUDE'; + +"%"{NAME}([^\r\n]*) + %{ + /* ignore unrecognized decl */ + this.warn(rmCommonWS` + LEX: ignoring unsupported lexer option ${dquote(yytext)} + while lexing in ${dquote(this.topState())} state. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + yytext = [ + this.matches[1], // {NAME} + this.matches[2].trim() // optional value/parameters + ]; + return 'UNKNOWN_DECL'; + %} +"%%" this.pushState('rules'); + return '%%'; +"{"\d+(","\s*\d+|",")?"}" return 'RANGE_REGEX'; +"{"{ID}"}" return 'NAME_BRACE'; +"{"{ID}"}" return 'NAME_BRACE'; +"{" return '{'; +"}" return '}'; + + +(?:"\\\\"|"\\]"|[^\]{])+ return 'REGEX_SET'; +"{" return 'REGEX_SET'; +"]" this.popState(); + return 'REGEX_SET_END'; + + +// in the trailing CODE block, only accept these `%include` macros when +// they appear at the start of a line and make sure the rest of lexer +// regexes account for this one so it'll match that way only: +[^\r\n]*(\r|\n)+ return 'CODE'; +[^\r\n]+ return 'CODE'; // the bit of CODE just before EOF... + + +{BR} this.popState(); this.unput(yytext); + +\"{DOUBLEQUOTED_STRING_CONTENT}\" + yytext = unescQuote(this.matches[1]); + this.popState(); + return 'PATH'; +\'{QUOTED_STRING_CONTENT}\' + yytext = unescQuote(this.matches[1]); + this.popState(); + return 'PATH'; + +{WS}+ // skip whitespace in the line +[^\s\r\n]+ this.popState(); + return 'PATH'; + + +// detect and report unterminated string constants ASAP +// for 'action', 'options', but also for other lexer conditions: +// +// these error catching rules fix https://github.com/GerHobbelt/jison/issues/13 +\" yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + return 'error'; +\' yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + return 'error'; +\` yyerror(rmCommonWS` + unterminated string constant in lexer rule action block. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + return 'error'; + +\" yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + return 'error'; +\' yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + return 'error'; +\` yyerror(rmCommonWS` + unterminated string constant in %options entry. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + return 'error'; + +<*>\" var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + yyerror(rmCommonWS` + unterminated string constant encountered while lexing + ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + return 'error'; +<*>\' var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + yyerror(rmCommonWS` + unterminated string constant encountered while lexing + ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + return 'error'; +<*>\` var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + yyerror(rmCommonWS` + unterminated string constant encountered while lexing + ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + return 'error'; + + +. %{ + /* b0rk on bad characters */ + var rules = (this.topState() === 'macro' ? 'macro\'s' : this.topState()); + yyerror(rmCommonWS` + unsupported lexer input encountered while lexing + ${rules} (i.e. jison lex regexes). + + NOTE: When you want this input to be interpreted as a LITERAL part + of a lex rule regex, you MUST enclose it in double or + single quotes. + + If not, then know that this input is not accepted as a valid + regex expression here in jison-lex ${rules}. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + %} + +<*>. %{ + yyerror(rmCommonWS` + unsupported lexer input: ${dquote(yytext)} + while lexing in ${dquote(this.topState())} state. + + Erroneous area: + ` + this.prettyPrintRange(yylloc)); + %} + +<*><> return 'EOF'; %% + +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); + } +}; diff --git a/lex.y b/lex.y index 599c382..19e950f 100644 --- a/lex.y +++ b/lex.y @@ -1,3 +1,12 @@ + +%code imports %{ + import XRegExp from '@gerhobbelt/xregexp'; // for helping out the `%options xregexp` in the lexer + import helpers from 'jison-helpers-lib'; + import fs from 'fs'; +%} + + + %start lex /* Jison lexer file format grammar */ @@ -5,170 +14,630 @@ %nonassoc '/' '/!' %left '*' '+' '?' RANGE_REGEX +%left '|' +%left '(' + + %% lex - : definitions '%%' rules epilogue - { - $$ = { rules: $rules }; - if ($definitions[0]) $$.macros = $definitions[0]; - if ($definitions[1]) $$.startConditions = $definitions[1]; - if ($epilogue) $$.moduleInclude = $epilogue; - if (yy.options) $$.options = yy.options; - if (yy.actionInclude) $$.actionInclude = yy.actionInclude; + : init definitions rules_and_epilogue EOF + { + $$ = $rules_and_epilogue; + $$.macros = $definitions.macros; + $$.startConditions = $definitions.startConditions; + $$.unknownDecls = $definitions.unknownDecls; + + // if there are any options, add them all, otherwise set options to NULL: + // can't check for 'empty object' by `if (yy.options) ...` so we do it this way: + for (var k in yy.options) { + $$.options = yy.options; + break; + } + + if (yy.actionInclude) { + var asrc = yy.actionInclude.join('\n\n'); + // Only a non-empty action code chunk should actually make it through: + if (asrc.trim() !== '') { + $$.actionInclude = asrc; + } + } + delete yy.options; delete yy.actionInclude; - return $$; + return $$; + } + | init definitions error EOF + { + yyerror(rmCommonWS` + There's an error in your lexer regex rules or epilogue. + Maybe you did not correctly separate the lexer sections with a '%%' + on an otherwise empty line? + The lexer spec file should have this structure: + + definitions + %% + rules + %% // <-- optional! + extra_module_code // <-- optional epilogue! + + Erroneous code: + ${yylexer.prettyPrintRange(@error)} + + Technical error report: + ${$error.errStr} + `); } ; -epilogue - : EOF - { $$ = null; } - | '%%' EOF - { $$ = null; } - | '%%' CODE EOF - { $$ = $2; } +rules_and_epilogue + : '%%' rules '%%' extra_lexer_module_code + { + if ($extra_lexer_module_code.trim() !== '') { + $$ = { rules: $rules, moduleInclude: $extra_lexer_module_code }; + } else { + $$ = { rules: $rules }; + } + } + | '%%' error rules '%%' extra_lexer_module_code + { + yyerror(rmCommonWS` + There's probably an error in one or more of your lexer regex rules. + The lexer rule spec should have this structure: + + regex action_code + + where 'regex' is a lex-style regex expression (see the + jison and jison-lex documentation) which is intended to match a chunk + of the input to lex, while the 'action_code' block is the JS code + which will be invoked when the regex is matched. The 'action_code' block + may be any (indented!) set of JS statements, optionally surrounded + by '{...}' curly braces or otherwise enclosed in a '%{...%}' block. + + Erroneous code: + ${yylexer.prettyPrintRange(@error)} + + Technical error report: + ${$error.errStr} + `); + } + | '%%' rules '%%' error + { + yyerror(rmCommonWS` + There's an error in your lexer epilogue a.k.a. 'extra_module_code' block. + + Erroneous code: + ${yylexer.prettyPrintRange(@error)} + + Technical error report: + ${$error.errStr} + `); + } + | '%%' error rules + { + yyerror(rmCommonWS` + There's probably an error in one or more of your lexer regex rules. + The lexer rule spec should have this structure: + + regex action_code + + where 'regex' is a lex-style regex expression (see the + jison and jison-lex documentation) which is intended to match a chunk + of the input to lex, while the 'action_code' block is the JS code + which will be invoked when the regex is matched. The 'action_code' block + may be any (indented!) set of JS statements, optionally surrounded + by '{...}' curly braces or otherwise enclosed in a '%{...%}' block. + + Erroneous code: + ${yylexer.prettyPrintRange(@error)} + + Technical error report: + ${$error.errStr} + `); + } + | '%%' rules + /* Note: an empty rules set is allowed when you are setting up an `%options custom_lexer` */ + { + $$ = { rules: $rules }; + } + | ε + /* Note: an empty rules set is allowed when you are setting up an `%options custom_lexer` */ + { + $$ = { rules: [] }; + } + ; + +// because JISON doesn't support mid-rule actions, +// we set up `yy` using this empty rule at the start: +init + : ε + { + yy.actionInclude = []; + if (!yy.options) yy.options = {}; + } ; definitions - : definition definitions + : definitions definition { $$ = $definitions; - if ('length' in $definition) { - $$[0] = $$[0] || {}; - $$[0][$definition[0]] = $definition[1]; - } else { - $$[1] = $$[1] || {}; - for (var name in $definition) { - $$[1][name] = $definition[name]; + if ($definition != null) { + if ('length' in $definition) { + $$.macros[$definition[0]] = $definition[1]; + } else if ($definition.type === 'names') { + for (var name in $definition.names) { + $$.startConditions[name] = $definition.names[name]; + } + } else if ($definition.type === 'unknown') { + $$.unknownDecls.push($definition.body); } } } - | ACTION definitions - { yy.actionInclude += $1; $$ = $definitions; } - | - { yy.actionInclude = ''; $$ = [null,null]; } + | ε + { + $$ = { + macros: {}, // { hash table } + startConditions: {}, // { hash table } + unknownDecls: [] // [ array of [key,value] pairs } + }; + } ; definition : NAME regex - { $$ = [$1, $2]; } + { $$ = [$NAME, $regex]; } | START_INC names_inclusive - { $$ = $2; } + { $$ = $names_inclusive; } | START_EXC names_exclusive - { $$ = $2; } + { $$ = $names_exclusive; } + | action + { + var rv = checkActionBlock($action, @action); + if (rv) { + yyerror(rmCommonWS` + The '%{...%}' lexer setup action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(@action)} + `); + } + yy.actionInclude.push($action); + $$ = null; + } + | options + { $$ = null; } + | UNKNOWN_DECL + { $$ = {type: 'unknown', body: $1}; } + | IMPORT import_name import_path + { $$ = {type: 'imports', name: $import_name, path: $import_path}; } + | IMPORT import_name error + { + 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 code: + ${yylexer.prettyPrintRange(@error, @IMPORT)} + + Technical error report: + ${$error.errStr} + `); + } + | IMPORT error + { + yyerror(rmCommonWS` + %import name or source filename missing maybe? + + Note: 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 code: + ${yylexer.prettyPrintRange(@error, @IMPORT)} + + Technical error report: + ${$error.errStr} + `); + } + | INIT_CODE init_code_name action + { + var rv = checkActionBlock($action, @action); + if (rv) { + yyerror(rmCommonWS` + The '%code ${$init_code_name}' action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(@action, @INIT_CODE)} + `); + } + $$ = { + type: 'codesection', + qualifier: $init_code_name, + include: $action + }; + } + | INIT_CODE error action + { + 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 code: + ${yylexer.prettyPrintRange(@error, @INIT_CODE, @action)} + + Technical error report: + ${$error.errStr} + `); + } + ; + +init_code_name + : NAME + { $$ = $NAME; } + | STRING_LIT + { $$ = $STRING_LIT; } + ; + +import_name + : NAME + { $$ = $NAME; } + | STRING_LIT + { $$ = $STRING_LIT; } + ; + +import_path + : NAME + { $$ = $NAME; } + | STRING_LIT + { $$ = $STRING_LIT; } ; names_inclusive : START_COND - { $$ = {}; $$[$1] = 0; } + { $$ = {type: 'names', names: {}}; $$.names[$START_COND] = 0; } | names_inclusive START_COND - { $$ = $1; $$[$2] = 0; } + { $$ = $names_inclusive; $$.names[$START_COND] = 0; } ; names_exclusive : START_COND - { $$ = {}; $$[$1] = 1; } + { $$ = {type: 'names', names: {}}; $$.names[$START_COND] = 1; } | names_exclusive START_COND - { $$ = $1; $$[$2] = 1; } + { $$ = $names_exclusive; $$.names[$START_COND] = 1; } ; rules - : rules rule - { $$ = $1; $$.push($2); } - | rule - { $$ = [$1]; } + : rules rules_collective + { $$ = $rules.concat($rules_collective); } + | ε + { $$ = []; } + ; + +rules_collective + : start_conditions rule + { + if ($start_conditions) { + $rule.unshift($start_conditions); + } + $$ = [$rule]; + } + | start_conditions '{' rule_block '}' + { + if ($start_conditions) { + $rule_block.forEach(function (d) { + d.unshift($start_conditions); + }); + } + $$ = $rule_block; + } + | start_conditions '{' error '}' + { + yyerror(rmCommonWS` + Seems you made a mistake while specifying one of the lexer rules inside + the start condition + <${$start_conditions.join(',')}> { rules... } + block. + + Erroneous area: + ${yylexer.prettyPrintRange(yylexer.mergeLocationInfo(##start_conditions, ##4), @start_conditions)} + + Technical error report: + ${$error.errStr} + `); + } + | start_conditions '{' error + { + yyerror(rmCommonWS` + Seems you did not correctly bracket a lexer rules set inside + the start condition + <${$start_conditions.join(',')}> { rules... } + as a terminating curly brace '}' could not be found. + + Erroneous area: + ${yylexer.prettyPrintRange(@error, @start_conditions)} + + Technical error report: + ${$error.errStr} + `); + } + ; + +rule_block + : rule_block rule + { $$ = $rule_block; $$.push($rule); } + | ε + { $$ = []; } ; rule - : start_conditions regex action - { $$ = $1 ? [$1, $2, $3] : [$2,$3]; } + : regex action + { + var rv = checkActionBlock($action, @action); + if (rv) { + yyerror(rmCommonWS` + The rule's action code section does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(@action)} + `); + } + $$ = [$regex, $action]; + } + | regex error + { + $$ = [$regex, $error]; + yyerror(rmCommonWS` + Lexer rule regex action code declaration error? + + Erroneous code: + ${yylexer.prettyPrintRange(@error, @regex)} + + Technical error report: + ${$error.errStr} + `); + } ; action - : '{' action_body '}' - {$$ = $2;} - | ACTION - {$$ = $1;} + : ACTION_START action_body BRACKET_MISSING + { + yyerror(rmCommonWS` + Missing curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: '{ ... }'. + + Offending action body: + ${yylexer.prettyPrintRange(@BRACKET_MISSING, @1)} + `); + } + | ACTION_START action_body BRACKET_SURPLUS + { + yyerror(rmCommonWS` + Too many curly braces: seems you did not correctly bracket a lexer rule action block in curly braces: '{ ... }'. + + Offending action body: + ${yylexer.prettyPrintRange(@BRACKET_SURPLUS, @1)} + `); + } + | ACTION_START action_body ACTION_END + { + var s = $action_body.trim(); + // remove outermost set of braces UNLESS there's + // a curly brace in there anywhere: in that case + // we should leave it up to the sophisticated + // code analyzer to simplify the code! + // + // This is a very rough check as it will also look + // inside code comments, which should not have + // any influence. + // + // Nevertheless: this is a *safe* transform! + if (s[0] === '{' && s.indexOf('}') === s.length - 1) { + $$ = s.substring(1, s.length - 1).trim(); + } else { + $$ = s; + } + } ; action_body - : - {$$ = '';} - | action_comments_body - {$$ = $1;} - | action_body '{' action_body '}' action_comments_body - {$$ = $1+$2+$3+$4+$5;} - | action_body '{' action_body '}' - {$$ = $1 + $2 + $3 + $4;} - ; + : action_body ACTION + { $$ = $action_body + '\n\n' + $ACTION + '\n\n'; } + | action_body ACTION_BODY + { $$ = $action_body + $ACTION_BODY; } + | action_body ACTION_BODY_C_COMMENT + { $$ = $action_body + $ACTION_BODY_C_COMMENT; } + | action_body ACTION_BODY_CPP_COMMENT + { $$ = $action_body + $ACTION_BODY_CPP_COMMENT; } + | action_body ACTION_BODY_WHITESPACE + { $$ = $action_body + $ACTION_BODY_WHITESPACE; } + | action_body include_macro_code + { $$ = $action_body + '\n\n' + $include_macro_code + '\n\n'; } + | action_body INCLUDE_PLACEMENT_ERROR + { + yyerror(rmCommonWS` + You may place the '%include' instruction only at the start/front of a line. -action_comments_body - : ACTION_BODY - { $$ = yytext; } - | action_comments_body ACTION_BODY - { $$ = $1+$2; } - ; + It's use is not permitted at this position: + ${yylexer.prettyPrintRange(@INCLUDE_PLACEMENT_ERROR, @action_body)} + `); + } + | action_body error + { + yyerror(rmCommonWS` + Seems you did not correctly match curly braces '{ ... }' in a lexer rule action block. + Erroneous code: + ${yylexer.prettyPrintRange(@error, @action_body)} + + Technical error report: + ${$error.errStr} + `); + } + | ε + { $$ = ''; } + ; start_conditions : '<' name_list '>' - { $$ = $2; } + { $$ = $name_list; } + | '<' name_list error + { + yyerror(rmCommonWS` + Seems you did not correctly terminate the start condition set <${$name_list.join(',')},???> with a terminating '>' + + Erroneous code: + ${yylexer.prettyPrintRange(@error, @1)} + + Technical error report: + ${$error.errStr} + `); + } | '<' '*' '>' { $$ = ['*']; } - | + | ε ; name_list : NAME - { $$ = [$1]; } + { $$ = [$NAME]; } | name_list ',' NAME - { $$ = $1; $$.push($3); } + { $$ = $name_list; $$.push($NAME); } ; regex - : regex_list + : nonempty_regex_list[re] { - $$ = $1; - if (!(yy.options && yy.options.flex) && $$.match(/[\w\d]$/) && !$$.match(/\\(r|f|n|t|v|s|b|c[A-Z]|x[0-9A-F]{2}|u[a-fA-F0-9]{4}|[0-7]{1,3})$/)) { - $$ += "\\b"; + // Detect if the regex ends with a pure (Unicode) word; + // we *do* consider escaped characters which are 'alphanumeric' + // to be equivalent to their non-escaped version, hence these are + // all valid 'words' for the 'easy keyword rules' option: + // + // - hello_kitty + // - γεια_σου_γατοÏλα + // - \u03B3\u03B5\u03B9\u03B1_\u03C3\u03BF\u03C5_\u03B3\u03B1\u03C4\u03BF\u03CD\u03BB\u03B1 + // + // http://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode#12869914 + // + // As we only check the *tail*, we also accept these as + // 'easy keywords': + // + // - %options + // - %foo-bar + // - +++a:b:c1 + // + // Note the dash in that last example: there the code will consider + // `bar` to be the keyword, which is fine with us as we're only + // interested in the trailing boundary and patching that one for + // the `easy_keyword_rules` option. + $$ = $re; + if (yy.options.easy_keyword_rules) { + // We need to 'protect' `eval` here as keywords are allowed + // to contain double-quotes and other leading cruft. + // `eval` *does* gobble some escapes (such as `\b`) but + // we protect against that through a simple replace regex: + // we're not interested in the special escapes' exact value + // anyway. + // It will also catch escaped escapes (`\\`), which are not + // word characters either, so no need to worry about + // `eval(str)` 'correctly' converting convoluted constructs + // like '\\\\\\\\\\b' in here. + $$ = $$ + .replace(/\\\\/g, '.') + .replace(/"/g, '.') + .replace(/\\c[A-Z]/g, '.') + .replace(/\\[^xu0-9]/g, '.'); + + try { + // Convert Unicode escapes and other escapes to their literal characters + // BEFORE we go and check whether this item is subject to the + // `easy_keyword_rules` option. + $$ = JSON.parse('"' + $$ + '"'); + } + catch (ex) { + yyparser.warn('easy-keyword-rule FAIL on eval: ', ex); + + // make the next keyword test fail: + $$ = '.'; + } + // a 'keyword' starts with an alphanumeric character, + // followed by zero or more alphanumerics or digits: + var re = new XRegExp('\\w[\\w\\d]*$'); + if (XRegExp.match($$, re)) { + $$ = $re + "\\b"; + } else { + $$ = $re; + } } } ; regex_list - : regex_list '|' regex_concat + : regex_list '|' regex_concat { $$ = $1 + '|' + $3; } - | regex_list '|' + | regex_list '|' { $$ = $1 + '|'; } | regex_concat - | - { $$ = '' } + { $$ = $1; } + | ε + { $$ = ''; } + ; + +nonempty_regex_list + : nonempty_regex_list '|' regex_concat + { $$ = $1 + '|' + $3; } + | nonempty_regex_list '|' + { $$ = $1 + '|'; } + | '|' regex_concat + { $$ = '|' + $2; } + | regex_concat + { $$ = $1; } ; regex_concat : regex_concat regex_base { $$ = $1 + $2; } | regex_base + { $$ = $1; } ; regex_base : '(' regex_list ')' - { $$ = '(' + $2 + ')'; } + { $$ = '(' + $regex_list + ')'; } | SPECIAL_GROUP regex_list ')' - { $$ = $1 + $2 + ')'; } + { $$ = $SPECIAL_GROUP + $regex_list + ')'; } + | '(' regex_list error + { + yyerror(rmCommonWS` + Seems you did not correctly bracket a lex rule regex part in '(...)' braces. + + Unterminated regex part: + ${yylexer.prettyPrintRange(@error, @1)} + + Technical error report: + ${$error.errStr} + `); + } + | SPECIAL_GROUP regex_list error + { + yyerror(rmCommonWS` + Seems you did not correctly bracket a lex rule regex part in '(...)' braces. + + Unterminated regex part: + ${yylexer.prettyPrintRange(@error, @SPECIAL_GROUP)} + + Technical error report: + ${$error.errStr} + `); + } | regex_base '+' - { $$ = $1 + '+'; } + { $$ = $regex_base + '+'; } | regex_base '*' - { $$ = $1 + '*'; } + { $$ = $regex_base + '*'; } | regex_base '?' - { $$ = $1 + '?'; } + { $$ = $regex_base + '?'; } | '/' regex_base - { $$ = '(?=' + $2 + ')'; } + { $$ = '(?=' + $regex_base + ')'; } | '/!' regex_base - { $$ = '(?!' + $2 + ')'; } + { $$ = '(?!' + $regex_base + ')'; } | name_expansion | regex_base range_regex { $$ = $1 + $2; } @@ -188,36 +657,256 @@ name_expansion ; any_group_regex - : ANY_GROUP_REGEX - { $$ = yytext; } + : REGEX_SET_START regex_set REGEX_SET_END + { $$ = $REGEX_SET_START + $regex_set + $REGEX_SET_END; } + | REGEX_SET_START regex_set error + { + yyerror(rmCommonWS` + Seems you did not correctly bracket a lex rule regex set in '[...]' brackets. + + Unterminated regex set: + ${yylexer.prettyPrintRange(@error, @REGEX_SET_START)} + + Technical error report: + ${$error.errStr} + `); + } + ; + +regex_set + : regex_set regex_set_atom + { $$ = $regex_set + $regex_set_atom; } + | regex_set_atom + ; + +regex_set_atom + : REGEX_SET + | name_expansion + { + if (XRegExp._getUnicodeProperty($name_expansion.replace(/[{}]/g, '')) + && $name_expansion.toUpperCase() !== $name_expansion + ) { + // treat this as part of an XRegExp `\p{...}` Unicode 'General Category' Property cf. http://unicode.org/reports/tr18/#Categories + $$ = $name_expansion; + } else { + $$ = $name_expansion; + } + //yyparser.log("name expansion for: ", { name: $name_expansion, redux: $name_expansion.replace(/[{}]/g, ''), output: $$ }); + } ; escape_char : ESCAPE_CHAR - { $$ = yytext; } + { $$ = $ESCAPE_CHAR; } ; range_regex : RANGE_REGEX - { $$ = yytext; } + { $$ = $RANGE_REGEX; } ; string : STRING_LIT - { $$ = prepareString(yytext.substr(1, yytext.length - 2)); } + { $$ = prepareString($STRING_LIT); } | CHARACTER_LIT ; +options + : OPTIONS option_list OPTIONS_END + { $$ = null; } + ; + +option_list + : option option_list + { $$ = null; } + | option + { $$ = null; } + ; + +option + : NAME[option] + { yy.options[$option] = true; } + | NAME[option] '=' OPTION_STRING_VALUE[value] + { yy.options[$option] = $value; } + | NAME[option] '=' OPTION_VALUE[value] + { yy.options[$option] = parseValue($value); } + | NAME[option] '=' NAME[value] + { yy.options[$option] = parseValue($value); } + | NAME[option] '=' error + { + // TODO ... + yyerror(rmCommonWS` + Internal error: option "${$option}" value assignment failure. + + Erroneous area: + ${yylexer.prettyPrintRange(@error, @option)} + + Technical error report: + ${$error.errStr} + `); + } + | error + { + // TODO ... + yyerror(rmCommonWS` + Expected a valid option name (with optional value assignment). + + Erroneous area: + ${yylexer.prettyPrintRange(@error)} + + Technical error report: + ${$error.errStr} + `); + } + ; + +extra_lexer_module_code + : optional_module_code_chunk + { + var rv = checkActionBlock($optional_module_code_chunk, @optional_module_code_chunk); + if (rv) { + yyerror(rmCommonWS` + The extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(@optional_module_code_chunk)} + `); + } + $$ = $optional_module_code_chunk; + } + | extra_lexer_module_code include_macro_code optional_module_code_chunk + { + // Each of the 3 chunks should be parse-able as a JS snippet on its own. + // + // Note: we have already checked the first section in a previous reduction + // of this rule, so we don't need to check that one again! + var rv = checkActionBlock($include_macro_code, @include_macro_code); + if (rv) { + yyerror(rmCommonWS` + The source code %include-d into the extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(@include_macro_code)} + `); + } + rv = checkActionBlock($optional_module_code_chunk, @optional_module_code_chunk); + if (rv) { + yyerror(rmCommonWS` + The extra lexer module code section (a.k.a. 'epilogue') does not compile: ${rv} + + Erroneous area: + ${yylexer.prettyPrintRange(@optional_module_code_chunk)} + `); + } + $$ = $extra_lexer_module_code + $include_macro_code + $optional_module_code_chunk; + } + ; + +include_macro_code + : INCLUDE PATH + { + var fileContent = fs.readFileSync($PATH, { encoding: 'utf-8' }); + // And no, we don't support nested '%include': + $$ = '\n// Included by Jison: ' + $PATH + ':\n\n' + fileContent + '\n\n// End Of Include by Jison: ' + $PATH + '\n\n'; + } + | INCLUDE error + { + yyerror(rmCommonWS` + %include MUST be followed by a valid file path. + + Erroneous path: + ${yylexer.prettyPrintRange(@error, @INCLUDE)} + + Technical error report: + ${$error.errStr} + `); + } + ; + +module_code_chunk + : CODE + { $$ = $CODE; } + | module_code_chunk CODE + { $$ = $module_code_chunk + $CODE; } + | error CODE + { + // TODO ... + yyerror(rmCommonWS` + Module code declaration error? + + Erroneous code: + ${yylexer.prettyPrintRange(@error)} + + Technical error report: + ${$error.errStr} + `); + } + ; + +optional_module_code_chunk + : module_code_chunk + { $$ = $module_code_chunk; } + | ε + { $$ = ''; } + ; + %% -function encodeRE (s) { - return s.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1').replace(/\\\\u([a-fA-F0-9]{4})/g,'\\u$1'); + +var rmCommonWS = helpers.rmCommonWS; +var checkActionBlock = helpers.checkActionBlock; + + +function encodeRE(s) { + return s.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1').replace(/\\\\u([a-fA-F0-9]{4})/g, '\\u$1'); } -function prepareString (s) { +function prepareString(s) { // unescape slashes s = s.replace(/\\\\/g, "\\"); s = encodeRE(s); return s; +} + +// 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); +}; + +parser.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse:', arguments); +}; + +parser.yy.pre_parse = function p_lex() { + if (parser.yydebug) parser.log('pre_parse YY:', arguments); +}; + +parser.yy.post_lex = function p_lex() { + if (parser.yydebug) parser.log('post_lex:', arguments); }; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..6cd2370 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2427 @@ +{ + "name": "@gerhobbelt/lex-parser", + "version": "0.6.1-205", + "lockfileVersion": 1, + "dependencies": { + "@gerhobbelt/ast-types": { + "version": "0.9.13-4", + "resolved": "https://registry.npmjs.org/@gerhobbelt/ast-types/-/ast-types-0.9.13-4.tgz", + "integrity": "sha512-V8UIj1XN6XOP014fPpecxEa7AlAB9kaTOB/wF9UbguuwIMWCHDmdA9i03JDK9zXyVDVaLWCYh42JK8F9f27AtA==" + }, + "@gerhobbelt/ast-util": { + "version": "0.6.1-4", + "resolved": "https://registry.npmjs.org/@gerhobbelt/ast-util/-/ast-util-0.6.1-4.tgz", + "integrity": "sha512-NP7YZh7rR6CNiMLyKTF+qb2Epx0r5x/zKQ3Z14TgXl73YJurC8WkMkFM9nDj8cRXb6R+f+BEu4DqAvvYKMxbqg==" + }, + "@gerhobbelt/linewrap": { + "version": "0.2.2-3", + "resolved": "https://registry.npmjs.org/@gerhobbelt/linewrap/-/linewrap-0.2.2-3.tgz", + "integrity": "sha512-u2eUbXgNtqckBI4gxds/uiUNoytT+qIqpePmVDI5isW8A18uB3Qz1P+UxAHgFafGOZWJNrpR0IKnZhl7QhaUng==", + "dev": true + }, + "@gerhobbelt/nomnom": { + "version": "1.8.4-24", + "resolved": "https://registry.npmjs.org/@gerhobbelt/nomnom/-/nomnom-1.8.4-24.tgz", + "integrity": "sha512-spzyz2vHd1BhYNSUMXjqJOwk4AjnOIzZz3cYCOryUCzMvlqz01/+SAPEy/pjT47CrOGdWd0JgemePjru1aLYgQ==", + "dev": true, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true + }, + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true + } + } + }, + "@gerhobbelt/recast": { + "version": "0.12.7-11", + "resolved": "https://registry.npmjs.org/@gerhobbelt/recast/-/recast-0.12.7-11.tgz", + "integrity": "sha512-vjk3AMqq8bgg8Wf5B6n2OdWmpa9iyBYX+/N5+vTf9mz/+etm0YUHcgGdzX98f8tSTCUl+LEdMKNN4vteLbUsxg==", + "dev": true, + "dependencies": { + "@gerhobbelt/ast-types": { + "version": "0.9.13-7", + "resolved": "https://registry.npmjs.org/@gerhobbelt/ast-types/-/ast-types-0.9.13-7.tgz", + "integrity": "sha512-OKLyvezcD1X9WHXsKfDm2nLhwt1ybNRvErTqVeM5wlq6vQvNMkWKG6SLwG3Y08gkseZWKfe7enhPiJWoJORf3A==", + "dev": true + } + } + }, + "@gerhobbelt/xregexp": { + "version": "3.2.0-22", + "resolved": "https://registry.npmjs.org/@gerhobbelt/xregexp/-/xregexp-3.2.0-22.tgz", + "integrity": "sha512-TRu38Z67VxFSMrBP3z/ORiJVQqp56ulidZirbobtmJnVGBWLdo4GbHtihgIJFGieIZuk+LxmPkK45SY+SQsR3A==" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "optional": true + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "optional": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "optional": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true, + "optional": true + }, + "assertion-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true, + "optional": true + }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true + }, + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", + "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "dev": true, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "dev": true + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "babel-preset-env": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", + "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", + "dev": true + }, + "babel-preset-modern-browsers": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-modern-browsers/-/babel-preset-modern-browsers-10.0.1.tgz", + "integrity": "sha512-OwJlaopcYWBjgw4jLkPRXaArpFzpdAdgn7ZDQdY6a284uAjpKGsFP3eRo7rxrXsvmDMcXXQu1CsQzg09IUQelQ==", + "dev": true + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "binary-extensions": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", + "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=", + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "optional": true + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "browserslist": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.5.1.tgz", + "integrity": "sha512-jAvM2ku7YDJ+leAq3bFH1DE0Ylw+F+EQDq4GkqZfgPEqpWYw9ofQH85uKSB9r3Tv7XDbfqVtE+sdvKJW7IlPJA==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30000749", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000749.tgz", + "integrity": "sha1-L/OChlrq2MyjXaz7qwT1jv+kwBw=", + "dev": true + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "optional": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", + "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", + "dev": true + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "core-js": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", + "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true, + "optional": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true + }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz", + "integrity": "sha1-eOy4o5kGYYe7N07t412ccFZagD0=", + "dev": true + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "optional": true + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "optional": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "optional": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "optional": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "optional": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "optional": true + }, + "fs-readdir-recursive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz", + "integrity": "sha1-jNF0XItPiinIyuw5JHaSG6GV9WA=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz", + "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==", + "dev": true, + "optional": true, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "optional": true + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.36", + "bundled": true, + "dev": true, + "optional": true + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "optional": true + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true, + "optional": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "optional": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "optional": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "optional": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true, + "optional": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true, + "optional": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "optional": true + }, + "jison-gho": { + "version": "0.6.1-203", + "resolved": "https://registry.npmjs.org/jison-gho/-/jison-gho-0.6.1-203.tgz", + "integrity": "sha512-sFPO1T5uuMojPkwi8wC0KB5RaFlBTb8EsfOKcXtHuKoukinlIMy6HqMYPMeJ61G7xVoha4tdlO1I9samUpmLEw==", + "dev": true, + "dependencies": { + "@gerhobbelt/json5": { + "version": "0.5.1-19", + "resolved": "https://registry.npmjs.org/@gerhobbelt/json5/-/json5-0.5.1-19.tgz", + "integrity": "sha512-TDAMTzjDUosbRbkz/l+wzARC3XYPU6bzMJA2WBmd2fIqKUHixg42fp04fX06aYyyDzM0noxSugl6Z0+l+N29mw==", + "dev": true + } + } + }, + "jison-helpers-lib": { + "version": "0.6.1-205", + "resolved": "https://registry.npmjs.org/jison-helpers-lib/-/jison-helpers-lib-0.6.1-205.tgz", + "integrity": "sha512-b4iWlapl1cAU0/pZJmIDeJnEUXKMnt7NkwnNahG7gMZWQKV3ogaQOl3ByGWyThYQKQLgGWO4rTUDUlzwgrv4SQ==", + "dependencies": { + "@gerhobbelt/ast-types": { + "version": "0.9.14-9", + "resolved": "https://registry.npmjs.org/@gerhobbelt/ast-types/-/ast-types-0.9.14-9.tgz", + "integrity": "sha512-5TmMhHOh6OE5VbGJuKnbQ2LEzN5z15CB1zGpA3hUYb00jN+G6qk/Z0ZhRFubS8GTp0h+JJaqnxUIbxneoNnTIQ==" + }, + "@gerhobbelt/recast": { + "version": "0.12.7-14", + "resolved": "https://registry.npmjs.org/@gerhobbelt/recast/-/recast-0.12.7-14.tgz", + "integrity": "sha512-U1PM+EXUYDXWxLYZiEdd+y5Gk4XHBiAjxolWeCviq3kbxobZiQJI7DWWjG72Ptow3gpXZYi7tMSeumOkoxnPwQ==" + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + } + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "optional": true + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true + }, + "mocha": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz", + "integrity": "sha512-evDmhkoA+cBNiQQQdSKZa2b9+W2mpLoj50367lhy+Klnx9OV8XlCIhigUnn1gaTFLQCa0kdNhEGDr0hCXOQFDw==", + "dev": true, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=", + "dev": true, + "optional": true + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "optional": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true, + "optional": true + }, + "private": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", + "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true, + "optional": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "optional": true, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "optional": true + } + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "optional": true + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", + "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "dev": true + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "optional": true + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "optional": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "dev": true + }, + "rollup": { + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.50.0.tgz", + "integrity": "sha512-7RqCBQ9iwsOBPkjYgoIaeUij606mSkDMExP0NT7QDI3bqkHYQHrQ83uoNIXwPcQm/vP2VbsUz3kiyZZ1qPlLTQ==", + "dev": true + }, + "rollup-plugin-node-resolve": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.0.0.tgz", + "integrity": "sha1-i4l8TDAw1QASd7BRSyXSygloPuA=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true, + "optional": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "optional": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "type-detect": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz", + "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo=", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true, + "optional": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true + } + } +} diff --git a/package.json b/package.json index a95535a..3fc285e 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,21 @@ { - "name": "lex-parser", - "version": "0.1.4", + "author": { + "name": "Zach Carter", + "email": "zach@carter.name", + "url": "http://zaa.ch" + }, + "name": "@gerhobbelt/lex-parser", + "version": "0.6.1-205", "description": "A parser for lexical grammars used by jison", - "main": "lex-parser.js", + "main": "dist/lex-parser-cjs-es5.js", + "module": "lex-parser.js", "scripts": { - "test": "make test" + "test": "make test", + "pub": "echo '### WARNING/NOTICE: publish from the jison monorepo! ###' && false" }, "repository": { "type": "git", - "repository": "https://github.com/zaach/lex-parser.git" + "url": "https://github.com/GerHobbelt/lex-parser.git" }, "keywords": [ "lexical", @@ -16,10 +23,22 @@ "parser", "jison" ], - "author": "Zach Carter", "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "dependencies": { + "@gerhobbelt/xregexp": "3.2.0-22", + "jison-helpers-lib": "0.6.1-205" + }, "devDependencies": { - "jison": "0.4.x", - "test": "*" + "babel-cli": "6.26.0", + "babel-preset-env": "1.6.1", + "babel-preset-modern-browsers": "10.0.1", + "chai": "4.1.2", + "jison-gho": "0.6.1-205", + "mocha": "4.0.1", + "rollup-plugin-node-resolve": "3.0.0", + "rollup": "0.50.0" } } diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..5cf550a --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,62 @@ +// rollup.config.js +import resolve from 'rollup-plugin-node-resolve'; + +export default { + input: 'lex-parser.js', + output: [ + { + file: 'dist/lex-parser-cjs.js', + format: 'cjs' + }, + { + file: 'dist/lex-parser-es6.js', + format: 'es' + }, + { + file: 'dist/lex-parser-umd.js', + name: 'lex-parser', + format: 'umd' + } + ], + plugins: [ + resolve({ + // use "module" field for ES6 module if possible + module: true, // Default: true + + // use "main" field or index.js, even if it's not an ES6 module + // (needs to be converted from CommonJS to ES6 + // – see https://github.com/rollup/rollup-plugin-commonjs + main: true, // Default: true + + // not all files you want to resolve are .js files + extensions: [ '.js' ], // Default: ['.js'] + + // whether to prefer built-in modules (e.g. `fs`, `path`) or + // local ones with the same names + preferBuiltins: true, // Default: true + + // If true, inspect resolved files to check that they are + // ES2015 modules + modulesOnly: true, // Default: false + }) + ], + external: [ + '@gerhobbelt/ast-util', + '@gerhobbelt/json5', + '@gerhobbelt/nomnom', + '@gerhobbelt/prettier-miscellaneous', + '@gerhobbelt/recast', + '@gerhobbelt/xregexp', + 'jison-helpers-lib', + '@gerhobbelt/lex-parser', + '@gerhobbelt/jison-lex', + '@gerhobbelt/ebnf-parser', + '@gerhobbelt/jison2json', + '@gerhobbelt/json2jison', + 'jison-gho', + 'assert', + 'fs', + 'path', + 'process', + ] +}; diff --git a/tests/all-tests.js b/tests/all-tests.js index 8a09501..374e01d 100644 --- a/tests/all-tests.js +++ b/tests/all-tests.js @@ -1,39 +1,118 @@ -var assert = require("assert"), - lex = require("../lex-parser"), - fs = require('fs'), - path = require('path'); +var assert = require("chai").assert; +var lex = require("../dist/lex-parser-cjs-es5"); +var fs = require('fs'); +var path = require('path'); function read (p, file) { return fs.readFileSync(path.join(__dirname, p, file), "utf8"); } -exports["test lex grammar with macros"] = function () { - var lexgrammar = 'D [0-9]\nID [a-zA-Z][a-zA-Z0-9]+\n%%\n\n{D}"ohhai" {print(9);}\n"{" return \'{\';'; +function lexer_reset() { + if (lex.parser.yy) { + var y = lex.parser.yy; + if (y.parser) { + delete y.parser; + } + if (y.lexer) { + delete y.lexer; + } + } + + lex.parser.yy = {}; + + var debug = 0; + + if (!debug) { + // silence warn+log messages from the test internals: + lex.warn = function tl_warn() { + // console.warn("TEST WARNING: ", arguments); + }; + + lex.log = function tl_log() { + // console.warn("TEST LOG: ", arguments); + }; + + lex.parser.warn = function tl_warn() { + // console.warn("TEST WARNING: ", arguments); + }; + + lex.parser.log = function tl_log() { + // console.warn("TEST LOG: ", arguments); + }; + } +} + +describe("LEX Parser", function () { + beforeEach(function beforeEachTest() { + lexer_reset(); + }); + + it("test lex grammar with macros", function () { + var lexgrammar = 'D [0-9]\nID [a-zA-Z_][a-zA-Z0-9_]+\n%%\n\n{D}"ohhai" {print(9);}\n"{" return \'{\';'; + var expected = { + macros: { + "D": "[0-9]", + "ID": "[a-zA-Z_][a-zA-Z0-9_]+" + }, + rules: [ + ["{D}ohhai", "print(9);"], + ["\\{", "return '{';"] + ], + startConditions: {}, + unknownDecls: [] + }; + + assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); + }); + + it("test lex grammar with macros in regex sets", function () { + var lexgrammar = 'D [0-9]\nL [a-zA-Z]\nID [{L}_][{L}{D}_]+\n%%\n\n[{D}]"ohhai" {print(9);}\n"{" return \'{\';'; var expected = { - macros: {"D": "[0-9]", "ID": "[a-zA-Z][a-zA-Z0-9]+"}, + macros: { + "D": "[0-9]", + "L": "[a-zA-Z]", + "ID": "[{L}_][{L}{D}_]+" + }, rules: [ - ["{D}ohhai\\b", "print(9);"], + ["[{D}]ohhai", "print(9);"], ["\\{", "return '{';"] - ] + ], + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); + + it("test rule-less grammar", function () { + var lexgrammar = '%export { D }\nD [0-9]'; + var expected = { + macros: { D: '[0-9]' }, + unknownDecls: [['export', '{ D }']], + rules: [], + startConditions: {}, + }; + + assert.deepEqual(lex.parse(lexgrammar), expected, 'grammar should be parsed correctly'); + }); -exports["test escaped chars"] = function () { + it("test escaped chars", function () { var lexgrammar = '%%\n"\\n"+ {return \'NL\';}\n\\n+ {return \'NL2\';}\n\\s+ {/* skip */}'; var expected = { rules: [ ["\\\\n+", "return 'NL';"], ["\\n+", "return 'NL2';"], ["\\s+", "/* skip */"] - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test advanced"] = function () { + it("test advanced", function () { var lexgrammar = '%%\n$ {return \'EOF\';}\n. {/* skip */}\n"stuff"*/("{"|";") {/* ok */}\n(.+)[a-z]{1,2}"hi"*? {/* skip */}\n'; var expected = { rules: [ @@ -41,136 +120,179 @@ exports["test advanced"] = function () { [".", "/* skip */"], ["stuff*(?=(\\{|;))", "/* ok */"], ["(.+)[a-z]{1,2}hi*?", "/* skip */"] - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test [^\\]]"] = function () { + it("test [^\\]]", function () { var lexgrammar = '%%\n"["[^\\]]"]" {return true;}\n\'f"oo\\\'bar\' {return \'baz2\';}\n"fo\\"obar" {return \'baz\';}\n'; var expected = { rules: [ ["\\[[^\\]]\\]", "return true;"], - ["f\"oo'bar\\b", "return 'baz2';"], - ['fo"obar\\b', "return 'baz';"] - ] + ["f\"oo'bar", "return 'baz2';"], + ['fo"obar', "return 'baz';"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test multiline action"] = function () { + it("test multiline action", function () { var lexgrammar = '%%\n"["[^\\]]"]" %{\nreturn true;\n%}\n'; var expected = { rules: [ - ["\\[[^\\]]\\]", "\nreturn true;\n"] - ] + ["\\[[^\\]]\\]", "return true;"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test multiline action with single braces"] = function () { + it("test multiline action with single braces", function () { var lexgrammar = '%%\n"["[^\\]]"]" {\nvar b={};return true;\n}\n'; var expected = { rules: [ - ["\\[[^\\]]\\]", "\nvar b={};return true;\n"] - ] + ["\\[[^\\]]\\]", "{\nvar b={};return true;\n}"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test multiline action with brace in a multi-line-comment"] = function () { - var lexgrammar = '%%\n"["[^\\]]"]" {\nvar b={}; /* { */ return true;\n}\n'; + it("test multiline action with brace in a multi-line-comment", function () { + var lexgrammar = '%%\n"["[^\\]]"]" {\nvar b=7; /* { */ return true;\n}\n'; var expected = { rules: [ - ["\\[[^\\]]\\]", "\nvar b={}; /* { */ return true;\n"] - ] + ["\\[[^\\]]\\]", "var b=7; /* { */ return true;"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test multiline action with brace in a single-line-comment"] = function () { + it("test multiline action with brace in a single-line-comment", function () { var lexgrammar = '%%\n"["[^\\]]"]" {\nvar b={}; // { \nreturn 2 / 3;\n}\n'; var expected = { rules: [ - ["\\[[^\\]]\\]", "\nvar b={}; // { \nreturn 2 / 3;\n"] - ] + ["\\[[^\\]]\\]", "{\nvar b={}; // { \nreturn 2 / 3;\n}"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test multiline action with braces in strings"] = function () { + it("test multiline action with braces in strings", function () { var lexgrammar = '%%\n"["[^\\]]"]" {\nvar b=\'{\' + "{"; // { \nreturn 2 / 3;\n}\n'; var expected = { rules: [ - ["\\[[^\\]]\\]", "\nvar b='{' + \"{\"; // { \nreturn 2 / 3;\n"] - ] + ["\\[[^\\]]\\]", "var b='{' + \"{\"; // { \nreturn 2 / 3;"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test multiline action with braces in regexp"] = function () { + it("test multiline action with braces in regexp", function () { var lexgrammar = '%%\n"["[^\\]]"]" {\nvar b=/{/; // { \nreturn 2 / 3;\n}\n'; var expected = { rules: [ - ["\\[[^\\]]\\]", "\nvar b=/{/; // { \nreturn 2 / 3;\n"] - ] + ["\\[[^\\]]\\]", "var b=/{/; // { \nreturn 2 / 3;"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] + }; + + assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); + }); + + it("test multiline (indented) action without braces", function () { + var lexgrammar = '%%\n"["[^\\]]"]"\n var b=/{/;\n // { \n return 2 / 3;\n'; + var expected = { + rules: [ + ["\\[[^\\]]\\]", "var b=/{/;\n // { \n return 2 / 3;"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test include"] = function () { - var lexgrammar = '\nRULE [0-9]\n\n%{\n hi \n%}\n%%\n"["[^\\]]"]" %{\nreturn true;\n%}\n'; + it("test include", function () { + var lexgrammar = '\nRULE [0-9]\n\n%{\n hi; {stuff;} \n%}\n%%\n"["[^\\]]"]" %{\nreturn true;\n%}\n'; var expected = { macros: {"RULE": "[0-9]"}, - actionInclude: "\n hi \n", + actionInclude: "hi; {stuff;}", rules: [ - ["\\[[^\\]]\\]", "\nreturn true;\n"] - ] + ["\\[[^\\]]\\]", "return true;"] + ], + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test bnf lex grammar"] = function () { + it("test bnf lex grammar", function () { var lexgrammar = lex.parse(read('lex', 'bnf.jisonlex')); var expected = JSON.parse(read('lex', 'bnf.lex.json')); assert.deepEqual(lexgrammar, expected, "grammar should be parsed correctly"); -}; + }); -exports["test lex grammar bootstrap"] = function () { + it("test lex grammar bootstrap", function () { var lexgrammar = lex.parse(read('lex', 'lex_grammar.jisonlex')); var expected = JSON.parse(read('lex', 'lex_grammar.lex.json')); assert.deepEqual(lexgrammar, expected, "grammar should be parsed correctly"); -}; + }); -exports["test ANSI C lexical grammar"] = function () { + it("test ANSI C lexical grammar", function () { var lexgrammar = lex.parse(read('lex','ansic.jisonlex')); assert.ok(lexgrammar, "grammar should be parsed correctly"); -}; + }); -exports["test advanced"] = function () { + it("test advanced", function () { var lexgrammar = '%%\n"stuff"*/!("{"|";") {/* ok */}\n'; var expected = { rules: [ ["stuff*(?!(\\{|;))", "/* ok */"], - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test start conditions"] = function () { + it("test start conditions", function () { var lexgrammar = '%s TEST TEST2\n%x EAT\n%%\n'+ '"enter-test" {this.begin(\'TEST\');}\n'+ '"x" {return \'T\';}\n'+ @@ -183,214 +305,436 @@ exports["test start conditions"] = function () { "EAT": 1, }, rules: [ - ["enter-test\\b", "this.begin('TEST');" ], - [["TEST","EAT"], "x\\b", "return 'T';" ], - [["*"], "z\\b", "return 'Z';" ], - [["TEST"], "y\\b", "this.begin('INITIAL'); return 'TY';" ] - ] + ["enter-test", "this.begin('TEST');" ], + [["TEST","EAT"], "x", "return 'T';" ], + [["*"], "z", "return 'Z';" ], + [["TEST"], "y", "this.begin('INITIAL'); return 'TY';" ] + ], + macros: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); + + it("test unknown declarations", function () { + var lexgrammar = '%a b c\n%foo[bar] baz qux\n%a b c\n%%\n. //'; + var expected = { + unknownDecls: [ + ['a', 'b c'], + ['foo', '[bar] baz qux'], + ['a', 'b c'] + ], + rules: [ + ['.', '//'] + ], + macros: {}, + startConditions: {} + }; -exports["test no brace action"] = function () { + assert.deepEqual(lex.parse(lexgrammar), expected, "unknown declarations should be parsed correctly"); + }); + + it("test no brace action", function () { var lexgrammar = '%%\n"["[^\\]]"]" return true;\n"x" return 1;'; var expected = { rules: [ ["\\[[^\\]]\\]", "return true;"], - ["x\\b", "return 1;"] - ] + ["x", "return 1;"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test quote escape"] = function () { + it("test quote escape", function () { var lexgrammar = '%%\n\\"\\\'"x" return 1;'; var expected = { rules: [ - ["\"'x\\b", "return 1;"] - ] + ["\"'x", "return 1;"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test escape things"] = function () { + it("test escape things", function () { var lexgrammar = '%%\n\\"\\\'\\\\\\*\\i return 1;\n"a"\\b return 2;\n\\cA {}\n\\012 {}\n\\xFF {}'; var expected = { rules: [ - ["\"'\\\\\\*i\\b", "return 1;"], + ["\"'\\\\\\*i", "return 1;"], ["a\\b", "return 2;"], ["\\cA", ""], ["\\012", ""], ["\\xFF", ""] - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test unicode encoding"] = function () { + it("test unicode encoding", function () { var lexgrammar = '%%\n"\\u03c0" return 1;'; var expected = { rules: [ ["\\u03c0", "return 1;"] - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test unicode"] = function () { + it("test unicode", function () { var lexgrammar = '%%\n"Ï€" return 1;'; var expected = { rules: [ ["Ï€", "return 1;"] - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test bugs"] = function () { + it("test unquoted lexer rule literals", function () { + var lexgrammar = '%%\nÏ€ return 1;\n-abc return 2;'; + var expected = { + rules: [ + ["Ï€", "return 1;"], + ["-abc", "return 2;"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] + }; + + assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); + }); + + it("test bugs", function () { var lexgrammar = '%%\n\\\'([^\\\\\']+|\\\\(\\n|.))*?\\\' return 1;'; var expected = { rules: [ ["'([^\\\\']+|\\\\(\\n|.))*?'", "return 1;"] - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test special groupings"] = function () { + it("test special groupings", function () { var lexgrammar = '%%\n(?:"foo"|"bar")\\(\\) return 1;'; var expected = { rules: [ ["(?:foo|bar)\\(\\)", "return 1;"] - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test trailing code include"] = function () { + it("test trailing code include", function () { var lexgrammar = '%%"foo" {return bar;}\n%% var bar = 1;'; var expected = { rules: [ - ['foo\\b', "return bar;"] + ['foo', "return bar;"] ], - moduleInclude: " var bar = 1;" + moduleInclude: " var bar = 1;", + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test empty or regex"] = function () { + it("test empty or regex", function () { var lexgrammar = '%%\n(|"bar")("foo"|)(|) return 1;'; var expected = { rules: [ ["(|bar)(foo|)(|)", "return 1;"] - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test options"] = function () { + it("test options", function () { var lexgrammar = '%options flex\n%%\n"foo" return 1;'; var expected = { rules: [ ["foo", "return 1;"] ], - options: {flex: true} + options: {flex: true}, + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); + + it("test if %options names with a hyphen are correctly recognized", function () { + var lexgrammar = '%options token-stack\n%%\n"foo" return 1;'; + var expected = { + rules: [ + ["foo", "return 1;"] + ], + options: {"token-stack": true}, + macros: {}, + startConditions: {}, + unknownDecls: [] + }; -exports["test unquoted string rules"] = function () { + assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); + }); + + it("test options with values", function () { + var lexgrammar = '%options ping=666 bla=blub bool1 s1="s1value" s2=\'s2value\' s3=false s4="false" a-b-c="d"\n%%\n"foo" return 1;'; + var expected = { + rules: [ + ["foo", "return 1;"] + ], + options: { + ping: 666, + bla: "blub", + bool1: true, + s1: "s1value", + s2: "s2value", + s3: false, + s4: "false", + "a-b-c": "d" // `%options camel-casing` is done very late in the game: see Jison.Generator source code. + }, + macros: {}, + startConditions: {}, + unknownDecls: [] + }; + + assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); + }); + + it("test options spread across multiple lines", function () { + var lexgrammar = '%options ping=666\n bla=blub\n bool1\n s1="s1value"\n s2=\'s2value\'\n s3=false\n s4="false"\n a-b-c="d"\n%%\n"foo" return 1;'; + var expected = { + rules: [ + ["foo", "return 1;"] + ], + options: { + ping: 666, + bla: "blub", + bool1: true, + s1: "s1value", + s2: "s2value", + s3: false, + s4: "false", + "a-b-c": "d" // `%options camel-casing` is done very late in the game: see Jison.Generator source code. + }, + macros: {}, + startConditions: {}, + unknownDecls: [] + }; + + assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); + }); + + it("test options with string values which have embedded quotes", function () { + var lexgrammar = '%options s1="s1\\"val\'ue" s2=\'s2\\\\x\\\'val\"ue\'\n%%\n"foo" return 1;'; + var expected = { + rules: [ + ["foo", "return 1;"] + ], + options: { + s1: "s1\"val'ue", + s2: "s2\\\\x'val\"ue" + }, + macros: {}, + startConditions: {}, + unknownDecls: [] + }; + + assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); + }); + + it("test unquoted string rules", function () { var lexgrammar = "%%\nfoo* return 1"; var expected = { rules: [ ["foo*", "return 1"] - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test [^\\\\]"] = function () { + it("test [^\\\\]", function () { var lexgrammar = '%%\n"["[^\\\\]"]" {return true;}\n\'f"oo\\\'bar\' {return \'baz2\';}\n"fo\\"obar" {return \'baz\';}\n'; var expected = { rules: [ ["\\[[^\\\\]\\]", "return true;"], - ["f\"oo'bar\\b", "return 'baz2';"], - ['fo"obar\\b', "return 'baz';"] - ] + ["f\"oo'bar", "return 'baz2';"], + ['fo"obar', "return 'baz';"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test comments"] = function () { + it("test comments", function () { var lexgrammar = "/* */ // foo\n%%\nfoo* return 1"; var expected = { rules: [ ["foo*", "return 1"] - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test rules with trailing escapes"] = function () { + it("test rules with trailing escapes", function () { var lexgrammar = '%%\n\\#[^\\n]*\\n {/* ok */}\n'; var expected = { rules: [ ["#[^\\n]*\\n", "/* ok */"], - ] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test no brace action with surplus whitespace between rules"] = function () { + it("test no brace action with surplus whitespace between rules", function () { var lexgrammar = '%%\n"a" return true;\n \n"b" return 1;\n \n'; var expected = { rules: [ - ["a\\b", "return true;"], - ["b\\b", "return 1;"] - ] + ["a", "return true;"], + ["b", "return 1;"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test windows line endings"] = function () { + it("test macro for commit SHA-1: 1246dbb75472cee8e4e91318cc5a0d4739a8fe12", function () { + var lexgrammar = 'BR \\r\\n|\\n|\\r\n%%\r\n{BR} %{\r\nreturn true;\r\n%}\r\n'; + var expected = { + macros: {"BR": "\\r\\n|\\n|\\r"}, + rules: [ + ["{BR}", "return true;"] + ], + startConditions: {}, + unknownDecls: [] + }; + + assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); + }); + + it("test windows line endings", function () { var lexgrammar = '%%\r\n"["[^\\]]"]" %{\r\nreturn true;\r\n%}\r\n'; var expected = { rules: [ - ["\\[[^\\]]\\]", "\r\nreturn true;\r\n"] - ] + ["\\[[^\\]]\\]", "return true;"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); -exports["test braced action with surplus whitespace between rules"] = function () { + it("test braced action with surplus whitespace between rules", function () { var lexgrammar = '%%\n"a" %{ \nreturn true;\n%} \n \n"b" %{ return 1;\n%} \n \n'; var expected = { rules: [ - ["a\\b", " \nreturn true;\n"], - ["b\\b", " return 1;\n"] - ] + ["a", "return true;"], + ["b", "return 1;"] + ], + macros: {}, + startConditions: {}, + unknownDecls: [] }; assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); -}; + }); + + it("test %options easy_keyword_rules", function () { + var lexgrammar = '%options easy_keyword_rules\n'+ + '%s TEST TEST2\n%x EAT\n%%\n'+ + '"enter-test" {this.begin(\'TEST\');}\n'+ + '"enter_test" {this.begin(\'TEST\');}\n'+ + '"x" {return \'T\';}\n'+ + '<*>"z" {return \'Z\';}\n'+ + '"y" {this.begin(\'INITIAL\'); return \'TY\';}\n'+ + '\\"\\\'"a" return 1;\n'+ + '\\"\\\'\\\\\\*\\i return 1;\n"a"\\b return 2;\n\\cA {}\n\\012 {}\n\\xFF {}\n'+ + '"["[^\\\\]"]" {return true;}\n\'f"oo\\\'bar\' {return \'baz2\';}\n"fo\\"obar" {return \'baz\';}\n'; + var expected = { + startConditions: { + "TEST": 0, + "TEST2": 0, + "EAT": 1, + }, + rules: [ + ["enter-test\\b", "this.begin('TEST');" ], // '-' dash is accepted as it's *followed* by a word, hence the *tail* is an 'easy keyword', hence it merits an automatic `\b` word-boundary check added! + ["enter_test\\b", "this.begin('TEST');" ], + [["TEST","EAT"], "x\\b", "return 'T';" ], + [["*"], "z\\b", "return 'Z';" ], + [["TEST"], "y\\b", "this.begin('INITIAL'); return 'TY';" ], + ["\"'a\\b", "return 1;"], // keywords *with any non-keyword prefix*, i.e. keywords 'at the tail end', get the special 'easy keyword' treatment too! + ["\"'\\\\\\*i\\b", "return 1;"], + ["a\\b", "return 2;"], + ["\\cA", ""], + ["\\012", ""], + ["\\xFF", ""], + ["\\[[^\\\\]\\]", "return true;"], + ["f\"oo'bar\\b", "return 'baz2';"], + ['fo"obar\\b', "return 'baz';"] + ], + options: { + "easy_keyword_rules": true + }, + macros: {}, + unknownDecls: [] + }; + assert.deepEqual(lex.parse(lexgrammar), expected, "grammar should be parsed correctly"); + }); +}); -if (require.main === module) - require("test").run(exports); diff --git a/tests/index.html b/tests/index.html new file mode 100644 index 0000000..7c1eb0e --- /dev/null +++ b/tests/index.html @@ -0,0 +1,25 @@ + + + + LEX Parser Tests + + + + + +
+ + + + + + + + + + + diff --git a/tests/lex/ansic.jisonlex b/tests/lex/ansic.jisonlex index 1b8e783..55ade4f 100644 --- a/tests/lex/ansic.jisonlex +++ b/tests/lex/ansic.jisonlex @@ -6,8 +6,8 @@ FS [fFlL] IS [uUlL]* %{ -#include -#include "y.tab.h" +//#include +//#include "y.tab.h" void count(); %} diff --git a/tests/lex/bnf.jisonlex b/tests/lex/bnf.jisonlex index 763298b..43d9cfd 100644 --- a/tests/lex/bnf.jisonlex +++ b/tests/lex/bnf.jisonlex @@ -2,7 +2,7 @@ %% \s+ {/* skip whitespace */} "/*"[^*]*"*" {return yy.lexComment(this);} -[a-zA-Z][a-zA-Z0-9_-]* {return 'ID';} +[a-zA-Z_][a-zA-Z0-9_]* {return 'ID';} '"'[^"]+'"' {yytext = yytext.substr(1, yyleng-2); return 'STRING';} "'"[^']+"'" {yytext = yytext.substr(1, yyleng-2); return 'STRING';} ":" {return ':';} diff --git a/tests/lex/bnf.lex.json b/tests/lex/bnf.lex.json index 0dc1f6c..1868212 100644 --- a/tests/lex/bnf.lex.json +++ b/tests/lex/bnf.lex.json @@ -2,23 +2,26 @@ "rules": [ ["\\s+", "/* skip whitespace */"], ["\\/\\*[^*]*\\*", "return yy.lexComment(this);"], - ["[a-zA-Z][a-zA-Z0-9_-]*", "return 'ID';"], + ["[a-zA-Z_][a-zA-Z0-9_]*", "return 'ID';"], ["\"[^\"]+\"", "yytext = yytext.substr(1, yyleng-2); return 'STRING';"], ["'[^']+'", "yytext = yytext.substr(1, yyleng-2); return 'STRING';"], [":", "return ':';"], [";", "return ';';"], ["\\|", "return '|';"], ["%%", "return '%%';"], - ["%prec\\b", "return 'PREC';"], - ["%start\\b", "return 'START';"], - ["%left\\b", "return 'LEFT';"], - ["%right\\b", "return 'RIGHT';"], - ["%nonassoc\\b", "return 'NONASSOC';"], + ["%prec", "return 'PREC';"], + ["%start", "return 'START';"], + ["%left", "return 'LEFT';"], + ["%right", "return 'RIGHT';"], + ["%nonassoc", "return 'NONASSOC';"], ["%[a-zA-Z]+[^\\n]*", "/* ignore unrecognized decl */"], ["\\{\\{[^}]*\\}", "return yy.lexAction(this);"], ["\\{[^}]*\\}", "yytext = yytext.substr(1, yyleng-2); return 'ACTION';"], ["<[^>]*>", "yytext = yytext.substr(1, yyleng-2); return 'ACTION';"], [".", "/* ignore bad characters */"], ["$", "return 'EOF';"] - ] + ], + "macros": {}, + "startConditions": {}, + "unknownDecls": [] } diff --git a/tests/lex/lex_grammar.jisonlex b/tests/lex/lex_grammar.jisonlex index ae7e896..e57ac31 100644 --- a/tests/lex/lex_grammar.jisonlex +++ b/tests/lex/lex_grammar.jisonlex @@ -2,8 +2,8 @@ %% \n+ {yy.freshLine = true;} \s+ {yy.freshLine = false;} -"y{"[^}]*"}" {yytext = yytext.substr(2, yytext.length-3);return 'ACTION';} -[a-zA-Z_][a-zA-Z0-9_-]* {return 'NAME';} +"y{"[^}]*"}" {yytext = yytext.substr(2, yyleng-3);return 'ACTION';} +[a-zA-Z_][a-zA-Z0-9_]* {return 'NAME';} '"'([^"]|'\"')*'"' {return 'STRING_LIT';} "'"([^']|"\'")*"'" {return 'STRING_LIT';} "|" {return '|';} @@ -23,7 +23,7 @@ "{"\d+(","\s?\d+|",")?"}" {return 'RANGE_REGEX';} /"{" %{if(yy.freshLine){this.input('{');return '{';} else this.unput('y');%} "}" %{return '}';%} -"%{"(.|\n)*?"}%" {yytext = yytext.substr(2, yytext.length-4);return 'ACTION';} +"%{"(.|\n)*?"}%" {yytext = yytext.substr(2, yyleng-4);return 'ACTION';} . {/* ignore bad characters */} <> {return 'EOF';} diff --git a/tests/lex/lex_grammar.lex.json b/tests/lex/lex_grammar.lex.json index 44d7aac..63dd32d 100644 --- a/tests/lex/lex_grammar.lex.json +++ b/tests/lex/lex_grammar.lex.json @@ -2,10 +2,10 @@ "rules": [ ["\\n+", "yy.freshLine = true;"], ["\\s+", "yy.freshLine = false;"], - ["y\\{[^}]*\\}", "yytext = yytext.substr(2, yytext.length-3);return 'ACTION';"], - ["[a-zA-Z_][a-zA-Z0-9_-]*", "return 'NAME';"], - ["\"([^\"]|\\\\\")*\"", "return 'STRING_LIT';"], - ["'([^']|\\\\')*'", "return 'STRING_LIT';"], + ["y\\{[^}]*\\}", "yytext = yytext.substr(2, yyleng-3);return 'ACTION';"], + ["[a-zA-Z_][a-zA-Z0-9_]*", "return 'NAME';"], + ["\"([^\"]|\")*\"", "return 'STRING_LIT';"], + ["'([^']|')*'", "return 'STRING_LIT';"], ["\\|", "return '|';"], ["\\[(\\\\\\]|[^\\]])*\\]", "return 'ANY_GROUP_REGEX';"], ["\\(", "return '(';"], @@ -23,8 +23,11 @@ ["\\{\\d+(,\\s?\\d+|,)?\\}", "return 'RANGE_REGEX';"], ["(?=\\{)", "if(yy.freshLine){this.input('{');return '{';} else this.unput('y');"], ["\\}", "return '}';"], - ["%\\{(.|\\n)*?\\}%", "yytext = yytext.substr(2, yytext.length-4);return 'ACTION';"], + ["%\\{(.|\\n)*?\\}%", "yytext = yytext.substr(2, yyleng-4);return 'ACTION';"], [".", "/* ignore bad characters */"], ["$", "return 'EOF';"] - ] + ], + "macros": {}, + "startConditions": {}, + "unknownDecls": [] }