2 Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
3 Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
4 Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
5 Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
6 Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
7 Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
8 Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are met:
13 * Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 /*jslint bitwise:true plusplus:true */
32 /*global esprima:true, define:true, exports:true, window: true,
33 throwError: true, createLiteral: true, generateStatement: true,
34 parseAssignmentExpression: true, parseBlock: true, parseExpression: true,
35 parseFunctionDeclaration: true, parseFunctionExpression: true,
36 parseFunctionSourceElements: true, parseVariableIdentifier: true,
37 parseLeftHandSideExpression: true,
38 parseStatement: true, parseSourceElement: true */
40 (function (root, factory) {
43 // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
44 // Rhino, and plain browser loading.
45 if (typeof define === 'function' && define.amd) {
46 define(['exports'], factory);
47 } else if (typeof exports !== 'undefined') {
50 factory((root.esprima = {}));
52 }(this, function (exports) {
83 TokenName[Token.BooleanLiteral] = 'Boolean';
84 TokenName[Token.EOF] = '<end>';
85 TokenName[Token.Identifier] = 'Identifier';
86 TokenName[Token.Keyword] = 'Keyword';
87 TokenName[Token.NullLiteral] = 'Null';
88 TokenName[Token.NumericLiteral] = 'Numeric';
89 TokenName[Token.Punctuator] = 'Punctuator';
90 TokenName[Token.StringLiteral] = 'String';
93 AssignmentExpression: 'AssignmentExpression',
94 ArrayExpression: 'ArrayExpression',
95 BlockStatement: 'BlockStatement',
96 BinaryExpression: 'BinaryExpression',
97 BreakStatement: 'BreakStatement',
98 CallExpression: 'CallExpression',
99 CatchClause: 'CatchClause',
100 ConditionalExpression: 'ConditionalExpression',
101 ContinueStatement: 'ContinueStatement',
102 DoWhileStatement: 'DoWhileStatement',
103 DebuggerStatement: 'DebuggerStatement',
104 EmptyStatement: 'EmptyStatement',
105 ExpressionStatement: 'ExpressionStatement',
106 ForStatement: 'ForStatement',
107 ForInStatement: 'ForInStatement',
108 FunctionDeclaration: 'FunctionDeclaration',
109 FunctionExpression: 'FunctionExpression',
110 Identifier: 'Identifier',
111 IfStatement: 'IfStatement',
113 LabeledStatement: 'LabeledStatement',
114 LogicalExpression: 'LogicalExpression',
115 MemberExpression: 'MemberExpression',
116 NewExpression: 'NewExpression',
117 ObjectExpression: 'ObjectExpression',
119 Property: 'Property',
120 ReturnStatement: 'ReturnStatement',
121 SequenceExpression: 'SequenceExpression',
122 SwitchStatement: 'SwitchStatement',
123 SwitchCase: 'SwitchCase',
124 ThisExpression: 'ThisExpression',
125 ThrowStatement: 'ThrowStatement',
126 TryStatement: 'TryStatement',
127 UnaryExpression: 'UnaryExpression',
128 UpdateExpression: 'UpdateExpression',
129 VariableDeclaration: 'VariableDeclaration',
130 VariableDeclarator: 'VariableDeclarator',
131 WhileStatement: 'WhileStatement',
132 WithStatement: 'WithStatement'
141 // Error messages should be identical to V8.
143 UnexpectedToken: 'Unexpected token %0',
144 UnexpectedNumber: 'Unexpected number',
145 UnexpectedString: 'Unexpected string',
146 UnexpectedIdentifier: 'Unexpected identifier',
147 UnexpectedReserved: 'Unexpected reserved word',
148 UnexpectedEOS: 'Unexpected end of input',
149 NewlineAfterThrow: 'Illegal newline after throw',
150 InvalidRegExp: 'Invalid regular expression',
151 UnterminatedRegExp: 'Invalid regular expression: missing /',
152 InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
153 InvalidLHSInForIn: 'Invalid left-hand side in for-in',
154 MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
155 NoCatchOrFinally: 'Missing catch or finally after try',
156 UnknownLabel: 'Undefined label \'%0\'',
157 Redeclaration: '%0 \'%1\' has already been declared',
158 IllegalContinue: 'Illegal continue statement',
159 IllegalBreak: 'Illegal break statement',
160 IllegalReturn: 'Illegal return statement',
161 StrictModeWith: 'Strict mode code may not include a with statement',
162 StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
163 StrictVarName: 'Variable name may not be eval or arguments in strict mode',
164 StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
165 StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
166 StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
167 StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
168 StrictDelete: 'Delete of an unqualified identifier in strict mode.',
169 StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
170 AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
171 AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
172 StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
173 StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
174 StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
175 StrictReservedWord: 'Use of future reserved word in strict mode'
178 // See also tools/generate-unicode-regex.py.
180 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]'),
181 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]')
184 // Ensure the condition is true, otherwise throw an error.
185 // This is only to have a better contract semantic, i.e. another safety net
186 // to catch a logic error. The condition shall be fulfilled in normal case.
187 // Do NOT use this to enforce a certain condition on any user input.
189 function assert(condition, message) {
191 throw new Error('ASSERT: ' + message);
195 function sliceSource(from, to) {
196 return source.slice(from, to);
199 if (typeof 'esprima'[0] === 'undefined') {
200 sliceSource = function sliceArraySource(from, to) {
201 return source.slice(from, to).join('');
205 function isDecimalDigit(ch) {
206 return '0123456789'.indexOf(ch) >= 0;
209 function isHexDigit(ch) {
210 return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
213 function isOctalDigit(ch) {
214 return '01234567'.indexOf(ch) >= 0;
220 function isWhiteSpace(ch) {
221 return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') ||
222 (ch === '\u000C') || (ch === '\u00A0') ||
223 (ch.charCodeAt(0) >= 0x1680 &&
224 '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0);
227 // 7.3 Line Terminators
229 function isLineTerminator(ch) {
230 return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029');
233 // 7.6 Identifier Names and Identifiers
235 function isIdentifierStart(ch) {
236 return (ch === '$') || (ch === '_') || (ch === '\\') ||
237 (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
238 ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch));
241 function isIdentifierPart(ch) {
242 return (ch === '$') || (ch === '_') || (ch === '\\') ||
243 (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
244 ((ch >= '0') && (ch <= '9')) ||
245 ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
248 // 7.6.1.2 Future Reserved Words
250 function isFutureReservedWord(id) {
253 // Future reserved words.
266 function isStrictModeReservedWord(id) {
269 // Strict Mode reserved words.
285 function isRestrictedWord(id) {
286 return id === 'eval' || id === 'arguments';
291 function isKeyword(id) {
295 keyword = (id === 'if') || (id === 'in') || (id === 'do');
298 keyword = (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try');
301 keyword = (id === 'this') || (id === 'else') || (id === 'case') || (id === 'void') || (id === 'with');
304 keyword = (id === 'while') || (id === 'break') || (id === 'catch') || (id === 'throw');
307 keyword = (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch');
310 keyword = (id === 'default') || (id === 'finally');
313 keyword = (id === 'function') || (id === 'continue') || (id === 'debugger');
316 keyword = (id === 'instanceof');
325 // Future reserved words.
326 // 'const' is specialized as Keyword in V8.
330 // For compatiblity to SpiderMonkey and ES.next
336 if (strict && isStrictModeReservedWord(id)) {
340 return isFutureReservedWord(id);
345 function skipComment() {
346 var ch, blockComment, lineComment;
348 blockComment = false;
351 while (index < length) {
355 ch = source[index++];
356 if (isLineTerminator(ch)) {
358 if (ch === '\r' && source[index] === '\n') {
364 } else if (blockComment) {
365 if (isLineTerminator(ch)) {
366 if (ch === '\r' && source[index + 1] === '\n') {
372 if (index >= length) {
373 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
376 ch = source[index++];
377 if (index >= length) {
378 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
384 blockComment = false;
388 } else if (ch === '/') {
389 ch = source[index + 1];
393 } else if (ch === '*') {
396 if (index >= length) {
397 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
402 } else if (isWhiteSpace(ch)) {
404 } else if (isLineTerminator(ch)) {
406 if (ch === '\r' && source[index] === '\n') {
417 function scanHexEscape(prefix) {
418 var i, len, ch, code = 0;
420 len = (prefix === 'u') ? 4 : 2;
421 for (i = 0; i < len; ++i) {
422 if (index < length && isHexDigit(source[index])) {
423 ch = source[index++];
424 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
429 return String.fromCharCode(code);
432 function scanIdentifier() {
433 var ch, start, id, restore;
436 if (!isIdentifierStart(ch)) {
443 if (source[index] !== 'u') {
448 ch = scanHexEscape('u');
450 if (ch === '\\' || !isIdentifierStart(ch)) {
459 id = source[index++];
462 while (index < length) {
464 if (!isIdentifierPart(ch)) {
469 if (source[index] !== 'u') {
474 ch = scanHexEscape('u');
476 if (ch === '\\' || !isIdentifierPart(ch)) {
485 id += source[index++];
489 // There is no keyword or literal with only one character.
490 // Thus, it must be an identifier.
491 if (id.length === 1) {
493 type: Token.Identifier,
495 lineNumber: lineNumber,
496 lineStart: lineStart,
497 range: [start, index]
505 lineNumber: lineNumber,
506 lineStart: lineStart,
507 range: [start, index]
511 // 7.8.1 Null Literals
515 type: Token.NullLiteral,
517 lineNumber: lineNumber,
518 lineStart: lineStart,
519 range: [start, index]
523 // 7.8.2 Boolean Literals
525 if (id === 'true' || id === 'false') {
527 type: Token.BooleanLiteral,
529 lineNumber: lineNumber,
530 lineStart: lineStart,
531 range: [start, index]
536 type: Token.Identifier,
538 lineNumber: lineNumber,
539 lineStart: lineStart,
540 range: [start, index]
546 function scanPunctuator() {
553 // Check for most common single-character punctuators.
555 if (ch1 === ';' || ch1 === '{' || ch1 === '}') {
558 type: Token.Punctuator,
560 lineNumber: lineNumber,
561 lineStart: lineStart,
562 range: [start, index]
566 if (ch1 === ',' || ch1 === '(' || ch1 === ')') {
569 type: Token.Punctuator,
571 lineNumber: lineNumber,
572 lineStart: lineStart,
573 range: [start, index]
577 // Dot (.) can also start a floating-point number, hence the need
578 // to check the next character.
580 ch2 = source[index + 1];
581 if (ch1 === '.' && !isDecimalDigit(ch2)) {
583 type: Token.Punctuator,
584 value: source[index++],
585 lineNumber: lineNumber,
586 lineStart: lineStart,
587 range: [start, index]
591 // Peek more characters.
593 ch3 = source[index + 2];
594 ch4 = source[index + 3];
596 // 4-character punctuator: >>>=
598 if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
602 type: Token.Punctuator,
604 lineNumber: lineNumber,
605 lineStart: lineStart,
606 range: [start, index]
611 // 3-character punctuators: === !== >>> <<= >>=
613 if (ch1 === '=' && ch2 === '=' && ch3 === '=') {
616 type: Token.Punctuator,
618 lineNumber: lineNumber,
619 lineStart: lineStart,
620 range: [start, index]
624 if (ch1 === '!' && ch2 === '=' && ch3 === '=') {
627 type: Token.Punctuator,
629 lineNumber: lineNumber,
630 lineStart: lineStart,
631 range: [start, index]
635 if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
638 type: Token.Punctuator,
640 lineNumber: lineNumber,
641 lineStart: lineStart,
642 range: [start, index]
646 if (ch1 === '<' && ch2 === '<' && ch3 === '=') {
649 type: Token.Punctuator,
651 lineNumber: lineNumber,
652 lineStart: lineStart,
653 range: [start, index]
657 if (ch1 === '>' && ch2 === '>' && ch3 === '=') {
660 type: Token.Punctuator,
662 lineNumber: lineNumber,
663 lineStart: lineStart,
664 range: [start, index]
668 // 2-character punctuators: <= >= == != ++ -- << >> && ||
669 // += -= *= %= &= |= ^= /=
672 if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
675 type: Token.Punctuator,
677 lineNumber: lineNumber,
678 lineStart: lineStart,
679 range: [start, index]
684 if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) {
685 if ('+-<>&|'.indexOf(ch2) >= 0) {
688 type: Token.Punctuator,
690 lineNumber: lineNumber,
691 lineStart: lineStart,
692 range: [start, index]
697 // The remaining 1-character punctuators.
699 if ('[]<>+-*%&|^!~?:=/'.indexOf(ch1) >= 0) {
701 type: Token.Punctuator,
702 value: source[index++],
703 lineNumber: lineNumber,
704 lineStart: lineStart,
705 range: [start, index]
710 // 7.8.3 Numeric Literals
712 function scanNumericLiteral() {
713 var number, start, ch;
716 assert(isDecimalDigit(ch) || (ch === '.'),
717 'Numeric literal must start with a decimal digit or a decimal point');
722 number = source[index++];
725 // Hex number starts with '0x'.
726 // Octal number starts with '0'.
727 if (number === '0') {
728 if (ch === 'x' || ch === 'X') {
729 number += source[index++];
730 while (index < length) {
732 if (!isHexDigit(ch)) {
735 number += source[index++];
738 if (number.length <= 2) {
740 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
743 if (index < length) {
745 if (isIdentifierStart(ch)) {
746 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
750 type: Token.NumericLiteral,
751 value: parseInt(number, 16),
752 lineNumber: lineNumber,
753 lineStart: lineStart,
754 range: [start, index]
756 } else if (isOctalDigit(ch)) {
757 number += source[index++];
758 while (index < length) {
760 if (!isOctalDigit(ch)) {
763 number += source[index++];
766 if (index < length) {
768 if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
769 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
773 type: Token.NumericLiteral,
774 value: parseInt(number, 8),
776 lineNumber: lineNumber,
777 lineStart: lineStart,
778 range: [start, index]
782 // decimal number starts with '0' such as '09' is illegal.
783 if (isDecimalDigit(ch)) {
784 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
788 while (index < length) {
790 if (!isDecimalDigit(ch)) {
793 number += source[index++];
798 number += source[index++];
799 while (index < length) {
801 if (!isDecimalDigit(ch)) {
804 number += source[index++];
808 if (ch === 'e' || ch === 'E') {
809 number += source[index++];
812 if (ch === '+' || ch === '-') {
813 number += source[index++];
817 if (isDecimalDigit(ch)) {
818 number += source[index++];
819 while (index < length) {
821 if (!isDecimalDigit(ch)) {
824 number += source[index++];
827 ch = 'character ' + ch;
828 if (index >= length) {
831 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
835 if (index < length) {
837 if (isIdentifierStart(ch)) {
838 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
843 type: Token.NumericLiteral,
844 value: parseFloat(number),
845 lineNumber: lineNumber,
846 lineStart: lineStart,
847 range: [start, index]
851 // 7.8.4 String Literals
853 function scanStringLiteral() {
854 var str = '', quote, start, ch, code, unescaped, restore, octal = false;
856 quote = source[index];
857 assert((quote === '\'' || quote === '"'),
858 'String literal must starts with a quote');
863 while (index < length) {
864 ch = source[index++];
869 } else if (ch === '\\') {
870 ch = source[index++];
871 if (!isLineTerminator(ch)) {
885 unescaped = scanHexEscape(ch);
904 if (isOctalDigit(ch)) {
905 code = '01234567'.indexOf(ch);
907 // \0 is not octal escape sequence
912 if (index < length && isOctalDigit(source[index])) {
914 code = code * 8 + '01234567'.indexOf(source[index++]);
916 // 3 digits are only allowed when string starts
918 if ('0123'.indexOf(ch) >= 0 &&
920 isOctalDigit(source[index])) {
921 code = code * 8 + '01234567'.indexOf(source[index++]);
924 str += String.fromCharCode(code);
932 if (ch === '\r' && source[index] === '\n') {
936 } else if (isLineTerminator(ch)) {
944 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
948 type: Token.StringLiteral,
951 lineNumber: lineNumber,
952 lineStart: lineStart,
953 range: [start, index]
957 function scanRegExp() {
958 var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false;
965 assert(ch === '/', 'Regular expression literal must start with a slash');
966 str = source[index++];
968 while (index < length) {
969 ch = source[index++];
972 ch = source[index++];
974 if (isLineTerminator(ch)) {
975 throwError({}, Messages.UnterminatedRegExp);
978 } else if (classMarker) {
986 } else if (ch === '[') {
988 } else if (isLineTerminator(ch)) {
989 throwError({}, Messages.UnterminatedRegExp);
995 throwError({}, Messages.UnterminatedRegExp);
998 // Exclude leading and trailing slash.
999 pattern = str.substr(1, str.length - 2);
1002 while (index < length) {
1004 if (!isIdentifierPart(ch)) {
1009 if (ch === '\\' && index < length) {
1014 ch = scanHexEscape('u');
1018 for (; restore < index; ++restore) {
1019 str += source[restore];
1036 value = new RegExp(pattern, flags);
1038 throwError({}, Messages.InvalidRegExp);
1044 range: [start, index]
1048 function isIdentifierName(token) {
1049 return token.type === Token.Identifier ||
1050 token.type === Token.Keyword ||
1051 token.type === Token.BooleanLiteral ||
1052 token.type === Token.NullLiteral;
1055 function advance() {
1060 if (index >= length) {
1063 lineNumber: lineNumber,
1064 lineStart: lineStart,
1065 range: [index, index]
1069 token = scanPunctuator();
1070 if (typeof token !== 'undefined') {
1076 if (ch === '\'' || ch === '"') {
1077 return scanStringLiteral();
1080 if (ch === '.' || isDecimalDigit(ch)) {
1081 return scanNumericLiteral();
1084 token = scanIdentifier();
1085 if (typeof token !== 'undefined') {
1089 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1096 index = buffer.range[1];
1097 lineNumber = buffer.lineNumber;
1098 lineStart = buffer.lineStart;
1108 function lookahead() {
1109 var pos, line, start;
1111 if (buffer !== null) {
1126 // Return true if there is a line terminator before the next token.
1128 function peekLineTerminator() {
1129 var pos, line, start, found;
1135 found = lineNumber !== line;
1143 // Throw an exception
1145 function throwError(token, messageFormat) {
1147 args = Array.prototype.slice.call(arguments, 2),
1148 msg = messageFormat.replace(
1150 function (whole, index) {
1151 return args[index] || '';
1155 if (typeof token.lineNumber === 'number') {
1156 error = new Error('Line ' + token.lineNumber + ': ' + msg);
1157 error.index = token.range[0];
1158 error.lineNumber = token.lineNumber;
1159 error.column = token.range[0] - lineStart + 1;
1161 error = new Error('Line ' + lineNumber + ': ' + msg);
1162 error.index = index;
1163 error.lineNumber = lineNumber;
1164 error.column = index - lineStart + 1;
1170 function throwErrorTolerant() {
1172 throwError.apply(null, arguments);
1175 extra.errors.push(e);
1183 // Throw an exception because of the token.
1185 function throwUnexpected(token) {
1186 if (token.type === Token.EOF) {
1187 throwError(token, Messages.UnexpectedEOS);
1190 if (token.type === Token.NumericLiteral) {
1191 throwError(token, Messages.UnexpectedNumber);
1194 if (token.type === Token.StringLiteral) {
1195 throwError(token, Messages.UnexpectedString);
1198 if (token.type === Token.Identifier) {
1199 throwError(token, Messages.UnexpectedIdentifier);
1202 if (token.type === Token.Keyword) {
1203 if (isFutureReservedWord(token.value)) {
1204 throwError(token, Messages.UnexpectedReserved);
1205 } else if (strict && isStrictModeReservedWord(token.value)) {
1206 throwErrorTolerant(token, Messages.StrictReservedWord);
1209 throwError(token, Messages.UnexpectedToken, token.value);
1212 // BooleanLiteral, NullLiteral, or Punctuator.
1213 throwError(token, Messages.UnexpectedToken, token.value);
1216 // Expect the next token to match the specified punctuator.
1217 // If not, an exception will be thrown.
1219 function expect(value) {
1221 if (token.type !== Token.Punctuator || token.value !== value) {
1222 throwUnexpected(token);
1226 // Expect the next token to match the specified keyword.
1227 // If not, an exception will be thrown.
1229 function expectKeyword(keyword) {
1231 if (token.type !== Token.Keyword || token.value !== keyword) {
1232 throwUnexpected(token);
1236 // Return true if the next token matches the specified punctuator.
1238 function match(value) {
1239 var token = lookahead();
1240 return token.type === Token.Punctuator && token.value === value;
1243 // Return true if the next token matches the specified keyword
1245 function matchKeyword(keyword) {
1246 var token = lookahead();
1247 return token.type === Token.Keyword && token.value === keyword;
1250 // Return true if the next token is an assignment operator
1252 function matchAssign() {
1253 var token = lookahead(),
1256 if (token.type !== Token.Punctuator) {
1259 return op === '=' ||
1273 function consumeSemicolon() {
1276 // Catch the very common case first.
1277 if (source[index] === ';') {
1284 if (lineNumber !== line) {
1293 token = lookahead();
1294 if (token.type !== Token.EOF && !match('}')) {
1295 throwUnexpected(token);
1299 // Return true if provided expression is LeftHandSideExpression
1301 function isLeftHandSide(expr) {
1302 return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
1305 // 11.1.4 Array Initialiser
1307 function parseArrayInitialiser() {
1312 while (!match(']')) {
1315 elements.push(null);
1317 elements.push(parseAssignmentExpression());
1328 type: Syntax.ArrayExpression,
1333 // 11.1.5 Object Initialiser
1335 function parsePropertyFunction(param, first) {
1336 var previousStrict, body;
1338 previousStrict = strict;
1339 body = parseFunctionSourceElements();
1340 if (first && strict && isRestrictedWord(param[0].name)) {
1341 throwErrorTolerant(first, Messages.StrictParamName);
1343 strict = previousStrict;
1346 type: Syntax.FunctionExpression,
1357 function parseObjectPropertyKey() {
1360 // Note: This function is called only from parseObjectProperty(), where
1361 // EOF and Punctuator tokens are already filtered out.
1363 if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
1364 if (strict && token.octal) {
1365 throwErrorTolerant(token, Messages.StrictOctalLiteral);
1367 return createLiteral(token);
1371 type: Syntax.Identifier,
1376 function parseObjectProperty() {
1377 var token, key, id, param;
1379 token = lookahead();
1381 if (token.type === Token.Identifier) {
1383 id = parseObjectPropertyKey();
1385 // Property Assignment: Getter and Setter.
1387 if (token.value === 'get' && !match(':')) {
1388 key = parseObjectPropertyKey();
1392 type: Syntax.Property,
1394 value: parsePropertyFunction([]),
1397 } else if (token.value === 'set' && !match(':')) {
1398 key = parseObjectPropertyKey();
1400 token = lookahead();
1401 if (token.type !== Token.Identifier) {
1403 throwErrorTolerant(token, Messages.UnexpectedToken, token.value);
1405 type: Syntax.Property,
1407 value: parsePropertyFunction([]),
1411 param = [ parseVariableIdentifier() ];
1414 type: Syntax.Property,
1416 value: parsePropertyFunction(param, token),
1423 type: Syntax.Property,
1425 value: parseAssignmentExpression(),
1429 } else if (token.type === Token.EOF || token.type === Token.Punctuator) {
1430 throwUnexpected(token);
1432 key = parseObjectPropertyKey();
1435 type: Syntax.Property,
1437 value: parseAssignmentExpression(),
1443 function parseObjectInitialiser() {
1444 var properties = [], property, name, kind, map = {}, toString = String;
1448 while (!match('}')) {
1449 property = parseObjectProperty();
1451 if (property.key.type === Syntax.Identifier) {
1452 name = property.key.name;
1454 name = toString(property.key.value);
1456 kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
1457 if (Object.prototype.hasOwnProperty.call(map, name)) {
1458 if (map[name] === PropertyKind.Data) {
1459 if (strict && kind === PropertyKind.Data) {
1460 throwErrorTolerant({}, Messages.StrictDuplicateProperty);
1461 } else if (kind !== PropertyKind.Data) {
1462 throwErrorTolerant({}, Messages.AccessorDataProperty);
1465 if (kind === PropertyKind.Data) {
1466 throwErrorTolerant({}, Messages.AccessorDataProperty);
1467 } else if (map[name] & kind) {
1468 throwErrorTolerant({}, Messages.AccessorGetSet);
1476 properties.push(property);
1486 type: Syntax.ObjectExpression,
1487 properties: properties
1491 // 11.1.6 The Grouping Operator
1493 function parseGroupExpression() {
1498 expr = parseExpression();
1506 // 11.1 Primary Expressions
1508 function parsePrimaryExpression() {
1509 var token = lookahead(),
1512 if (type === Token.Identifier) {
1514 type: Syntax.Identifier,
1519 if (type === Token.StringLiteral || type === Token.NumericLiteral) {
1520 if (strict && token.octal) {
1521 throwErrorTolerant(token, Messages.StrictOctalLiteral);
1523 return createLiteral(lex());
1526 if (type === Token.Keyword) {
1527 if (matchKeyword('this')) {
1530 type: Syntax.ThisExpression
1534 if (matchKeyword('function')) {
1535 return parseFunctionExpression();
1539 if (type === Token.BooleanLiteral) {
1541 token.value = (token.value === 'true');
1542 return createLiteral(token);
1545 if (type === Token.NullLiteral) {
1548 return createLiteral(token);
1552 return parseArrayInitialiser();
1556 return parseObjectInitialiser();
1560 return parseGroupExpression();
1563 if (match('/') || match('/=')) {
1564 return createLiteral(scanRegExp());
1567 return throwUnexpected(lex());
1570 // 11.2 Left-Hand-Side Expressions
1572 function parseArguments() {
1578 while (index < length) {
1579 args.push(parseAssignmentExpression());
1592 function parseNonComputedProperty() {
1595 if (!isIdentifierName(token)) {
1596 throwUnexpected(token);
1600 type: Syntax.Identifier,
1605 function parseNonComputedMember() {
1608 return parseNonComputedProperty();
1611 function parseComputedMember() {
1616 expr = parseExpression();
1623 function parseNewExpression() {
1626 expectKeyword('new');
1629 type: Syntax.NewExpression,
1630 callee: parseLeftHandSideExpression(),
1635 expr['arguments'] = parseArguments();
1641 function parseLeftHandSideExpressionAllowCall() {
1644 expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
1646 while (match('.') || match('[') || match('(')) {
1649 type: Syntax.CallExpression,
1651 'arguments': parseArguments()
1653 } else if (match('[')) {
1655 type: Syntax.MemberExpression,
1658 property: parseComputedMember()
1662 type: Syntax.MemberExpression,
1665 property: parseNonComputedMember()
1674 function parseLeftHandSideExpression() {
1677 expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
1679 while (match('.') || match('[')) {
1682 type: Syntax.MemberExpression,
1685 property: parseComputedMember()
1689 type: Syntax.MemberExpression,
1692 property: parseNonComputedMember()
1700 // 11.3 Postfix Expressions
1702 function parsePostfixExpression() {
1703 var expr = parseLeftHandSideExpressionAllowCall(), token;
1705 token = lookahead();
1706 if (token.type !== Token.Punctuator) {
1710 if ((match('++') || match('--')) && !peekLineTerminator()) {
1712 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
1713 throwErrorTolerant({}, Messages.StrictLHSPostfix);
1715 if (!isLeftHandSide(expr)) {
1716 throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
1720 type: Syntax.UpdateExpression,
1721 operator: lex().value,
1730 // 11.4 Unary Operators
1732 function parseUnaryExpression() {
1735 token = lookahead();
1736 if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
1737 return parsePostfixExpression();
1740 if (match('++') || match('--')) {
1742 expr = parseUnaryExpression();
1744 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
1745 throwErrorTolerant({}, Messages.StrictLHSPrefix);
1748 if (!isLeftHandSide(expr)) {
1749 throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
1753 type: Syntax.UpdateExpression,
1754 operator: token.value,
1761 if (match('+') || match('-') || match('~') || match('!')) {
1763 type: Syntax.UnaryExpression,
1764 operator: lex().value,
1765 argument: parseUnaryExpression(),
1771 if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
1773 type: Syntax.UnaryExpression,
1774 operator: lex().value,
1775 argument: parseUnaryExpression(),
1778 if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
1779 throwErrorTolerant({}, Messages.StrictDelete);
1784 return parsePostfixExpression();
1787 // 11.5 Multiplicative Operators
1789 function parseMultiplicativeExpression() {
1790 var expr = parseUnaryExpression();
1792 while (match('*') || match('/') || match('%')) {
1794 type: Syntax.BinaryExpression,
1795 operator: lex().value,
1797 right: parseUnaryExpression()
1804 // 11.6 Additive Operators
1806 function parseAdditiveExpression() {
1807 var expr = parseMultiplicativeExpression();
1809 while (match('+') || match('-')) {
1811 type: Syntax.BinaryExpression,
1812 operator: lex().value,
1814 right: parseMultiplicativeExpression()
1821 // 11.7 Bitwise Shift Operators
1823 function parseShiftExpression() {
1824 var expr = parseAdditiveExpression();
1826 while (match('<<') || match('>>') || match('>>>')) {
1828 type: Syntax.BinaryExpression,
1829 operator: lex().value,
1831 right: parseAdditiveExpression()
1837 // 11.8 Relational Operators
1839 function parseRelationalExpression() {
1840 var expr, previousAllowIn;
1842 previousAllowIn = state.allowIn;
1843 state.allowIn = true;
1845 expr = parseShiftExpression();
1847 while (match('<') || match('>') || match('<=') || match('>=') || (previousAllowIn && matchKeyword('in')) || matchKeyword('instanceof')) {
1849 type: Syntax.BinaryExpression,
1850 operator: lex().value,
1852 right: parseShiftExpression()
1856 state.allowIn = previousAllowIn;
1860 // 11.9 Equality Operators
1862 function parseEqualityExpression() {
1863 var expr = parseRelationalExpression();
1865 while (match('==') || match('!=') || match('===') || match('!==')) {
1867 type: Syntax.BinaryExpression,
1868 operator: lex().value,
1870 right: parseRelationalExpression()
1877 // 11.10 Binary Bitwise Operators
1879 function parseBitwiseANDExpression() {
1880 var expr = parseEqualityExpression();
1882 while (match('&')) {
1885 type: Syntax.BinaryExpression,
1888 right: parseEqualityExpression()
1895 function parseBitwiseXORExpression() {
1896 var expr = parseBitwiseANDExpression();
1898 while (match('^')) {
1901 type: Syntax.BinaryExpression,
1904 right: parseBitwiseANDExpression()
1911 function parseBitwiseORExpression() {
1912 var expr = parseBitwiseXORExpression();
1914 while (match('|')) {
1917 type: Syntax.BinaryExpression,
1920 right: parseBitwiseXORExpression()
1927 // 11.11 Binary Logical Operators
1929 function parseLogicalANDExpression() {
1930 var expr = parseBitwiseORExpression();
1932 while (match('&&')) {
1935 type: Syntax.LogicalExpression,
1938 right: parseBitwiseORExpression()
1945 function parseLogicalORExpression() {
1946 var expr = parseLogicalANDExpression();
1948 while (match('||')) {
1951 type: Syntax.LogicalExpression,
1954 right: parseLogicalANDExpression()
1961 // 11.12 Conditional Operator
1963 function parseConditionalExpression() {
1964 var expr, previousAllowIn, consequent;
1966 expr = parseLogicalORExpression();
1970 previousAllowIn = state.allowIn;
1971 state.allowIn = true;
1972 consequent = parseAssignmentExpression();
1973 state.allowIn = previousAllowIn;
1977 type: Syntax.ConditionalExpression,
1979 consequent: consequent,
1980 alternate: parseAssignmentExpression()
1987 // 11.13 Assignment Operators
1989 function parseAssignmentExpression() {
1992 token = lookahead();
1993 expr = parseConditionalExpression();
1995 if (matchAssign()) {
1996 // LeftHandSideExpression
1997 if (!isLeftHandSide(expr)) {
1998 throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
2002 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
2003 throwErrorTolerant(token, Messages.StrictLHSAssignment);
2007 type: Syntax.AssignmentExpression,
2008 operator: lex().value,
2010 right: parseAssignmentExpression()
2017 // 11.14 Comma Operator
2019 function parseExpression() {
2020 var expr = parseAssignmentExpression();
2024 type: Syntax.SequenceExpression,
2025 expressions: [ expr ]
2028 while (index < length) {
2033 expr.expressions.push(parseAssignmentExpression());
2042 function parseStatementList() {
2046 while (index < length) {
2050 statement = parseSourceElement();
2051 if (typeof statement === 'undefined') {
2054 list.push(statement);
2060 function parseBlock() {
2065 block = parseStatementList();
2070 type: Syntax.BlockStatement,
2075 // 12.2 Variable Statement
2077 function parseVariableIdentifier() {
2080 if (token.type !== Token.Identifier) {
2081 throwUnexpected(token);
2085 type: Syntax.Identifier,
2090 function parseVariableDeclaration(kind) {
2091 var id = parseVariableIdentifier(),
2095 if (strict && isRestrictedWord(id.name)) {
2096 throwErrorTolerant({}, Messages.StrictVarName);
2099 if (kind === 'const') {
2101 init = parseAssignmentExpression();
2102 } else if (match('=')) {
2104 init = parseAssignmentExpression();
2108 type: Syntax.VariableDeclarator,
2114 function parseVariableDeclarationList(kind) {
2118 list.push(parseVariableDeclaration(kind));
2123 } while (index < length);
2128 function parseVariableStatement() {
2131 expectKeyword('var');
2133 declarations = parseVariableDeclarationList();
2138 type: Syntax.VariableDeclaration,
2139 declarations: declarations,
2144 // kind may be `const` or `let`
2145 // Both are experimental and not in the specification yet.
2146 // see http://wiki.ecmascript.org/doku.php?id=harmony:const
2147 // and http://wiki.ecmascript.org/doku.php?id=harmony:let
2148 function parseConstLetDeclaration(kind) {
2151 expectKeyword(kind);
2153 declarations = parseVariableDeclarationList(kind);
2158 type: Syntax.VariableDeclaration,
2159 declarations: declarations,
2164 // 12.3 Empty Statement
2166 function parseEmptyStatement() {
2170 type: Syntax.EmptyStatement
2174 // 12.4 Expression Statement
2176 function parseExpressionStatement() {
2177 var expr = parseExpression();
2182 type: Syntax.ExpressionStatement,
2187 // 12.5 If statement
2189 function parseIfStatement() {
2190 var test, consequent, alternate;
2192 expectKeyword('if');
2196 test = parseExpression();
2200 consequent = parseStatement();
2202 if (matchKeyword('else')) {
2204 alternate = parseStatement();
2210 type: Syntax.IfStatement,
2212 consequent: consequent,
2213 alternate: alternate
2217 // 12.6 Iteration Statements
2219 function parseDoWhileStatement() {
2220 var body, test, oldInIteration;
2222 expectKeyword('do');
2224 oldInIteration = state.inIteration;
2225 state.inIteration = true;
2227 body = parseStatement();
2229 state.inIteration = oldInIteration;
2231 expectKeyword('while');
2235 test = parseExpression();
2244 type: Syntax.DoWhileStatement,
2250 function parseWhileStatement() {
2251 var test, body, oldInIteration;
2253 expectKeyword('while');
2257 test = parseExpression();
2261 oldInIteration = state.inIteration;
2262 state.inIteration = true;
2264 body = parseStatement();
2266 state.inIteration = oldInIteration;
2269 type: Syntax.WhileStatement,
2275 function parseForVariableDeclaration() {
2279 type: Syntax.VariableDeclaration,
2280 declarations: parseVariableDeclarationList(),
2285 function parseForStatement() {
2286 var init, test, update, left, right, body, oldInIteration;
2288 init = test = update = null;
2290 expectKeyword('for');
2297 if (matchKeyword('var') || matchKeyword('let')) {
2298 state.allowIn = false;
2299 init = parseForVariableDeclaration();
2300 state.allowIn = true;
2302 if (init.declarations.length === 1 && matchKeyword('in')) {
2305 right = parseExpression();
2309 state.allowIn = false;
2310 init = parseExpression();
2311 state.allowIn = true;
2313 if (matchKeyword('in')) {
2314 // LeftHandSideExpression
2315 if (!isLeftHandSide(init)) {
2316 throwErrorTolerant({}, Messages.InvalidLHSInForIn);
2321 right = parseExpression();
2326 if (typeof left === 'undefined') {
2331 if (typeof left === 'undefined') {
2334 test = parseExpression();
2339 update = parseExpression();
2345 oldInIteration = state.inIteration;
2346 state.inIteration = true;
2348 body = parseStatement();
2350 state.inIteration = oldInIteration;
2352 if (typeof left === 'undefined') {
2354 type: Syntax.ForStatement,
2363 type: Syntax.ForInStatement,
2371 // 12.7 The continue statement
2373 function parseContinueStatement() {
2374 var token, label = null;
2376 expectKeyword('continue');
2378 // Optimize the most common form: 'continue;'.
2379 if (source[index] === ';') {
2382 if (!state.inIteration) {
2383 throwError({}, Messages.IllegalContinue);
2387 type: Syntax.ContinueStatement,
2392 if (peekLineTerminator()) {
2393 if (!state.inIteration) {
2394 throwError({}, Messages.IllegalContinue);
2398 type: Syntax.ContinueStatement,
2403 token = lookahead();
2404 if (token.type === Token.Identifier) {
2405 label = parseVariableIdentifier();
2407 if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
2408 throwError({}, Messages.UnknownLabel, label.name);
2414 if (label === null && !state.inIteration) {
2415 throwError({}, Messages.IllegalContinue);
2419 type: Syntax.ContinueStatement,
2424 // 12.8 The break statement
2426 function parseBreakStatement() {
2427 var token, label = null;
2429 expectKeyword('break');
2431 // Optimize the most common form: 'break;'.
2432 if (source[index] === ';') {
2435 if (!(state.inIteration || state.inSwitch)) {
2436 throwError({}, Messages.IllegalBreak);
2440 type: Syntax.BreakStatement,
2445 if (peekLineTerminator()) {
2446 if (!(state.inIteration || state.inSwitch)) {
2447 throwError({}, Messages.IllegalBreak);
2451 type: Syntax.BreakStatement,
2456 token = lookahead();
2457 if (token.type === Token.Identifier) {
2458 label = parseVariableIdentifier();
2460 if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
2461 throwError({}, Messages.UnknownLabel, label.name);
2467 if (label === null && !(state.inIteration || state.inSwitch)) {
2468 throwError({}, Messages.IllegalBreak);
2472 type: Syntax.BreakStatement,
2477 // 12.9 The return statement
2479 function parseReturnStatement() {
2480 var token, argument = null;
2482 expectKeyword('return');
2484 if (!state.inFunctionBody) {
2485 throwErrorTolerant({}, Messages.IllegalReturn);
2488 // 'return' followed by a space and an identifier is very common.
2489 if (source[index] === ' ') {
2490 if (isIdentifierStart(source[index + 1])) {
2491 argument = parseExpression();
2494 type: Syntax.ReturnStatement,
2500 if (peekLineTerminator()) {
2502 type: Syntax.ReturnStatement,
2508 token = lookahead();
2509 if (!match('}') && token.type !== Token.EOF) {
2510 argument = parseExpression();
2517 type: Syntax.ReturnStatement,
2522 // 12.10 The with statement
2524 function parseWithStatement() {
2528 throwErrorTolerant({}, Messages.StrictModeWith);
2531 expectKeyword('with');
2535 object = parseExpression();
2539 body = parseStatement();
2542 type: Syntax.WithStatement,
2548 // 12.10 The swith statement
2550 function parseSwitchCase() {
2555 if (matchKeyword('default')) {
2559 expectKeyword('case');
2560 test = parseExpression();
2564 while (index < length) {
2565 if (match('}') || matchKeyword('default') || matchKeyword('case')) {
2568 statement = parseStatement();
2569 if (typeof statement === 'undefined') {
2572 consequent.push(statement);
2576 type: Syntax.SwitchCase,
2578 consequent: consequent
2582 function parseSwitchStatement() {
2583 var discriminant, cases, clause, oldInSwitch, defaultFound;
2585 expectKeyword('switch');
2589 discriminant = parseExpression();
2600 type: Syntax.SwitchStatement,
2601 discriminant: discriminant,
2606 oldInSwitch = state.inSwitch;
2607 state.inSwitch = true;
2608 defaultFound = false;
2610 while (index < length) {
2614 clause = parseSwitchCase();
2615 if (clause.test === null) {
2617 throwError({}, Messages.MultipleDefaultsInSwitch);
2619 defaultFound = true;
2624 state.inSwitch = oldInSwitch;
2629 type: Syntax.SwitchStatement,
2630 discriminant: discriminant,
2635 // 12.13 The throw statement
2637 function parseThrowStatement() {
2640 expectKeyword('throw');
2642 if (peekLineTerminator()) {
2643 throwError({}, Messages.NewlineAfterThrow);
2646 argument = parseExpression();
2651 type: Syntax.ThrowStatement,
2656 // 12.14 The try statement
2658 function parseCatchClause() {
2661 expectKeyword('catch');
2665 throwUnexpected(lookahead());
2668 param = parseVariableIdentifier();
2670 if (strict && isRestrictedWord(param.name)) {
2671 throwErrorTolerant({}, Messages.StrictCatchVariable);
2677 type: Syntax.CatchClause,
2683 function parseTryStatement() {
2684 var block, handlers = [], finalizer = null;
2686 expectKeyword('try');
2688 block = parseBlock();
2690 if (matchKeyword('catch')) {
2691 handlers.push(parseCatchClause());
2694 if (matchKeyword('finally')) {
2696 finalizer = parseBlock();
2699 if (handlers.length === 0 && !finalizer) {
2700 throwError({}, Messages.NoCatchOrFinally);
2704 type: Syntax.TryStatement,
2706 guardedHandlers: [],
2708 finalizer: finalizer
2712 // 12.15 The debugger statement
2714 function parseDebuggerStatement() {
2715 expectKeyword('debugger');
2720 type: Syntax.DebuggerStatement
2726 function parseStatement() {
2727 var token = lookahead(),
2731 if (token.type === Token.EOF) {
2732 throwUnexpected(token);
2735 if (token.type === Token.Punctuator) {
2736 switch (token.value) {
2738 return parseEmptyStatement();
2740 return parseBlock();
2742 return parseExpressionStatement();
2748 if (token.type === Token.Keyword) {
2749 switch (token.value) {
2751 return parseBreakStatement();
2753 return parseContinueStatement();
2755 return parseDebuggerStatement();
2757 return parseDoWhileStatement();
2759 return parseForStatement();
2761 return parseFunctionDeclaration();
2763 return parseIfStatement();
2765 return parseReturnStatement();
2767 return parseSwitchStatement();
2769 return parseThrowStatement();
2771 return parseTryStatement();
2773 return parseVariableStatement();
2775 return parseWhileStatement();
2777 return parseWithStatement();
2783 expr = parseExpression();
2785 // 12.12 Labelled Statements
2786 if ((expr.type === Syntax.Identifier) && match(':')) {
2789 if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) {
2790 throwError({}, Messages.Redeclaration, 'Label', expr.name);
2793 state.labelSet[expr.name] = true;
2794 labeledBody = parseStatement();
2795 delete state.labelSet[expr.name];
2798 type: Syntax.LabeledStatement,
2807 type: Syntax.ExpressionStatement,
2812 // 13 Function Definition
2814 function parseFunctionSourceElements() {
2815 var sourceElement, sourceElements = [], token, directive, firstRestricted,
2816 oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody;
2820 while (index < length) {
2821 token = lookahead();
2822 if (token.type !== Token.StringLiteral) {
2826 sourceElement = parseSourceElement();
2827 sourceElements.push(sourceElement);
2828 if (sourceElement.expression.type !== Syntax.Literal) {
2829 // this is not directive
2832 directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
2833 if (directive === 'use strict') {
2835 if (firstRestricted) {
2836 throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
2839 if (!firstRestricted && token.octal) {
2840 firstRestricted = token;
2845 oldLabelSet = state.labelSet;
2846 oldInIteration = state.inIteration;
2847 oldInSwitch = state.inSwitch;
2848 oldInFunctionBody = state.inFunctionBody;
2850 state.labelSet = {};
2851 state.inIteration = false;
2852 state.inSwitch = false;
2853 state.inFunctionBody = true;
2855 while (index < length) {
2859 sourceElement = parseSourceElement();
2860 if (typeof sourceElement === 'undefined') {
2863 sourceElements.push(sourceElement);
2868 state.labelSet = oldLabelSet;
2869 state.inIteration = oldInIteration;
2870 state.inSwitch = oldInSwitch;
2871 state.inFunctionBody = oldInFunctionBody;
2874 type: Syntax.BlockStatement,
2875 body: sourceElements
2879 function parseFunctionDeclaration() {
2880 var id, param, params = [], body, token, stricted, firstRestricted, message, previousStrict, paramSet;
2882 expectKeyword('function');
2883 token = lookahead();
2884 id = parseVariableIdentifier();
2886 if (isRestrictedWord(token.value)) {
2887 throwErrorTolerant(token, Messages.StrictFunctionName);
2890 if (isRestrictedWord(token.value)) {
2891 firstRestricted = token;
2892 message = Messages.StrictFunctionName;
2893 } else if (isStrictModeReservedWord(token.value)) {
2894 firstRestricted = token;
2895 message = Messages.StrictReservedWord;
2903 while (index < length) {
2904 token = lookahead();
2905 param = parseVariableIdentifier();
2907 if (isRestrictedWord(token.value)) {
2909 message = Messages.StrictParamName;
2911 if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
2913 message = Messages.StrictParamDupe;
2915 } else if (!firstRestricted) {
2916 if (isRestrictedWord(token.value)) {
2917 firstRestricted = token;
2918 message = Messages.StrictParamName;
2919 } else if (isStrictModeReservedWord(token.value)) {
2920 firstRestricted = token;
2921 message = Messages.StrictReservedWord;
2922 } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
2923 firstRestricted = token;
2924 message = Messages.StrictParamDupe;
2928 paramSet[param.name] = true;
2938 previousStrict = strict;
2939 body = parseFunctionSourceElements();
2940 if (strict && firstRestricted) {
2941 throwError(firstRestricted, message);
2943 if (strict && stricted) {
2944 throwErrorTolerant(stricted, message);
2946 strict = previousStrict;
2949 type: Syntax.FunctionDeclaration,
2960 function parseFunctionExpression() {
2961 var token, id = null, stricted, firstRestricted, message, param, params = [], body, previousStrict, paramSet;
2963 expectKeyword('function');
2966 token = lookahead();
2967 id = parseVariableIdentifier();
2969 if (isRestrictedWord(token.value)) {
2970 throwErrorTolerant(token, Messages.StrictFunctionName);
2973 if (isRestrictedWord(token.value)) {
2974 firstRestricted = token;
2975 message = Messages.StrictFunctionName;
2976 } else if (isStrictModeReservedWord(token.value)) {
2977 firstRestricted = token;
2978 message = Messages.StrictReservedWord;
2987 while (index < length) {
2988 token = lookahead();
2989 param = parseVariableIdentifier();
2991 if (isRestrictedWord(token.value)) {
2993 message = Messages.StrictParamName;
2995 if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
2997 message = Messages.StrictParamDupe;
2999 } else if (!firstRestricted) {
3000 if (isRestrictedWord(token.value)) {
3001 firstRestricted = token;
3002 message = Messages.StrictParamName;
3003 } else if (isStrictModeReservedWord(token.value)) {
3004 firstRestricted = token;
3005 message = Messages.StrictReservedWord;
3006 } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
3007 firstRestricted = token;
3008 message = Messages.StrictParamDupe;
3012 paramSet[param.name] = true;
3022 previousStrict = strict;
3023 body = parseFunctionSourceElements();
3024 if (strict && firstRestricted) {
3025 throwError(firstRestricted, message);
3027 if (strict && stricted) {
3028 throwErrorTolerant(stricted, message);
3030 strict = previousStrict;
3033 type: Syntax.FunctionExpression,
3046 function parseSourceElement() {
3047 var token = lookahead();
3049 if (token.type === Token.Keyword) {
3050 switch (token.value) {
3053 return parseConstLetDeclaration(token.value);
3055 return parseFunctionDeclaration();
3057 return parseStatement();
3061 if (token.type !== Token.EOF) {
3062 return parseStatement();
3066 function parseSourceElements() {
3067 var sourceElement, sourceElements = [], token, directive, firstRestricted;
3069 while (index < length) {
3070 token = lookahead();
3071 if (token.type !== Token.StringLiteral) {
3075 sourceElement = parseSourceElement();
3076 sourceElements.push(sourceElement);
3077 if (sourceElement.expression.type !== Syntax.Literal) {
3078 // this is not directive
3081 directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
3082 if (directive === 'use strict') {
3084 if (firstRestricted) {
3085 throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
3088 if (!firstRestricted && token.octal) {
3089 firstRestricted = token;
3094 while (index < length) {
3095 sourceElement = parseSourceElement();
3096 if (typeof sourceElement === 'undefined') {
3099 sourceElements.push(sourceElement);
3101 return sourceElements;
3104 function parseProgram() {
3108 type: Syntax.Program,
3109 body: parseSourceElements()
3114 // The following functions are needed only when the option to preserve
3115 // the comments is active.
3117 function addComment(type, value, start, end, loc) {
3118 assert(typeof start === 'number', 'Comment must have valid position');
3120 // Because the way the actual token is scanned, often the comments
3121 // (if any) are skipped twice during the lexical analysis.
3122 // Thus, we need to skip adding a comment if the comment array already
3124 if (extra.comments.length > 0) {
3125 if (extra.comments[extra.comments.length - 1].range[1] > start) {
3130 extra.comments.push({
3133 range: [start, end],
3138 function scanComment() {
3139 var comment, ch, loc, start, blockComment, lineComment;
3142 blockComment = false;
3143 lineComment = false;
3145 while (index < length) {
3149 ch = source[index++];
3150 if (isLineTerminator(ch)) {
3153 column: index - lineStart - 1
3155 lineComment = false;
3156 addComment('Line', comment, start, index - 1, loc);
3157 if (ch === '\r' && source[index] === '\n') {
3163 } else if (index >= length) {
3164 lineComment = false;
3168 column: length - lineStart
3170 addComment('Line', comment, start, length, loc);
3174 } else if (blockComment) {
3175 if (isLineTerminator(ch)) {
3176 if (ch === '\r' && source[index + 1] === '\n') {
3185 if (index >= length) {
3186 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
3189 ch = source[index++];
3190 if (index >= length) {
3191 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
3197 comment = comment.substr(0, comment.length - 1);
3198 blockComment = false;
3202 column: index - lineStart
3204 addComment('Block', comment, start, index, loc);
3209 } else if (ch === '/') {
3210 ch = source[index + 1];
3215 column: index - lineStart
3221 if (index >= length) {
3224 column: index - lineStart
3226 lineComment = false;
3227 addComment('Line', comment, start, index, loc);
3229 } else if (ch === '*') {
3232 blockComment = true;
3236 column: index - lineStart - 2
3239 if (index >= length) {
3240 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
3245 } else if (isWhiteSpace(ch)) {
3247 } else if (isLineTerminator(ch)) {
3249 if (ch === '\r' && source[index] === '\n') {
3260 function filterCommentLocation() {
3261 var i, entry, comment, comments = [];
3263 for (i = 0; i < extra.comments.length; ++i) {
3264 entry = extra.comments[i];
3270 comment.range = entry.range;
3273 comment.loc = entry.loc;
3275 comments.push(comment);
3278 extra.comments = comments;
3281 function collectToken() {
3282 var start, loc, token, range, value;
3289 column: index - lineStart
3293 token = extra.advance();
3296 column: index - lineStart
3299 if (token.type !== Token.EOF) {
3300 range = [token.range[0], token.range[1]];
3301 value = sliceSource(token.range[0], token.range[1]);
3303 type: TokenName[token.type],
3313 function collectRegex() {
3314 var pos, loc, regex, token;
3322 column: index - lineStart
3326 regex = extra.scanRegExp();
3329 column: index - lineStart
3332 // Pop the previous token, which is likely '/' or '/='
3333 if (extra.tokens.length > 0) {
3334 token = extra.tokens[extra.tokens.length - 1];
3335 if (token.range[0] === pos && token.type === 'Punctuator') {
3336 if (token.value === '/' || token.value === '/=') {
3343 type: 'RegularExpression',
3344 value: regex.literal,
3345 range: [pos, index],
3352 function filterTokenLocation() {
3353 var i, entry, token, tokens = [];
3355 for (i = 0; i < extra.tokens.length; ++i) {
3356 entry = extra.tokens[i];
3362 token.range = entry.range;
3365 token.loc = entry.loc;
3370 extra.tokens = tokens;
3373 function createLiteral(token) {
3375 type: Syntax.Literal,
3380 function createRawLiteral(token) {
3382 type: Syntax.Literal,
3384 raw: sliceSource(token.range[0], token.range[1])
3388 function createLocationMarker() {
3391 marker.range = [index, index];
3395 column: index - lineStart
3399 column: index - lineStart
3403 marker.end = function () {
3404 this.range[1] = index;
3405 this.loc.end.line = lineNumber;
3406 this.loc.end.column = index - lineStart;
3409 marker.applyGroup = function (node) {
3411 node.groupRange = [this.range[0], this.range[1]];
3416 line: this.loc.start.line,
3417 column: this.loc.start.column
3420 line: this.loc.end.line,
3421 column: this.loc.end.column
3427 marker.apply = function (node) {
3429 node.range = [this.range[0], this.range[1]];
3434 line: this.loc.start.line,
3435 column: this.loc.start.column
3438 line: this.loc.end.line,
3439 column: this.loc.end.column
3448 function trackGroupExpression() {
3452 marker = createLocationMarker();
3455 expr = parseExpression();
3460 marker.applyGroup(expr);
3465 function trackLeftHandSideExpression() {
3469 marker = createLocationMarker();
3471 expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
3473 while (match('.') || match('[')) {
3476 type: Syntax.MemberExpression,
3479 property: parseComputedMember()
3485 type: Syntax.MemberExpression,
3488 property: parseNonComputedMember()
3498 function trackLeftHandSideExpressionAllowCall() {
3502 marker = createLocationMarker();
3504 expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
3506 while (match('.') || match('[') || match('(')) {
3509 type: Syntax.CallExpression,
3511 'arguments': parseArguments()
3515 } else if (match('[')) {
3517 type: Syntax.MemberExpression,
3520 property: parseComputedMember()
3526 type: Syntax.MemberExpression,
3529 property: parseNonComputedMember()
3539 function filterGroup(node) {
3542 n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {};
3544 if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') {
3546 if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) {
3549 n[i] = filterGroup(entry);
3556 function wrapTrackingFunction(range, loc) {
3558 return function (parseFunction) {
3560 function isBinary(node) {
3561 return node.type === Syntax.LogicalExpression ||
3562 node.type === Syntax.BinaryExpression;
3565 function visit(node) {
3568 if (isBinary(node.left)) {
3571 if (isBinary(node.right)) {
3576 if (node.left.groupRange || node.right.groupRange) {
3577 start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0];
3578 end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1];
3579 node.range = [start, end];
3580 } else if (typeof node.range === 'undefined') {
3581 start = node.left.range[0];
3582 end = node.right.range[1];
3583 node.range = [start, end];
3587 if (node.left.groupLoc || node.right.groupLoc) {
3588 start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start;
3589 end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end;
3594 } else if (typeof node.loc === 'undefined') {
3596 start: node.left.loc.start,
3597 end: node.right.loc.end
3603 return function () {
3608 marker = createLocationMarker();
3609 node = parseFunction.apply(null, arguments);
3612 if (range && typeof node.range === 'undefined') {
3616 if (loc && typeof node.loc === 'undefined') {
3620 if (isBinary(node)) {
3633 if (extra.comments) {
3634 extra.skipComment = skipComment;
3635 skipComment = scanComment;
3639 extra.createLiteral = createLiteral;
3640 createLiteral = createRawLiteral;
3643 if (extra.range || extra.loc) {
3645 extra.parseGroupExpression = parseGroupExpression;
3646 extra.parseLeftHandSideExpression = parseLeftHandSideExpression;
3647 extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall;
3648 parseGroupExpression = trackGroupExpression;
3649 parseLeftHandSideExpression = trackLeftHandSideExpression;
3650 parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall;
3652 wrapTracking = wrapTrackingFunction(extra.range, extra.loc);
3654 extra.parseAdditiveExpression = parseAdditiveExpression;
3655 extra.parseAssignmentExpression = parseAssignmentExpression;
3656 extra.parseBitwiseANDExpression = parseBitwiseANDExpression;
3657 extra.parseBitwiseORExpression = parseBitwiseORExpression;
3658 extra.parseBitwiseXORExpression = parseBitwiseXORExpression;
3659 extra.parseBlock = parseBlock;
3660 extra.parseFunctionSourceElements = parseFunctionSourceElements;
3661 extra.parseCatchClause = parseCatchClause;
3662 extra.parseComputedMember = parseComputedMember;
3663 extra.parseConditionalExpression = parseConditionalExpression;
3664 extra.parseConstLetDeclaration = parseConstLetDeclaration;
3665 extra.parseEqualityExpression = parseEqualityExpression;
3666 extra.parseExpression = parseExpression;
3667 extra.parseForVariableDeclaration = parseForVariableDeclaration;
3668 extra.parseFunctionDeclaration = parseFunctionDeclaration;
3669 extra.parseFunctionExpression = parseFunctionExpression;
3670 extra.parseLogicalANDExpression = parseLogicalANDExpression;
3671 extra.parseLogicalORExpression = parseLogicalORExpression;
3672 extra.parseMultiplicativeExpression = parseMultiplicativeExpression;
3673 extra.parseNewExpression = parseNewExpression;
3674 extra.parseNonComputedProperty = parseNonComputedProperty;
3675 extra.parseObjectProperty = parseObjectProperty;
3676 extra.parseObjectPropertyKey = parseObjectPropertyKey;
3677 extra.parsePostfixExpression = parsePostfixExpression;
3678 extra.parsePrimaryExpression = parsePrimaryExpression;
3679 extra.parseProgram = parseProgram;
3680 extra.parsePropertyFunction = parsePropertyFunction;
3681 extra.parseRelationalExpression = parseRelationalExpression;
3682 extra.parseStatement = parseStatement;
3683 extra.parseShiftExpression = parseShiftExpression;
3684 extra.parseSwitchCase = parseSwitchCase;
3685 extra.parseUnaryExpression = parseUnaryExpression;
3686 extra.parseVariableDeclaration = parseVariableDeclaration;
3687 extra.parseVariableIdentifier = parseVariableIdentifier;
3689 parseAdditiveExpression = wrapTracking(extra.parseAdditiveExpression);
3690 parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression);
3691 parseBitwiseANDExpression = wrapTracking(extra.parseBitwiseANDExpression);
3692 parseBitwiseORExpression = wrapTracking(extra.parseBitwiseORExpression);
3693 parseBitwiseXORExpression = wrapTracking(extra.parseBitwiseXORExpression);
3694 parseBlock = wrapTracking(extra.parseBlock);
3695 parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements);
3696 parseCatchClause = wrapTracking(extra.parseCatchClause);
3697 parseComputedMember = wrapTracking(extra.parseComputedMember);
3698 parseConditionalExpression = wrapTracking(extra.parseConditionalExpression);
3699 parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration);
3700 parseEqualityExpression = wrapTracking(extra.parseEqualityExpression);
3701 parseExpression = wrapTracking(extra.parseExpression);
3702 parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration);
3703 parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration);
3704 parseFunctionExpression = wrapTracking(extra.parseFunctionExpression);
3705 parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression);
3706 parseLogicalANDExpression = wrapTracking(extra.parseLogicalANDExpression);
3707 parseLogicalORExpression = wrapTracking(extra.parseLogicalORExpression);
3708 parseMultiplicativeExpression = wrapTracking(extra.parseMultiplicativeExpression);
3709 parseNewExpression = wrapTracking(extra.parseNewExpression);
3710 parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty);
3711 parseObjectProperty = wrapTracking(extra.parseObjectProperty);
3712 parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey);
3713 parsePostfixExpression = wrapTracking(extra.parsePostfixExpression);
3714 parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression);
3715 parseProgram = wrapTracking(extra.parseProgram);
3716 parsePropertyFunction = wrapTracking(extra.parsePropertyFunction);
3717 parseRelationalExpression = wrapTracking(extra.parseRelationalExpression);
3718 parseStatement = wrapTracking(extra.parseStatement);
3719 parseShiftExpression = wrapTracking(extra.parseShiftExpression);
3720 parseSwitchCase = wrapTracking(extra.parseSwitchCase);
3721 parseUnaryExpression = wrapTracking(extra.parseUnaryExpression);
3722 parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration);
3723 parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier);
3726 if (typeof extra.tokens !== 'undefined') {
3727 extra.advance = advance;
3728 extra.scanRegExp = scanRegExp;
3730 advance = collectToken;
3731 scanRegExp = collectRegex;
3735 function unpatch() {
3736 if (typeof extra.skipComment === 'function') {
3737 skipComment = extra.skipComment;
3741 createLiteral = extra.createLiteral;
3744 if (extra.range || extra.loc) {
3745 parseAdditiveExpression = extra.parseAdditiveExpression;
3746 parseAssignmentExpression = extra.parseAssignmentExpression;
3747 parseBitwiseANDExpression = extra.parseBitwiseANDExpression;
3748 parseBitwiseORExpression = extra.parseBitwiseORExpression;
3749 parseBitwiseXORExpression = extra.parseBitwiseXORExpression;
3750 parseBlock = extra.parseBlock;
3751 parseFunctionSourceElements = extra.parseFunctionSourceElements;
3752 parseCatchClause = extra.parseCatchClause;
3753 parseComputedMember = extra.parseComputedMember;
3754 parseConditionalExpression = extra.parseConditionalExpression;
3755 parseConstLetDeclaration = extra.parseConstLetDeclaration;
3756 parseEqualityExpression = extra.parseEqualityExpression;
3757 parseExpression = extra.parseExpression;
3758 parseForVariableDeclaration = extra.parseForVariableDeclaration;
3759 parseFunctionDeclaration = extra.parseFunctionDeclaration;
3760 parseFunctionExpression = extra.parseFunctionExpression;
3761 parseGroupExpression = extra.parseGroupExpression;
3762 parseLeftHandSideExpression = extra.parseLeftHandSideExpression;
3763 parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall;
3764 parseLogicalANDExpression = extra.parseLogicalANDExpression;
3765 parseLogicalORExpression = extra.parseLogicalORExpression;
3766 parseMultiplicativeExpression = extra.parseMultiplicativeExpression;
3767 parseNewExpression = extra.parseNewExpression;
3768 parseNonComputedProperty = extra.parseNonComputedProperty;
3769 parseObjectProperty = extra.parseObjectProperty;
3770 parseObjectPropertyKey = extra.parseObjectPropertyKey;
3771 parsePrimaryExpression = extra.parsePrimaryExpression;
3772 parsePostfixExpression = extra.parsePostfixExpression;
3773 parseProgram = extra.parseProgram;
3774 parsePropertyFunction = extra.parsePropertyFunction;
3775 parseRelationalExpression = extra.parseRelationalExpression;
3776 parseStatement = extra.parseStatement;
3777 parseShiftExpression = extra.parseShiftExpression;
3778 parseSwitchCase = extra.parseSwitchCase;
3779 parseUnaryExpression = extra.parseUnaryExpression;
3780 parseVariableDeclaration = extra.parseVariableDeclaration;
3781 parseVariableIdentifier = extra.parseVariableIdentifier;
3784 if (typeof extra.scanRegExp === 'function') {
3785 advance = extra.advance;
3786 scanRegExp = extra.scanRegExp;
3790 function stringToArray(str) {
3791 var length = str.length,
3794 for (i = 0; i < length; ++i) {
3795 result[i] = str.charAt(i);
3800 function parse(code, options) {
3801 var program, toString;
3804 if (typeof code !== 'string' && !(code instanceof String)) {
3805 code = toString(code);
3810 lineNumber = (source.length > 0) ? 1 : 0;
3812 length = source.length;
3817 inFunctionBody: false,
3823 if (typeof options !== 'undefined') {
3824 extra.range = (typeof options.range === 'boolean') && options.range;
3825 extra.loc = (typeof options.loc === 'boolean') && options.loc;
3826 extra.raw = (typeof options.raw === 'boolean') && options.raw;
3827 if (typeof options.tokens === 'boolean' && options.tokens) {
3830 if (typeof options.comment === 'boolean' && options.comment) {
3831 extra.comments = [];
3833 if (typeof options.tolerant === 'boolean' && options.tolerant) {
3839 if (typeof source[0] === 'undefined') {
3840 // Try first to convert to a string. This is good as fast path
3841 // for old IE which understands string indexing for string
3842 // literals only and not for string object.
3843 if (code instanceof String) {
3844 source = code.valueOf();
3847 // Force accessing the characters via an array.
3848 if (typeof source[0] === 'undefined') {
3849 source = stringToArray(code);
3856 program = parseProgram();
3857 if (typeof extra.comments !== 'undefined') {
3858 filterCommentLocation();
3859 program.comments = extra.comments;
3861 if (typeof extra.tokens !== 'undefined') {
3862 filterTokenLocation();
3863 program.tokens = extra.tokens;
3865 if (typeof extra.errors !== 'undefined') {
3866 program.errors = extra.errors;
3868 if (extra.range || extra.loc) {
3869 program.body = filterGroup(program.body);
3881 // Sync with package.json.
3882 exports.version = '1.0.4';
3884 exports.parse = parse;
3887 exports.Syntax = (function () {
3888 var name, types = {};
3890 if (typeof Object.create === 'function') {
3891 types = Object.create(null);
3894 for (name in Syntax) {
3895 if (Syntax.hasOwnProperty(name)) {
3896 types[name] = Syntax[name];
3900 if (typeof Object.freeze === 'function') {
3901 Object.freeze(types);
3908 /* vim: set sw=4 ts=4 et tw=80 : */