UNPKG

bungee

Version:

Bungee is a declarative language engine to run inside a browser. The node module contains the offline compiler.

1,296 lines (1,095 loc) 152 kB
;(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){ 'use strict'; var Bungee = require('./index.js'); },{"./index.js":2}],2:[function(require,module,exports){ /* ************************************************** * Bungee.js * * (c) 2012-2013 Johannes Zellner * * Bungee may be freely distributed under the MIT license. * For all details and documentation: * http://bungeejs.org ************************************************** */ "use strict"; var fs = require('fs'); module.exports = (function () { var ret = {}; ret.tokenizer = require('./src/tokenizer.js'); ret.compiler = require('./src/compiler.js'); ret.compileFile = function(file, options, callback) { fs.readFile(file, 'utf8', function (error, data) { if (error) { callback(error); } else { ret.compile(data, options, callback); } }); }; ret.compile = function(source, options, callback) { var tokens = ret.tokenizer.parse(source); // console.log("$$$$", tokens); ret.compiler.compileAndRender(tokens, options, function (error, result) { callback(error, result); }); }; return ret; }()); },{"fs":3,"./src/tokenizer.js":4,"./src/compiler.js":5}],5:[function(require,module,exports){ (function(){/* ************************************************** * Bungee.js * * (c) 2012-2013 Johannes Zellner * * Bungee may be freely distributed under the MIT license. * For all details and documentation: * http://bungeejs.org ************************************************** */ "use strict"; /* ************************************************** * Compiler ************************************************** */ if (!Bungee) { var Bungee = {}; } var compiler = (function () { // public compiler properties var compiler = {}; // TODO sort out this kindof global variable mess var ELEM_PREFIX = "e"; // just a define var ELEM_NS = "Bungee."; // main namespace var output; // output buffer used by all render functions var index; // index used for tracking the indentation var errorCodes = { GENERIC: 0, UNKNOWN_ELEMENT: 1, NO_PROPERTY: 2, NO_ELEMENTTYPE: 3, NO_TYPENAME: 4, NO_EXPRESSION: 5, NO_COLON: 6, INVALID_PROPERTY_NAME: 7, UNEXPECTED_END: 8 }; // make error codes public compiler.errorCodes = errorCodes; var errorMessages = []; errorMessages[errorCodes.GENERIC] = "generic error"; errorMessages[errorCodes.UNKNOWN_ELEMENT] = "Cannot create element."; errorMessages[errorCodes.NO_PROPERTY] = "No property to assing expression."; errorMessages[errorCodes.NO_ELEMENTTYPE] = "No type to create an element."; errorMessages[errorCodes.NO_TYPENAME] = "No typename for the new type definition."; errorMessages[errorCodes.NO_COLON] = "Property must be followed by a ':'."; errorMessages[errorCodes.NO_EXPRESSION] = "No right-hand-side expression or element found."; errorMessages[errorCodes.INVALID_PROPERTY_NAME] = "Invalid property name found."; errorMessages[errorCodes.UNEXPECTED_END] = "Unexpected end of input."; function error(code, token) { var ret = {}; ret.code = code; ret.context = token ? token.CONTEXT : undefined; ret.message = errorMessages[code]; ret.line = token ? token.LINE : -1; return ret; } function log(msg) { if (Bungee.verbose) { console.log(msg); } } function isNumeric (c) { return (c >= '0' && c <= '9'); } /* * adds current indentation to compiler output */ function addIndentation(additional) { var indentLevel = index + (additional ? additional : 0); var i; for (i = indentLevel; i; --i) { output += " "; } } /* * Renders the head of the javascript output * Only called once */ function renderBegin(options) { if (Bungee.debug) { addIndentation(1); output += "debugger;\n"; } output += "if (!window.Bungee) {\n"; output += " window.Bungee = {};\n"; output += "}\n\n"; if (options.module) { output += "window.Bungee.Modules." + options.module + " = function () {\n"; } else { output += "(function() {\n"; } addIndentation(); output += "'use strict';\n\n"; // add pseudo parent addIndentation(); output += "var " + ELEM_PREFIX + " = { \n"; addIndentation(1); output += "children: [],\n"; addIndentation(1); output += "addChild: function(child) {\n"; addIndentation(2); output += "this[child.id] = child;\n"; addIndentation(2); output += "for (var i in this.children) {\n"; addIndentation(2); output += " if (this.children.hasOwnProperty(i)) {\n"; addIndentation(2); output += " this.children[i][child.id] = child;\n"; addIndentation(2); output += " child[this.children[i].id] = this.children[i];\n"; addIndentation(2); output += " }\n"; addIndentation(2); output += "}\n"; addIndentation(2); output += ELEM_PREFIX + ".children.push(child);\n"; addIndentation(2); output += "Bungee.Engine.addElement(child);\n"; addIndentation(2); output += "return child;\n"; addIndentation(1); output += "},\n"; addIndentation(1); output += "initializeBindings: function() {\n"; addIndentation(2); output += "for (var i = 0; i < " + ELEM_PREFIX + ".children.length; ++i) { " + ELEM_PREFIX + ".children[i].initializeBindings(); }\n"; addIndentation(1); output += "},\n"; addIndentation(1); output += "render: function() {\n"; addIndentation(2); output += "for (var i = 0; i < " + ELEM_PREFIX + ".children.length; ++i) { " + ELEM_PREFIX + ".children[i].render(); }\n"; addIndentation(1); output += "}\n"; addIndentation(); output += "};\n\n"; } /* * Render the end of the javascript output * Only called once */ function renderEnd(options) { addIndentation(); output += ELEM_PREFIX + ".initializeBindings();\n"; addIndentation(); output += ELEM_PREFIX + ".render();\n"; if (options.module) { addIndentation(); output += "return " + ELEM_PREFIX + ";\n"; output += "};\n"; } else { output += "})();\n"; } } /* * Renders the start of a new Element instance * Called for each element instantiation in jump */ function renderBeginElement(type, id) { addIndentation(); output += ELEM_PREFIX + ".addChild((function() {\n"; ++index; addIndentation(); output += "var " + ELEM_PREFIX + " = new " + ELEM_NS + type + "("; output += id ? "\"" + id + "\"" : ""; output += ");\n"; } /* * Renders the end of a new Element instance * Called for each element instantiation in jump */ function renderEndElement() { addIndentation(); output += "return " + ELEM_PREFIX + ";\n"; --index; addIndentation(); output += "})());\n"; } /* * Renders the start of a new Type definition * Called for each type in jump */ function renderBeginType(type, inheritedType) { addIndentation(); output += ELEM_NS + type + " = function (id, parent) {\n"; ++index; addIndentation(); output += "var " + ELEM_PREFIX + " = new " + ELEM_NS + inheritedType + "(id, parent);\n"; } /* * Renders the end of a new Type definition * Called for each type in jump */ function renderEndType() { addIndentation(); output += "return " + ELEM_PREFIX + ";\n"; --index; addIndentation(); output += "};\n"; } /* * Renders an event handler for the current element/type in scope * Event handlers will be generated whenever a property name * begins with 'on' like 'onmousedown' */ function renderEventHandler(property, value) { addIndentation(); output += ELEM_PREFIX + ".addEventHandler(\"" + property + "\", "; output += "function () {\n"; addIndentation(); output += value + "\n"; addIndentation(); output += "});\n"; } /* * Renders a function for the current element/type in scope * Functions will be generated whenever a property name * contains a '(', a preceeding 'function ' is not necessary * and will be stripped */ function renderFunction(property, value) { var name = property.slice(property.indexOf(' ') + 1, property.indexOf('(')); var args = property.slice(property.indexOf('(') + 1, -1); addIndentation(); output += ELEM_PREFIX + ".addFunction(\"" + name + "\", "; output += "function (" + args + ") {\n"; addIndentation(); output += value + "\n"; addIndentation(); output += "});\n"; } /* * Renders a property for the current element/type in scope */ function renderProperty(property, value) { // special case for ID if (property === "id") { return; } if (property.indexOf('on') === 0) { renderEventHandler(property, value); return; } if (property.indexOf('(') !== -1) { renderFunction(property, value); return; } addIndentation(); output += ELEM_PREFIX + ".addProperty(\"" + property + "\", "; output += "function () {"; if (String(value).indexOf("return") !== -1) { output += value + " "; } else { output += "return " + value + ";"; } output += "});\n"; } /* * Renders a delegate for the current element/type in scope */ function renderDelegate(property, value) { addIndentation(); output += ELEM_PREFIX + ".create" + property + " = function () {\n"; addIndentation(1); output += "return new " + ELEM_NS + value + "();\n"; addIndentation(); output += "}\n"; } /* * Takes a TreeObject, containing either a Type or an Element * and runs over the object's properties, types and children * this is called recoursively */ function renderTreeObject(tree) { var i; if (tree.typeDefinition) { renderBeginType(tree.typeDefinition, tree.type); } else { renderBeginElement(tree.type, tree.id); } for (i = 0; i < tree.properties.length; ++i) { renderProperty(tree.properties[i].name, tree.properties[i].value); } for (i = 0; i < tree.delegates.length; ++i) { renderDelegate(tree.delegates[i].name, tree.delegates[i].value); } for (i = 0; i < tree.types.length; ++i) { renderTreeObject(tree.types[i]); } for (i = 0; i < tree.elements.length; ++i) { renderTreeObject(tree.elements[i]); } if (tree.typeDefinition) { renderEndType(); } else { renderEndElement(); } } /* * Starting point of the renderer * Takes a TreeObject tree to render * The first tree object is root and needs special treatment */ compiler.renderTree = function (tree, options, callback) { var i; index = 1; output = ""; renderBegin(options); for (i = 0; i < tree.types.length; ++i) { renderTreeObject(tree.types[i]); } for (i = 0; i < tree.elements.length; ++i) { renderTreeObject(tree.elements[i]); } renderEnd(options); callback(null, output); }; /* * Dump out the current object tree to the console */ function dumpObjectTree(tree, indent) { var i; if (indent === undefined) { indent = 0; } function niceLog(msg) { var j; var out = ""; for (j = 0; j < indent; ++j) { out += " "; } console.log(out + msg); } niceLog("+ Element:"); niceLog("|- type: " + tree.type); niceLog("|- type definition: " + tree.typeDefinition); niceLog("|+ Properties:"); for (i = 0; i < tree.properties.length; ++i) { niceLog("|--> " + tree.properties[i].name); } niceLog("|+ Delegates:"); for (i = 0; i < tree.delegates.length; ++i) { niceLog("|--> " + tree.delegates[i].name + " : " + tree.delegates[i].value); } if (tree.types.length) { niceLog("|+ Types:"); for (i = 0; i < tree.types.length; ++i) { dumpObjectTree(tree.types[i], indent + 2); } } if (tree.elements.length) { niceLog("|+ Elements: "); for (i = 0; i < tree.elements.length; ++i) { dumpObjectTree(tree.elements[i], indent + 2); } } } /* * Take all tokens and compile it to a object tree, which can be rendered */ compiler.createObjectTree = function (tok, options, callback) { var property; var tokens = tok; var token_length = tokens.length; var elementType; var elementTypeDefinition; var i, j; // TreeObject is a helper to pass information to the renderer var TreeObject = function (parent) { this.id = undefined; this.type = undefined; this.typeDefinition = undefined; this.parent = parent; this.types = []; this.elements = []; this.properties = []; this.delegates = []; }; var objectTreeRoot = new TreeObject(); objectTreeRoot.type = "RootObject"; var objectTree = objectTreeRoot; for (i = 0; i < token_length; i += 1) { var token = tokens[i]; if (token.TOKEN === "IS_A") { if (elementType) { elementTypeDefinition = elementType; elementType = undefined; } else { callback(error(errorCodes.NO_TYPENAME, token), null); return; } } if (token.TOKEN === "ELEMENT") { elementType = token.DATA; } if (token.TOKEN === "SCOPE_START") { log("start element description"); // only if elementType was found previously if (elementType) { // we found a element definition, so add one to create an element instance var tmp = new TreeObject(objectTree); tmp.type = elementType; // check if we have a type definition or an element if (elementTypeDefinition) { tmp.typeDefinition = elementTypeDefinition; objectTree.types.push(tmp); } else { objectTree.elements.push(tmp); } objectTree = tmp; elementType = undefined; elementTypeDefinition = undefined; } else { callback(error(errorCodes.NO_ELEMENTTYPE, token), null); } } if (token.TOKEN === "SCOPE_END") { log("end element description"); // scope end, so reset the objectTree pointer objectTree = objectTree.parent; } if (token.TOKEN === "EXPRESSION") { // next token must be COLON var next_token = (i + 1 < token_length) ? tokens[i + 1] : undefined; if (next_token && next_token.TOKEN === "COLON") { property = token.DATA; log("property found '" + property + "'"); // check for valid property names if (isNumeric(property[0])) { log("property name '" + property + "' is invalid."); callback(error(errorCodes.INVALID_PROPERTY_NAME, token), null); return; } i += 1; next_token = undefined; } else { callback(error(errorCodes.NO_COLON, token), null); return; } // next token must be EXPRESSION or ELEMENT next_token = (i + 1 < token_length) ? tokens[i + 1] : undefined; if (next_token && next_token.TOKEN === "EXPRESSION") { log("right-hand-side expression found for property '" + property + "' '" + next_token.DATA + "'"); // special treatment for element IDs they are no real properties if (property === "id") { objectTree.id = next_token.DATA; } else { objectTree.properties.push({name: property, value: next_token.DATA}); } i += 1; property = undefined; } else if (next_token && next_token.TOKEN === "ELEMENT") { log("right-hand-side element found for property", property, next_token.DATA); objectTree.delegates.push({name: property, value: next_token.DATA}); i += 1; property = undefined; } else { callback(error(errorCodes.NO_EXPRESSION, next_token), null); return; } } } if (objectTree !== objectTreeRoot) { callback(error(errorCodes.UNEXPECTED_END, null), null); return; } callback(null, objectTreeRoot); }; /* * Take all tokens, compile it to a object tree and render it * options: * - 'dump' dump object tree */ compiler.compileAndRender = function (tok, options, callback) { compiler.createObjectTree(tok, options, function (error, result) { if (error) { callback(error, null); return; } if (options.dump) { dumpObjectTree(result); } compiler.renderTree(result, options, callback); }); }; return compiler; }()); // TODO is this the proper check? if (typeof window === 'undefined') { module.exports = compiler; } else { window.Bungee.Compiler = compiler; } })() },{}],3:[function(require,module,exports){ // nothing to see here... no file methods for the browser },{}],4:[function(require,module,exports){ /* ************************************************** * Bungee.js * * (c) 2012-2013 Johannes Zellner * * Bungee may be freely distributed under the MIT license. * For all details and documentation: * http://bungeejs.org ************************************************** */ "use strict"; /* ************************************************** * Tokenizer ************************************************** */ if (!Bungee) { var Bungee = {}; } var tokenizer = (function () { var c, i, line, tokens, bindings, exp, colonOnLine, comment, lineContext; var ret = {}; function log (msg) { if (Bungee.verbose) { console.log(msg); } } // add a found token to the token table function addToken (type, data) { tokens.push( {"TOKEN" : type, "DATA" : data, "LINE" : line, "CONTEXT" : lineContext} ); } // extract an element name function parseElementName () { var token = ""; while (c) { if (c === '\n') { i -= 1; break; } if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c === '_' || c === '-') token += c; else break; advance(); } // strip trailing ';' if (token[token.length-1] === ';') { token = token.substring(0, token.length-1); } return token; } // extract an expression, can be a property definition, function or right side expression after : function parseExpression () { var expression = ""; while (c) { if (c === '\n') { i -= 1; break; } // only break if this is the first colon in that line if (!colonOnLine && c === ':') { i -= 1; break; } // ignore whitespace // if ((c !== '\t' && c !== ' ') || expression === "function") expression += c; advance(); } // strip trailing ';' if (expression[expression.length-1] === ';') { expression = expression.substring(0, expression.length-1); } return expression; } function parseInlineBlock () { var block = ''; var script; while (c) { block += c; if (c === '}') { try { script = Bungee.esprima.parse(block, { tolerant: true}); break; } catch (e) { // block statement parsing failed, force esprima to check for object notation var tmp = "var a = " + block; try { script = Bungee.esprima.parse(tmp, { tolerant: true}); break; } catch (e) { } } } if (c === '\n') { ++line; } advance(); } // if we have a block statement, this means we need to trim the // prepending and trailing curly brackets if (script && script.body && script.body[0] && script.body[0].type === "BlockStatement") { // TODO this looks a bit messy and error prone block = block.trim(); if (block[0] === '{') { block = block.slice(1); } if (block[block.length-1] === '}') { block = block.slice(0, block.length-1); } } return block; } // Convenience function to advance the current tokenizer character function advance () { c = exp[++i]; return (c); } /* * Parse the input string and create tokens */ ret.parse = function (input) { exp = input; i = -1; line = 1; lineContext = ""; tokens = []; c = undefined;//exp[i]; bindings = []; colonOnLine = false; comment = false; while (advance()) { if (comment && c !== '\n') continue; // check for one line comments if (c === '/' && exp[i+1] === '/') { comment = true; continue; } if (c === '\n') { comment = false; colonOnLine = false; ++line; lineContext = ""; // add next line so we have a error context to print var j = i; var tmpChar = exp[++j]; while(tmpChar) { if (tmpChar === '\n') { break; } lineContext += tmpChar; tmpChar = exp[++j]; } continue; } // check for element name if (c >= 'A' && c <= 'Z') { addToken("ELEMENT", parseElementName()); continue; } if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c === '"' || c === '\'' || c === '(' || c === '-' || c === '_' || c === '[') { addToken("EXPRESSION", parseExpression()); continue; } if (c === '{' && tokens[tokens.length-1].TOKEN === "ELEMENT") { addToken("SCOPE_START"); continue; } if (c === '{') { addToken("EXPRESSION", parseInlineBlock()); continue; } if (c === '}') { addToken("SCOPE_END"); continue; } if (c === ':') { colonOnLine = true; addToken("COLON"); continue; } if (c === '@') { addToken("IS_A"); continue; } if (c === ';') { colonOnLine = false; addToken("SEMICOLON"); continue; } } if (Bungee.verbose) { ret.dumpTokens(); } return tokens; }; /* * Print all found tokens on the console */ ret.dumpTokens = function () { for (var i = 0; i < tokens.length; ++i) console.log("TOKEN: " + tokens[i].TOKEN + " " + (tokens[i].DATA ? tokens[i].DATA : "")); }; return ret; }()); // TODO is this the proper check? if (typeof window === 'undefined') { Bungee.esprima = require("esprima"); module.exports = tokenizer; } else { window.Bungee.Tokenizer = tokenizer; } },{"esprima":6}],6:[function(require,module,exports){ (function(){/* Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com> Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be> Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl> Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com> Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com> Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com> Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com> Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /*jslint bitwise:true plusplus:true */ /*global esprima:true, define:true, exports:true, window: true, throwError: true, createLiteral: true, generateStatement: true, parseAssignmentExpression: true, parseBlock: true, parseExpression: true, parseFunctionDeclaration: true, parseFunctionExpression: true, parseFunctionSourceElements: true, parseVariableIdentifier: true, parseLeftHandSideExpression: true, parseStatement: true, parseSourceElement: true */ (function (root, factory) { 'use strict'; // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, // Rhino, and plain browser loading. if (typeof define === 'function' && define.amd) { define(['exports'], factory); } else if (typeof exports !== 'undefined') { factory(exports); } else { factory((root.esprima = {})); } }(this, function (exports) { 'use strict'; var Token, TokenName, Syntax, PropertyKind, Messages, Regex, source, strict, index, lineNumber, lineStart, length, buffer, state, extra; Token = { BooleanLiteral: 1, EOF: 2, Identifier: 3, Keyword: 4, NullLiteral: 5, NumericLiteral: 6, Punctuator: 7, StringLiteral: 8 }; TokenName = {}; TokenName[Token.BooleanLiteral] = 'Boolean'; TokenName[Token.EOF] = '<end>'; TokenName[Token.Identifier] = 'Identifier'; TokenName[Token.Keyword] = 'Keyword'; TokenName[Token.NullLiteral] = 'Null'; TokenName[Token.NumericLiteral] = 'Numeric'; TokenName[Token.Punctuator] = 'Punctuator'; TokenName[Token.StringLiteral] = 'String'; Syntax = { AssignmentExpression: 'AssignmentExpression', ArrayExpression: 'ArrayExpression', BlockStatement: 'BlockStatement', BinaryExpression: 'BinaryExpression', BreakStatement: 'BreakStatement', CallExpression: 'CallExpression', CatchClause: 'CatchClause', ConditionalExpression: 'ConditionalExpression', ContinueStatement: 'ContinueStatement', DoWhileStatement: 'DoWhileStatement', DebuggerStatement: 'DebuggerStatement', EmptyStatement: 'EmptyStatement', ExpressionStatement: 'ExpressionStatement', ForStatement: 'ForStatement', ForInStatement: 'ForInStatement', FunctionDeclaration: 'FunctionDeclaration', FunctionExpression: 'FunctionExpression', Identifier: 'Identifier', IfStatement: 'IfStatement', Literal: 'Literal', LabeledStatement: 'LabeledStatement', LogicalExpression: 'LogicalExpression', MemberExpression: 'MemberExpression', NewExpression: 'NewExpression', ObjectExpression: 'ObjectExpression', Program: 'Program', Property: 'Property', ReturnStatement: 'ReturnStatement', SequenceExpression: 'SequenceExpression', SwitchStatement: 'SwitchStatement', SwitchCase: 'SwitchCase', ThisExpression: 'ThisExpression', ThrowStatement: 'ThrowStatement', TryStatement: 'TryStatement', UnaryExpression: 'UnaryExpression', UpdateExpression: 'UpdateExpression', VariableDeclaration: 'VariableDeclaration', VariableDeclarator: 'VariableDeclarator', WhileStatement: 'WhileStatement', WithStatement: 'WithStatement' }; PropertyKind = { Data: 1, Get: 2, Set: 4 }; // Error messages should be identical to V8. Messages = { UnexpectedToken: 'Unexpected token %0', UnexpectedNumber: 'Unexpected number', UnexpectedString: 'Unexpected string', UnexpectedIdentifier: 'Unexpected identifier', UnexpectedReserved: 'Unexpected reserved word', UnexpectedEOS: 'Unexpected end of input', NewlineAfterThrow: 'Illegal newline after throw', InvalidRegExp: 'Invalid regular expression', UnterminatedRegExp: 'Invalid regular expression: missing /', InvalidLHSInAssignment: 'Invalid left-hand side in assignment', InvalidLHSInForIn: 'Invalid left-hand side in for-in', MultipleDefaultsInSwitch: 'More than one default clause in switch statement', NoCatchOrFinally: 'Missing catch or finally after try', UnknownLabel: 'Undefined label \'%0\'', Redeclaration: '%0 \'%1\' has already been declared', IllegalContinue: 'Illegal continue statement', IllegalBreak: 'Illegal break statement', IllegalReturn: 'Illegal return statement', StrictModeWith: 'Strict mode code may not include a with statement', StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', StrictVarName: 'Variable name may not be eval or arguments in strict mode', StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', StrictParamDupe: 'Strict mode function may not have duplicate parameter names', StrictFunctionName: 'Function name may not be eval or arguments in strict mode', StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', StrictDelete: 'Delete of an unqualified identifier in strict mode.', StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', StrictReservedWord: 'Use of future reserved word in strict mode' }; // See also tools/generate-unicode-regex.py. Regex = { NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') }; // Ensure the condition is true, otherwise throw an error. // This is only to have a better contract semantic, i.e. another safety net // to catch a logic error. The condition shall be fulfilled in normal case. // Do NOT use this to enforce a certain condition on any user input. function assert(condition, message) { if (!condition) { throw new Error('ASSERT: ' + message); } } function sliceSource(from, to) { return source.slice(from, to); } if (typeof 'esprima'[0] === 'undefined') { sliceSource = function sliceArraySource(from, to) { return source.slice(from, to).join(''); }; } function isDecimalDigit(ch) { return '0123456789'.indexOf(ch) >= 0; } function isHexDigit(ch) { return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; } function isOctalDigit(ch) { return '01234567'.indexOf(ch) >= 0; } // 7.2 White Space function isWhiteSpace(ch) { return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') || (ch === '\u000C') || (ch === '\u00A0') || (ch.charCodeAt(0) >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0); } // 7.3 Line Terminators function isLineTerminator(ch) { return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029'); } // 7.6 Identifier Names and Identifiers function isIdentifierStart(ch) { return (ch === '$') || (ch === '_') || (ch === '\\') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch)); } function isIdentifierPart(ch) { return (ch === '$') || (ch === '_') || (ch === '\\') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ((ch >= '0') && (ch <= '9')) || ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch)); } // 7.6.1.2 Future Reserved Words function isFutureReservedWord(id) { switch (id) { // Future reserved words. case 'class': case 'enum': case 'export': case 'extends': case 'import': case 'super': return true; } return false; } function isStrictModeReservedWord(id) { switch (id) { // Strict Mode reserved words. case 'implements': case 'interface': case 'package': case 'private': case 'protected': case 'public': case 'static': case 'yield': case 'let': return true; } return false; } function isRestrictedWord(id) { return id === 'eval' || id === 'arguments'; } // 7.6.1.1 Keywords function isKeyword(id) { var keyword = false; switch (id.length) { case 2: keyword = (id === 'if') || (id === 'in') || (id === 'do'); break; case 3: keyword = (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try'); break; case 4: keyword = (id === 'this') || (id === 'else') || (id === 'case') || (id === 'void') || (id === 'with'); break; case 5: keyword = (id === 'while') || (id === 'break') || (id === 'catch') || (id === 'throw'); break; case 6: keyword = (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch'); break; case 7: keyword = (id === 'default') || (id === 'finally'); break; case 8: keyword = (id === 'function') || (id === 'continue') || (id === 'debugger'); break; case 10: keyword = (id === 'instanceof'); break; } if (keyword) { return true; } switch (id) { // Future reserved words. // 'const' is specialized as Keyword in V8. case 'const': return true; // For compatiblity to SpiderMonkey and ES.next case 'yield': case 'let': return true; } if (strict && isStrictModeReservedWord(id)) { return true; } return isFutureReservedWord(id); } // 7.4 Comments function skipComment() { var ch, blockComment, lineComment; blockComment = false; lineComment = false; while (index < length) { ch = source[index]; if (lineComment) { ch = source[index++]; if (isLineTerminator(ch)) { lineComment = false; if (ch === '\r' && source[index] === '\n') { ++index; } ++lineNumber; lineStart = index; } } else if (blockComment) { if (isLineTerminator(ch)) { if (ch === '\r' && source[index + 1] === '\n') { ++index; } ++lineNumber; ++index; lineStart = index; if (index >= length) { throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); } } else { ch = source[index++]; if (index >= length) { throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); } if (ch === '*') { ch = source[index]; if (ch === '/') { ++index; blockComment = false; } } } } else if (ch === '/') {