UNPKG

jscc-parser

Version:

A LALR(1) Parser Generator for JavaScript written in JavaScript.

1,232 lines (1,139 loc) 253 kB
/** * @fileoverview * @suppress {globalThis} */ /* * Contains type definitions for Closure's benefit. Used as a * start file when optimizing with requirejs. */ /** * The root namespace. Re-add the const tag after Closure bug #1235 is fixed. * @namespace */ this["jscc"] = {}; var jscc = this["jscc"]; /** * The namespace to which enum definitions belong. * @namespace */ jscc["enums"] = {}; /** * The namespace to which certain classes belong. * @namespace */ jscc["classes"] = {}; jscc.enums = jscc["enums"]; jscc.classes = jscc["classes"]; /* * To avoid type errors with enums, add the enum module code here. The enum modules * will simply return the enum objects when the closure pragma is defined. There * really should be a better solution than this, and maybe there is. */ /** * Indicates the associativity of a symbol. * @enum {number} */ jscc.enums.ASSOC = { /** * The associativity has not yet been set. */ NONE: 0, /** * The symbol is left-associative. */ LEFT: 1, /** * The symbol is right-associative. */ RIGHT: 2, /** * The symbol is non-associative. */ NOASSOC: 3 }; /** * Identifies the type of an edge in an automation graph. * @enum {number} */ jscc.enums.EDGE = { FREE: 0, EPSILON: 1, CHAR: 2 }; /** * Indicates whether the executable environment is a * console-based Javascript engine or a web environment. * @enum {number} */ jscc.enums.EXEC = { /** * A console-based Javascript engine is in use. */ CONSOLE: 0, /** * A web-browser-based Javascript engine is in use. */ WEB: 1 }; /** * Specifies the minimum logging level. * @enum {number} */ jscc.enums.LOG_LEVEL = { /** * Log all messages. */ TRACE: 0, /** * Log debug messages and higher. */ DEBUG: 1, /** * Log info messages and higher. */ INFO: 2, /** * Log warning messages and higher. */ WARN: 3, /** * Log error and fatal messages. */ ERROR: 4, /** * Log only fatal messages. */ FATAL: 5 }; // Export from Closure, as this enumeration may be used in the // mainOptions typedef. jscc.enums.LOG_LEVEL['TRACE'] = jscc.enums.LOG_LEVEL.TRACE; jscc.enums.LOG_LEVEL['DEBUG'] = jscc.enums.LOG_LEVEL.DEBUG; jscc.enums.LOG_LEVEL['INFO'] = jscc.enums.LOG_LEVEL.INFO; jscc.enums.LOG_LEVEL['WARN'] = jscc.enums.LOG_LEVEL.WARN; jscc.enums.LOG_LEVEL['ERROR'] = jscc.enums.LOG_LEVEL.ERROR; jscc.enums.LOG_LEVEL['FATAL'] = jscc.enums.LOG_LEVEL.FATAL; jscc.enums['LOG_LEVEL'] = jscc.enums.LOG_LEVEL; /** * Indicates an output mode for the parser. * @enum {number} */ jscc.enums.MODE_GEN = { /** * Output is plain text. */ TEXT: 0, /** * Output is JavaScript code. */ JS: 1, /** * Output is HTML-formatted. */ HTML: 2 }; /** * Identifies a special symbol. Special symbols include * end-of-file, whitespace, and error symbols. Use * NONE to indicate a non-special symbol. * @enum {number} */ jscc.enums.SPECIAL = { /** * Identifies a non-special symbol. */ NONE: 0, /** * Identifies an end-of-file symbol. */ EOF: 1, /** * Identifies a whitespace symbol. */ WHITESPACE: 2, /** * Identifies an error symbol. */ ERROR: 3 }; /** * Identifies a symbol as nonterminating or terminating. * @enum {number} */ jscc.enums.SYM = { /** * The symbol is nonterminating. */ NONTERM: 0, /** * The symbol is terminating. */ TERM: 1 }; /* * Some option-override, fictional types. */ /** * @typedef {{id: ?number, kind: ?jscc.enums.SYM, label: ?string, prods: ?Array<number>, first: * ?Array, associativity: ?jscc.enums.ASSOC, level: ?number, code: ?string, special: ?jscc.enums.SPECIAL, * defined: ?boolean, "nullable": ?boolean}} */ var SymbolOptions; /** * @typedef {{id: ?number, lhs: ?number, rhs: ?Array<!number>, level: ?number, code: ?string}} */ var ProductionOptions; /** * @typedef {{kernel: ?Array<!jscc.classes.Item>, epsilon: ?Array<!jscc.classes.Item>, def_act: ?number, done: * ?boolean, closed: ?boolean, actionrow: ?Array<!jscc.classes.TableEntry>, gotorow: * ?Array<!jscc.classes.TableEntry>}} */ var StateOptions; /** * @typedef {{prod: ?number, dot_offset: ?number, lookahead: ?Array<!number>}} */ var ItemOptions; /** * @typedef {{edge: ?jscc.enums.EDGE, ccl: ?jscc.bitset, follow: ?number, follow2: ?number, accept: ?number, * weight: ?number}} */ var NfaOptions; /** * @typedef {{line: ?Array, nfa_set: ?Array<!number>, accept: ?number, done: ?boolean, group: ?number}} */ var DfaOptions; /** * @typedef {{out_file: ?string, src_file: ?string, tpl_file: ?string, input: ?(string|function():!string), * template: ?(string|function():!string), outputCallback: ?function(string):void, dump_nfa: ?boolean, * dump_dfa: ?boolean, verbose: ?boolean, logLevel: ?(string|jscc.enums.LOG_LEVEL)}} * @property {?string} out_file - The path of the output file. Defaults to * the empty string, which means to print to standard output (or the engine's equivalent). * @property {?string} src_file - The path of the input grammar file. * Defaults to the empty string, which means to read from standard input (or * the engine's equivalent). * @property {?string} tpl_file - The path of the input template file. * Defaults to the module's default template file, which is intended for generic * compilation tasks. * @property {?(string|function():!string)} input - If a string, the contents of the * input grammar. If a function with no arguments, a function that returns * the contents of the grammar. When input is specified, src_file is ignored. * @property {?(string|function():!string)} template - If a string, the contents of the * template. If a function with no arguments, a function that returns the contents * of the template. When template is specified, tpl_file is ignored. * @property {?function(string):void} outputCallback - A function with a parameter * that will be called with the output. When outputCallback is specified, * out_file is ignored. * @property {?boolean} dump_nfa - Whether to output the nondeterministic finite * automata for debugging purposes. Defaults to false. * @property {?boolean} dump_dfa - Whether to output the deterministic finite * automata for debugging purposes. Defaults to false. * @property {?boolean} verbose - Make debugging output chattier. Defaults to * false. * @property {?(string|jscc.enums.LOG_LEVEL)} logLevel - The logging * level. Can be the name of one of the {@link module:jscc.enums.LOG_LEVEL} values * or one of the values themselves. Defaults to WARN. * @property {?boolean} throwIfErrors - Whether to throw an exception before completion * of the main method if there are any errors. * @property {?boolean} exitIfErrors - Whether to exit the process with a non-zero exit * code if there are any errors, provided that the platform permits doing so. Intended * for use with shell scripts. */ var mainOptions; /** * @typedef {function(!string):*} */ var reqParameter; /** * @typedef {function((undefined|string|Array<string>|{deps: (string|Array<string>), callback: (string|Function)}), (string|Function|Array<string>)=, (string|Function)=, (string|boolean)=, boolean=):almondRequire} */ var almondRequire; var almondRequireExtension = /** * @lends {almondRequire} */ ({ /** * @type {!Object<string, *>} */ _defined: {}, /** * @param {Object<string, *>} cfg * @returns {almondRequire} */ config: function(cfg) { } }); /** * @typedef {string} */ var stringWithErrorMessage; var stringWithErrorMessageExtension = /** * @lends {stringWithErrorMessage} */ ({ /** * @type {string} */ ERROR_MSG: "" }); /** * @typedef {function(string):boolean} */ var hasObject; var hasObjectExtension = /** * @lends {hasObject} */ ({ /** * @param {string} name * @param {function(...*):boolean} test * @param {boolean=} now */ add: function(name, test, now) { }, /** * @param {T} el * @returns {T} * @template T */ clearElement: function(el) { }, /** * @param {string} name * @param {*} el * @returns {boolean} */ cssprop: function(name, el) { }, /** * @param {*} obj * @param {*=} property * @returns {boolean} */ isHostType: function(obj, property) { }, /** * @returns {Object<string, (boolean|stringWithErrorMessage)>} */ all: function() { } }); /** * @typedef {{filename: ?(string|undefined), chunkCallback: ?(function(string):void|undefined), endCallback: * ?(function():void|undefined)}} * @property {?(string|undefined)} filename - The filename to read. If omitted, read from standard input. * @property {?(function(string):void|undefined)} chunkCallback - The function to call when an input chunk is read * asynchronously. * @property {?(function():void|undefined)} endCallback - The function to call when the asynchronous read operation has * completed. */ var ioOptions; /** * @typedef {{text: string, destination: ?(string|undefined), callback: ?(function():void|undefined)}} * @property {string} text - The text to be written. * @property {?(string|undefined)} destination - The filename to which to write the text. If omitted, text is written * to standard output. * @property {?(function():void|undefined)} callback - A callback to be executed when the asynchronous write operation * has completed. If omitted, the operation occurs synchronously instead. */ var ioWriteOutputOptions; /** * Interface for engine-specific IO modules. * @interface */ jscc.io = function() { }; jscc.io.prototype = { /** * Reads input from the specified file or from standard input. * If chunkCallback and/or endCallback are specified, the operation * is asynchronous, and the function returns nothing. Otherwise, * the operation is synchronous, and the function returns a string * with the contents read from the file or from standard input. * * @param {(string|function(string):void|ioOptions)=} options - * If a string, the filename to read. If an object, has optional filename, chunkCallback, and endCallback * properties. If a function, the callback function to execute for each chunk read from standard input. * @returns {(string|void)} When running synchronously, the text read from * the file or standard input. When running asynchronously, returns nothing. */ read_all_input: function(options) { }, /** * Reads the template file into which the parser code is inserted. * If not specified, uses the default driver specified in * {@link jscc.global.DEFAULT_DRIVER}. * * @param {(string|function(string):void|ioOptions)=} options - * If a string, specifies the template filename. If a function, specifies the callback function to be used * when reading a file chunk has completed. If an object, specifies either or both. If omitted, causes the * function to read * {@link jscc.global.DEFAULT_DRIVER} synchronously. * @returns {(string|void)} When running synchronously, returns the contents of * the template file as a string. When running asynchronously, returns * nothing. */ read_template: function(options) { }, /** * Writes the provided text to the specified file or to standard output. * * @param {(string|ioWriteOutputOptions)} options - When a string, the text * to be written to standard output. When an object, contains text, destination, and callback properties. */ write_output: function(options) { }, /** * Writes the provided text to a debugging output, provided that such an output * exists in the implementation of this interface. * * @param {string} text - The text to write to the debugging output. */ write_debug: function(text) { }, /** * Attempts to exit the entire process with the provided exit code if the * platform supports doing so. Callers should also ensure that all functions * exit appropriately if the platform does not support this feature. * * @param {number=} exitCode - The exit code to use. */ exit: function(exitCode) { } }; /** * Interface for engine-specific logging modules. * @interface */ jscc.log = function() { }; jscc.log.prototype = { /** * Logs a message at the fatal level. * @param {string} msg - The message to log. */ fatal: function(msg) { }, /** * Logs a message at the error level. * @param {string} msg - The message to log. */ error: function(msg) { }, /** * Logs a message at the warning level. * @param {string} msg - The message to log. */ warn: function(msg) { }, /** * Logs a message at the info level. * @param {string} msg - The message to log. */ info: function(msg) { }, /** * Logs a message at the debug level. * @param {string} msg - The message to log. */ debug: function(msg) { }, /** * Logs a message at the trace level. * @param {string} msg - The message to log. */ trace: function(msg) { }, /** * Sets the minimum level to log. This function * may not have an effect at all times with all * loggers. * @param {jscc.enums.LOG_LEVEL} level - The * minimum level to log. */ setLevel: function(level) { } }; /** * Interface definition for bitset implementations. * @interface */ jscc.bitset = function() { }; jscc.bitset.prototype = { /** * Sets the specified bit to true or false. * @param {!number} bit - The index of the bit to set * @param {boolean=} state - Whether to set the bit to true or false * @returns {!boolean} Returns the state parameter for chaining purposes * @method */ set: function(bit, state) { return false; }, /** * Gets the bit at the specified index. * @param {!number} bit - The index of the bit to get * @returns {!boolean} Whether the bit is currently true or false * @method */ get: function(bit) { return false; }, /** * Returns the number of true values in the bitset. * @returns {!number} The number of true values in the bitset * @method */ count: function() { return 0; } }; /** * @license almond 0.3.2 Copyright jQuery Foundation and other contributors. * Released under MIT license, http://github.com/requirejs/almond/LICENSE */ //Going sloppy to avoid 'use strict' string cost, but strict practices should //be followed. /*global setTimeout: false */ /** @type {almondRequire} */ var requirejs; /** @type {almondRequire} */ var require; var define; (function (undef) { var main, req, makeMap, handlers, /** @type {!Object<string, *>} */ defined = {}, /** @type {!Object<string, Array>} */ waiting = {}, config = {}, /** @type {!Object<string, boolean>} */ defining = {}, hasOwn = Object.prototype.hasOwnProperty, aps = [].slice, jsSuffixRegExp = /\.js$/; /** * @param {!Object} obj * @param {!string} prop * @returns {!boolean} */ function hasProp(obj, prop) { return hasOwn.call(obj, prop); } /** * Given a relative module name, like ./something, normalize it to * a real name that can be mapped to a path. * @param {string} name the relative name * @param {string} baseName a real name that the name arg is relative * to. * @returns {string} normalized name */ function normalize(name, baseName) { var /** @type {Array<string>} */ nameParts, nameSegment, mapValue, foundMap, lastIndex, foundI, foundStarMap, starI, i, j, part, normalizedBaseParts, baseParts = /** @type {Array<string>} */ (baseName && baseName.split("/")), map = config.map, starMap = (map && map['*']) || {}; //Adjust any relative paths. if (name) { nameParts = name.split('/'); lastIndex = nameParts.length - 1; // If wanting node ID compatibility, strip .js from end // of IDs. Have to do this here, and not in nameToUrl // because node allows either .js or non .js to map // to same file. if (config.nodeIdCompat && jsSuffixRegExp.test(nameParts[lastIndex])) { nameParts[lastIndex] = nameParts[lastIndex].replace(jsSuffixRegExp, ''); } // Starts with a '.' so need the baseName if (nameParts[0].charAt(0) === '.' && baseParts) { //Convert baseName to array, and lop off the last part, //so that . matches that 'directory' and not name of the baseName's //module. For instance, baseName of 'one/two/three', maps to //'one/two/three.js', but we want the directory, 'one/two' for //this normalization. normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); nameParts = normalizedBaseParts.concat(nameParts); } //start trimDots for (i = 0; i < nameParts.length; i++) { part = nameParts[i]; if (part === '.') { nameParts.splice(i, 1); i -= 1; } else if (part === '..') { // If at the start, or previous value is still .., // keep them so that when converted to a path it may // still work when converted to a path, even though // as an ID it is less than ideal. In larger point // releases, may be better to just kick out an error. if (!((i === 1 && nameParts[2] === '..') || nameParts[i - 1] === '..') && i > 0) { nameParts.splice(i - 1, 2); i -= 2; } } } //end trimDots name = nameParts.join('/'); nameParts = null; } //Apply map config if available. if ((baseParts || starMap) && map) { nameParts = name.split('/'); for (i = nameParts.length; i > 0; i -= 1) { nameSegment = nameParts.slice(0, i).join("/"); if (baseParts) { //Find the longest baseName segment match in the config. //So, do joins on the biggest to smallest lengths of baseParts. for (j = baseParts.length; j > 0; j -= 1) { mapValue = map[baseParts.slice(0, j).join('/')]; //baseName segment has config, find if it has one for //this name. if (mapValue) { mapValue = mapValue[nameSegment]; if (mapValue) { //Match, update name to the new value. foundMap = mapValue; foundI = i; break; } } } } if (foundMap) { break; } //Check for a star map match, but just hold on to it, //if there is a shorter segment match later in a matching //config, then favor over this star map. if (!foundStarMap && starMap && starMap[nameSegment]) { foundStarMap = starMap[nameSegment]; starI = i; } } if (!foundMap && foundStarMap) { foundMap = foundStarMap; foundI = starI; } if (foundMap) { nameParts.splice(0, foundI, foundMap); name = nameParts.join('/'); } } return name; } /** * @param {(string|Array<string>|undefined)} relName * @param {boolean=} forceSync * @returns {Function} */ function makeRequire(relName, forceSync) { return function () { //A version of a require function that passes a moduleName //value for items that may need to //look up paths relative to the moduleName var args = aps.call(arguments, 0); //If first arg is not require('string'), and there is only //one arg, it is the array form without a callback. Insert //a null so that the following concat is correct. if (typeof args[0] !== 'string' && args.length === 1) { args.push(null); } return req.apply(undef, args.concat([relName, forceSync])); }; } /** * @param {string} relName * @returns {function(string):string} */ function makeNormalize(relName) { return function (name) { return normalize(name, relName); }; } /** * @param {string} depName * @returns {function(*)} */ function makeLoad(depName) { return function (value) { defined[depName] = value; }; } /** * @param {!string} name * @returns {*} */ function callDep(name) { if (hasProp(waiting, name)) { var args = waiting[name]; delete waiting[name]; defining[name] = true; main.apply(undef, args); } if (!hasProp(defined, name) && !hasProp(defining, name)) { throw new Error('No ' + name); } return defined[name]; } //Turns a plugin!resource to [plugin, resource] //with the plugin being undefined if the name //did not have a plugin prefix. /** * @param {string} name * @returns {Array<(string|undefined)>} */ function splitPrefix(name) { var prefix, index = name ? name.indexOf('!') : -1; if (index > -1) { prefix = name.substring(0, index); name = name.substring(index + 1, name.length); } return [prefix, name]; } /** * Makes a name map, normalizing the name, and using a plugin * for normalization if necessary. Grabs a ref to plugin * too, as an optimization. * @param {string} name * @param {string} relName * @returns {{f: string, n: string, pr: (string|undefined), p: *}} */ makeMap = function (name, relName) { var plugin, parts = splitPrefix(name), prefix = parts[0]; name = /** @type {string} */ (parts[1]); if (prefix) { prefix = normalize(prefix, relName); plugin = callDep(prefix); } //Normalize according if (prefix) { if (plugin && plugin.normalize) { name = (/** @type {{normalize: function(string, function(string):string):string}} */ (plugin)).normalize(name, makeNormalize(relName)); } else { name = normalize(name, relName); } } else { name = normalize(name, relName); parts = splitPrefix(name); prefix = parts[0]; name = /** @type {string} */ (parts[1]); if (prefix) { plugin = callDep(prefix); } } //Using ridiculous property names for space reasons return { f: prefix ? prefix + '!' + name : name, //fullName n: name, pr: prefix, p: plugin }; }; /** * @param {string} name * @returns {function():Object} */ function makeConfig(name) { return function () { return (config && config.config && config.config[name]) || {}; }; } handlers = { require: function (name) { return makeRequire(name); }, exports: function (name) { var e = defined[name]; if (typeof e !== 'undefined') { return e; } else { return (defined[name] = {}); } }, module: function (name) { return { id: name, uri: '', exports: defined[name], config: makeConfig(name) }; } }; /** * @param {(string|undefined)} name * @param {(Array<string>|undefined)} deps * @param {Function=} callback * @param {?string=} relName */ main = function (name, deps, callback, relName) { var cjsModule, depName, ret, map, i, args = [], callbackType = typeof callback, usingExports; //Use name if no relName relName = /** @type {string} */ (relName || name); //Call the callback to define the module, if necessary. if (callbackType === 'undefined' || callbackType === 'function') { //Pull out the defined dependencies and pass the ordered //values to the callback. //Default to [require, exports, module] if no deps deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; for (i = 0; i < deps.length; i += 1) { map = makeMap(deps[i], relName); depName = map.f; //Fast path CommonJS standard dependencies. if (depName === "require") { args[i] = handlers.require(name); } else if (depName === "exports") { //CommonJS module spec 1.1 args[i] = handlers.exports(name); usingExports = true; } else if (depName === "module") { //CommonJS module spec 1.1 cjsModule = args[i] = handlers.module(name); } else if (hasProp(defined, depName) || hasProp(waiting, depName) || hasProp(defining, depName)) { args[i] = callDep(depName); } else if (map.p) { map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); args[i] = defined[depName]; } else { throw new Error(name + ' missing ' + depName); } } ret = callback ? callback.apply(defined[/** @type {string} */ (name)], args) : undefined; if (name) { //If setting exports via "module" is in play, //favor that over return value and exports. After that, //favor a non-undefined return value over exports use. if (cjsModule && cjsModule.exports !== undef && cjsModule.exports !== defined[name]) { defined[name] = cjsModule.exports; } else if (ret !== undef || !usingExports) { //Use the return value from the function. defined[name] = ret; } } } else if (name) { //May just be an object definition for the module. Only //worry about defining if have a module name. defined[name] = callback; } }; requirejs = require = req = /** @type {almondRequire} */ (function (deps, callback, relName, forceSync, alt) { if (typeof deps === "string") { if (handlers[deps]) { //callback in this case is really relName return handlers[deps](/** string */ (callback)); } //Just return the module wanted. In this scenario, the //deps arg is the module name, and second arg (if passed) //is just the relName. //Normalize module name, if it contains . or .. return callDep(makeMap(deps, /** @type {string} */ (callback)).f); } if (!deps.splice) { //deps is a config object, not an array. config = deps; if (config.deps) { req(config.deps, config.callback); } if (!callback) { return; } if (callback.splice) { //callback is an array, which means it is a dependency list. //Adjust args if there are dependencies deps = /** @type {Array<string>} */ (callback); callback = relName; relName = null; } else { deps = undef; } } //Support require(['a']) callback = /** @type {!Function} */ (callback || function () {}); //If relName is a function, it is an errback handler, //so remove it. if (typeof relName === 'function') { relName = /** @type {string} */ (forceSync); forceSync = alt; } //Simulate async callback; if (forceSync) { main(undef, /** @type {(Array<string>|undefined)} */ (deps), callback, /** @type {(string|undefined)} */ (relName)); } else { //Using a non-zero value because of concern for what old browsers //do, and latest browsers "upgrade" to 4 if lower value is used: //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: //If want a value immediately, use require('id') instead -- something //that works in almond on the global level, but not guaranteed and //unlikely to work in other AMD implementations. setTimeout(function () { main(undef, /** @type {(Array<string>|undefined)} */ (deps), /** @type {!Function} */ (callback), /** @type {(string|undefined)} */ (relName)); }, 4); } return req; }); /** * Just drops the config on the floor, but returns req in case * the config return value is used. */ req.config = function (cfg) { return req(cfg); }; /** * Expose module registry for debugging and tooling */ requirejs._defined = defined; /** * @param {!string} name * @param {!(Array<string>|Function)} deps * @param {(Function)=} callback */ define = function (name, deps, callback) { if (typeof name !== 'string') { throw new Error('See almond README: incorrect module build, no module name'); } //This module may not have dependencies if (!deps.splice) { //deps is not an array, so probably means //an object literal or factory function for //the value. Adjust args. callback = /** @type {Function} */ (deps); deps = []; } if (!hasProp(defined, name) && !hasProp(waiting, name)) { waiting[name] = [name, deps, callback]; } }; define.amd = { jQuery: true }; }(undefined)); define("bin/almond", function(){}); define('text',{load: function(id){throw new Error("Dynamic load not allowed: " + id);}}); define('text!lib/jscc/template/parser-driver-js.txt',[],function () { return '/*\r\n\tThis is the general, platform-independent part of every parser driver;\r\n\tInput-/Output and Feature-Functions are done by the particular drivers\r\n\tcreated for the particular platform.\r\n*/\r\n##HEADER##\r\nvar __parse=(function(/** number */ eof, /** number */ whitespace, /** number */ error_token){\r\n\t\r\n/// there was "continue" in code, we must to replace it\r\nvar Continue = function(){throw Continue;};\r\n\r\n\t/**\r\n\t * @template T\r\n\t * @param {T} value\r\n\t * @constructor\r\n\t * @extends {Error}\r\n */\r\n\tvar ReturnValue = function(value) {\r\n\t\tError.call(this);\r\n\t\tthis._value = value;\r\n\t};\r\n\tReturnValue.prototype = Object.create(Error.prototype);\r\n\tReturnValue.prototype.constructor = ReturnValue;\r\n\t/**\r\n\t * @type {T}\r\n\t * @private\r\n */\r\n\tReturnValue.prototype._value = null;\r\n\t/**\r\n\t * @returns {T}\r\n */\r\n\tReturnValue.prototype.valueOf = function() {\r\n\t\treturn this._value;\r\n\t};\r\n\r\n\t///can return value from any place of callback\r\n\tfunction Return(value){\r\n\t\tthrow new ReturnValue(value);\r\n\t}\r\n\r\n\tvar TERMINAL_ACTIONS = (function(){\r\n\t\tfunction emptyFn(PCB){return PCB.att;}\r\n\t\tvar actions = ##TERMINAL_ACTIONS##\r\n\t\treturn function(/** @type {!PcbClass} */ PCB, match){\r\n\t\t\ttry{\r\n\t\t\t\treturn (actions[match] || emptyFn)(PCB);\r\n\t\t\t}catch(e){\r\n\t\t\t\tif(e instanceof ReturnValue)return e.valueOf();\r\n\t\t\t\tif(e == Continue)return Continue;\r\n\t\t\t\tthrow e;\r\n\t\t\t}\r\n\t\t}\r\n\t})();\r\n\t/**\r\n\t * @constructor\r\n */\r\n\tvar DfaLex = function() {\r\n\t\tthis._dfaData = ##DFA##;\r\n\t};\r\n\t/**\r\n\t * @type {!Array<!{line: !Array, accept: !number}>}\r\n\t * @private\r\n */\r\n\tDfaLex.prototype._dfaData = [];\r\n\t/**\r\n\t * @type {number}\r\n */\r\n\tDfaLex.prototype.match_pos = 0;\r\n\t/**\r\n\t * @type {?number}\r\n */\r\n\tDfaLex.prototype.state = 0;\r\n\t/**\r\n\t * @type {?number}\r\n */\r\n\tDfaLex.prototype.match = null;\r\n\t/**\r\n\t * @param {number} chr\r\n\t * @param {number} pos\r\n */\r\n\tDfaLex.prototype.exec = function(chr, pos) {\r\n\t\tif (this.state !== null) {\r\n\t\t if ((typeof this.state !== "number") || this.state >= this._dfaData.length) {\r\n\t\t this.state = null;\r\n\t\t throw new Error("Invalid value for DfaLex.state at chr " + chr + " and pos " + pos);\r\n\t\t }\r\n\t\t\tvar line = this._dfaData[this.state].line;\r\n\t\t\tif (typeof line === "undefined" || line === null) {\r\n\t\t\t var badState = this.state;\r\n\t\t\t this.state = null;\r\n\t\t\t throw new Error("At chr " + chr + " and pos " + pos +\r\n\t\t\t ", DfaLex._dfaData[" + badState +\r\n\t\t\t "] appears to exist, but its line property is " +\r\n\t\t\t (typeof line === "undefined" ? "undefined." : "null."));\r\n\t\t\t}\r\n\t\t\tvar p, st;\r\n\t\t\tfor (p = 1 << 8, st = line; p; p >>= 1) {\r\n\t\t\t\tif ((chr & p) !== 0) {\r\n\t\t\t\t\tst = st[1];\r\n\t\t\t\t} else {\r\n\t\t\t\t\tst = st[0];\r\n\t\t\t\t}\r\n\t\t\t\tif (typeof st === "undefined") {\r\n\t\t\t\t st = null;\r\n\t\t\t\t}\r\n\t\t\t\tif (st === null)break;\r\n\t\t\t\tif (Array.isArray(st))continue;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tvar ac = this._dfaData[this.state].accept;\r\n\t\t\tthis.state = /** @type {?number} */ (st);\r\n\t\t\tif (ac !== -1) {\r\n\t\t\t\tthis.match = /** @type{number} */ (ac);\r\n\t\t\t\tthis.match_pos = pos;\r\n\t\t\t}\r\n\t\t}\r\n\t};\r\n##TABLES##\r\n##LABELS##\r\n\tvar ACTIONS = (function(){\r\n\t\tvar PCB = {};\r\n\t\tvar actions = ##ACTIONS##;\r\n\t\treturn function (/** number */ act, /** Array<*> */ vstack, /** !PcbClass */ pcb){\r\n\t\t\ttry{\r\n\t\t\t\tPCB = pcb;\r\n\t\t\t\treturn actions[act].apply(null,vstack);\r\n\t\t\t}catch(e){\r\n\t\t\t\tif(e instanceof ReturnValue)return e.valueOf();\r\n\t\t\t\tthrow e;\r\n\t\t\t}\r\n\t\t}\r\n\t})();\r\n\r\n\t/**\r\n\t * @param {number} top\r\n\t * @param {?number} la\r\n\t * @returns {?number}\r\n */\r\n\tfunction get_act(top, la){\t\r\n\t\tfor(var i = 0; i < act_tab[top].length; i+=2)\r\n\t\t\tif(act_tab[top][i] === la)\r\n\t\t\t\treturn act_tab[top][i+1];\r\n\t\treturn null;\r\n\t}\r\n\tfunction get_goto(top, pop){\t\r\n\t\tfor(var i = 0; i < goto_tab[top].length; i+=2)\r\n\t\t\tif(goto_tab[top][i] === pop)\r\n\t\t\t\treturn goto_tab[top][i+1];\r\n\t\treturn null;\r\n\t}\r\n\r\n\t/**\r\n\t * @param {!string} src\r\n\t * @constructor\r\n */\r\n\tvar PcbClass = function(src) {\r\n\t\tthis.src = src;\r\n\t};\r\n\t/**\r\n\t * @type {number}\r\n */\r\n\tPcbClass.prototype.line = 1;\r\n\t/**\r\n\t * @type {number}\r\n */\r\n\tPcbClass.prototype.column = 1;\r\n\t/**\r\n\t * @type {number}\r\n */\r\n\tPcbClass.prototype.offset = 0;\r\n\t/**\r\n\t * @type {number}\r\n */\r\n\tPcbClass.prototype.error_step = 0;\r\n\t/**\r\n\t * @type {string}\r\n */\r\n\tPcbClass.prototype.src = "";\r\n\t/**\r\n\t * @type {string}\r\n */\r\n\tPcbClass.prototype.att = "";\r\n\t/**\r\n\t * @type {?number}\r\n */\r\n\tPcbClass.prototype.la = null;\r\n\t/**\r\n\t * @type {?number}\r\n */\r\n\tPcbClass.prototype.act = null;\r\n\t/**\r\n\t * @returns {?number}\r\n */\r\n\tPcbClass.prototype.lex = function() {\r\n var /** number */ start, /** number */ pos, /** number */ chr, actionResult;\r\n\t\tvar dfa = new DfaLex();\r\n\t\tvar loop = true;\r\n\t\twhile(loop){\r\n\t\t\tdfa.match_pos = 0;\r\n\t\t\tpos = this.offset + 1;\r\n\t\t\tdo{\r\n\t\t\t\tpos--;\r\n\t\t\t\tdfa.state = 0;\r\n\t\t\t\tdfa.match = null;\r\n\t\t\t\tstart = pos;\r\n\t\t\t\tif(this.src.length <= start) {\r\n\t\t\t\t\tthis.la = eof;\r\n\t\t\t\t\treturn eof;\r\n\t\t\t\t}\r\n\t\t\t\tdo{\r\n\t\t\t\t\tchr = this.src.charCodeAt(pos);\r\n\t\t\t\t\tdfa.exec(chr,pos);\r\n\t\t\t\t\tif(dfa.state !== null)\r\n\t\t\t\t\t\tthis.accountChar(chr);\r\n\t\t\t\t\tpos++;\r\n\t\t\t\t}while(dfa.state !== null);\r\n\t\t\t}while(whitespace > -1 && dfa.match === whitespace);\r\n\t\t\tif(dfa.match !== null){\r\n\t\t\t\tthis.att = this.src.slice(start, dfa.match_pos);\r\n\t\t\t\tthis.offset = dfa.match_pos;\r\n\t\t\t\tactionResult = TERMINAL_ACTIONS(this,dfa.match);\r\n\t\t\t\tif(dfa.state !== null)\r\n\t\t\t\t\tthis.accountChar(chr);\r\n\t\t\t\tif(actionResult === Continue)\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\tthis.att = actionResult;\r\n\t\t\t}else {\r\n\t\t\t\tthis.att = "";\r\n\t\t\t}\r\n\t\t\tloop = false;\r\n\t\t}\r\n\t\tthis.la = dfa.match;\r\n\t\treturn this.la;\r\n\t};\r\n\t/**\r\n\t * @param {number} chr\r\n */\r\n PcbClass.prototype.accountChar = function(chr) {\r\n\t\tif( chr === 10 ){\r\n\t\t\tthis.line++;\r\n\t\t\tthis.column = 0;\r\n\t\t}\r\n\t\tthis.column++;\r\n\t};\r\n\tfunction parse(/** string */ src, err_off, err_la){\r\n\t\t/**\r\n\t\t * @type {!Array<number>}\r\n */\r\n\t\tvar\t\tsstack\t\t\t= [0];\r\n\t\t/**\r\n\t\t * @type {!Array<*>}\r\n */\r\n\t\tvar\t\tvstack\t\t\t= [0];\r\n\t\t/**\r\n\t\t * @type {number}\r\n */\r\n\t\tvar \terr_cnt\t\t\t= 0;\r\n\t\t/**\r\n\t\t * @type {*}\r\n\t\t */\r\n\t\tvar\t\trval;\r\n\t\t/**\r\n\t\t * @type {?number}\r\n\t\t */\r\n\t\tvar\t\tact;\r\n\t\t/**\r\n\t\t * @type {number}\r\n\t\t */\r\n\t\tvar i = 0;\r\n\r\n\t\tvar PCB\t= new PcbClass(src);\r\n\t\terr_off\t= err_off || [];\r\n\t\terr_la = err_la || [];\r\n\t\tPCB.lex();\r\n\t\twhile(true){\r\n\t\t\tPCB.act = get_act(sstack[0],PCB.la);\r\n\t\t\tif(PCB.act === null && defact_tab[sstack[0]] >= 0)\r\n\t\t\t\tPCB.act = -defact_tab[sstack[0]];\r\n\t\t\tif(PCB.act === null){//Parse error? Try to recover!\r\n\t\t\t\t//Report errors only when error_step is 0, and this is not a\r\n\t\t\t\t//subsequent error from a previous parse\r\n\t\t\t\tif(PCB.error_step === 0){\r\n\t\t\t\t\terr_cnt++;\r\n\t\t\t\t\terr_off.unshift(PCB.offset - PCB.att.length);\r\n\t\t\t\t\terr_la.unshift([]);\r\n\t\t\t\t\tfor(i = 0; i < act_tab[sstack[0]].length; i+=2)\r\n\t\t\t\t\t\terr_la[0].push(labels[act_tab[sstack[0]][i]]);\r\n\t\t\t\t}\r\n\t\t\t\t//Perform error recovery\t\t\t\r\n\t\t\t\twhile(sstack.length > 1 && PCB.act === null){\r\n\t\t\t\t\tsstack.shift();\r\n\t\t\t\t\tvstack.shift();\r\n\t\t\t\t\t//Try to shift on error token\r\n\t\t\t\t\tPCB.act = get_act(sstack[0],PCB.la);\r\n\t\t\t\t\tif(PCB.act === error_token){\r\n\t\t\t\t\t\tsstack.unshift(PCB.act);\r\n\t\t\t\t\t\tvstack.unshift("");\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t//Is it better to leave the parser now?\r\n\t\t\t\tif(sstack.length > 1 && PCB.act !== null){\r\n\t\t\t\t\t//Ok, now try to shift on the next tokens\r\n\t\t\t\t\twhile(PCB.la !== eof){\r\n\t\t\t\t\t\tPCB.act = act_tab[sstack[0]][i+1];\r\n\t\t\t\t\t\tif(PCB.act != null)break;\r\n\t\t\t\t\t\twhile(PCB.lex() != null)PCB.offset++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif(PCB.act === null || PCB.la === eof){\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t//Try to parse the next three tokens successfully...\r\n\t\t\t\tPCB.error_step = 3;\r\n\t\t\t}\r\n\t\t\tif(PCB.act > 0){//Shift\r\n\t\t\t\t//Parse tree generation\r\n\t\t\t\tsstack.unshift(PCB.act);\r\n\t\t\t\tvstack.unshift(PCB.att);\r\n\t\t\t\tPCB.lex();\r\n\t\t\t\t//Successfull shift and right beyond error recovery?\r\n\t\t\t\tif(PCB.error_step > 0)\r\n\t\t\t\t\tPCB.error_step--;\r\n\t\t\t}else{\t//Reduce\t\r\n\t\t\t\tact = -PCB.act;\r\n\t\t\t\t//vstack.unshift(vstack);\r\n\t\t\t\trval = ACTIONS(act,vstack,PCB);\r\n\t\t\t\t//vstack.shift();\r\n\t\t\t\tsstack.splice(0,pop_tab[act][1]);\r\n\t\t\t\tvstack.splice(0,pop_tab[act][1]);\r\n\t\t\t\t\r\n\t\t\t\tPCB.act = get_goto(sstack[0],pop_tab[act][0]);\r\n\t\t\t\t//Do some parse tree construction if desired\r\n\t\t\t\t//Goal symbol match?\r\n\t\t\t\tif(act === 0) break; //Don\'t use PCB.act here!\r\n\t\t\t\r\n\t\t\t\t//...and push it!\r\n\t\t\t\tsstack.unshift(PCB.act);\r\n\t\t\t\tvstack.unshift(rval);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn err_cnt;\r\n\t}\r\n\treturn parse;\r\n})(##EOF##,##WHITESPACE##,##ERROR_TOKEN##);\r\n\r\n##FOOTER##\r\n';}); /* * Universal module definition for a bitset implementation backed by * integer bitmasks. */ (function(root, factory) { /* istanbul ignore next */ if (typeof define === 'function' && define.amd) { define('lib/jscc/bitset/BitSet32',factory); } else if (typeof module === 'object' && module.exports) { module.exports = factory(); } else { root.jsccbitset = factory(); } }(this, function() { /** * Creates a new BitSet32 object. * @classdesc A bitset implementation backed by integer bitmasks. * @implements {jscc.bitset} * @constructor */ jscc.BitSet32 = function() { var that = this; /** * @private * @type {!Array<number>} */ this._data = []; /** * @inheritDoc * @param {!number} bit * @param {boolean=} state * @returns {!boolean} */ this.set = function(bit, state) { state = !!state; that._data[bit >> 5] = (state ? (that._data[bit >> 5] | (1 << (bit & 31))) : (that._data[bit >> 5] & ~(1 << (bit & 31)))); return state; }; /** * @inheritDoc * @param {!number} bit * @returns {!boolean} */ this.get = function(bit) { return ((that._data[bit >> 5] & (1 << (bit & 31))) != 0); }; /** * @inheritDoc * @returns {!number} */ this.count = function() { var i, l, c = 0; for (i = 0, l = that._data.length * 32; i < l; i++) { if (that.get(i)) { c++; } } return c; }; }; /** * Module containing BitSet32 implementation. Returns a factory * function to make Closure slightly happier elsewhere. * @module {function(new:jscc.BitSet32)} jscc/bitset/BitSet32 */ return jscc.BitSet32; })); (function(root, factory) { /* istanbul ignore next */ if (typeof define === 'function' && define.amd) { define('lib/jscc/enums/EDGE',factory); } else if (typeof module === 'object' && module.exports) { module.exports = factory(); } else { root.jsccEDGE = factory(); } }(this, function() { /** * Module containing EDGE enumeration. * @module jscc/enums/EDGE */ return jscc.enums.EDGE; })); /* * Universal module definition for module containing the Nfa class. */ (function(root, factory) { /* istanbul ignore next */ if (typeof define === 'function' && define.amd) { define('lib/jscc/classes/Nfa',['require', '../enums/EDGE', '../bitset'], factory); } else if (typeof module === 'object' && module.exports) { module.exports = factory(require); } else { root.jsccNfa = factory(function(mod) { return root["jscc" + mod.split("/").pop()]; }); } }(this, /** * @param {reqParameter} require * @param {...*} others * @returns {function(new:jscc.classes.Nfa, NfaOptions=)} */ function(require, others) { var BitSet, tmpBitSet, EDGE = require("../enums/EDGE"); /** * @suppress {uselessCode} */ (function() { if (false) { tmpBitSet = require("../bitset/BitSet32"); } else { tmpBitSet = require("../bitset"); } })(); BitSet = /** @type {function(new:jscc.bitset)} */ (tmpBitSet); /** * Creates a new Nfa instance. * @classdesc Represents a state in a nondeterministic finite automata. * @param {NfaOptions=} o - Optional overrides for default property values. * @constructor * @const */ jscc.classes.Nfa = function(o) { var p = o || {}; if (p.edge === EDGE.CHAR || p.edge === EDGE.FREE) { this.edge = /** @type {!jscc.enums.EDGE} */ (p.edge); } if (typeof p.ccl === 'object' && p.ccl.hasOwnProperty("get") && p.ccl.hasOwnProperty("set") && p.ccl.hasOwnProperty("count")) { this.ccl = /** @type {!jscc.bitset} */ (p.ccl); } else { this.ccl = new BitSet(); } if (typeof p.follow === 'number') { this.follow = /** @type {!number} */ (p.follow); } if (typeof p.follow2 === 'number') { this.follow2 = /** @type {!number} */ (p.follow2); } if (typeof p.accept === 'number') { this.accept = /** @type {!number} */ (p.accept); } if (typeof p.weight === 'number') { this.weight = /** @type {!number} */ (p.weight); } }; /** * The type of edge in this NFA state. * @type {!jscc.enums.EDGE} */ jscc.classes.Nfa.prototype.edge = EDGE.EPSILON; /** * The bitset for this NFA state. * @type {!jscc.bitset} */ jscc.classes.Nfa.prototype.ccl = new BitSet(); /** * Index of an immediately-following state. * @type {!number} */ jscc.classes.Nfa.prototype.follow = -1; /** * Index of a second following state. * @type {!number} */ jscc.classes.Nfa.prototype.follow2 = -1; /** * Index of an accepting state. * @type {!number} */ jscc.classes.Nfa.prototype.accept = -1; /** * The weight of this particular state. * @type {!number} */ jscc.classes.Nfa.prototype.weight = -1; /** * The module containing the Nfa class. * @module jscc/classes/Nfa */ return jscc.classes.Nfa; })); /* * Universal module definition for NFAStates (previously in global.js). */ (function(root, factory) { /* istanbul ignore next */ if (typeof define === 'function' && define.amd) { define('lib/jscc/nfaStates',['require', './bitset', './enums/EDGE', './classes/Nfa'], factory); } else if (typeof module === 'object' && module.exports) { module.exports = factory(require); } else { root.jsccnfaStates = factory(function(mod) { return root["jscc" + mod.split("/").pop()]; }); } }(this, /** * @param {reqParameter} require * @param {...*} others * @returns {function(new:jscc.NFAStates)} */ function(require, others) { var BitSet, tmpBitSet, EDGE = require("./enums/EDGE"), Nfa = /** @type {function(new:jscc.classes.Nfa, ?NfaOptions=)} */ (require("./classes/Nfa")); /** * @suppress {uselessCode} */ (function() { if (false) { tmpBitSet = r