Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / istanbul / node_modules / esprima / esprima.js
1 /*
2   Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
3
4   Redistribution and use in source and binary forms, with or without
5   modification, are permitted provided that the following conditions are met:
6
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in the
11       documentation and/or other materials provided with the distribution.
12
13   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16   ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
17   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25 (function (root, factory) {
26     'use strict';
27
28     // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
29     // Rhino, and plain browser loading.
30
31     /* istanbul ignore next */
32     if (typeof define === 'function' && define.amd) {
33         define(['exports'], factory);
34     } else if (typeof exports !== 'undefined') {
35         factory(exports);
36     } else {
37         factory((root.esprima = {}));
38     }
39 }(this, function (exports) {
40     'use strict';
41
42     var Token,
43         TokenName,
44         FnExprTokens,
45         Syntax,
46         PlaceHolders,
47         Messages,
48         Regex,
49         source,
50         strict,
51         sourceType,
52         index,
53         lineNumber,
54         lineStart,
55         hasLineTerminator,
56         lastIndex,
57         lastLineNumber,
58         lastLineStart,
59         startIndex,
60         startLineNumber,
61         startLineStart,
62         scanning,
63         length,
64         lookahead,
65         state,
66         extra,
67         isBindingElement,
68         isAssignmentTarget,
69         firstCoverInitializedNameError;
70
71     Token = {
72         BooleanLiteral: 1,
73         EOF: 2,
74         Identifier: 3,
75         Keyword: 4,
76         NullLiteral: 5,
77         NumericLiteral: 6,
78         Punctuator: 7,
79         StringLiteral: 8,
80         RegularExpression: 9,
81         Template: 10
82     };
83
84     TokenName = {};
85     TokenName[Token.BooleanLiteral] = 'Boolean';
86     TokenName[Token.EOF] = '<end>';
87     TokenName[Token.Identifier] = 'Identifier';
88     TokenName[Token.Keyword] = 'Keyword';
89     TokenName[Token.NullLiteral] = 'Null';
90     TokenName[Token.NumericLiteral] = 'Numeric';
91     TokenName[Token.Punctuator] = 'Punctuator';
92     TokenName[Token.StringLiteral] = 'String';
93     TokenName[Token.RegularExpression] = 'RegularExpression';
94     TokenName[Token.Template] = 'Template';
95
96     // A function following one of those tokens is an expression.
97     FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
98                     'return', 'case', 'delete', 'throw', 'void',
99                     // assignment operators
100                     '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=',
101                     '&=', '|=', '^=', ',',
102                     // binary/unary operators
103                     '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&',
104                     '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=',
105                     '<=', '<', '>', '!=', '!=='];
106
107     Syntax = {
108         AssignmentExpression: 'AssignmentExpression',
109         AssignmentPattern: 'AssignmentPattern',
110         ArrayExpression: 'ArrayExpression',
111         ArrayPattern: 'ArrayPattern',
112         ArrowFunctionExpression: 'ArrowFunctionExpression',
113         BlockStatement: 'BlockStatement',
114         BinaryExpression: 'BinaryExpression',
115         BreakStatement: 'BreakStatement',
116         CallExpression: 'CallExpression',
117         CatchClause: 'CatchClause',
118         ClassBody: 'ClassBody',
119         ClassDeclaration: 'ClassDeclaration',
120         ClassExpression: 'ClassExpression',
121         ConditionalExpression: 'ConditionalExpression',
122         ContinueStatement: 'ContinueStatement',
123         DoWhileStatement: 'DoWhileStatement',
124         DebuggerStatement: 'DebuggerStatement',
125         EmptyStatement: 'EmptyStatement',
126         ExportAllDeclaration: 'ExportAllDeclaration',
127         ExportDefaultDeclaration: 'ExportDefaultDeclaration',
128         ExportNamedDeclaration: 'ExportNamedDeclaration',
129         ExportSpecifier: 'ExportSpecifier',
130         ExpressionStatement: 'ExpressionStatement',
131         ForStatement: 'ForStatement',
132         ForOfStatement: 'ForOfStatement',
133         ForInStatement: 'ForInStatement',
134         FunctionDeclaration: 'FunctionDeclaration',
135         FunctionExpression: 'FunctionExpression',
136         Identifier: 'Identifier',
137         IfStatement: 'IfStatement',
138         ImportDeclaration: 'ImportDeclaration',
139         ImportDefaultSpecifier: 'ImportDefaultSpecifier',
140         ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
141         ImportSpecifier: 'ImportSpecifier',
142         Literal: 'Literal',
143         LabeledStatement: 'LabeledStatement',
144         LogicalExpression: 'LogicalExpression',
145         MemberExpression: 'MemberExpression',
146         MetaProperty: 'MetaProperty',
147         MethodDefinition: 'MethodDefinition',
148         NewExpression: 'NewExpression',
149         ObjectExpression: 'ObjectExpression',
150         ObjectPattern: 'ObjectPattern',
151         Program: 'Program',
152         Property: 'Property',
153         RestElement: 'RestElement',
154         ReturnStatement: 'ReturnStatement',
155         SequenceExpression: 'SequenceExpression',
156         SpreadElement: 'SpreadElement',
157         Super: 'Super',
158         SwitchCase: 'SwitchCase',
159         SwitchStatement: 'SwitchStatement',
160         TaggedTemplateExpression: 'TaggedTemplateExpression',
161         TemplateElement: 'TemplateElement',
162         TemplateLiteral: 'TemplateLiteral',
163         ThisExpression: 'ThisExpression',
164         ThrowStatement: 'ThrowStatement',
165         TryStatement: 'TryStatement',
166         UnaryExpression: 'UnaryExpression',
167         UpdateExpression: 'UpdateExpression',
168         VariableDeclaration: 'VariableDeclaration',
169         VariableDeclarator: 'VariableDeclarator',
170         WhileStatement: 'WhileStatement',
171         WithStatement: 'WithStatement',
172         YieldExpression: 'YieldExpression'
173     };
174
175     PlaceHolders = {
176         ArrowParameterPlaceHolder: 'ArrowParameterPlaceHolder'
177     };
178
179     // Error messages should be identical to V8.
180     Messages = {
181         UnexpectedToken: 'Unexpected token %0',
182         UnexpectedNumber: 'Unexpected number',
183         UnexpectedString: 'Unexpected string',
184         UnexpectedIdentifier: 'Unexpected identifier',
185         UnexpectedReserved: 'Unexpected reserved word',
186         UnexpectedTemplate: 'Unexpected quasi %0',
187         UnexpectedEOS: 'Unexpected end of input',
188         NewlineAfterThrow: 'Illegal newline after throw',
189         InvalidRegExp: 'Invalid regular expression',
190         UnterminatedRegExp: 'Invalid regular expression: missing /',
191         InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
192         InvalidLHSInForIn: 'Invalid left-hand side in for-in',
193         InvalidLHSInForLoop: 'Invalid left-hand side in for-loop',
194         MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
195         NoCatchOrFinally: 'Missing catch or finally after try',
196         UnknownLabel: 'Undefined label \'%0\'',
197         Redeclaration: '%0 \'%1\' has already been declared',
198         IllegalContinue: 'Illegal continue statement',
199         IllegalBreak: 'Illegal break statement',
200         IllegalReturn: 'Illegal return statement',
201         StrictModeWith: 'Strict mode code may not include a with statement',
202         StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
203         StrictVarName: 'Variable name may not be eval or arguments in strict mode',
204         StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
205         StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
206         StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
207         StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
208         StrictDelete: 'Delete of an unqualified identifier in strict mode.',
209         StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
210         StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
211         StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
212         StrictReservedWord: 'Use of future reserved word in strict mode',
213         TemplateOctalLiteral: 'Octal literals are not allowed in template strings.',
214         ParameterAfterRestParameter: 'Rest parameter must be last formal parameter',
215         DefaultRestParameter: 'Unexpected token =',
216         ObjectPatternAsRestParameter: 'Unexpected token {',
217         DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals',
218         ConstructorSpecialMethod: 'Class constructor may not be an accessor',
219         DuplicateConstructor: 'A class may only have one constructor',
220         StaticPrototype: 'Classes may not have static property named prototype',
221         MissingFromClause: 'Unexpected token',
222         NoAsAfterImportNamespace: 'Unexpected token',
223         InvalidModuleSpecifier: 'Unexpected token',
224         IllegalImportDeclaration: 'Unexpected token',
225         IllegalExportDeclaration: 'Unexpected token',
226         DuplicateBinding: 'Duplicate binding %0'
227     };
228
229     // See also tools/generate-unicode-regex.js.
230     Regex = {
231         // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart:
232         NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\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-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\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-\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-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\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\u2118-\u211D\u2124\u2126\u2128\u212A-\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\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\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-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\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]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/,
233
234         // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart:
235         NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\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-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\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\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\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\u0D01-\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\u0DE6-\u0DEF\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\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\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-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\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\u2118-\u211D\u2124\u2126\u2128\u212A-\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\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\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-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\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-\uFE2D\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]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
236     };
237
238     // Ensure the condition is true, otherwise throw an error.
239     // This is only to have a better contract semantic, i.e. another safety net
240     // to catch a logic error. The condition shall be fulfilled in normal case.
241     // Do NOT use this to enforce a certain condition on any user input.
242
243     function assert(condition, message) {
244         /* istanbul ignore if */
245         if (!condition) {
246             throw new Error('ASSERT: ' + message);
247         }
248     }
249
250     function isDecimalDigit(ch) {
251         return (ch >= 0x30 && ch <= 0x39);   // 0..9
252     }
253
254     function isHexDigit(ch) {
255         return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
256     }
257
258     function isOctalDigit(ch) {
259         return '01234567'.indexOf(ch) >= 0;
260     }
261
262     function octalToDecimal(ch) {
263         // \0 is not octal escape sequence
264         var octal = (ch !== '0'), code = '01234567'.indexOf(ch);
265
266         if (index < length && isOctalDigit(source[index])) {
267             octal = true;
268             code = code * 8 + '01234567'.indexOf(source[index++]);
269
270             // 3 digits are only allowed when string starts
271             // with 0, 1, 2, 3
272             if ('0123'.indexOf(ch) >= 0 &&
273                     index < length &&
274                     isOctalDigit(source[index])) {
275                 code = code * 8 + '01234567'.indexOf(source[index++]);
276             }
277         }
278
279         return {
280             code: code,
281             octal: octal
282         };
283     }
284
285     // ECMA-262 11.2 White Space
286
287     function isWhiteSpace(ch) {
288         return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) ||
289             (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0);
290     }
291
292     // ECMA-262 11.3 Line Terminators
293
294     function isLineTerminator(ch) {
295         return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029);
296     }
297
298     // ECMA-262 11.6 Identifier Names and Identifiers
299
300     function fromCodePoint(cp) {
301         return (cp < 0x10000) ? String.fromCharCode(cp) :
302             String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) +
303             String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023));
304     }
305
306     function isIdentifierStart(ch) {
307         return (ch === 0x24) || (ch === 0x5F) ||  // $ (dollar) and _ (underscore)
308             (ch >= 0x41 && ch <= 0x5A) ||         // A..Z
309             (ch >= 0x61 && ch <= 0x7A) ||         // a..z
310             (ch === 0x5C) ||                      // \ (backslash)
311             ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch)));
312     }
313
314     function isIdentifierPart(ch) {
315         return (ch === 0x24) || (ch === 0x5F) ||  // $ (dollar) and _ (underscore)
316             (ch >= 0x41 && ch <= 0x5A) ||         // A..Z
317             (ch >= 0x61 && ch <= 0x7A) ||         // a..z
318             (ch >= 0x30 && ch <= 0x39) ||         // 0..9
319             (ch === 0x5C) ||                      // \ (backslash)
320             ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch)));
321     }
322
323     // ECMA-262 11.6.2.2 Future Reserved Words
324
325     function isFutureReservedWord(id) {
326         switch (id) {
327         case 'enum':
328         case 'export':
329         case 'import':
330         case 'super':
331             return true;
332         default:
333             return false;
334         }
335     }
336
337     function isStrictModeReservedWord(id) {
338         switch (id) {
339         case 'implements':
340         case 'interface':
341         case 'package':
342         case 'private':
343         case 'protected':
344         case 'public':
345         case 'static':
346         case 'yield':
347         case 'let':
348             return true;
349         default:
350             return false;
351         }
352     }
353
354     function isRestrictedWord(id) {
355         return id === 'eval' || id === 'arguments';
356     }
357
358     // ECMA-262 11.6.2.1 Keywords
359
360     function isKeyword(id) {
361
362         // 'const' is specialized as Keyword in V8.
363         // 'yield' and 'let' are for compatibility with SpiderMonkey and ES.next.
364         // Some others are from future reserved words.
365
366         switch (id.length) {
367         case 2:
368             return (id === 'if') || (id === 'in') || (id === 'do');
369         case 3:
370             return (id === 'var') || (id === 'for') || (id === 'new') ||
371                 (id === 'try') || (id === 'let');
372         case 4:
373             return (id === 'this') || (id === 'else') || (id === 'case') ||
374                 (id === 'void') || (id === 'with') || (id === 'enum');
375         case 5:
376             return (id === 'while') || (id === 'break') || (id === 'catch') ||
377                 (id === 'throw') || (id === 'const') || (id === 'yield') ||
378                 (id === 'class') || (id === 'super');
379         case 6:
380             return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
381                 (id === 'switch') || (id === 'export') || (id === 'import');
382         case 7:
383             return (id === 'default') || (id === 'finally') || (id === 'extends');
384         case 8:
385             return (id === 'function') || (id === 'continue') || (id === 'debugger');
386         case 10:
387             return (id === 'instanceof');
388         default:
389             return false;
390         }
391     }
392
393     // ECMA-262 11.4 Comments
394
395     function addComment(type, value, start, end, loc) {
396         var comment;
397
398         assert(typeof start === 'number', 'Comment must have valid position');
399
400         state.lastCommentStart = start;
401
402         comment = {
403             type: type,
404             value: value
405         };
406         if (extra.range) {
407             comment.range = [start, end];
408         }
409         if (extra.loc) {
410             comment.loc = loc;
411         }
412         extra.comments.push(comment);
413         if (extra.attachComment) {
414             extra.leadingComments.push(comment);
415             extra.trailingComments.push(comment);
416         }
417     }
418
419     function skipSingleLineComment(offset) {
420         var start, loc, ch, comment;
421
422         start = index - offset;
423         loc = {
424             start: {
425                 line: lineNumber,
426                 column: index - lineStart - offset
427             }
428         };
429
430         while (index < length) {
431             ch = source.charCodeAt(index);
432             ++index;
433             if (isLineTerminator(ch)) {
434                 hasLineTerminator = true;
435                 if (extra.comments) {
436                     comment = source.slice(start + offset, index - 1);
437                     loc.end = {
438                         line: lineNumber,
439                         column: index - lineStart - 1
440                     };
441                     addComment('Line', comment, start, index - 1, loc);
442                 }
443                 if (ch === 13 && source.charCodeAt(index) === 10) {
444                     ++index;
445                 }
446                 ++lineNumber;
447                 lineStart = index;
448                 return;
449             }
450         }
451
452         if (extra.comments) {
453             comment = source.slice(start + offset, index);
454             loc.end = {
455                 line: lineNumber,
456                 column: index - lineStart
457             };
458             addComment('Line', comment, start, index, loc);
459         }
460     }
461
462     function skipMultiLineComment() {
463         var start, loc, ch, comment;
464
465         if (extra.comments) {
466             start = index - 2;
467             loc = {
468                 start: {
469                     line: lineNumber,
470                     column: index - lineStart - 2
471                 }
472             };
473         }
474
475         while (index < length) {
476             ch = source.charCodeAt(index);
477             if (isLineTerminator(ch)) {
478                 if (ch === 0x0D && source.charCodeAt(index + 1) === 0x0A) {
479                     ++index;
480                 }
481                 hasLineTerminator = true;
482                 ++lineNumber;
483                 ++index;
484                 lineStart = index;
485             } else if (ch === 0x2A) {
486                 // Block comment ends with '*/'.
487                 if (source.charCodeAt(index + 1) === 0x2F) {
488                     ++index;
489                     ++index;
490                     if (extra.comments) {
491                         comment = source.slice(start + 2, index - 2);
492                         loc.end = {
493                             line: lineNumber,
494                             column: index - lineStart
495                         };
496                         addComment('Block', comment, start, index, loc);
497                     }
498                     return;
499                 }
500                 ++index;
501             } else {
502                 ++index;
503             }
504         }
505
506         // Ran off the end of the file - the whole thing is a comment
507         if (extra.comments) {
508             loc.end = {
509                 line: lineNumber,
510                 column: index - lineStart
511             };
512             comment = source.slice(start + 2, index);
513             addComment('Block', comment, start, index, loc);
514         }
515         tolerateUnexpectedToken();
516     }
517
518     function skipComment() {
519         var ch, start;
520         hasLineTerminator = false;
521
522         start = (index === 0);
523         while (index < length) {
524             ch = source.charCodeAt(index);
525
526             if (isWhiteSpace(ch)) {
527                 ++index;
528             } else if (isLineTerminator(ch)) {
529                 hasLineTerminator = true;
530                 ++index;
531                 if (ch === 0x0D && source.charCodeAt(index) === 0x0A) {
532                     ++index;
533                 }
534                 ++lineNumber;
535                 lineStart = index;
536                 start = true;
537             } else if (ch === 0x2F) { // U+002F is '/'
538                 ch = source.charCodeAt(index + 1);
539                 if (ch === 0x2F) {
540                     ++index;
541                     ++index;
542                     skipSingleLineComment(2);
543                     start = true;
544                 } else if (ch === 0x2A) {  // U+002A is '*'
545                     ++index;
546                     ++index;
547                     skipMultiLineComment();
548                 } else {
549                     break;
550                 }
551             } else if (start && ch === 0x2D) { // U+002D is '-'
552                 // U+003E is '>'
553                 if ((source.charCodeAt(index + 1) === 0x2D) && (source.charCodeAt(index + 2) === 0x3E)) {
554                     // '-->' is a single-line comment
555                     index += 3;
556                     skipSingleLineComment(3);
557                 } else {
558                     break;
559                 }
560             } else if (ch === 0x3C) { // U+003C is '<'
561                 if (source.slice(index + 1, index + 4) === '!--') {
562                     ++index; // `<`
563                     ++index; // `!`
564                     ++index; // `-`
565                     ++index; // `-`
566                     skipSingleLineComment(4);
567                 } else {
568                     break;
569                 }
570             } else {
571                 break;
572             }
573         }
574     }
575
576     function scanHexEscape(prefix) {
577         var i, len, ch, code = 0;
578
579         len = (prefix === 'u') ? 4 : 2;
580         for (i = 0; i < len; ++i) {
581             if (index < length && isHexDigit(source[index])) {
582                 ch = source[index++];
583                 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
584             } else {
585                 return '';
586             }
587         }
588         return String.fromCharCode(code);
589     }
590
591     function scanUnicodeCodePointEscape() {
592         var ch, code;
593
594         ch = source[index];
595         code = 0;
596
597         // At least, one hex digit is required.
598         if (ch === '}') {
599             throwUnexpectedToken();
600         }
601
602         while (index < length) {
603             ch = source[index++];
604             if (!isHexDigit(ch)) {
605                 break;
606             }
607             code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
608         }
609
610         if (code > 0x10FFFF || ch !== '}') {
611             throwUnexpectedToken();
612         }
613
614         return fromCodePoint(code);
615     }
616
617     function codePointAt(i) {
618         var cp, first, second;
619
620         cp = source.charCodeAt(i);
621         if (cp >= 0xD800 && cp <= 0xDBFF) {
622             second = source.charCodeAt(i + 1);
623             if (second >= 0xDC00 && second <= 0xDFFF) {
624                 first = cp;
625                 cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
626             }
627         }
628
629         return cp;
630     }
631
632     function getComplexIdentifier() {
633         var cp, ch, id;
634
635         cp = codePointAt(index);
636         id = fromCodePoint(cp);
637         index += id.length;
638
639         // '\u' (U+005C, U+0075) denotes an escaped character.
640         if (cp === 0x5C) {
641             if (source.charCodeAt(index) !== 0x75) {
642                 throwUnexpectedToken();
643             }
644             ++index;
645             if (source[index] === '{') {
646                 ++index;
647                 ch = scanUnicodeCodePointEscape();
648             } else {
649                 ch = scanHexEscape('u');
650                 cp = ch.charCodeAt(0);
651                 if (!ch || ch === '\\' || !isIdentifierStart(cp)) {
652                     throwUnexpectedToken();
653                 }
654             }
655             id = ch;
656         }
657
658         while (index < length) {
659             cp = codePointAt(index);
660             if (!isIdentifierPart(cp)) {
661                 break;
662             }
663             ch = fromCodePoint(cp);
664             id += ch;
665             index += ch.length;
666
667             // '\u' (U+005C, U+0075) denotes an escaped character.
668             if (cp === 0x5C) {
669                 id = id.substr(0, id.length - 1);
670                 if (source.charCodeAt(index) !== 0x75) {
671                     throwUnexpectedToken();
672                 }
673                 ++index;
674                 if (source[index] === '{') {
675                     ++index;
676                     ch = scanUnicodeCodePointEscape();
677                 } else {
678                     ch = scanHexEscape('u');
679                     cp = ch.charCodeAt(0);
680                     if (!ch || ch === '\\' || !isIdentifierPart(cp)) {
681                         throwUnexpectedToken();
682                     }
683                 }
684                 id += ch;
685             }
686         }
687
688         return id;
689     }
690
691     function getIdentifier() {
692         var start, ch;
693
694         start = index++;
695         while (index < length) {
696             ch = source.charCodeAt(index);
697             if (ch === 0x5C) {
698                 // Blackslash (U+005C) marks Unicode escape sequence.
699                 index = start;
700                 return getComplexIdentifier();
701             } else if (ch >= 0xD800 && ch < 0xDFFF) {
702                 // Need to handle surrogate pairs.
703                 index = start;
704                 return getComplexIdentifier();
705             }
706             if (isIdentifierPart(ch)) {
707                 ++index;
708             } else {
709                 break;
710             }
711         }
712
713         return source.slice(start, index);
714     }
715
716     function scanIdentifier() {
717         var start, id, type;
718
719         start = index;
720
721         // Backslash (U+005C) starts an escaped character.
722         id = (source.charCodeAt(index) === 0x5C) ? getComplexIdentifier() : getIdentifier();
723
724         // There is no keyword or literal with only one character.
725         // Thus, it must be an identifier.
726         if (id.length === 1) {
727             type = Token.Identifier;
728         } else if (isKeyword(id)) {
729             type = Token.Keyword;
730         } else if (id === 'null') {
731             type = Token.NullLiteral;
732         } else if (id === 'true' || id === 'false') {
733             type = Token.BooleanLiteral;
734         } else {
735             type = Token.Identifier;
736         }
737
738         return {
739             type: type,
740             value: id,
741             lineNumber: lineNumber,
742             lineStart: lineStart,
743             start: start,
744             end: index
745         };
746     }
747
748
749     // ECMA-262 11.7 Punctuators
750
751     function scanPunctuator() {
752         var token, str;
753
754         token = {
755             type: Token.Punctuator,
756             value: '',
757             lineNumber: lineNumber,
758             lineStart: lineStart,
759             start: index,
760             end: index
761         };
762
763         // Check for most common single-character punctuators.
764         str = source[index];
765         switch (str) {
766
767         case '(':
768             if (extra.tokenize) {
769                 extra.openParenToken = extra.tokens.length;
770             }
771             ++index;
772             break;
773
774         case '{':
775             if (extra.tokenize) {
776                 extra.openCurlyToken = extra.tokens.length;
777             }
778             state.curlyStack.push('{');
779             ++index;
780             break;
781
782         case '.':
783             ++index;
784             if (source[index] === '.' && source[index + 1] === '.') {
785                 // Spread operator: ...
786                 index += 2;
787                 str = '...';
788             }
789             break;
790
791         case '}':
792             ++index;
793             state.curlyStack.pop();
794             break;
795         case ')':
796         case ';':
797         case ',':
798         case '[':
799         case ']':
800         case ':':
801         case '?':
802         case '~':
803             ++index;
804             break;
805
806         default:
807             // 4-character punctuator.
808             str = source.substr(index, 4);
809             if (str === '>>>=') {
810                 index += 4;
811             } else {
812
813                 // 3-character punctuators.
814                 str = str.substr(0, 3);
815                 if (str === '===' || str === '!==' || str === '>>>' ||
816                     str === '<<=' || str === '>>=') {
817                     index += 3;
818                 } else {
819
820                     // 2-character punctuators.
821                     str = str.substr(0, 2);
822                     if (str === '&&' || str === '||' || str === '==' || str === '!=' ||
823                         str === '+=' || str === '-=' || str === '*=' || str === '/=' ||
824                         str === '++' || str === '--' || str === '<<' || str === '>>' ||
825                         str === '&=' || str === '|=' || str === '^=' || str === '%=' ||
826                         str === '<=' || str === '>=' || str === '=>') {
827                         index += 2;
828                     } else {
829
830                         // 1-character punctuators.
831                         str = source[index];
832                         if ('<>=!+-*%&|^/'.indexOf(str) >= 0) {
833                             ++index;
834                         }
835                     }
836                 }
837             }
838         }
839
840         if (index === token.start) {
841             throwUnexpectedToken();
842         }
843
844         token.end = index;
845         token.value = str;
846         return token;
847     }
848
849     // ECMA-262 11.8.3 Numeric Literals
850
851     function scanHexLiteral(start) {
852         var number = '';
853
854         while (index < length) {
855             if (!isHexDigit(source[index])) {
856                 break;
857             }
858             number += source[index++];
859         }
860
861         if (number.length === 0) {
862             throwUnexpectedToken();
863         }
864
865         if (isIdentifierStart(source.charCodeAt(index))) {
866             throwUnexpectedToken();
867         }
868
869         return {
870             type: Token.NumericLiteral,
871             value: parseInt('0x' + number, 16),
872             lineNumber: lineNumber,
873             lineStart: lineStart,
874             start: start,
875             end: index
876         };
877     }
878
879     function scanBinaryLiteral(start) {
880         var ch, number;
881
882         number = '';
883
884         while (index < length) {
885             ch = source[index];
886             if (ch !== '0' && ch !== '1') {
887                 break;
888             }
889             number += source[index++];
890         }
891
892         if (number.length === 0) {
893             // only 0b or 0B
894             throwUnexpectedToken();
895         }
896
897         if (index < length) {
898             ch = source.charCodeAt(index);
899             /* istanbul ignore else */
900             if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
901                 throwUnexpectedToken();
902             }
903         }
904
905         return {
906             type: Token.NumericLiteral,
907             value: parseInt(number, 2),
908             lineNumber: lineNumber,
909             lineStart: lineStart,
910             start: start,
911             end: index
912         };
913     }
914
915     function scanOctalLiteral(prefix, start) {
916         var number, octal;
917
918         if (isOctalDigit(prefix)) {
919             octal = true;
920             number = '0' + source[index++];
921         } else {
922             octal = false;
923             ++index;
924             number = '';
925         }
926
927         while (index < length) {
928             if (!isOctalDigit(source[index])) {
929                 break;
930             }
931             number += source[index++];
932         }
933
934         if (!octal && number.length === 0) {
935             // only 0o or 0O
936             throwUnexpectedToken();
937         }
938
939         if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
940             throwUnexpectedToken();
941         }
942
943         return {
944             type: Token.NumericLiteral,
945             value: parseInt(number, 8),
946             octal: octal,
947             lineNumber: lineNumber,
948             lineStart: lineStart,
949             start: start,
950             end: index
951         };
952     }
953
954     function isImplicitOctalLiteral() {
955         var i, ch;
956
957         // Implicit octal, unless there is a non-octal digit.
958         // (Annex B.1.1 on Numeric Literals)
959         for (i = index + 1; i < length; ++i) {
960             ch = source[i];
961             if (ch === '8' || ch === '9') {
962                 return false;
963             }
964             if (!isOctalDigit(ch)) {
965                 return true;
966             }
967         }
968
969         return true;
970     }
971
972     function scanNumericLiteral() {
973         var number, start, ch;
974
975         ch = source[index];
976         assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
977             'Numeric literal must start with a decimal digit or a decimal point');
978
979         start = index;
980         number = '';
981         if (ch !== '.') {
982             number = source[index++];
983             ch = source[index];
984
985             // Hex number starts with '0x'.
986             // Octal number starts with '0'.
987             // Octal number in ES6 starts with '0o'.
988             // Binary number in ES6 starts with '0b'.
989             if (number === '0') {
990                 if (ch === 'x' || ch === 'X') {
991                     ++index;
992                     return scanHexLiteral(start);
993                 }
994                 if (ch === 'b' || ch === 'B') {
995                     ++index;
996                     return scanBinaryLiteral(start);
997                 }
998                 if (ch === 'o' || ch === 'O') {
999                     return scanOctalLiteral(ch, start);
1000                 }
1001
1002                 if (isOctalDigit(ch)) {
1003                     if (isImplicitOctalLiteral()) {
1004                         return scanOctalLiteral(ch, start);
1005                     }
1006                 }
1007             }
1008
1009             while (isDecimalDigit(source.charCodeAt(index))) {
1010                 number += source[index++];
1011             }
1012             ch = source[index];
1013         }
1014
1015         if (ch === '.') {
1016             number += source[index++];
1017             while (isDecimalDigit(source.charCodeAt(index))) {
1018                 number += source[index++];
1019             }
1020             ch = source[index];
1021         }
1022
1023         if (ch === 'e' || ch === 'E') {
1024             number += source[index++];
1025
1026             ch = source[index];
1027             if (ch === '+' || ch === '-') {
1028                 number += source[index++];
1029             }
1030             if (isDecimalDigit(source.charCodeAt(index))) {
1031                 while (isDecimalDigit(source.charCodeAt(index))) {
1032                     number += source[index++];
1033                 }
1034             } else {
1035                 throwUnexpectedToken();
1036             }
1037         }
1038
1039         if (isIdentifierStart(source.charCodeAt(index))) {
1040             throwUnexpectedToken();
1041         }
1042
1043         return {
1044             type: Token.NumericLiteral,
1045             value: parseFloat(number),
1046             lineNumber: lineNumber,
1047             lineStart: lineStart,
1048             start: start,
1049             end: index
1050         };
1051     }
1052
1053     // ECMA-262 11.8.4 String Literals
1054
1055     function scanStringLiteral() {
1056         var str = '', quote, start, ch, unescaped, octToDec, octal = false;
1057
1058         quote = source[index];
1059         assert((quote === '\'' || quote === '"'),
1060             'String literal must starts with a quote');
1061
1062         start = index;
1063         ++index;
1064
1065         while (index < length) {
1066             ch = source[index++];
1067
1068             if (ch === quote) {
1069                 quote = '';
1070                 break;
1071             } else if (ch === '\\') {
1072                 ch = source[index++];
1073                 if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
1074                     switch (ch) {
1075                     case 'u':
1076                     case 'x':
1077                         if (source[index] === '{') {
1078                             ++index;
1079                             str += scanUnicodeCodePointEscape();
1080                         } else {
1081                             unescaped = scanHexEscape(ch);
1082                             if (!unescaped) {
1083                                 throw throwUnexpectedToken();
1084                             }
1085                             str += unescaped;
1086                         }
1087                         break;
1088                     case 'n':
1089                         str += '\n';
1090                         break;
1091                     case 'r':
1092                         str += '\r';
1093                         break;
1094                     case 't':
1095                         str += '\t';
1096                         break;
1097                     case 'b':
1098                         str += '\b';
1099                         break;
1100                     case 'f':
1101                         str += '\f';
1102                         break;
1103                     case 'v':
1104                         str += '\x0B';
1105                         break;
1106                     case '8':
1107                     case '9':
1108                         str += ch;
1109                         tolerateUnexpectedToken();
1110                         break;
1111
1112                     default:
1113                         if (isOctalDigit(ch)) {
1114                             octToDec = octalToDecimal(ch);
1115
1116                             octal = octToDec.octal || octal;
1117                             str += String.fromCharCode(octToDec.code);
1118                         } else {
1119                             str += ch;
1120                         }
1121                         break;
1122                     }
1123                 } else {
1124                     ++lineNumber;
1125                     if (ch === '\r' && source[index] === '\n') {
1126                         ++index;
1127                     }
1128                     lineStart = index;
1129                 }
1130             } else if (isLineTerminator(ch.charCodeAt(0))) {
1131                 break;
1132             } else {
1133                 str += ch;
1134             }
1135         }
1136
1137         if (quote !== '') {
1138             throwUnexpectedToken();
1139         }
1140
1141         return {
1142             type: Token.StringLiteral,
1143             value: str,
1144             octal: octal,
1145             lineNumber: startLineNumber,
1146             lineStart: startLineStart,
1147             start: start,
1148             end: index
1149         };
1150     }
1151
1152     // ECMA-262 11.8.6 Template Literal Lexical Components
1153
1154     function scanTemplate() {
1155         var cooked = '', ch, start, rawOffset, terminated, head, tail, restore, unescaped;
1156
1157         terminated = false;
1158         tail = false;
1159         start = index;
1160         head = (source[index] === '`');
1161         rawOffset = 2;
1162
1163         ++index;
1164
1165         while (index < length) {
1166             ch = source[index++];
1167             if (ch === '`') {
1168                 rawOffset = 1;
1169                 tail = true;
1170                 terminated = true;
1171                 break;
1172             } else if (ch === '$') {
1173                 if (source[index] === '{') {
1174                     state.curlyStack.push('${');
1175                     ++index;
1176                     terminated = true;
1177                     break;
1178                 }
1179                 cooked += ch;
1180             } else if (ch === '\\') {
1181                 ch = source[index++];
1182                 if (!isLineTerminator(ch.charCodeAt(0))) {
1183                     switch (ch) {
1184                     case 'n':
1185                         cooked += '\n';
1186                         break;
1187                     case 'r':
1188                         cooked += '\r';
1189                         break;
1190                     case 't':
1191                         cooked += '\t';
1192                         break;
1193                     case 'u':
1194                     case 'x':
1195                         if (source[index] === '{') {
1196                             ++index;
1197                             cooked += scanUnicodeCodePointEscape();
1198                         } else {
1199                             restore = index;
1200                             unescaped = scanHexEscape(ch);
1201                             if (unescaped) {
1202                                 cooked += unescaped;
1203                             } else {
1204                                 index = restore;
1205                                 cooked += ch;
1206                             }
1207                         }
1208                         break;
1209                     case 'b':
1210                         cooked += '\b';
1211                         break;
1212                     case 'f':
1213                         cooked += '\f';
1214                         break;
1215                     case 'v':
1216                         cooked += '\v';
1217                         break;
1218
1219                     default:
1220                         if (ch === '0') {
1221                             if (isDecimalDigit(source.charCodeAt(index))) {
1222                                 // Illegal: \01 \02 and so on
1223                                 throwError(Messages.TemplateOctalLiteral);
1224                             }
1225                             cooked += '\0';
1226                         } else if (isOctalDigit(ch)) {
1227                             // Illegal: \1 \2
1228                             throwError(Messages.TemplateOctalLiteral);
1229                         } else {
1230                             cooked += ch;
1231                         }
1232                         break;
1233                     }
1234                 } else {
1235                     ++lineNumber;
1236                     if (ch === '\r' && source[index] === '\n') {
1237                         ++index;
1238                     }
1239                     lineStart = index;
1240                 }
1241             } else if (isLineTerminator(ch.charCodeAt(0))) {
1242                 ++lineNumber;
1243                 if (ch === '\r' && source[index] === '\n') {
1244                     ++index;
1245                 }
1246                 lineStart = index;
1247                 cooked += '\n';
1248             } else {
1249                 cooked += ch;
1250             }
1251         }
1252
1253         if (!terminated) {
1254             throwUnexpectedToken();
1255         }
1256
1257         if (!head) {
1258             state.curlyStack.pop();
1259         }
1260
1261         return {
1262             type: Token.Template,
1263             value: {
1264                 cooked: cooked,
1265                 raw: source.slice(start + 1, index - rawOffset)
1266             },
1267             head: head,
1268             tail: tail,
1269             lineNumber: lineNumber,
1270             lineStart: lineStart,
1271             start: start,
1272             end: index
1273         };
1274     }
1275
1276     // ECMA-262 11.8.5 Regular Expression Literals
1277
1278     function testRegExp(pattern, flags) {
1279         // The BMP character to use as a replacement for astral symbols when
1280         // translating an ES6 "u"-flagged pattern to an ES5-compatible
1281         // approximation.
1282         // Note: replacing with '\uFFFF' enables false positives in unlikely
1283         // scenarios. For example, `[\u{1044f}-\u{10440}]` is an invalid
1284         // pattern that would not be detected by this substitution.
1285         var astralSubstitute = '\uFFFF',
1286             tmp = pattern;
1287
1288         if (flags.indexOf('u') >= 0) {
1289             tmp = tmp
1290                 // Replace every Unicode escape sequence with the equivalent
1291                 // BMP character or a constant ASCII code point in the case of
1292                 // astral symbols. (See the above note on `astralSubstitute`
1293                 // for more information.)
1294                 .replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, function ($0, $1, $2) {
1295                     var codePoint = parseInt($1 || $2, 16);
1296                     if (codePoint > 0x10FFFF) {
1297                         throwUnexpectedToken(null, Messages.InvalidRegExp);
1298                     }
1299                     if (codePoint <= 0xFFFF) {
1300                         return String.fromCharCode(codePoint);
1301                     }
1302                     return astralSubstitute;
1303                 })
1304                 // Replace each paired surrogate with a single ASCII symbol to
1305                 // avoid throwing on regular expressions that are only valid in
1306                 // combination with the "u" flag.
1307                 .replace(
1308                     /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
1309                     astralSubstitute
1310                 );
1311         }
1312
1313         // First, detect invalid regular expressions.
1314         try {
1315             RegExp(tmp);
1316         } catch (e) {
1317             throwUnexpectedToken(null, Messages.InvalidRegExp);
1318         }
1319
1320         // Return a regular expression object for this pattern-flag pair, or
1321         // `null` in case the current environment doesn't support the flags it
1322         // uses.
1323         try {
1324             return new RegExp(pattern, flags);
1325         } catch (exception) {
1326             return null;
1327         }
1328     }
1329
1330     function scanRegExpBody() {
1331         var ch, str, classMarker, terminated, body;
1332
1333         ch = source[index];
1334         assert(ch === '/', 'Regular expression literal must start with a slash');
1335         str = source[index++];
1336
1337         classMarker = false;
1338         terminated = false;
1339         while (index < length) {
1340             ch = source[index++];
1341             str += ch;
1342             if (ch === '\\') {
1343                 ch = source[index++];
1344                 // ECMA-262 7.8.5
1345                 if (isLineTerminator(ch.charCodeAt(0))) {
1346                     throwUnexpectedToken(null, Messages.UnterminatedRegExp);
1347                 }
1348                 str += ch;
1349             } else if (isLineTerminator(ch.charCodeAt(0))) {
1350                 throwUnexpectedToken(null, Messages.UnterminatedRegExp);
1351             } else if (classMarker) {
1352                 if (ch === ']') {
1353                     classMarker = false;
1354                 }
1355             } else {
1356                 if (ch === '/') {
1357                     terminated = true;
1358                     break;
1359                 } else if (ch === '[') {
1360                     classMarker = true;
1361                 }
1362             }
1363         }
1364
1365         if (!terminated) {
1366             throwUnexpectedToken(null, Messages.UnterminatedRegExp);
1367         }
1368
1369         // Exclude leading and trailing slash.
1370         body = str.substr(1, str.length - 2);
1371         return {
1372             value: body,
1373             literal: str
1374         };
1375     }
1376
1377     function scanRegExpFlags() {
1378         var ch, str, flags, restore;
1379
1380         str = '';
1381         flags = '';
1382         while (index < length) {
1383             ch = source[index];
1384             if (!isIdentifierPart(ch.charCodeAt(0))) {
1385                 break;
1386             }
1387
1388             ++index;
1389             if (ch === '\\' && index < length) {
1390                 ch = source[index];
1391                 if (ch === 'u') {
1392                     ++index;
1393                     restore = index;
1394                     ch = scanHexEscape('u');
1395                     if (ch) {
1396                         flags += ch;
1397                         for (str += '\\u'; restore < index; ++restore) {
1398                             str += source[restore];
1399                         }
1400                     } else {
1401                         index = restore;
1402                         flags += 'u';
1403                         str += '\\u';
1404                     }
1405                     tolerateUnexpectedToken();
1406                 } else {
1407                     str += '\\';
1408                     tolerateUnexpectedToken();
1409                 }
1410             } else {
1411                 flags += ch;
1412                 str += ch;
1413             }
1414         }
1415
1416         return {
1417             value: flags,
1418             literal: str
1419         };
1420     }
1421
1422     function scanRegExp() {
1423         scanning = true;
1424         var start, body, flags, value;
1425
1426         lookahead = null;
1427         skipComment();
1428         start = index;
1429
1430         body = scanRegExpBody();
1431         flags = scanRegExpFlags();
1432         value = testRegExp(body.value, flags.value);
1433         scanning = false;
1434         if (extra.tokenize) {
1435             return {
1436                 type: Token.RegularExpression,
1437                 value: value,
1438                 regex: {
1439                     pattern: body.value,
1440                     flags: flags.value
1441                 },
1442                 lineNumber: lineNumber,
1443                 lineStart: lineStart,
1444                 start: start,
1445                 end: index
1446             };
1447         }
1448
1449         return {
1450             literal: body.literal + flags.literal,
1451             value: value,
1452             regex: {
1453                 pattern: body.value,
1454                 flags: flags.value
1455             },
1456             start: start,
1457             end: index
1458         };
1459     }
1460
1461     function collectRegex() {
1462         var pos, loc, regex, token;
1463
1464         skipComment();
1465
1466         pos = index;
1467         loc = {
1468             start: {
1469                 line: lineNumber,
1470                 column: index - lineStart
1471             }
1472         };
1473
1474         regex = scanRegExp();
1475
1476         loc.end = {
1477             line: lineNumber,
1478             column: index - lineStart
1479         };
1480
1481         /* istanbul ignore next */
1482         if (!extra.tokenize) {
1483             // Pop the previous token, which is likely '/' or '/='
1484             if (extra.tokens.length > 0) {
1485                 token = extra.tokens[extra.tokens.length - 1];
1486                 if (token.range[0] === pos && token.type === 'Punctuator') {
1487                     if (token.value === '/' || token.value === '/=') {
1488                         extra.tokens.pop();
1489                     }
1490                 }
1491             }
1492
1493             extra.tokens.push({
1494                 type: 'RegularExpression',
1495                 value: regex.literal,
1496                 regex: regex.regex,
1497                 range: [pos, index],
1498                 loc: loc
1499             });
1500         }
1501
1502         return regex;
1503     }
1504
1505     function isIdentifierName(token) {
1506         return token.type === Token.Identifier ||
1507             token.type === Token.Keyword ||
1508             token.type === Token.BooleanLiteral ||
1509             token.type === Token.NullLiteral;
1510     }
1511
1512     function advanceSlash() {
1513         var prevToken,
1514             checkToken;
1515         // Using the following algorithm:
1516         // https://github.com/mozilla/sweet.js/wiki/design
1517         prevToken = extra.tokens[extra.tokens.length - 1];
1518         if (!prevToken) {
1519             // Nothing before that: it cannot be a division.
1520             return collectRegex();
1521         }
1522         if (prevToken.type === 'Punctuator') {
1523             if (prevToken.value === ']') {
1524                 return scanPunctuator();
1525             }
1526             if (prevToken.value === ')') {
1527                 checkToken = extra.tokens[extra.openParenToken - 1];
1528                 if (checkToken &&
1529                         checkToken.type === 'Keyword' &&
1530                         (checkToken.value === 'if' ||
1531                          checkToken.value === 'while' ||
1532                          checkToken.value === 'for' ||
1533                          checkToken.value === 'with')) {
1534                     return collectRegex();
1535                 }
1536                 return scanPunctuator();
1537             }
1538             if (prevToken.value === '}') {
1539                 // Dividing a function by anything makes little sense,
1540                 // but we have to check for that.
1541                 if (extra.tokens[extra.openCurlyToken - 3] &&
1542                         extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') {
1543                     // Anonymous function.
1544                     checkToken = extra.tokens[extra.openCurlyToken - 4];
1545                     if (!checkToken) {
1546                         return scanPunctuator();
1547                     }
1548                 } else if (extra.tokens[extra.openCurlyToken - 4] &&
1549                         extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') {
1550                     // Named function.
1551                     checkToken = extra.tokens[extra.openCurlyToken - 5];
1552                     if (!checkToken) {
1553                         return collectRegex();
1554                     }
1555                 } else {
1556                     return scanPunctuator();
1557                 }
1558                 // checkToken determines whether the function is
1559                 // a declaration or an expression.
1560                 if (FnExprTokens.indexOf(checkToken.value) >= 0) {
1561                     // It is an expression.
1562                     return scanPunctuator();
1563                 }
1564                 // It is a declaration.
1565                 return collectRegex();
1566             }
1567             return collectRegex();
1568         }
1569         if (prevToken.type === 'Keyword' && prevToken.value !== 'this') {
1570             return collectRegex();
1571         }
1572         return scanPunctuator();
1573     }
1574
1575     function advance() {
1576         var cp, token;
1577
1578         if (index >= length) {
1579             return {
1580                 type: Token.EOF,
1581                 lineNumber: lineNumber,
1582                 lineStart: lineStart,
1583                 start: index,
1584                 end: index
1585             };
1586         }
1587
1588         cp = source.charCodeAt(index);
1589
1590         if (isIdentifierStart(cp)) {
1591             token = scanIdentifier();
1592             if (strict && isStrictModeReservedWord(token.value)) {
1593                 token.type = Token.Keyword;
1594             }
1595             return token;
1596         }
1597
1598         // Very common: ( and ) and ;
1599         if (cp === 0x28 || cp === 0x29 || cp === 0x3B) {
1600             return scanPunctuator();
1601         }
1602
1603         // String literal starts with single quote (U+0027) or double quote (U+0022).
1604         if (cp === 0x27 || cp === 0x22) {
1605             return scanStringLiteral();
1606         }
1607
1608         // Dot (.) U+002E can also start a floating-point number, hence the need
1609         // to check the next character.
1610         if (cp === 0x2E) {
1611             if (isDecimalDigit(source.charCodeAt(index + 1))) {
1612                 return scanNumericLiteral();
1613             }
1614             return scanPunctuator();
1615         }
1616
1617         if (isDecimalDigit(cp)) {
1618             return scanNumericLiteral();
1619         }
1620
1621         // Slash (/) U+002F can also start a regex.
1622         if (extra.tokenize && cp === 0x2F) {
1623             return advanceSlash();
1624         }
1625
1626         // Template literals start with ` (U+0060) for template head
1627         // or } (U+007D) for template middle or template tail.
1628         if (cp === 0x60 || (cp === 0x7D && state.curlyStack[state.curlyStack.length - 1] === '${')) {
1629             return scanTemplate();
1630         }
1631
1632         // Possible identifier start in a surrogate pair.
1633         if (cp >= 0xD800 && cp < 0xDFFF) {
1634             cp = codePointAt(index);
1635             if (isIdentifierStart(cp)) {
1636                 return scanIdentifier();
1637             }
1638         }
1639
1640         return scanPunctuator();
1641     }
1642
1643     function collectToken() {
1644         var loc, token, value, entry;
1645
1646         loc = {
1647             start: {
1648                 line: lineNumber,
1649                 column: index - lineStart
1650             }
1651         };
1652
1653         token = advance();
1654         loc.end = {
1655             line: lineNumber,
1656             column: index - lineStart
1657         };
1658
1659         if (token.type !== Token.EOF) {
1660             value = source.slice(token.start, token.end);
1661             entry = {
1662                 type: TokenName[token.type],
1663                 value: value,
1664                 range: [token.start, token.end],
1665                 loc: loc
1666             };
1667             if (token.regex) {
1668                 entry.regex = {
1669                     pattern: token.regex.pattern,
1670                     flags: token.regex.flags
1671                 };
1672             }
1673             extra.tokens.push(entry);
1674         }
1675
1676         return token;
1677     }
1678
1679     function lex() {
1680         var token;
1681         scanning = true;
1682
1683         lastIndex = index;
1684         lastLineNumber = lineNumber;
1685         lastLineStart = lineStart;
1686
1687         skipComment();
1688
1689         token = lookahead;
1690
1691         startIndex = index;
1692         startLineNumber = lineNumber;
1693         startLineStart = lineStart;
1694
1695         lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
1696         scanning = false;
1697         return token;
1698     }
1699
1700     function peek() {
1701         scanning = true;
1702
1703         skipComment();
1704
1705         lastIndex = index;
1706         lastLineNumber = lineNumber;
1707         lastLineStart = lineStart;
1708
1709         startIndex = index;
1710         startLineNumber = lineNumber;
1711         startLineStart = lineStart;
1712
1713         lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
1714         scanning = false;
1715     }
1716
1717     function Position() {
1718         this.line = startLineNumber;
1719         this.column = startIndex - startLineStart;
1720     }
1721
1722     function SourceLocation() {
1723         this.start = new Position();
1724         this.end = null;
1725     }
1726
1727     function WrappingSourceLocation(startToken) {
1728         this.start = {
1729             line: startToken.lineNumber,
1730             column: startToken.start - startToken.lineStart
1731         };
1732         this.end = null;
1733     }
1734
1735     function Node() {
1736         if (extra.range) {
1737             this.range = [startIndex, 0];
1738         }
1739         if (extra.loc) {
1740             this.loc = new SourceLocation();
1741         }
1742     }
1743
1744     function WrappingNode(startToken) {
1745         if (extra.range) {
1746             this.range = [startToken.start, 0];
1747         }
1748         if (extra.loc) {
1749             this.loc = new WrappingSourceLocation(startToken);
1750         }
1751     }
1752
1753     WrappingNode.prototype = Node.prototype = {
1754
1755         processComment: function () {
1756             var lastChild,
1757                 leadingComments,
1758                 trailingComments,
1759                 bottomRight = extra.bottomRightStack,
1760                 i,
1761                 comment,
1762                 last = bottomRight[bottomRight.length - 1];
1763
1764             if (this.type === Syntax.Program) {
1765                 if (this.body.length > 0) {
1766                     return;
1767                 }
1768             }
1769
1770             if (extra.trailingComments.length > 0) {
1771                 trailingComments = [];
1772                 for (i = extra.trailingComments.length - 1; i >= 0; --i) {
1773                     comment = extra.trailingComments[i];
1774                     if (comment.range[0] >= this.range[1]) {
1775                         trailingComments.unshift(comment);
1776                         extra.trailingComments.splice(i, 1);
1777                     }
1778                 }
1779                 extra.trailingComments = [];
1780             } else {
1781                 if (last && last.trailingComments && last.trailingComments[0].range[0] >= this.range[1]) {
1782                     trailingComments = last.trailingComments;
1783                     delete last.trailingComments;
1784                 }
1785             }
1786
1787             // Eating the stack.
1788             while (last && last.range[0] >= this.range[0]) {
1789                 lastChild = bottomRight.pop();
1790                 last = bottomRight[bottomRight.length - 1];
1791             }
1792
1793             if (lastChild) {
1794                 if (lastChild.leadingComments) {
1795                     leadingComments = [];
1796                     for (i = lastChild.leadingComments.length - 1; i >= 0; --i) {
1797                         comment = lastChild.leadingComments[i];
1798                         if (comment.range[1] <= this.range[0]) {
1799                             leadingComments.unshift(comment);
1800                             lastChild.leadingComments.splice(i, 1);
1801                         }
1802                     }
1803
1804                     if (!lastChild.leadingComments.length) {
1805                         lastChild.leadingComments = undefined;
1806                     }
1807                 }
1808             } else if (extra.leadingComments.length > 0) {
1809                 leadingComments = [];
1810                 for (i = extra.leadingComments.length - 1; i >= 0; --i) {
1811                     comment = extra.leadingComments[i];
1812                     if (comment.range[1] <= this.range[0]) {
1813                         leadingComments.unshift(comment);
1814                         extra.leadingComments.splice(i, 1);
1815                     }
1816                 }
1817             }
1818
1819
1820             if (leadingComments && leadingComments.length > 0) {
1821                 this.leadingComments = leadingComments;
1822             }
1823             if (trailingComments && trailingComments.length > 0) {
1824                 this.trailingComments = trailingComments;
1825             }
1826
1827             bottomRight.push(this);
1828         },
1829
1830         finish: function () {
1831             if (extra.range) {
1832                 this.range[1] = lastIndex;
1833             }
1834             if (extra.loc) {
1835                 this.loc.end = {
1836                     line: lastLineNumber,
1837                     column: lastIndex - lastLineStart
1838                 };
1839                 if (extra.source) {
1840                     this.loc.source = extra.source;
1841                 }
1842             }
1843
1844             if (extra.attachComment) {
1845                 this.processComment();
1846             }
1847         },
1848
1849         finishArrayExpression: function (elements) {
1850             this.type = Syntax.ArrayExpression;
1851             this.elements = elements;
1852             this.finish();
1853             return this;
1854         },
1855
1856         finishArrayPattern: function (elements) {
1857             this.type = Syntax.ArrayPattern;
1858             this.elements = elements;
1859             this.finish();
1860             return this;
1861         },
1862
1863         finishArrowFunctionExpression: function (params, defaults, body, expression) {
1864             this.type = Syntax.ArrowFunctionExpression;
1865             this.id = null;
1866             this.params = params;
1867             this.defaults = defaults;
1868             this.body = body;
1869             this.generator = false;
1870             this.expression = expression;
1871             this.finish();
1872             return this;
1873         },
1874
1875         finishAssignmentExpression: function (operator, left, right) {
1876             this.type = Syntax.AssignmentExpression;
1877             this.operator = operator;
1878             this.left = left;
1879             this.right = right;
1880             this.finish();
1881             return this;
1882         },
1883
1884         finishAssignmentPattern: function (left, right) {
1885             this.type = Syntax.AssignmentPattern;
1886             this.left = left;
1887             this.right = right;
1888             this.finish();
1889             return this;
1890         },
1891
1892         finishBinaryExpression: function (operator, left, right) {
1893             this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression;
1894             this.operator = operator;
1895             this.left = left;
1896             this.right = right;
1897             this.finish();
1898             return this;
1899         },
1900
1901         finishBlockStatement: function (body) {
1902             this.type = Syntax.BlockStatement;
1903             this.body = body;
1904             this.finish();
1905             return this;
1906         },
1907
1908         finishBreakStatement: function (label) {
1909             this.type = Syntax.BreakStatement;
1910             this.label = label;
1911             this.finish();
1912             return this;
1913         },
1914
1915         finishCallExpression: function (callee, args) {
1916             this.type = Syntax.CallExpression;
1917             this.callee = callee;
1918             this.arguments = args;
1919             this.finish();
1920             return this;
1921         },
1922
1923         finishCatchClause: function (param, body) {
1924             this.type = Syntax.CatchClause;
1925             this.param = param;
1926             this.body = body;
1927             this.finish();
1928             return this;
1929         },
1930
1931         finishClassBody: function (body) {
1932             this.type = Syntax.ClassBody;
1933             this.body = body;
1934             this.finish();
1935             return this;
1936         },
1937
1938         finishClassDeclaration: function (id, superClass, body) {
1939             this.type = Syntax.ClassDeclaration;
1940             this.id = id;
1941             this.superClass = superClass;
1942             this.body = body;
1943             this.finish();
1944             return this;
1945         },
1946
1947         finishClassExpression: function (id, superClass, body) {
1948             this.type = Syntax.ClassExpression;
1949             this.id = id;
1950             this.superClass = superClass;
1951             this.body = body;
1952             this.finish();
1953             return this;
1954         },
1955
1956         finishConditionalExpression: function (test, consequent, alternate) {
1957             this.type = Syntax.ConditionalExpression;
1958             this.test = test;
1959             this.consequent = consequent;
1960             this.alternate = alternate;
1961             this.finish();
1962             return this;
1963         },
1964
1965         finishContinueStatement: function (label) {
1966             this.type = Syntax.ContinueStatement;
1967             this.label = label;
1968             this.finish();
1969             return this;
1970         },
1971
1972         finishDebuggerStatement: function () {
1973             this.type = Syntax.DebuggerStatement;
1974             this.finish();
1975             return this;
1976         },
1977
1978         finishDoWhileStatement: function (body, test) {
1979             this.type = Syntax.DoWhileStatement;
1980             this.body = body;
1981             this.test = test;
1982             this.finish();
1983             return this;
1984         },
1985
1986         finishEmptyStatement: function () {
1987             this.type = Syntax.EmptyStatement;
1988             this.finish();
1989             return this;
1990         },
1991
1992         finishExpressionStatement: function (expression) {
1993             this.type = Syntax.ExpressionStatement;
1994             this.expression = expression;
1995             this.finish();
1996             return this;
1997         },
1998
1999         finishForStatement: function (init, test, update, body) {
2000             this.type = Syntax.ForStatement;
2001             this.init = init;
2002             this.test = test;
2003             this.update = update;
2004             this.body = body;
2005             this.finish();
2006             return this;
2007         },
2008
2009         finishForOfStatement: function (left, right, body) {
2010             this.type = Syntax.ForOfStatement;
2011             this.left = left;
2012             this.right = right;
2013             this.body = body;
2014             this.finish();
2015             return this;
2016         },
2017
2018         finishForInStatement: function (left, right, body) {
2019             this.type = Syntax.ForInStatement;
2020             this.left = left;
2021             this.right = right;
2022             this.body = body;
2023             this.each = false;
2024             this.finish();
2025             return this;
2026         },
2027
2028         finishFunctionDeclaration: function (id, params, defaults, body, generator) {
2029             this.type = Syntax.FunctionDeclaration;
2030             this.id = id;
2031             this.params = params;
2032             this.defaults = defaults;
2033             this.body = body;
2034             this.generator = generator;
2035             this.expression = false;
2036             this.finish();
2037             return this;
2038         },
2039
2040         finishFunctionExpression: function (id, params, defaults, body, generator) {
2041             this.type = Syntax.FunctionExpression;
2042             this.id = id;
2043             this.params = params;
2044             this.defaults = defaults;
2045             this.body = body;
2046             this.generator = generator;
2047             this.expression = false;
2048             this.finish();
2049             return this;
2050         },
2051
2052         finishIdentifier: function (name) {
2053             this.type = Syntax.Identifier;
2054             this.name = name;
2055             this.finish();
2056             return this;
2057         },
2058
2059         finishIfStatement: function (test, consequent, alternate) {
2060             this.type = Syntax.IfStatement;
2061             this.test = test;
2062             this.consequent = consequent;
2063             this.alternate = alternate;
2064             this.finish();
2065             return this;
2066         },
2067
2068         finishLabeledStatement: function (label, body) {
2069             this.type = Syntax.LabeledStatement;
2070             this.label = label;
2071             this.body = body;
2072             this.finish();
2073             return this;
2074         },
2075
2076         finishLiteral: function (token) {
2077             this.type = Syntax.Literal;
2078             this.value = token.value;
2079             this.raw = source.slice(token.start, token.end);
2080             if (token.regex) {
2081                 this.regex = token.regex;
2082             }
2083             this.finish();
2084             return this;
2085         },
2086
2087         finishMemberExpression: function (accessor, object, property) {
2088             this.type = Syntax.MemberExpression;
2089             this.computed = accessor === '[';
2090             this.object = object;
2091             this.property = property;
2092             this.finish();
2093             return this;
2094         },
2095
2096         finishMetaProperty: function (meta, property) {
2097             this.type = Syntax.MetaProperty;
2098             this.meta = meta;
2099             this.property = property;
2100             this.finish();
2101             return this;
2102         },
2103
2104         finishNewExpression: function (callee, args) {
2105             this.type = Syntax.NewExpression;
2106             this.callee = callee;
2107             this.arguments = args;
2108             this.finish();
2109             return this;
2110         },
2111
2112         finishObjectExpression: function (properties) {
2113             this.type = Syntax.ObjectExpression;
2114             this.properties = properties;
2115             this.finish();
2116             return this;
2117         },
2118
2119         finishObjectPattern: function (properties) {
2120             this.type = Syntax.ObjectPattern;
2121             this.properties = properties;
2122             this.finish();
2123             return this;
2124         },
2125
2126         finishPostfixExpression: function (operator, argument) {
2127             this.type = Syntax.UpdateExpression;
2128             this.operator = operator;
2129             this.argument = argument;
2130             this.prefix = false;
2131             this.finish();
2132             return this;
2133         },
2134
2135         finishProgram: function (body) {
2136             this.type = Syntax.Program;
2137             this.body = body;
2138             if (sourceType === 'module') {
2139                 // very restrictive for now
2140                 this.sourceType = sourceType;
2141             }
2142             this.finish();
2143             return this;
2144         },
2145
2146         finishProperty: function (kind, key, computed, value, method, shorthand) {
2147             this.type = Syntax.Property;
2148             this.key = key;
2149             this.computed = computed;
2150             this.value = value;
2151             this.kind = kind;
2152             this.method = method;
2153             this.shorthand = shorthand;
2154             this.finish();
2155             return this;
2156         },
2157
2158         finishRestElement: function (argument) {
2159             this.type = Syntax.RestElement;
2160             this.argument = argument;
2161             this.finish();
2162             return this;
2163         },
2164
2165         finishReturnStatement: function (argument) {
2166             this.type = Syntax.ReturnStatement;
2167             this.argument = argument;
2168             this.finish();
2169             return this;
2170         },
2171
2172         finishSequenceExpression: function (expressions) {
2173             this.type = Syntax.SequenceExpression;
2174             this.expressions = expressions;
2175             this.finish();
2176             return this;
2177         },
2178
2179         finishSpreadElement: function (argument) {
2180             this.type = Syntax.SpreadElement;
2181             this.argument = argument;
2182             this.finish();
2183             return this;
2184         },
2185
2186         finishSwitchCase: function (test, consequent) {
2187             this.type = Syntax.SwitchCase;
2188             this.test = test;
2189             this.consequent = consequent;
2190             this.finish();
2191             return this;
2192         },
2193
2194         finishSuper: function () {
2195             this.type = Syntax.Super;
2196             this.finish();
2197             return this;
2198         },
2199
2200         finishSwitchStatement: function (discriminant, cases) {
2201             this.type = Syntax.SwitchStatement;
2202             this.discriminant = discriminant;
2203             this.cases = cases;
2204             this.finish();
2205             return this;
2206         },
2207
2208         finishTaggedTemplateExpression: function (tag, quasi) {
2209             this.type = Syntax.TaggedTemplateExpression;
2210             this.tag = tag;
2211             this.quasi = quasi;
2212             this.finish();
2213             return this;
2214         },
2215
2216         finishTemplateElement: function (value, tail) {
2217             this.type = Syntax.TemplateElement;
2218             this.value = value;
2219             this.tail = tail;
2220             this.finish();
2221             return this;
2222         },
2223
2224         finishTemplateLiteral: function (quasis, expressions) {
2225             this.type = Syntax.TemplateLiteral;
2226             this.quasis = quasis;
2227             this.expressions = expressions;
2228             this.finish();
2229             return this;
2230         },
2231
2232         finishThisExpression: function () {
2233             this.type = Syntax.ThisExpression;
2234             this.finish();
2235             return this;
2236         },
2237
2238         finishThrowStatement: function (argument) {
2239             this.type = Syntax.ThrowStatement;
2240             this.argument = argument;
2241             this.finish();
2242             return this;
2243         },
2244
2245         finishTryStatement: function (block, handler, finalizer) {
2246             this.type = Syntax.TryStatement;
2247             this.block = block;
2248             this.guardedHandlers = [];
2249             this.handlers = handler ? [ handler ] : [];
2250             this.handler = handler;
2251             this.finalizer = finalizer;
2252             this.finish();
2253             return this;
2254         },
2255
2256         finishUnaryExpression: function (operator, argument) {
2257             this.type = (operator === '++' || operator === '--') ? Syntax.UpdateExpression : Syntax.UnaryExpression;
2258             this.operator = operator;
2259             this.argument = argument;
2260             this.prefix = true;
2261             this.finish();
2262             return this;
2263         },
2264
2265         finishVariableDeclaration: function (declarations) {
2266             this.type = Syntax.VariableDeclaration;
2267             this.declarations = declarations;
2268             this.kind = 'var';
2269             this.finish();
2270             return this;
2271         },
2272
2273         finishLexicalDeclaration: function (declarations, kind) {
2274             this.type = Syntax.VariableDeclaration;
2275             this.declarations = declarations;
2276             this.kind = kind;
2277             this.finish();
2278             return this;
2279         },
2280
2281         finishVariableDeclarator: function (id, init) {
2282             this.type = Syntax.VariableDeclarator;
2283             this.id = id;
2284             this.init = init;
2285             this.finish();
2286             return this;
2287         },
2288
2289         finishWhileStatement: function (test, body) {
2290             this.type = Syntax.WhileStatement;
2291             this.test = test;
2292             this.body = body;
2293             this.finish();
2294             return this;
2295         },
2296
2297         finishWithStatement: function (object, body) {
2298             this.type = Syntax.WithStatement;
2299             this.object = object;
2300             this.body = body;
2301             this.finish();
2302             return this;
2303         },
2304
2305         finishExportSpecifier: function (local, exported) {
2306             this.type = Syntax.ExportSpecifier;
2307             this.exported = exported || local;
2308             this.local = local;
2309             this.finish();
2310             return this;
2311         },
2312
2313         finishImportDefaultSpecifier: function (local) {
2314             this.type = Syntax.ImportDefaultSpecifier;
2315             this.local = local;
2316             this.finish();
2317             return this;
2318         },
2319
2320         finishImportNamespaceSpecifier: function (local) {
2321             this.type = Syntax.ImportNamespaceSpecifier;
2322             this.local = local;
2323             this.finish();
2324             return this;
2325         },
2326
2327         finishExportNamedDeclaration: function (declaration, specifiers, src) {
2328             this.type = Syntax.ExportNamedDeclaration;
2329             this.declaration = declaration;
2330             this.specifiers = specifiers;
2331             this.source = src;
2332             this.finish();
2333             return this;
2334         },
2335
2336         finishExportDefaultDeclaration: function (declaration) {
2337             this.type = Syntax.ExportDefaultDeclaration;
2338             this.declaration = declaration;
2339             this.finish();
2340             return this;
2341         },
2342
2343         finishExportAllDeclaration: function (src) {
2344             this.type = Syntax.ExportAllDeclaration;
2345             this.source = src;
2346             this.finish();
2347             return this;
2348         },
2349
2350         finishImportSpecifier: function (local, imported) {
2351             this.type = Syntax.ImportSpecifier;
2352             this.local = local || imported;
2353             this.imported = imported;
2354             this.finish();
2355             return this;
2356         },
2357
2358         finishImportDeclaration: function (specifiers, src) {
2359             this.type = Syntax.ImportDeclaration;
2360             this.specifiers = specifiers;
2361             this.source = src;
2362             this.finish();
2363             return this;
2364         },
2365
2366         finishYieldExpression: function (argument, delegate) {
2367             this.type = Syntax.YieldExpression;
2368             this.argument = argument;
2369             this.delegate = delegate;
2370             this.finish();
2371             return this;
2372         }
2373     };
2374
2375
2376     function recordError(error) {
2377         var e, existing;
2378
2379         for (e = 0; e < extra.errors.length; e++) {
2380             existing = extra.errors[e];
2381             // Prevent duplicated error.
2382             /* istanbul ignore next */
2383             if (existing.index === error.index && existing.message === error.message) {
2384                 return;
2385             }
2386         }
2387
2388         extra.errors.push(error);
2389     }
2390
2391     function createError(line, pos, description) {
2392         var error = new Error('Line ' + line + ': ' + description);
2393         error.index = pos;
2394         error.lineNumber = line;
2395         error.column = pos - (scanning ? lineStart : lastLineStart) + 1;
2396         error.description = description;
2397         return error;
2398     }
2399
2400     // Throw an exception
2401
2402     function throwError(messageFormat) {
2403         var args, msg;
2404
2405         args = Array.prototype.slice.call(arguments, 1);
2406         msg = messageFormat.replace(/%(\d)/g,
2407             function (whole, idx) {
2408                 assert(idx < args.length, 'Message reference must be in range');
2409                 return args[idx];
2410             }
2411         );
2412
2413         throw createError(lastLineNumber, lastIndex, msg);
2414     }
2415
2416     function tolerateError(messageFormat) {
2417         var args, msg, error;
2418
2419         args = Array.prototype.slice.call(arguments, 1);
2420         /* istanbul ignore next */
2421         msg = messageFormat.replace(/%(\d)/g,
2422             function (whole, idx) {
2423                 assert(idx < args.length, 'Message reference must be in range');
2424                 return args[idx];
2425             }
2426         );
2427
2428         error = createError(lineNumber, lastIndex, msg);
2429         if (extra.errors) {
2430             recordError(error);
2431         } else {
2432             throw error;
2433         }
2434     }
2435
2436     // Throw an exception because of the token.
2437
2438     function unexpectedTokenError(token, message) {
2439         var value, msg = message || Messages.UnexpectedToken;
2440
2441         if (token) {
2442             if (!message) {
2443                 msg = (token.type === Token.EOF) ? Messages.UnexpectedEOS :
2444                     (token.type === Token.Identifier) ? Messages.UnexpectedIdentifier :
2445                     (token.type === Token.NumericLiteral) ? Messages.UnexpectedNumber :
2446                     (token.type === Token.StringLiteral) ? Messages.UnexpectedString :
2447                     (token.type === Token.Template) ? Messages.UnexpectedTemplate :
2448                     Messages.UnexpectedToken;
2449
2450                 if (token.type === Token.Keyword) {
2451                     if (isFutureReservedWord(token.value)) {
2452                         msg = Messages.UnexpectedReserved;
2453                     } else if (strict && isStrictModeReservedWord(token.value)) {
2454                         msg = Messages.StrictReservedWord;
2455                     }
2456                 }
2457             }
2458
2459             value = (token.type === Token.Template) ? token.value.raw : token.value;
2460         } else {
2461             value = 'ILLEGAL';
2462         }
2463
2464         msg = msg.replace('%0', value);
2465
2466         return (token && typeof token.lineNumber === 'number') ?
2467             createError(token.lineNumber, token.start, msg) :
2468             createError(scanning ? lineNumber : lastLineNumber, scanning ? index : lastIndex, msg);
2469     }
2470
2471     function throwUnexpectedToken(token, message) {
2472         throw unexpectedTokenError(token, message);
2473     }
2474
2475     function tolerateUnexpectedToken(token, message) {
2476         var error = unexpectedTokenError(token, message);
2477         if (extra.errors) {
2478             recordError(error);
2479         } else {
2480             throw error;
2481         }
2482     }
2483
2484     // Expect the next token to match the specified punctuator.
2485     // If not, an exception will be thrown.
2486
2487     function expect(value) {
2488         var token = lex();
2489         if (token.type !== Token.Punctuator || token.value !== value) {
2490             throwUnexpectedToken(token);
2491         }
2492     }
2493
2494     /**
2495      * @name expectCommaSeparator
2496      * @description Quietly expect a comma when in tolerant mode, otherwise delegates
2497      * to <code>expect(value)</code>
2498      * @since 2.0
2499      */
2500     function expectCommaSeparator() {
2501         var token;
2502
2503         if (extra.errors) {
2504             token = lookahead;
2505             if (token.type === Token.Punctuator && token.value === ',') {
2506                 lex();
2507             } else if (token.type === Token.Punctuator && token.value === ';') {
2508                 lex();
2509                 tolerateUnexpectedToken(token);
2510             } else {
2511                 tolerateUnexpectedToken(token, Messages.UnexpectedToken);
2512             }
2513         } else {
2514             expect(',');
2515         }
2516     }
2517
2518     // Expect the next token to match the specified keyword.
2519     // If not, an exception will be thrown.
2520
2521     function expectKeyword(keyword) {
2522         var token = lex();
2523         if (token.type !== Token.Keyword || token.value !== keyword) {
2524             throwUnexpectedToken(token);
2525         }
2526     }
2527
2528     // Return true if the next token matches the specified punctuator.
2529
2530     function match(value) {
2531         return lookahead.type === Token.Punctuator && lookahead.value === value;
2532     }
2533
2534     // Return true if the next token matches the specified keyword
2535
2536     function matchKeyword(keyword) {
2537         return lookahead.type === Token.Keyword && lookahead.value === keyword;
2538     }
2539
2540     // Return true if the next token matches the specified contextual keyword
2541     // (where an identifier is sometimes a keyword depending on the context)
2542
2543     function matchContextualKeyword(keyword) {
2544         return lookahead.type === Token.Identifier && lookahead.value === keyword;
2545     }
2546
2547     // Return true if the next token is an assignment operator
2548
2549     function matchAssign() {
2550         var op;
2551
2552         if (lookahead.type !== Token.Punctuator) {
2553             return false;
2554         }
2555         op = lookahead.value;
2556         return op === '=' ||
2557             op === '*=' ||
2558             op === '/=' ||
2559             op === '%=' ||
2560             op === '+=' ||
2561             op === '-=' ||
2562             op === '<<=' ||
2563             op === '>>=' ||
2564             op === '>>>=' ||
2565             op === '&=' ||
2566             op === '^=' ||
2567             op === '|=';
2568     }
2569
2570     function consumeSemicolon() {
2571         // Catch the very common case first: immediately a semicolon (U+003B).
2572         if (source.charCodeAt(startIndex) === 0x3B || match(';')) {
2573             lex();
2574             return;
2575         }
2576
2577         if (hasLineTerminator) {
2578             return;
2579         }
2580
2581         // FIXME(ikarienator): this is seemingly an issue in the previous location info convention.
2582         lastIndex = startIndex;
2583         lastLineNumber = startLineNumber;
2584         lastLineStart = startLineStart;
2585
2586         if (lookahead.type !== Token.EOF && !match('}')) {
2587             throwUnexpectedToken(lookahead);
2588         }
2589     }
2590
2591     // Cover grammar support.
2592     //
2593     // When an assignment expression position starts with an left parenthesis, the determination of the type
2594     // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead)
2595     // or the first comma. This situation also defers the determination of all the expressions nested in the pair.
2596     //
2597     // There are three productions that can be parsed in a parentheses pair that needs to be determined
2598     // after the outermost pair is closed. They are:
2599     //
2600     //   1. AssignmentExpression
2601     //   2. BindingElements
2602     //   3. AssignmentTargets
2603     //
2604     // In order to avoid exponential backtracking, we use two flags to denote if the production can be
2605     // binding element or assignment target.
2606     //
2607     // The three productions have the relationship:
2608     //
2609     //   BindingElements âŠ† AssignmentTargets âŠ† AssignmentExpression
2610     //
2611     // with a single exception that CoverInitializedName when used directly in an Expression, generates
2612     // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the
2613     // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair.
2614     //
2615     // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not
2616     // effect the current flags. This means the production the parser parses is only used as an expression. Therefore
2617     // the CoverInitializedName check is conducted.
2618     //
2619     // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates
2620     // the flags outside of the parser. This means the production the parser parses is used as a part of a potential
2621     // pattern. The CoverInitializedName check is deferred.
2622     function isolateCoverGrammar(parser) {
2623         var oldIsBindingElement = isBindingElement,
2624             oldIsAssignmentTarget = isAssignmentTarget,
2625             oldFirstCoverInitializedNameError = firstCoverInitializedNameError,
2626             result;
2627         isBindingElement = true;
2628         isAssignmentTarget = true;
2629         firstCoverInitializedNameError = null;
2630         result = parser();
2631         if (firstCoverInitializedNameError !== null) {
2632             throwUnexpectedToken(firstCoverInitializedNameError);
2633         }
2634         isBindingElement = oldIsBindingElement;
2635         isAssignmentTarget = oldIsAssignmentTarget;
2636         firstCoverInitializedNameError = oldFirstCoverInitializedNameError;
2637         return result;
2638     }
2639
2640     function inheritCoverGrammar(parser) {
2641         var oldIsBindingElement = isBindingElement,
2642             oldIsAssignmentTarget = isAssignmentTarget,
2643             oldFirstCoverInitializedNameError = firstCoverInitializedNameError,
2644             result;
2645         isBindingElement = true;
2646         isAssignmentTarget = true;
2647         firstCoverInitializedNameError = null;
2648         result = parser();
2649         isBindingElement = isBindingElement && oldIsBindingElement;
2650         isAssignmentTarget = isAssignmentTarget && oldIsAssignmentTarget;
2651         firstCoverInitializedNameError = oldFirstCoverInitializedNameError || firstCoverInitializedNameError;
2652         return result;
2653     }
2654
2655     // ECMA-262 13.3.3 Destructuring Binding Patterns
2656
2657     function parseArrayPattern(params) {
2658         var node = new Node(), elements = [], rest, restNode;
2659         expect('[');
2660
2661         while (!match(']')) {
2662             if (match(',')) {
2663                 lex();
2664                 elements.push(null);
2665             } else {
2666                 if (match('...')) {
2667                     restNode = new Node();
2668                     lex();
2669                     params.push(lookahead);
2670                     rest = parseVariableIdentifier(params);
2671                     elements.push(restNode.finishRestElement(rest));
2672                     break;
2673                 } else {
2674                     elements.push(parsePatternWithDefault(params));
2675                 }
2676                 if (!match(']')) {
2677                     expect(',');
2678                 }
2679             }
2680
2681         }
2682
2683         expect(']');
2684
2685         return node.finishArrayPattern(elements);
2686     }
2687
2688     function parsePropertyPattern(params) {
2689         var node = new Node(), key, keyToken, computed = match('['), init;
2690         if (lookahead.type === Token.Identifier) {
2691             keyToken = lookahead;
2692             key = parseVariableIdentifier();
2693             if (match('=')) {
2694                 params.push(keyToken);
2695                 lex();
2696                 init = parseAssignmentExpression();
2697
2698                 return node.finishProperty(
2699                     'init', key, false,
2700                     new WrappingNode(keyToken).finishAssignmentPattern(key, init), false, false);
2701             } else if (!match(':')) {
2702                 params.push(keyToken);
2703                 return node.finishProperty('init', key, false, key, false, true);
2704             }
2705         } else {
2706             key = parseObjectPropertyKey(params);
2707         }
2708         expect(':');
2709         init = parsePatternWithDefault(params);
2710         return node.finishProperty('init', key, computed, init, false, false);
2711     }
2712
2713     function parseObjectPattern(params) {
2714         var node = new Node(), properties = [];
2715
2716         expect('{');
2717
2718         while (!match('}')) {
2719             properties.push(parsePropertyPattern(params));
2720             if (!match('}')) {
2721                 expect(',');
2722             }
2723         }
2724
2725         lex();
2726
2727         return node.finishObjectPattern(properties);
2728     }
2729
2730     function parsePattern(params) {
2731         if (match('[')) {
2732             return parseArrayPattern(params);
2733         } else if (match('{')) {
2734             return parseObjectPattern(params);
2735         }
2736         params.push(lookahead);
2737         return parseVariableIdentifier();
2738     }
2739
2740     function parsePatternWithDefault(params) {
2741         var startToken = lookahead, pattern, previousAllowYield, right;
2742         pattern = parsePattern(params);
2743         if (match('=')) {
2744             lex();
2745             previousAllowYield = state.allowYield;
2746             state.allowYield = true;
2747             right = isolateCoverGrammar(parseAssignmentExpression);
2748             state.allowYield = previousAllowYield;
2749             pattern = new WrappingNode(startToken).finishAssignmentPattern(pattern, right);
2750         }
2751         return pattern;
2752     }
2753
2754     // ECMA-262 12.2.5 Array Initializer
2755
2756     function parseArrayInitializer() {
2757         var elements = [], node = new Node(), restSpread;
2758
2759         expect('[');
2760
2761         while (!match(']')) {
2762             if (match(',')) {
2763                 lex();
2764                 elements.push(null);
2765             } else if (match('...')) {
2766                 restSpread = new Node();
2767                 lex();
2768                 restSpread.finishSpreadElement(inheritCoverGrammar(parseAssignmentExpression));
2769
2770                 if (!match(']')) {
2771                     isAssignmentTarget = isBindingElement = false;
2772                     expect(',');
2773                 }
2774                 elements.push(restSpread);
2775             } else {
2776                 elements.push(inheritCoverGrammar(parseAssignmentExpression));
2777
2778                 if (!match(']')) {
2779                     expect(',');
2780                 }
2781             }
2782         }
2783
2784         lex();
2785
2786         return node.finishArrayExpression(elements);
2787     }
2788
2789     // ECMA-262 12.2.6 Object Initializer
2790
2791     function parsePropertyFunction(node, paramInfo, isGenerator) {
2792         var previousStrict, body;
2793
2794         isAssignmentTarget = isBindingElement = false;
2795
2796         previousStrict = strict;
2797         body = isolateCoverGrammar(parseFunctionSourceElements);
2798
2799         if (strict && paramInfo.firstRestricted) {
2800             tolerateUnexpectedToken(paramInfo.firstRestricted, paramInfo.message);
2801         }
2802         if (strict && paramInfo.stricted) {
2803             tolerateUnexpectedToken(paramInfo.stricted, paramInfo.message);
2804         }
2805
2806         strict = previousStrict;
2807         return node.finishFunctionExpression(null, paramInfo.params, paramInfo.defaults, body, isGenerator);
2808     }
2809
2810     function parsePropertyMethodFunction() {
2811         var params, method, node = new Node(),
2812             previousAllowYield = state.allowYield;
2813
2814         state.allowYield = false;
2815         params = parseParams();
2816         state.allowYield = previousAllowYield;
2817
2818         state.allowYield = false;
2819         method = parsePropertyFunction(node, params, false);
2820         state.allowYield = previousAllowYield;
2821
2822         return method;
2823     }
2824
2825     function parseObjectPropertyKey() {
2826         var token, node = new Node(), expr;
2827
2828         token = lex();
2829
2830         // Note: This function is called only from parseObjectProperty(), where
2831         // EOF and Punctuator tokens are already filtered out.
2832
2833         switch (token.type) {
2834         case Token.StringLiteral:
2835         case Token.NumericLiteral:
2836             if (strict && token.octal) {
2837                 tolerateUnexpectedToken(token, Messages.StrictOctalLiteral);
2838             }
2839             return node.finishLiteral(token);
2840         case Token.Identifier:
2841         case Token.BooleanLiteral:
2842         case Token.NullLiteral:
2843         case Token.Keyword:
2844             return node.finishIdentifier(token.value);
2845         case Token.Punctuator:
2846             if (token.value === '[') {
2847                 expr = isolateCoverGrammar(parseAssignmentExpression);
2848                 expect(']');
2849                 return expr;
2850             }
2851             break;
2852         }
2853         throwUnexpectedToken(token);
2854     }
2855
2856     function lookaheadPropertyName() {
2857         switch (lookahead.type) {
2858         case Token.Identifier:
2859         case Token.StringLiteral:
2860         case Token.BooleanLiteral:
2861         case Token.NullLiteral:
2862         case Token.NumericLiteral:
2863         case Token.Keyword:
2864             return true;
2865         case Token.Punctuator:
2866             return lookahead.value === '[';
2867         }
2868         return false;
2869     }
2870
2871     // This function is to try to parse a MethodDefinition as defined in 14.3. But in the case of object literals,
2872     // it might be called at a position where there is in fact a short hand identifier pattern or a data property.
2873     // This can only be determined after we consumed up to the left parentheses.
2874     //
2875     // In order to avoid back tracking, it returns `null` if the position is not a MethodDefinition and the caller
2876     // is responsible to visit other options.
2877     function tryParseMethodDefinition(token, key, computed, node) {
2878         var value, options, methodNode, params,
2879             previousAllowYield = state.allowYield;
2880
2881         if (token.type === Token.Identifier) {
2882             // check for `get` and `set`;
2883
2884             if (token.value === 'get' && lookaheadPropertyName()) {
2885                 computed = match('[');
2886                 key = parseObjectPropertyKey();
2887                 methodNode = new Node();
2888                 expect('(');
2889                 expect(')');
2890
2891                 state.allowYield = false;
2892                 value = parsePropertyFunction(methodNode, {
2893                     params: [],
2894                     defaults: [],
2895                     stricted: null,
2896                     firstRestricted: null,
2897                     message: null
2898                 }, false);
2899                 state.allowYield = previousAllowYield;
2900
2901                 return node.finishProperty('get', key, computed, value, false, false);
2902             } else if (token.value === 'set' && lookaheadPropertyName()) {
2903                 computed = match('[');
2904                 key = parseObjectPropertyKey();
2905                 methodNode = new Node();
2906                 expect('(');
2907
2908                 options = {
2909                     params: [],
2910                     defaultCount: 0,
2911                     defaults: [],
2912                     firstRestricted: null,
2913                     paramSet: {}
2914                 };
2915                 if (match(')')) {
2916                     tolerateUnexpectedToken(lookahead);
2917                 } else {
2918                     state.allowYield = false;
2919                     parseParam(options);
2920                     state.allowYield = previousAllowYield;
2921                     if (options.defaultCount === 0) {
2922                         options.defaults = [];
2923                     }
2924                 }
2925                 expect(')');
2926
2927                 state.allowYield = false;
2928                 value = parsePropertyFunction(methodNode, options, false);
2929                 state.allowYield = previousAllowYield;
2930
2931                 return node.finishProperty('set', key, computed, value, false, false);
2932             }
2933         } else if (token.type === Token.Punctuator && token.value === '*' && lookaheadPropertyName()) {
2934             computed = match('[');
2935             key = parseObjectPropertyKey();
2936             methodNode = new Node();
2937
2938             state.allowYield = true;
2939             params = parseParams();
2940             state.allowYield = previousAllowYield;
2941
2942             state.allowYield = false;
2943             value = parsePropertyFunction(methodNode, params, true);
2944             state.allowYield = previousAllowYield;
2945
2946             return node.finishProperty('init', key, computed, value, true, false);
2947         }
2948
2949         if (key && match('(')) {
2950             value = parsePropertyMethodFunction();
2951             return node.finishProperty('init', key, computed, value, true, false);
2952         }
2953
2954         // Not a MethodDefinition.
2955         return null;
2956     }
2957
2958     function parseObjectProperty(hasProto) {
2959         var token = lookahead, node = new Node(), computed, key, maybeMethod, proto, value;
2960
2961         computed = match('[');
2962         if (match('*')) {
2963             lex();
2964         } else {
2965             key = parseObjectPropertyKey();
2966         }
2967         maybeMethod = tryParseMethodDefinition(token, key, computed, node);
2968         if (maybeMethod) {
2969             return maybeMethod;
2970         }
2971
2972         if (!key) {
2973             throwUnexpectedToken(lookahead);
2974         }
2975
2976         // Check for duplicated __proto__
2977         if (!computed) {
2978             proto = (key.type === Syntax.Identifier && key.name === '__proto__') ||
2979                 (key.type === Syntax.Literal && key.value === '__proto__');
2980             if (hasProto.value && proto) {
2981                 tolerateError(Messages.DuplicateProtoProperty);
2982             }
2983             hasProto.value |= proto;
2984         }
2985
2986         if (match(':')) {
2987             lex();
2988             value = inheritCoverGrammar(parseAssignmentExpression);
2989             return node.finishProperty('init', key, computed, value, false, false);
2990         }
2991
2992         if (token.type === Token.Identifier) {
2993             if (match('=')) {
2994                 firstCoverInitializedNameError = lookahead;
2995                 lex();
2996                 value = isolateCoverGrammar(parseAssignmentExpression);
2997                 return node.finishProperty('init', key, computed,
2998                     new WrappingNode(token).finishAssignmentPattern(key, value), false, true);
2999             }
3000             return node.finishProperty('init', key, computed, key, false, true);
3001         }
3002
3003         throwUnexpectedToken(lookahead);
3004     }
3005
3006     function parseObjectInitializer() {
3007         var properties = [], hasProto = {value: false}, node = new Node();
3008
3009         expect('{');
3010
3011         while (!match('}')) {
3012             properties.push(parseObjectProperty(hasProto));
3013
3014             if (!match('}')) {
3015                 expectCommaSeparator();
3016             }
3017         }
3018
3019         expect('}');
3020
3021         return node.finishObjectExpression(properties);
3022     }
3023
3024     function reinterpretExpressionAsPattern(expr) {
3025         var i;
3026         switch (expr.type) {
3027         case Syntax.Identifier:
3028         case Syntax.MemberExpression:
3029         case Syntax.RestElement:
3030         case Syntax.AssignmentPattern:
3031             break;
3032         case Syntax.SpreadElement:
3033             expr.type = Syntax.RestElement;
3034             reinterpretExpressionAsPattern(expr.argument);
3035             break;
3036         case Syntax.ArrayExpression:
3037             expr.type = Syntax.ArrayPattern;
3038             for (i = 0; i < expr.elements.length; i++) {
3039                 if (expr.elements[i] !== null) {
3040                     reinterpretExpressionAsPattern(expr.elements[i]);
3041                 }
3042             }
3043             break;
3044         case Syntax.ObjectExpression:
3045             expr.type = Syntax.ObjectPattern;
3046             for (i = 0; i < expr.properties.length; i++) {
3047                 reinterpretExpressionAsPattern(expr.properties[i].value);
3048             }
3049             break;
3050         case Syntax.AssignmentExpression:
3051             expr.type = Syntax.AssignmentPattern;
3052             reinterpretExpressionAsPattern(expr.left);
3053             break;
3054         default:
3055             // Allow other node type for tolerant parsing.
3056             break;
3057         }
3058     }
3059
3060     // ECMA-262 12.2.9 Template Literals
3061
3062     function parseTemplateElement(option) {
3063         var node, token;
3064
3065         if (lookahead.type !== Token.Template || (option.head && !lookahead.head)) {
3066             throwUnexpectedToken();
3067         }
3068
3069         node = new Node();
3070         token = lex();
3071
3072         return node.finishTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail);
3073     }
3074
3075     function parseTemplateLiteral() {
3076         var quasi, quasis, expressions, node = new Node();
3077
3078         quasi = parseTemplateElement({ head: true });
3079         quasis = [ quasi ];
3080         expressions = [];
3081
3082         while (!quasi.tail) {
3083             expressions.push(parseExpression());
3084             quasi = parseTemplateElement({ head: false });
3085             quasis.push(quasi);
3086         }
3087
3088         return node.finishTemplateLiteral(quasis, expressions);
3089     }
3090
3091     // ECMA-262 12.2.10 The Grouping Operator
3092
3093     function parseGroupExpression() {
3094         var expr, expressions, startToken, i, params = [];
3095
3096         expect('(');
3097
3098         if (match(')')) {
3099             lex();
3100             if (!match('=>')) {
3101                 expect('=>');
3102             }
3103             return {
3104                 type: PlaceHolders.ArrowParameterPlaceHolder,
3105                 params: [],
3106                 rawParams: []
3107             };
3108         }
3109
3110         startToken = lookahead;
3111         if (match('...')) {
3112             expr = parseRestElement(params);
3113             expect(')');
3114             if (!match('=>')) {
3115                 expect('=>');
3116             }
3117             return {
3118                 type: PlaceHolders.ArrowParameterPlaceHolder,
3119                 params: [expr]
3120             };
3121         }
3122
3123         isBindingElement = true;
3124         expr = inheritCoverGrammar(parseAssignmentExpression);
3125
3126         if (match(',')) {
3127             isAssignmentTarget = false;
3128             expressions = [expr];
3129
3130             while (startIndex < length) {
3131                 if (!match(',')) {
3132                     break;
3133                 }
3134                 lex();
3135
3136                 if (match('...')) {
3137                     if (!isBindingElement) {
3138                         throwUnexpectedToken(lookahead);
3139                     }
3140                     expressions.push(parseRestElement(params));
3141                     expect(')');
3142                     if (!match('=>')) {
3143                         expect('=>');
3144                     }
3145                     isBindingElement = false;
3146                     for (i = 0; i < expressions.length; i++) {
3147                         reinterpretExpressionAsPattern(expressions[i]);
3148                     }
3149                     return {
3150                         type: PlaceHolders.ArrowParameterPlaceHolder,
3151                         params: expressions
3152                     };
3153                 }
3154
3155                 expressions.push(inheritCoverGrammar(parseAssignmentExpression));
3156             }
3157
3158             expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
3159         }
3160
3161
3162         expect(')');
3163
3164         if (match('=>')) {
3165             if (expr.type === Syntax.Identifier && expr.name === 'yield') {
3166                 return {
3167                     type: PlaceHolders.ArrowParameterPlaceHolder,
3168                     params: [expr]
3169                 };
3170             }
3171
3172             if (!isBindingElement) {
3173                 throwUnexpectedToken(lookahead);
3174             }
3175
3176             if (expr.type === Syntax.SequenceExpression) {
3177                 for (i = 0; i < expr.expressions.length; i++) {
3178                     reinterpretExpressionAsPattern(expr.expressions[i]);
3179                 }
3180             } else {
3181                 reinterpretExpressionAsPattern(expr);
3182             }
3183
3184             expr = {
3185                 type: PlaceHolders.ArrowParameterPlaceHolder,
3186                 params: expr.type === Syntax.SequenceExpression ? expr.expressions : [expr]
3187             };
3188         }
3189         isBindingElement = false;
3190         return expr;
3191     }
3192
3193
3194     // ECMA-262 12.2 Primary Expressions
3195
3196     function parsePrimaryExpression() {
3197         var type, token, expr, node;
3198
3199         if (match('(')) {
3200             isBindingElement = false;
3201             return inheritCoverGrammar(parseGroupExpression);
3202         }
3203
3204         if (match('[')) {
3205             return inheritCoverGrammar(parseArrayInitializer);
3206         }
3207
3208         if (match('{')) {
3209             return inheritCoverGrammar(parseObjectInitializer);
3210         }
3211
3212         type = lookahead.type;
3213         node = new Node();
3214
3215         if (type === Token.Identifier) {
3216             if (sourceType === 'module' && lookahead.value === 'await') {
3217                 tolerateUnexpectedToken(lookahead);
3218             }
3219             expr = node.finishIdentifier(lex().value);
3220         } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
3221             isAssignmentTarget = isBindingElement = false;
3222             if (strict && lookahead.octal) {
3223                 tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral);
3224             }
3225             expr = node.finishLiteral(lex());
3226         } else if (type === Token.Keyword) {
3227             if (!strict && state.allowYield && matchKeyword('yield')) {
3228                 return parseNonComputedProperty();
3229             }
3230             isAssignmentTarget = isBindingElement = false;
3231             if (matchKeyword('function')) {
3232                 return parseFunctionExpression();
3233             }
3234             if (matchKeyword('this')) {
3235                 lex();
3236                 return node.finishThisExpression();
3237             }
3238             if (matchKeyword('class')) {
3239                 return parseClassExpression();
3240             }
3241             throwUnexpectedToken(lex());
3242         } else if (type === Token.BooleanLiteral) {
3243             isAssignmentTarget = isBindingElement = false;
3244             token = lex();
3245             token.value = (token.value === 'true');
3246             expr = node.finishLiteral(token);
3247         } else if (type === Token.NullLiteral) {
3248             isAssignmentTarget = isBindingElement = false;
3249             token = lex();
3250             token.value = null;
3251             expr = node.finishLiteral(token);
3252         } else if (match('/') || match('/=')) {
3253             isAssignmentTarget = isBindingElement = false;
3254             index = startIndex;
3255
3256             if (typeof extra.tokens !== 'undefined') {
3257                 token = collectRegex();
3258             } else {
3259                 token = scanRegExp();
3260             }
3261             lex();
3262             expr = node.finishLiteral(token);
3263         } else if (type === Token.Template) {
3264             expr = parseTemplateLiteral();
3265         } else {
3266             throwUnexpectedToken(lex());
3267         }
3268
3269         return expr;
3270     }
3271
3272     // ECMA-262 12.3 Left-Hand-Side Expressions
3273
3274     function parseArguments() {
3275         var args = [], expr;
3276
3277         expect('(');
3278
3279         if (!match(')')) {
3280             while (startIndex < length) {
3281                 if (match('...')) {
3282                     expr = new Node();
3283                     lex();
3284                     expr.finishSpreadElement(isolateCoverGrammar(parseAssignmentExpression));
3285                 } else {
3286                     expr = isolateCoverGrammar(parseAssignmentExpression);
3287                 }
3288                 args.push(expr);
3289                 if (match(')')) {
3290                     break;
3291                 }
3292                 expectCommaSeparator();
3293             }
3294         }
3295
3296         expect(')');
3297
3298         return args;
3299     }
3300
3301     function parseNonComputedProperty() {
3302         var token, node = new Node();
3303
3304         token = lex();
3305
3306         if (!isIdentifierName(token)) {
3307             throwUnexpectedToken(token);
3308         }
3309
3310         return node.finishIdentifier(token.value);
3311     }
3312
3313     function parseNonComputedMember() {
3314         expect('.');
3315
3316         return parseNonComputedProperty();
3317     }
3318
3319     function parseComputedMember() {
3320         var expr;
3321
3322         expect('[');
3323
3324         expr = isolateCoverGrammar(parseExpression);
3325
3326         expect(']');
3327
3328         return expr;
3329     }
3330
3331     // ECMA-262 12.3.3 The new Operator
3332
3333     function parseNewExpression() {
3334         var callee, args, node = new Node();
3335
3336         expectKeyword('new');
3337
3338         if (match('.')) {
3339             lex();
3340             if (lookahead.type === Token.Identifier && lookahead.value === 'target') {
3341                 if (state.inFunctionBody) {
3342                     lex();
3343                     return node.finishMetaProperty('new', 'target');
3344                 }
3345             }
3346             throwUnexpectedToken(lookahead);
3347         }
3348
3349         callee = isolateCoverGrammar(parseLeftHandSideExpression);
3350         args = match('(') ? parseArguments() : [];
3351
3352         isAssignmentTarget = isBindingElement = false;
3353
3354         return node.finishNewExpression(callee, args);
3355     }
3356
3357     // ECMA-262 12.3.4 Function Calls
3358
3359     function parseLeftHandSideExpressionAllowCall() {
3360         var quasi, expr, args, property, startToken, previousAllowIn = state.allowIn;
3361
3362         startToken = lookahead;
3363         state.allowIn = true;
3364
3365         if (matchKeyword('super') && state.inFunctionBody) {
3366             expr = new Node();
3367             lex();
3368             expr = expr.finishSuper();
3369             if (!match('(') && !match('.') && !match('[')) {
3370                 throwUnexpectedToken(lookahead);
3371             }
3372         } else {
3373             expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression);
3374         }
3375
3376         for (;;) {
3377             if (match('.')) {
3378                 isBindingElement = false;
3379                 isAssignmentTarget = true;
3380                 property = parseNonComputedMember();
3381                 expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
3382             } else if (match('(')) {
3383                 isBindingElement = false;
3384                 isAssignmentTarget = false;
3385                 args = parseArguments();
3386                 expr = new WrappingNode(startToken).finishCallExpression(expr, args);
3387             } else if (match('[')) {
3388                 isBindingElement = false;
3389                 isAssignmentTarget = true;
3390                 property = parseComputedMember();
3391                 expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
3392             } else if (lookahead.type === Token.Template && lookahead.head) {
3393                 quasi = parseTemplateLiteral();
3394                 expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi);
3395             } else {
3396                 break;
3397             }
3398         }
3399         state.allowIn = previousAllowIn;
3400
3401         return expr;
3402     }
3403
3404     // ECMA-262 12.3 Left-Hand-Side Expressions
3405
3406     function parseLeftHandSideExpression() {
3407         var quasi, expr, property, startToken;
3408         assert(state.allowIn, 'callee of new expression always allow in keyword.');
3409
3410         startToken = lookahead;
3411
3412         if (matchKeyword('super') && state.inFunctionBody) {
3413             expr = new Node();
3414             lex();
3415             expr = expr.finishSuper();
3416             if (!match('[') && !match('.')) {
3417                 throwUnexpectedToken(lookahead);
3418             }
3419         } else {
3420             expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression);
3421         }
3422
3423         for (;;) {
3424             if (match('[')) {
3425                 isBindingElement = false;
3426                 isAssignmentTarget = true;
3427                 property = parseComputedMember();
3428                 expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
3429             } else if (match('.')) {
3430                 isBindingElement = false;
3431                 isAssignmentTarget = true;
3432                 property = parseNonComputedMember();
3433                 expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
3434             } else if (lookahead.type === Token.Template && lookahead.head) {
3435                 quasi = parseTemplateLiteral();
3436                 expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi);
3437             } else {
3438                 break;
3439             }
3440         }
3441         return expr;
3442     }
3443
3444     // ECMA-262 12.4 Postfix Expressions
3445
3446     function parsePostfixExpression() {
3447         var expr, token, startToken = lookahead;
3448
3449         expr = inheritCoverGrammar(parseLeftHandSideExpressionAllowCall);
3450
3451         if (!hasLineTerminator && lookahead.type === Token.Punctuator) {
3452             if (match('++') || match('--')) {
3453                 // ECMA-262 11.3.1, 11.3.2
3454                 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
3455                     tolerateError(Messages.StrictLHSPostfix);
3456                 }
3457
3458                 if (!isAssignmentTarget) {
3459                     tolerateError(Messages.InvalidLHSInAssignment);
3460                 }
3461
3462                 isAssignmentTarget = isBindingElement = false;
3463
3464                 token = lex();
3465                 expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr);
3466             }
3467         }
3468
3469         return expr;
3470     }
3471
3472     // ECMA-262 12.5 Unary Operators
3473
3474     function parseUnaryExpression() {
3475         var token, expr, startToken;
3476
3477         if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
3478             expr = parsePostfixExpression();
3479         } else if (match('++') || match('--')) {
3480             startToken = lookahead;
3481             token = lex();
3482             expr = inheritCoverGrammar(parseUnaryExpression);
3483             // ECMA-262 11.4.4, 11.4.5
3484             if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
3485                 tolerateError(Messages.StrictLHSPrefix);
3486             }
3487
3488             if (!isAssignmentTarget) {
3489                 tolerateError(Messages.InvalidLHSInAssignment);
3490             }
3491             expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
3492             isAssignmentTarget = isBindingElement = false;
3493         } else if (match('+') || match('-') || match('~') || match('!')) {
3494             startToken = lookahead;
3495             token = lex();
3496             expr = inheritCoverGrammar(parseUnaryExpression);
3497             expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
3498             isAssignmentTarget = isBindingElement = false;
3499         } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
3500             startToken = lookahead;
3501             token = lex();
3502             expr = inheritCoverGrammar(parseUnaryExpression);
3503             expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
3504             if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
3505                 tolerateError(Messages.StrictDelete);
3506             }
3507             isAssignmentTarget = isBindingElement = false;
3508         } else {
3509             expr = parsePostfixExpression();
3510         }
3511
3512         return expr;
3513     }
3514
3515     function binaryPrecedence(token, allowIn) {
3516         var prec = 0;
3517
3518         if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
3519             return 0;
3520         }
3521
3522         switch (token.value) {
3523         case '||':
3524             prec = 1;
3525             break;
3526
3527         case '&&':
3528             prec = 2;
3529             break;
3530
3531         case '|':
3532             prec = 3;
3533             break;
3534
3535         case '^':
3536             prec = 4;
3537             break;
3538
3539         case '&':
3540             prec = 5;
3541             break;
3542
3543         case '==':
3544         case '!=':
3545         case '===':
3546         case '!==':
3547             prec = 6;
3548             break;
3549
3550         case '<':
3551         case '>':
3552         case '<=':
3553         case '>=':
3554         case 'instanceof':
3555             prec = 7;
3556             break;
3557
3558         case 'in':
3559             prec = allowIn ? 7 : 0;
3560             break;
3561
3562         case '<<':
3563         case '>>':
3564         case '>>>':
3565             prec = 8;
3566             break;
3567
3568         case '+':
3569         case '-':
3570             prec = 9;
3571             break;
3572
3573         case '*':
3574         case '/':
3575         case '%':
3576             prec = 11;
3577             break;
3578
3579         default:
3580             break;
3581         }
3582
3583         return prec;
3584     }
3585
3586     // ECMA-262 12.6 Multiplicative Operators
3587     // ECMA-262 12.7 Additive Operators
3588     // ECMA-262 12.8 Bitwise Shift Operators
3589     // ECMA-262 12.9 Relational Operators
3590     // ECMA-262 12.10 Equality Operators
3591     // ECMA-262 12.11 Binary Bitwise Operators
3592     // ECMA-262 12.12 Binary Logical Operators
3593
3594     function parseBinaryExpression() {
3595         var marker, markers, expr, token, prec, stack, right, operator, left, i;
3596
3597         marker = lookahead;
3598         left = inheritCoverGrammar(parseUnaryExpression);
3599
3600         token = lookahead;
3601         prec = binaryPrecedence(token, state.allowIn);
3602         if (prec === 0) {
3603             return left;
3604         }
3605         isAssignmentTarget = isBindingElement = false;
3606         token.prec = prec;
3607         lex();
3608
3609         markers = [marker, lookahead];
3610         right = isolateCoverGrammar(parseUnaryExpression);
3611
3612         stack = [left, token, right];
3613
3614         while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) {
3615
3616             // Reduce: make a binary expression from the three topmost entries.
3617             while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
3618                 right = stack.pop();
3619                 operator = stack.pop().value;
3620                 left = stack.pop();
3621                 markers.pop();
3622                 expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right);
3623                 stack.push(expr);
3624             }
3625
3626             // Shift.
3627             token = lex();
3628             token.prec = prec;
3629             stack.push(token);
3630             markers.push(lookahead);
3631             expr = isolateCoverGrammar(parseUnaryExpression);
3632             stack.push(expr);
3633         }
3634
3635         // Final reduce to clean-up the stack.
3636         i = stack.length - 1;
3637         expr = stack[i];
3638         markers.pop();
3639         while (i > 1) {
3640             expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
3641             i -= 2;
3642         }
3643
3644         return expr;
3645     }
3646
3647
3648     // ECMA-262 12.13 Conditional Operator
3649
3650     function parseConditionalExpression() {
3651         var expr, previousAllowIn, consequent, alternate, startToken;
3652
3653         startToken = lookahead;
3654
3655         expr = inheritCoverGrammar(parseBinaryExpression);
3656         if (match('?')) {
3657             lex();
3658             previousAllowIn = state.allowIn;
3659             state.allowIn = true;
3660             consequent = isolateCoverGrammar(parseAssignmentExpression);
3661             state.allowIn = previousAllowIn;
3662             expect(':');
3663             alternate = isolateCoverGrammar(parseAssignmentExpression);
3664
3665             expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
3666             isAssignmentTarget = isBindingElement = false;
3667         }
3668
3669         return expr;
3670     }
3671
3672     // ECMA-262 14.2 Arrow Function Definitions
3673
3674     function parseConciseBody() {
3675         if (match('{')) {
3676             return parseFunctionSourceElements();
3677         }
3678         return isolateCoverGrammar(parseAssignmentExpression);
3679     }
3680
3681     function checkPatternParam(options, param) {
3682         var i;
3683         switch (param.type) {
3684         case Syntax.Identifier:
3685             validateParam(options, param, param.name);
3686             break;
3687         case Syntax.RestElement:
3688             checkPatternParam(options, param.argument);
3689             break;
3690         case Syntax.AssignmentPattern:
3691             checkPatternParam(options, param.left);
3692             break;
3693         case Syntax.ArrayPattern:
3694             for (i = 0; i < param.elements.length; i++) {
3695                 if (param.elements[i] !== null) {
3696                     checkPatternParam(options, param.elements[i]);
3697                 }
3698             }
3699             break;
3700         case Syntax.YieldExpression:
3701             break;
3702         default:
3703             assert(param.type === Syntax.ObjectPattern, 'Invalid type');
3704             for (i = 0; i < param.properties.length; i++) {
3705                 checkPatternParam(options, param.properties[i].value);
3706             }
3707             break;
3708         }
3709     }
3710     function reinterpretAsCoverFormalsList(expr) {
3711         var i, len, param, params, defaults, defaultCount, options, token;
3712
3713         defaults = [];
3714         defaultCount = 0;
3715         params = [expr];
3716
3717         switch (expr.type) {
3718         case Syntax.Identifier:
3719             break;
3720         case PlaceHolders.ArrowParameterPlaceHolder:
3721             params = expr.params;
3722             break;
3723         default:
3724             return null;
3725         }
3726
3727         options = {
3728             paramSet: {}
3729         };
3730
3731         for (i = 0, len = params.length; i < len; i += 1) {
3732             param = params[i];
3733             switch (param.type) {
3734             case Syntax.AssignmentPattern:
3735                 params[i] = param.left;
3736                 if (param.right.type === Syntax.YieldExpression) {
3737                     if (param.right.argument) {
3738                         throwUnexpectedToken(lookahead);
3739                     }
3740                     param.right.type = Syntax.Identifier;
3741                     param.right.name = 'yield';
3742                     delete param.right.argument;
3743                     delete param.right.delegate;
3744                 }
3745                 defaults.push(param.right);
3746                 ++defaultCount;
3747                 checkPatternParam(options, param.left);
3748                 break;
3749             default:
3750                 checkPatternParam(options, param);
3751                 params[i] = param;
3752                 defaults.push(null);
3753                 break;
3754             }
3755         }
3756
3757         if (strict || !state.allowYield) {
3758             for (i = 0, len = params.length; i < len; i += 1) {
3759                 param = params[i];
3760                 if (param.type === Syntax.YieldExpression) {
3761                     throwUnexpectedToken(lookahead);
3762                 }
3763             }
3764         }
3765
3766         if (options.message === Messages.StrictParamDupe) {
3767             token = strict ? options.stricted : options.firstRestricted;
3768             throwUnexpectedToken(token, options.message);
3769         }
3770
3771         if (defaultCount === 0) {
3772             defaults = [];
3773         }
3774
3775         return {
3776             params: params,
3777             defaults: defaults,
3778             stricted: options.stricted,
3779             firstRestricted: options.firstRestricted,
3780             message: options.message
3781         };
3782     }
3783
3784     function parseArrowFunctionExpression(options, node) {
3785         var previousStrict, previousAllowYield, body;
3786
3787         if (hasLineTerminator) {
3788             tolerateUnexpectedToken(lookahead);
3789         }
3790         expect('=>');
3791
3792         previousStrict = strict;
3793         previousAllowYield = state.allowYield;
3794         state.allowYield = true;
3795
3796         body = parseConciseBody();
3797
3798         if (strict && options.firstRestricted) {
3799             throwUnexpectedToken(options.firstRestricted, options.message);
3800         }
3801         if (strict && options.stricted) {
3802             tolerateUnexpectedToken(options.stricted, options.message);
3803         }
3804
3805         strict = previousStrict;
3806         state.allowYield = previousAllowYield;
3807
3808         return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement);
3809     }
3810
3811     // ECMA-262 14.4 Yield expression
3812
3813     function parseYieldExpression() {
3814         var argument, expr, delegate, previousAllowYield;
3815
3816         argument = null;
3817         expr = new Node();
3818
3819         expectKeyword('yield');
3820
3821         if (!hasLineTerminator) {
3822             previousAllowYield = state.allowYield;
3823             state.allowYield = false;
3824             delegate = match('*');
3825             if (delegate) {
3826                 lex();
3827                 argument = parseAssignmentExpression();
3828             } else {
3829                 if (!match(';') && !match('}') && !match(')') && lookahead.type !== Token.EOF) {
3830                     argument = parseAssignmentExpression();
3831                 }
3832             }
3833             state.allowYield = previousAllowYield;
3834         }
3835
3836         return expr.finishYieldExpression(argument, delegate);
3837     }
3838
3839     // ECMA-262 12.14 Assignment Operators
3840
3841     function parseAssignmentExpression() {
3842         var token, expr, right, list, startToken;
3843
3844         startToken = lookahead;
3845         token = lookahead;
3846
3847         if (!state.allowYield && matchKeyword('yield')) {
3848             return parseYieldExpression();
3849         }
3850
3851         expr = parseConditionalExpression();
3852
3853         if (expr.type === PlaceHolders.ArrowParameterPlaceHolder || match('=>')) {
3854             isAssignmentTarget = isBindingElement = false;
3855             list = reinterpretAsCoverFormalsList(expr);
3856
3857             if (list) {
3858                 firstCoverInitializedNameError = null;
3859                 return parseArrowFunctionExpression(list, new WrappingNode(startToken));
3860             }
3861
3862             return expr;
3863         }
3864
3865         if (matchAssign()) {
3866             if (!isAssignmentTarget) {
3867                 tolerateError(Messages.InvalidLHSInAssignment);
3868             }
3869
3870             // ECMA-262 11.13.1
3871             if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
3872                 tolerateUnexpectedToken(token, Messages.StrictLHSAssignment);
3873             }
3874
3875             if (!match('=')) {
3876                 isAssignmentTarget = isBindingElement = false;
3877             } else {
3878                 reinterpretExpressionAsPattern(expr);
3879             }
3880
3881             token = lex();
3882             right = isolateCoverGrammar(parseAssignmentExpression);
3883             expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right);
3884             firstCoverInitializedNameError = null;
3885         }
3886
3887         return expr;
3888     }
3889
3890     // ECMA-262 12.15 Comma Operator
3891
3892     function parseExpression() {
3893         var expr, startToken = lookahead, expressions;
3894
3895         expr = isolateCoverGrammar(parseAssignmentExpression);
3896
3897         if (match(',')) {
3898             expressions = [expr];
3899
3900             while (startIndex < length) {
3901                 if (!match(',')) {
3902                     break;
3903                 }
3904                 lex();
3905                 expressions.push(isolateCoverGrammar(parseAssignmentExpression));
3906             }
3907
3908             expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
3909         }
3910
3911         return expr;
3912     }
3913
3914     // ECMA-262 13.2 Block
3915
3916     function parseStatementListItem() {
3917         if (lookahead.type === Token.Keyword) {
3918             switch (lookahead.value) {
3919             case 'export':
3920                 if (sourceType !== 'module') {
3921                     tolerateUnexpectedToken(lookahead, Messages.IllegalExportDeclaration);
3922                 }
3923                 return parseExportDeclaration();
3924             case 'import':
3925                 if (sourceType !== 'module') {
3926                     tolerateUnexpectedToken(lookahead, Messages.IllegalImportDeclaration);
3927                 }
3928                 return parseImportDeclaration();
3929             case 'const':
3930             case 'let':
3931                 return parseLexicalDeclaration({inFor: false});
3932             case 'function':
3933                 return parseFunctionDeclaration(new Node());
3934             case 'class':
3935                 return parseClassDeclaration();
3936             }
3937         }
3938
3939         return parseStatement();
3940     }
3941
3942     function parseStatementList() {
3943         var list = [];
3944         while (startIndex < length) {
3945             if (match('}')) {
3946                 break;
3947             }
3948             list.push(parseStatementListItem());
3949         }
3950
3951         return list;
3952     }
3953
3954     function parseBlock() {
3955         var block, node = new Node();
3956
3957         expect('{');
3958
3959         block = parseStatementList();
3960
3961         expect('}');
3962
3963         return node.finishBlockStatement(block);
3964     }
3965
3966     // ECMA-262 13.3.2 Variable Statement
3967
3968     function parseVariableIdentifier() {
3969         var token, node = new Node();
3970
3971         token = lex();
3972
3973         if (token.type === Token.Keyword && token.value === 'yield') {
3974             if (strict) {
3975                 tolerateUnexpectedToken(token, Messages.StrictReservedWord);
3976             } if (!state.allowYield) {
3977                 throwUnexpectedToken(token);
3978             }
3979         } else if (token.type !== Token.Identifier) {
3980             if (strict && token.type === Token.Keyword && isStrictModeReservedWord(token.value)) {
3981                 tolerateUnexpectedToken(token, Messages.StrictReservedWord);
3982             } else {
3983                 throwUnexpectedToken(token);
3984             }
3985         } else if (sourceType === 'module' && token.type === Token.Identifier && token.value === 'await') {
3986             tolerateUnexpectedToken(token);
3987         }
3988
3989         return node.finishIdentifier(token.value);
3990     }
3991
3992     function parseVariableDeclaration() {
3993         var init = null, id, node = new Node(), params = [];
3994
3995         id = parsePattern(params);
3996
3997         // ECMA-262 12.2.1
3998         if (strict && isRestrictedWord(id.name)) {
3999             tolerateError(Messages.StrictVarName);
4000         }
4001
4002         if (match('=')) {
4003             lex();
4004             init = isolateCoverGrammar(parseAssignmentExpression);
4005         } else if (id.type !== Syntax.Identifier) {
4006             expect('=');
4007         }
4008
4009         return node.finishVariableDeclarator(id, init);
4010     }
4011
4012     function parseVariableDeclarationList() {
4013         var list = [];
4014
4015         do {
4016             list.push(parseVariableDeclaration());
4017             if (!match(',')) {
4018                 break;
4019             }
4020             lex();
4021         } while (startIndex < length);
4022
4023         return list;
4024     }
4025
4026     function parseVariableStatement(node) {
4027         var declarations;
4028
4029         expectKeyword('var');
4030
4031         declarations = parseVariableDeclarationList();
4032
4033         consumeSemicolon();
4034
4035         return node.finishVariableDeclaration(declarations);
4036     }
4037
4038     // ECMA-262 13.3.1 Let and Const Declarations
4039
4040     function parseLexicalBinding(kind, options) {
4041         var init = null, id, node = new Node(), params = [];
4042
4043         id = parsePattern(params);
4044
4045         // ECMA-262 12.2.1
4046         if (strict && id.type === Syntax.Identifier && isRestrictedWord(id.name)) {
4047             tolerateError(Messages.StrictVarName);
4048         }
4049
4050         if (kind === 'const') {
4051             if (!matchKeyword('in') && !matchContextualKeyword('of')) {
4052                 expect('=');
4053                 init = isolateCoverGrammar(parseAssignmentExpression);
4054             }
4055         } else if ((!options.inFor && id.type !== Syntax.Identifier) || match('=')) {
4056             expect('=');
4057             init = isolateCoverGrammar(parseAssignmentExpression);
4058         }
4059
4060         return node.finishVariableDeclarator(id, init);
4061     }
4062
4063     function parseBindingList(kind, options) {
4064         var list = [];
4065
4066         do {
4067             list.push(parseLexicalBinding(kind, options));
4068             if (!match(',')) {
4069                 break;
4070             }
4071             lex();
4072         } while (startIndex < length);
4073
4074         return list;
4075     }
4076
4077     function parseLexicalDeclaration(options) {
4078         var kind, declarations, node = new Node();
4079
4080         kind = lex().value;
4081         assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const');
4082
4083         declarations = parseBindingList(kind, options);
4084
4085         consumeSemicolon();
4086
4087         return node.finishLexicalDeclaration(declarations, kind);
4088     }
4089
4090     function parseRestElement(params) {
4091         var param, node = new Node();
4092
4093         lex();
4094
4095         if (match('{')) {
4096             throwError(Messages.ObjectPatternAsRestParameter);
4097         }
4098
4099         params.push(lookahead);
4100
4101         param = parseVariableIdentifier();
4102
4103         if (match('=')) {
4104             throwError(Messages.DefaultRestParameter);
4105         }
4106
4107         if (!match(')')) {
4108             throwError(Messages.ParameterAfterRestParameter);
4109         }
4110
4111         return node.finishRestElement(param);
4112     }
4113
4114     // ECMA-262 13.4 Empty Statement
4115
4116     function parseEmptyStatement(node) {
4117         expect(';');
4118         return node.finishEmptyStatement();
4119     }
4120
4121     // ECMA-262 12.4 Expression Statement
4122
4123     function parseExpressionStatement(node) {
4124         var expr = parseExpression();
4125         consumeSemicolon();
4126         return node.finishExpressionStatement(expr);
4127     }
4128
4129     // ECMA-262 13.6 If statement
4130
4131     function parseIfStatement(node) {
4132         var test, consequent, alternate;
4133
4134         expectKeyword('if');
4135
4136         expect('(');
4137
4138         test = parseExpression();
4139
4140         expect(')');
4141
4142         consequent = parseStatement();
4143
4144         if (matchKeyword('else')) {
4145             lex();
4146             alternate = parseStatement();
4147         } else {
4148             alternate = null;
4149         }
4150
4151         return node.finishIfStatement(test, consequent, alternate);
4152     }
4153
4154     // ECMA-262 13.7 Iteration Statements
4155
4156     function parseDoWhileStatement(node) {
4157         var body, test, oldInIteration;
4158
4159         expectKeyword('do');
4160
4161         oldInIteration = state.inIteration;
4162         state.inIteration = true;
4163
4164         body = parseStatement();
4165
4166         state.inIteration = oldInIteration;
4167
4168         expectKeyword('while');
4169
4170         expect('(');
4171
4172         test = parseExpression();
4173
4174         expect(')');
4175
4176         if (match(';')) {
4177             lex();
4178         }
4179
4180         return node.finishDoWhileStatement(body, test);
4181     }
4182
4183     function parseWhileStatement(node) {
4184         var test, body, oldInIteration;
4185
4186         expectKeyword('while');
4187
4188         expect('(');
4189
4190         test = parseExpression();
4191
4192         expect(')');
4193
4194         oldInIteration = state.inIteration;
4195         state.inIteration = true;
4196
4197         body = parseStatement();
4198
4199         state.inIteration = oldInIteration;
4200
4201         return node.finishWhileStatement(test, body);
4202     }
4203
4204     function parseForStatement(node) {
4205         var init, forIn, initSeq, initStartToken, test, update, left, right, kind, declarations,
4206             body, oldInIteration, previousAllowIn = state.allowIn;
4207
4208         init = test = update = null;
4209         forIn = true;
4210
4211         expectKeyword('for');
4212
4213         expect('(');
4214
4215         if (match(';')) {
4216             lex();
4217         } else {
4218             if (matchKeyword('var')) {
4219                 init = new Node();
4220                 lex();
4221
4222                 state.allowIn = false;
4223                 init = init.finishVariableDeclaration(parseVariableDeclarationList());
4224                 state.allowIn = previousAllowIn;
4225
4226                 if (init.declarations.length === 1 && matchKeyword('in')) {
4227                     lex();
4228                     left = init;
4229                     right = parseExpression();
4230                     init = null;
4231                 } else if (init.declarations.length === 1 && init.declarations[0].init === null && matchContextualKeyword('of')) {
4232                     lex();
4233                     left = init;
4234                     right = parseAssignmentExpression();
4235                     init = null;
4236                     forIn = false;
4237                 } else {
4238                     expect(';');
4239                 }
4240             } else if (matchKeyword('const') || matchKeyword('let')) {
4241                 init = new Node();
4242                 kind = lex().value;
4243
4244                 state.allowIn = false;
4245                 declarations = parseBindingList(kind, {inFor: true});
4246                 state.allowIn = previousAllowIn;
4247
4248                 if (declarations.length === 1 && declarations[0].init === null && matchKeyword('in')) {
4249                     init = init.finishLexicalDeclaration(declarations, kind);
4250                     lex();
4251                     left = init;
4252                     right = parseExpression();
4253                     init = null;
4254                 } else if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) {
4255                     init = init.finishLexicalDeclaration(declarations, kind);
4256                     lex();
4257                     left = init;
4258                     right = parseAssignmentExpression();
4259                     init = null;
4260                     forIn = false;
4261                 } else {
4262                     consumeSemicolon();
4263                     init = init.finishLexicalDeclaration(declarations, kind);
4264                 }
4265             } else {
4266                 initStartToken = lookahead;
4267                 state.allowIn = false;
4268                 init = inheritCoverGrammar(parseAssignmentExpression);
4269                 state.allowIn = previousAllowIn;
4270
4271                 if (matchKeyword('in')) {
4272                     if (!isAssignmentTarget) {
4273                         tolerateError(Messages.InvalidLHSInForIn);
4274                     }
4275
4276                     lex();
4277                     reinterpretExpressionAsPattern(init);
4278                     left = init;
4279                     right = parseExpression();
4280                     init = null;
4281                 } else if (matchContextualKeyword('of')) {
4282                     if (!isAssignmentTarget) {
4283                         tolerateError(Messages.InvalidLHSInForLoop);
4284                     }
4285
4286                     lex();
4287                     reinterpretExpressionAsPattern(init);
4288                     left = init;
4289                     right = parseAssignmentExpression();
4290                     init = null;
4291                     forIn = false;
4292                 } else {
4293                     if (match(',')) {
4294                         initSeq = [init];
4295                         while (match(',')) {
4296                             lex();
4297                             initSeq.push(isolateCoverGrammar(parseAssignmentExpression));
4298                         }
4299                         init = new WrappingNode(initStartToken).finishSequenceExpression(initSeq);
4300                     }
4301                     expect(';');
4302                 }
4303             }
4304         }
4305
4306         if (typeof left === 'undefined') {
4307
4308             if (!match(';')) {
4309                 test = parseExpression();
4310             }
4311             expect(';');
4312
4313             if (!match(')')) {
4314                 update = parseExpression();
4315             }
4316         }
4317
4318         expect(')');
4319
4320         oldInIteration = state.inIteration;
4321         state.inIteration = true;
4322
4323         body = isolateCoverGrammar(parseStatement);
4324
4325         state.inIteration = oldInIteration;
4326
4327         return (typeof left === 'undefined') ?
4328                 node.finishForStatement(init, test, update, body) :
4329                 forIn ? node.finishForInStatement(left, right, body) :
4330                     node.finishForOfStatement(left, right, body);
4331     }
4332
4333     // ECMA-262 13.8 The continue statement
4334
4335     function parseContinueStatement(node) {
4336         var label = null, key;
4337
4338         expectKeyword('continue');
4339
4340         // Optimize the most common form: 'continue;'.
4341         if (source.charCodeAt(startIndex) === 0x3B) {
4342             lex();
4343
4344             if (!state.inIteration) {
4345                 throwError(Messages.IllegalContinue);
4346             }
4347
4348             return node.finishContinueStatement(null);
4349         }
4350
4351         if (hasLineTerminator) {
4352             if (!state.inIteration) {
4353                 throwError(Messages.IllegalContinue);
4354             }
4355
4356             return node.finishContinueStatement(null);
4357         }
4358
4359         if (lookahead.type === Token.Identifier) {
4360             label = parseVariableIdentifier();
4361
4362             key = '$' + label.name;
4363             if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
4364                 throwError(Messages.UnknownLabel, label.name);
4365             }
4366         }
4367
4368         consumeSemicolon();
4369
4370         if (label === null && !state.inIteration) {
4371             throwError(Messages.IllegalContinue);
4372         }
4373
4374         return node.finishContinueStatement(label);
4375     }
4376
4377     // ECMA-262 13.9 The break statement
4378
4379     function parseBreakStatement(node) {
4380         var label = null, key;
4381
4382         expectKeyword('break');
4383
4384         // Catch the very common case first: immediately a semicolon (U+003B).
4385         if (source.charCodeAt(lastIndex) === 0x3B) {
4386             lex();
4387
4388             if (!(state.inIteration || state.inSwitch)) {
4389                 throwError(Messages.IllegalBreak);
4390             }
4391
4392             return node.finishBreakStatement(null);
4393         }
4394
4395         if (hasLineTerminator) {
4396             if (!(state.inIteration || state.inSwitch)) {
4397                 throwError(Messages.IllegalBreak);
4398             }
4399
4400             return node.finishBreakStatement(null);
4401         }
4402
4403         if (lookahead.type === Token.Identifier) {
4404             label = parseVariableIdentifier();
4405
4406             key = '$' + label.name;
4407             if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
4408                 throwError(Messages.UnknownLabel, label.name);
4409             }
4410         }
4411
4412         consumeSemicolon();
4413
4414         if (label === null && !(state.inIteration || state.inSwitch)) {
4415             throwError(Messages.IllegalBreak);
4416         }
4417
4418         return node.finishBreakStatement(label);
4419     }
4420
4421     // ECMA-262 13.10 The return statement
4422
4423     function parseReturnStatement(node) {
4424         var argument = null;
4425
4426         expectKeyword('return');
4427
4428         if (!state.inFunctionBody) {
4429             tolerateError(Messages.IllegalReturn);
4430         }
4431
4432         // 'return' followed by a space and an identifier is very common.
4433         if (source.charCodeAt(lastIndex) === 0x20) {
4434             if (isIdentifierStart(source.charCodeAt(lastIndex + 1))) {
4435                 argument = parseExpression();
4436                 consumeSemicolon();
4437                 return node.finishReturnStatement(argument);
4438             }
4439         }
4440
4441         if (hasLineTerminator) {
4442             // HACK
4443             return node.finishReturnStatement(null);
4444         }
4445
4446         if (!match(';')) {
4447             if (!match('}') && lookahead.type !== Token.EOF) {
4448                 argument = parseExpression();
4449             }
4450         }
4451
4452         consumeSemicolon();
4453
4454         return node.finishReturnStatement(argument);
4455     }
4456
4457     // ECMA-262 13.11 The with statement
4458
4459     function parseWithStatement(node) {
4460         var object, body;
4461
4462         if (strict) {
4463             tolerateError(Messages.StrictModeWith);
4464         }
4465
4466         expectKeyword('with');
4467
4468         expect('(');
4469
4470         object = parseExpression();
4471
4472         expect(')');
4473
4474         body = parseStatement();
4475
4476         return node.finishWithStatement(object, body);
4477     }
4478
4479     // ECMA-262 13.12 The switch statement
4480
4481     function parseSwitchCase() {
4482         var test, consequent = [], statement, node = new Node();
4483
4484         if (matchKeyword('default')) {
4485             lex();
4486             test = null;
4487         } else {
4488             expectKeyword('case');
4489             test = parseExpression();
4490         }
4491         expect(':');
4492
4493         while (startIndex < length) {
4494             if (match('}') || matchKeyword('default') || matchKeyword('case')) {
4495                 break;
4496             }
4497             statement = parseStatementListItem();
4498             consequent.push(statement);
4499         }
4500
4501         return node.finishSwitchCase(test, consequent);
4502     }
4503
4504     function parseSwitchStatement(node) {
4505         var discriminant, cases, clause, oldInSwitch, defaultFound;
4506
4507         expectKeyword('switch');
4508
4509         expect('(');
4510
4511         discriminant = parseExpression();
4512
4513         expect(')');
4514
4515         expect('{');
4516
4517         cases = [];
4518
4519         if (match('}')) {
4520             lex();
4521             return node.finishSwitchStatement(discriminant, cases);
4522         }
4523
4524         oldInSwitch = state.inSwitch;
4525         state.inSwitch = true;
4526         defaultFound = false;
4527
4528         while (startIndex < length) {
4529             if (match('}')) {
4530                 break;
4531             }
4532             clause = parseSwitchCase();
4533             if (clause.test === null) {
4534                 if (defaultFound) {
4535                     throwError(Messages.MultipleDefaultsInSwitch);
4536                 }
4537                 defaultFound = true;
4538             }
4539             cases.push(clause);
4540         }
4541
4542         state.inSwitch = oldInSwitch;
4543
4544         expect('}');
4545
4546         return node.finishSwitchStatement(discriminant, cases);
4547     }
4548
4549     // ECMA-262 13.14 The throw statement
4550
4551     function parseThrowStatement(node) {
4552         var argument;
4553
4554         expectKeyword('throw');
4555
4556         if (hasLineTerminator) {
4557             throwError(Messages.NewlineAfterThrow);
4558         }
4559
4560         argument = parseExpression();
4561
4562         consumeSemicolon();
4563
4564         return node.finishThrowStatement(argument);
4565     }
4566
4567     // ECMA-262 13.15 The try statement
4568
4569     function parseCatchClause() {
4570         var param, params = [], paramMap = {}, key, i, body, node = new Node();
4571
4572         expectKeyword('catch');
4573
4574         expect('(');
4575         if (match(')')) {
4576             throwUnexpectedToken(lookahead);
4577         }
4578
4579         param = parsePattern(params);
4580         for (i = 0; i < params.length; i++) {
4581             key = '$' + params[i].value;
4582             if (Object.prototype.hasOwnProperty.call(paramMap, key)) {
4583                 tolerateError(Messages.DuplicateBinding, params[i].value);
4584             }
4585             paramMap[key] = true;
4586         }
4587
4588         // ECMA-262 12.14.1
4589         if (strict && isRestrictedWord(param.name)) {
4590             tolerateError(Messages.StrictCatchVariable);
4591         }
4592
4593         expect(')');
4594         body = parseBlock();
4595         return node.finishCatchClause(param, body);
4596     }
4597
4598     function parseTryStatement(node) {
4599         var block, handler = null, finalizer = null;
4600
4601         expectKeyword('try');
4602
4603         block = parseBlock();
4604
4605         if (matchKeyword('catch')) {
4606             handler = parseCatchClause();
4607         }
4608
4609         if (matchKeyword('finally')) {
4610             lex();
4611             finalizer = parseBlock();
4612         }
4613
4614         if (!handler && !finalizer) {
4615             throwError(Messages.NoCatchOrFinally);
4616         }
4617
4618         return node.finishTryStatement(block, handler, finalizer);
4619     }
4620
4621     // ECMA-262 13.16 The debugger statement
4622
4623     function parseDebuggerStatement(node) {
4624         expectKeyword('debugger');
4625
4626         consumeSemicolon();
4627
4628         return node.finishDebuggerStatement();
4629     }
4630
4631     // 13 Statements
4632
4633     function parseStatement() {
4634         var type = lookahead.type,
4635             expr,
4636             labeledBody,
4637             key,
4638             node;
4639
4640         if (type === Token.EOF) {
4641             throwUnexpectedToken(lookahead);
4642         }
4643
4644         if (type === Token.Punctuator && lookahead.value === '{') {
4645             return parseBlock();
4646         }
4647         isAssignmentTarget = isBindingElement = true;
4648         node = new Node();
4649
4650         if (type === Token.Punctuator) {
4651             switch (lookahead.value) {
4652             case ';':
4653                 return parseEmptyStatement(node);
4654             case '(':
4655                 return parseExpressionStatement(node);
4656             default:
4657                 break;
4658             }
4659         } else if (type === Token.Keyword) {
4660             switch (lookahead.value) {
4661             case 'break':
4662                 return parseBreakStatement(node);
4663             case 'continue':
4664                 return parseContinueStatement(node);
4665             case 'debugger':
4666                 return parseDebuggerStatement(node);
4667             case 'do':
4668                 return parseDoWhileStatement(node);
4669             case 'for':
4670                 return parseForStatement(node);
4671             case 'function':
4672                 return parseFunctionDeclaration(node);
4673             case 'if':
4674                 return parseIfStatement(node);
4675             case 'return':
4676                 return parseReturnStatement(node);
4677             case 'switch':
4678                 return parseSwitchStatement(node);
4679             case 'throw':
4680                 return parseThrowStatement(node);
4681             case 'try':
4682                 return parseTryStatement(node);
4683             case 'var':
4684                 return parseVariableStatement(node);
4685             case 'while':
4686                 return parseWhileStatement(node);
4687             case 'with':
4688                 return parseWithStatement(node);
4689             default:
4690                 break;
4691             }
4692         }
4693
4694         expr = parseExpression();
4695
4696         // ECMA-262 12.12 Labelled Statements
4697         if ((expr.type === Syntax.Identifier) && match(':')) {
4698             lex();
4699
4700             key = '$' + expr.name;
4701             if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
4702                 throwError(Messages.Redeclaration, 'Label', expr.name);
4703             }
4704
4705             state.labelSet[key] = true;
4706             labeledBody = parseStatement();
4707             delete state.labelSet[key];
4708             return node.finishLabeledStatement(expr, labeledBody);
4709         }
4710
4711         consumeSemicolon();
4712
4713         return node.finishExpressionStatement(expr);
4714     }
4715
4716     // ECMA-262 14.1 Function Definition
4717
4718     function parseFunctionSourceElements() {
4719         var statement, body = [], token, directive, firstRestricted,
4720             oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesisCount,
4721             node = new Node();
4722
4723         expect('{');
4724
4725         while (startIndex < length) {
4726             if (lookahead.type !== Token.StringLiteral) {
4727                 break;
4728             }
4729             token = lookahead;
4730
4731             statement = parseStatementListItem();
4732             body.push(statement);
4733             if (statement.expression.type !== Syntax.Literal) {
4734                 // this is not directive
4735                 break;
4736             }
4737             directive = source.slice(token.start + 1, token.end - 1);
4738             if (directive === 'use strict') {
4739                 strict = true;
4740                 if (firstRestricted) {
4741                     tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
4742                 }
4743             } else {
4744                 if (!firstRestricted && token.octal) {
4745                     firstRestricted = token;
4746                 }
4747             }
4748         }
4749
4750         oldLabelSet = state.labelSet;
4751         oldInIteration = state.inIteration;
4752         oldInSwitch = state.inSwitch;
4753         oldInFunctionBody = state.inFunctionBody;
4754         oldParenthesisCount = state.parenthesizedCount;
4755
4756         state.labelSet = {};
4757         state.inIteration = false;
4758         state.inSwitch = false;
4759         state.inFunctionBody = true;
4760         state.parenthesizedCount = 0;
4761
4762         while (startIndex < length) {
4763             if (match('}')) {
4764                 break;
4765             }
4766             body.push(parseStatementListItem());
4767         }
4768
4769         expect('}');
4770
4771         state.labelSet = oldLabelSet;
4772         state.inIteration = oldInIteration;
4773         state.inSwitch = oldInSwitch;
4774         state.inFunctionBody = oldInFunctionBody;
4775         state.parenthesizedCount = oldParenthesisCount;
4776
4777         return node.finishBlockStatement(body);
4778     }
4779
4780     function validateParam(options, param, name) {
4781         var key = '$' + name;
4782         if (strict) {
4783             if (isRestrictedWord(name)) {
4784                 options.stricted = param;
4785                 options.message = Messages.StrictParamName;
4786             }
4787             if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
4788                 options.stricted = param;
4789                 options.message = Messages.StrictParamDupe;
4790             }
4791         } else if (!options.firstRestricted) {
4792             if (isRestrictedWord(name)) {
4793                 options.firstRestricted = param;
4794                 options.message = Messages.StrictParamName;
4795             } else if (isStrictModeReservedWord(name)) {
4796                 options.firstRestricted = param;
4797                 options.message = Messages.StrictReservedWord;
4798             } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
4799                 options.stricted = param;
4800                 options.message = Messages.StrictParamDupe;
4801             }
4802         }
4803         options.paramSet[key] = true;
4804     }
4805
4806     function parseParam(options) {
4807         var token, param, params = [], i, def;
4808
4809         token = lookahead;
4810         if (token.value === '...') {
4811             param = parseRestElement(params);
4812             validateParam(options, param.argument, param.argument.name);
4813             options.params.push(param);
4814             options.defaults.push(null);
4815             return false;
4816         }
4817
4818         param = parsePatternWithDefault(params);
4819         for (i = 0; i < params.length; i++) {
4820             validateParam(options, params[i], params[i].value);
4821         }
4822
4823         if (param.type === Syntax.AssignmentPattern) {
4824             def = param.right;
4825             param = param.left;
4826             ++options.defaultCount;
4827         }
4828
4829         options.params.push(param);
4830         options.defaults.push(def);
4831
4832         return !match(')');
4833     }
4834
4835     function parseParams(firstRestricted) {
4836         var options;
4837
4838         options = {
4839             params: [],
4840             defaultCount: 0,
4841             defaults: [],
4842             firstRestricted: firstRestricted
4843         };
4844
4845         expect('(');
4846
4847         if (!match(')')) {
4848             options.paramSet = {};
4849             while (startIndex < length) {
4850                 if (!parseParam(options)) {
4851                     break;
4852                 }
4853                 expect(',');
4854             }
4855         }
4856
4857         expect(')');
4858
4859         if (options.defaultCount === 0) {
4860             options.defaults = [];
4861         }
4862
4863         return {
4864             params: options.params,
4865             defaults: options.defaults,
4866             stricted: options.stricted,
4867             firstRestricted: options.firstRestricted,
4868             message: options.message
4869         };
4870     }
4871
4872     function parseFunctionDeclaration(node, identifierIsOptional) {
4873         var id = null, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict,
4874             isGenerator, previousAllowYield;
4875
4876         previousAllowYield = state.allowYield;
4877
4878         expectKeyword('function');
4879
4880         isGenerator = match('*');
4881         if (isGenerator) {
4882             lex();
4883         }
4884
4885         if (!identifierIsOptional || !match('(')) {
4886             token = lookahead;
4887             id = parseVariableIdentifier();
4888             if (strict) {
4889                 if (isRestrictedWord(token.value)) {
4890                     tolerateUnexpectedToken(token, Messages.StrictFunctionName);
4891                 }
4892             } else {
4893                 if (isRestrictedWord(token.value)) {
4894                     firstRestricted = token;
4895                     message = Messages.StrictFunctionName;
4896                 } else if (isStrictModeReservedWord(token.value)) {
4897                     firstRestricted = token;
4898                     message = Messages.StrictReservedWord;
4899                 }
4900             }
4901         }
4902
4903         state.allowYield = !isGenerator;
4904         tmp = parseParams(firstRestricted);
4905         params = tmp.params;
4906         defaults = tmp.defaults;
4907         stricted = tmp.stricted;
4908         firstRestricted = tmp.firstRestricted;
4909         if (tmp.message) {
4910             message = tmp.message;
4911         }
4912
4913
4914         previousStrict = strict;
4915         body = parseFunctionSourceElements();
4916         if (strict && firstRestricted) {
4917             throwUnexpectedToken(firstRestricted, message);
4918         }
4919         if (strict && stricted) {
4920             tolerateUnexpectedToken(stricted, message);
4921         }
4922
4923         strict = previousStrict;
4924         state.allowYield = previousAllowYield;
4925
4926         return node.finishFunctionDeclaration(id, params, defaults, body, isGenerator);
4927     }
4928
4929     function parseFunctionExpression() {
4930         var token, id = null, stricted, firstRestricted, message, tmp,
4931             params = [], defaults = [], body, previousStrict, node = new Node(),
4932             isGenerator, previousAllowYield;
4933
4934         previousAllowYield = state.allowYield;
4935
4936         expectKeyword('function');
4937
4938         isGenerator = match('*');
4939         if (isGenerator) {
4940             lex();
4941         }
4942
4943         state.allowYield = !isGenerator;
4944         if (!match('(')) {
4945             token = lookahead;
4946             id = (!strict && !isGenerator && matchKeyword('yield')) ? parseNonComputedProperty() : parseVariableIdentifier();
4947             if (strict) {
4948                 if (isRestrictedWord(token.value)) {
4949                     tolerateUnexpectedToken(token, Messages.StrictFunctionName);
4950                 }
4951             } else {
4952                 if (isRestrictedWord(token.value)) {
4953                     firstRestricted = token;
4954                     message = Messages.StrictFunctionName;
4955                 } else if (isStrictModeReservedWord(token.value)) {
4956                     firstRestricted = token;
4957                     message = Messages.StrictReservedWord;
4958                 }
4959             }
4960         }
4961
4962         tmp = parseParams(firstRestricted);
4963         params = tmp.params;
4964         defaults = tmp.defaults;
4965         stricted = tmp.stricted;
4966         firstRestricted = tmp.firstRestricted;
4967         if (tmp.message) {
4968             message = tmp.message;
4969         }
4970
4971         previousStrict = strict;
4972         body = parseFunctionSourceElements();
4973         if (strict && firstRestricted) {
4974             throwUnexpectedToken(firstRestricted, message);
4975         }
4976         if (strict && stricted) {
4977             tolerateUnexpectedToken(stricted, message);
4978         }
4979         strict = previousStrict;
4980         state.allowYield = previousAllowYield;
4981
4982         return node.finishFunctionExpression(id, params, defaults, body, isGenerator);
4983     }
4984
4985     // ECMA-262 14.5 Class Definitions
4986
4987     function parseClassBody() {
4988         var classBody, token, isStatic, hasConstructor = false, body, method, computed, key;
4989
4990         classBody = new Node();
4991
4992         expect('{');
4993         body = [];
4994         while (!match('}')) {
4995             if (match(';')) {
4996                 lex();
4997             } else {
4998                 method = new Node();
4999                 token = lookahead;
5000                 isStatic = false;
5001                 computed = match('[');
5002                 if (match('*')) {
5003                     lex();
5004                 } else {
5005                     key = parseObjectPropertyKey();
5006                     if (key.name === 'static' && (lookaheadPropertyName() || match('*'))) {
5007                         token = lookahead;
5008                         isStatic = true;
5009                         computed = match('[');
5010                         if (match('*')) {
5011                             lex();
5012                         } else {
5013                             key = parseObjectPropertyKey();
5014                         }
5015                     }
5016                 }
5017                 method = tryParseMethodDefinition(token, key, computed, method);
5018                 if (method) {
5019                     method['static'] = isStatic; // jscs:ignore requireDotNotation
5020                     if (method.kind === 'init') {
5021                         method.kind = 'method';
5022                     }
5023                     if (!isStatic) {
5024                         if (!method.computed && (method.key.name || method.key.value.toString()) === 'constructor') {
5025                             if (method.kind !== 'method' || !method.method || method.value.generator) {
5026                                 throwUnexpectedToken(token, Messages.ConstructorSpecialMethod);
5027                             }
5028                             if (hasConstructor) {
5029                                 throwUnexpectedToken(token, Messages.DuplicateConstructor);
5030                             } else {
5031                                 hasConstructor = true;
5032                             }
5033                             method.kind = 'constructor';
5034                         }
5035                     } else {
5036                         if (!method.computed && (method.key.name || method.key.value.toString()) === 'prototype') {
5037                             throwUnexpectedToken(token, Messages.StaticPrototype);
5038                         }
5039                     }
5040                     method.type = Syntax.MethodDefinition;
5041                     delete method.method;
5042                     delete method.shorthand;
5043                     body.push(method);
5044                 } else {
5045                     throwUnexpectedToken(lookahead);
5046                 }
5047             }
5048         }
5049         lex();
5050         return classBody.finishClassBody(body);
5051     }
5052
5053     function parseClassDeclaration(identifierIsOptional) {
5054         var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
5055         strict = true;
5056
5057         expectKeyword('class');
5058
5059         if (!identifierIsOptional || lookahead.type === Token.Identifier) {
5060             id = parseVariableIdentifier();
5061         }
5062
5063         if (matchKeyword('extends')) {
5064             lex();
5065             superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall);
5066         }
5067         classBody = parseClassBody();
5068         strict = previousStrict;
5069
5070         return classNode.finishClassDeclaration(id, superClass, classBody);
5071     }
5072
5073     function parseClassExpression() {
5074         var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
5075         strict = true;
5076
5077         expectKeyword('class');
5078
5079         if (lookahead.type === Token.Identifier) {
5080             id = parseVariableIdentifier();
5081         }
5082
5083         if (matchKeyword('extends')) {
5084             lex();
5085             superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall);
5086         }
5087         classBody = parseClassBody();
5088         strict = previousStrict;
5089
5090         return classNode.finishClassExpression(id, superClass, classBody);
5091     }
5092
5093     // ECMA-262 15.2 Modules
5094
5095     function parseModuleSpecifier() {
5096         var node = new Node();
5097
5098         if (lookahead.type !== Token.StringLiteral) {
5099             throwError(Messages.InvalidModuleSpecifier);
5100         }
5101         return node.finishLiteral(lex());
5102     }
5103
5104     // ECMA-262 15.2.3 Exports
5105
5106     function parseExportSpecifier() {
5107         var exported, local, node = new Node(), def;
5108         if (matchKeyword('default')) {
5109             // export {default} from 'something';
5110             def = new Node();
5111             lex();
5112             local = def.finishIdentifier('default');
5113         } else {
5114             local = parseVariableIdentifier();
5115         }
5116         if (matchContextualKeyword('as')) {
5117             lex();
5118             exported = parseNonComputedProperty();
5119         }
5120         return node.finishExportSpecifier(local, exported);
5121     }
5122
5123     function parseExportNamedDeclaration(node) {
5124         var declaration = null,
5125             isExportFromIdentifier,
5126             src = null, specifiers = [];
5127
5128         // non-default export
5129         if (lookahead.type === Token.Keyword) {
5130             // covers:
5131             // export var f = 1;
5132             switch (lookahead.value) {
5133                 case 'let':
5134                 case 'const':
5135                 case 'var':
5136                 case 'class':
5137                 case 'function':
5138                     declaration = parseStatementListItem();
5139                     return node.finishExportNamedDeclaration(declaration, specifiers, null);
5140             }
5141         }
5142
5143         expect('{');
5144         while (!match('}')) {
5145             isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default');
5146             specifiers.push(parseExportSpecifier());
5147             if (!match('}')) {
5148                 expect(',');
5149                 if (match('}')) {
5150                     break;
5151                 }
5152             }
5153         }
5154         expect('}');
5155
5156         if (matchContextualKeyword('from')) {
5157             // covering:
5158             // export {default} from 'foo';
5159             // export {foo} from 'foo';
5160             lex();
5161             src = parseModuleSpecifier();
5162             consumeSemicolon();
5163         } else if (isExportFromIdentifier) {
5164             // covering:
5165             // export {default}; // missing fromClause
5166             throwError(lookahead.value ?
5167                     Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
5168         } else {
5169             // cover
5170             // export {foo};
5171             consumeSemicolon();
5172         }
5173         return node.finishExportNamedDeclaration(declaration, specifiers, src);
5174     }
5175
5176     function parseExportDefaultDeclaration(node) {
5177         var declaration = null,
5178             expression = null;
5179
5180         // covers:
5181         // export default ...
5182         expectKeyword('default');
5183
5184         if (matchKeyword('function')) {
5185             // covers:
5186             // export default function foo () {}
5187             // export default function () {}
5188             declaration = parseFunctionDeclaration(new Node(), true);
5189             return node.finishExportDefaultDeclaration(declaration);
5190         }
5191         if (matchKeyword('class')) {
5192             declaration = parseClassDeclaration(true);
5193             return node.finishExportDefaultDeclaration(declaration);
5194         }
5195
5196         if (matchContextualKeyword('from')) {
5197             throwError(Messages.UnexpectedToken, lookahead.value);
5198         }
5199
5200         // covers:
5201         // export default {};
5202         // export default [];
5203         // export default (1 + 2);
5204         if (match('{')) {
5205             expression = parseObjectInitializer();
5206         } else if (match('[')) {
5207             expression = parseArrayInitializer();
5208         } else {
5209             expression = parseAssignmentExpression();
5210         }
5211         consumeSemicolon();
5212         return node.finishExportDefaultDeclaration(expression);
5213     }
5214
5215     function parseExportAllDeclaration(node) {
5216         var src;
5217
5218         // covers:
5219         // export * from 'foo';
5220         expect('*');
5221         if (!matchContextualKeyword('from')) {
5222             throwError(lookahead.value ?
5223                     Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
5224         }
5225         lex();
5226         src = parseModuleSpecifier();
5227         consumeSemicolon();
5228
5229         return node.finishExportAllDeclaration(src);
5230     }
5231
5232     function parseExportDeclaration() {
5233         var node = new Node();
5234         if (state.inFunctionBody) {
5235             throwError(Messages.IllegalExportDeclaration);
5236         }
5237
5238         expectKeyword('export');
5239
5240         if (matchKeyword('default')) {
5241             return parseExportDefaultDeclaration(node);
5242         }
5243         if (match('*')) {
5244             return parseExportAllDeclaration(node);
5245         }
5246         return parseExportNamedDeclaration(node);
5247     }
5248
5249     // ECMA-262 15.2.2 Imports
5250
5251     function parseImportSpecifier() {
5252         // import {<foo as bar>} ...;
5253         var local, imported, node = new Node();
5254
5255         imported = parseNonComputedProperty();
5256         if (matchContextualKeyword('as')) {
5257             lex();
5258             local = parseVariableIdentifier();
5259         }
5260
5261         return node.finishImportSpecifier(local, imported);
5262     }
5263
5264     function parseNamedImports() {
5265         var specifiers = [];
5266         // {foo, bar as bas}
5267         expect('{');
5268         while (!match('}')) {
5269             specifiers.push(parseImportSpecifier());
5270             if (!match('}')) {
5271                 expect(',');
5272                 if (match('}')) {
5273                     break;
5274                 }
5275             }
5276         }
5277         expect('}');
5278         return specifiers;
5279     }
5280
5281     function parseImportDefaultSpecifier() {
5282         // import <foo> ...;
5283         var local, node = new Node();
5284
5285         local = parseNonComputedProperty();
5286
5287         return node.finishImportDefaultSpecifier(local);
5288     }
5289
5290     function parseImportNamespaceSpecifier() {
5291         // import <* as foo> ...;
5292         var local, node = new Node();
5293
5294         expect('*');
5295         if (!matchContextualKeyword('as')) {
5296             throwError(Messages.NoAsAfterImportNamespace);
5297         }
5298         lex();
5299         local = parseNonComputedProperty();
5300
5301         return node.finishImportNamespaceSpecifier(local);
5302     }
5303
5304     function parseImportDeclaration() {
5305         var specifiers = [], src, node = new Node();
5306
5307         if (state.inFunctionBody) {
5308             throwError(Messages.IllegalImportDeclaration);
5309         }
5310
5311         expectKeyword('import');
5312
5313         if (lookahead.type === Token.StringLiteral) {
5314             // import 'foo';
5315             src = parseModuleSpecifier();
5316         } else {
5317
5318             if (match('{')) {
5319                 // import {bar}
5320                 specifiers = specifiers.concat(parseNamedImports());
5321             } else if (match('*')) {
5322                 // import * as foo
5323                 specifiers.push(parseImportNamespaceSpecifier());
5324             } else if (isIdentifierName(lookahead) && !matchKeyword('default')) {
5325                 // import foo
5326                 specifiers.push(parseImportDefaultSpecifier());
5327                 if (match(',')) {
5328                     lex();
5329                     if (match('*')) {
5330                         // import foo, * as foo
5331                         specifiers.push(parseImportNamespaceSpecifier());
5332                     } else if (match('{')) {
5333                         // import foo, {bar}
5334                         specifiers = specifiers.concat(parseNamedImports());
5335                     } else {
5336                         throwUnexpectedToken(lookahead);
5337                     }
5338                 }
5339             } else {
5340                 throwUnexpectedToken(lex());
5341             }
5342
5343             if (!matchContextualKeyword('from')) {
5344                 throwError(lookahead.value ?
5345                         Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
5346             }
5347             lex();
5348             src = parseModuleSpecifier();
5349         }
5350
5351         consumeSemicolon();
5352         return node.finishImportDeclaration(specifiers, src);
5353     }
5354
5355     // ECMA-262 15.1 Scripts
5356
5357     function parseScriptBody() {
5358         var statement, body = [], token, directive, firstRestricted;
5359
5360         while (startIndex < length) {
5361             token = lookahead;
5362             if (token.type !== Token.StringLiteral) {
5363                 break;
5364             }
5365
5366             statement = parseStatementListItem();
5367             body.push(statement);
5368             if (statement.expression.type !== Syntax.Literal) {
5369                 // this is not directive
5370                 break;
5371             }
5372             directive = source.slice(token.start + 1, token.end - 1);
5373             if (directive === 'use strict') {
5374                 strict = true;
5375                 if (firstRestricted) {
5376                     tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
5377                 }
5378             } else {
5379                 if (!firstRestricted && token.octal) {
5380                     firstRestricted = token;
5381                 }
5382             }
5383         }
5384
5385         while (startIndex < length) {
5386             statement = parseStatementListItem();
5387             /* istanbul ignore if */
5388             if (typeof statement === 'undefined') {
5389                 break;
5390             }
5391             body.push(statement);
5392         }
5393         return body;
5394     }
5395
5396     function parseProgram() {
5397         var body, node;
5398
5399         peek();
5400         node = new Node();
5401
5402         body = parseScriptBody();
5403         return node.finishProgram(body);
5404     }
5405
5406     function filterTokenLocation() {
5407         var i, entry, token, tokens = [];
5408
5409         for (i = 0; i < extra.tokens.length; ++i) {
5410             entry = extra.tokens[i];
5411             token = {
5412                 type: entry.type,
5413                 value: entry.value
5414             };
5415             if (entry.regex) {
5416                 token.regex = {
5417                     pattern: entry.regex.pattern,
5418                     flags: entry.regex.flags
5419                 };
5420             }
5421             if (extra.range) {
5422                 token.range = entry.range;
5423             }
5424             if (extra.loc) {
5425                 token.loc = entry.loc;
5426             }
5427             tokens.push(token);
5428         }
5429
5430         extra.tokens = tokens;
5431     }
5432
5433     function tokenize(code, options) {
5434         var toString,
5435             tokens;
5436
5437         toString = String;
5438         if (typeof code !== 'string' && !(code instanceof String)) {
5439             code = toString(code);
5440         }
5441
5442         source = code;
5443         index = 0;
5444         lineNumber = (source.length > 0) ? 1 : 0;
5445         lineStart = 0;
5446         startIndex = index;
5447         startLineNumber = lineNumber;
5448         startLineStart = lineStart;
5449         length = source.length;
5450         lookahead = null;
5451         state = {
5452             allowIn: true,
5453             allowYield: true,
5454             labelSet: {},
5455             inFunctionBody: false,
5456             inIteration: false,
5457             inSwitch: false,
5458             lastCommentStart: -1,
5459             curlyStack: []
5460         };
5461
5462         extra = {};
5463
5464         // Options matching.
5465         options = options || {};
5466
5467         // Of course we collect tokens here.
5468         options.tokens = true;
5469         extra.tokens = [];
5470         extra.tokenize = true;
5471         // The following two fields are necessary to compute the Regex tokens.
5472         extra.openParenToken = -1;
5473         extra.openCurlyToken = -1;
5474
5475         extra.range = (typeof options.range === 'boolean') && options.range;
5476         extra.loc = (typeof options.loc === 'boolean') && options.loc;
5477
5478         if (typeof options.comment === 'boolean' && options.comment) {
5479             extra.comments = [];
5480         }
5481         if (typeof options.tolerant === 'boolean' && options.tolerant) {
5482             extra.errors = [];
5483         }
5484
5485         try {
5486             peek();
5487             if (lookahead.type === Token.EOF) {
5488                 return extra.tokens;
5489             }
5490
5491             lex();
5492             while (lookahead.type !== Token.EOF) {
5493                 try {
5494                     lex();
5495                 } catch (lexError) {
5496                     if (extra.errors) {
5497                         recordError(lexError);
5498                         // We have to break on the first error
5499                         // to avoid infinite loops.
5500                         break;
5501                     } else {
5502                         throw lexError;
5503                     }
5504                 }
5505             }
5506
5507             filterTokenLocation();
5508             tokens = extra.tokens;
5509             if (typeof extra.comments !== 'undefined') {
5510                 tokens.comments = extra.comments;
5511             }
5512             if (typeof extra.errors !== 'undefined') {
5513                 tokens.errors = extra.errors;
5514             }
5515         } catch (e) {
5516             throw e;
5517         } finally {
5518             extra = {};
5519         }
5520         return tokens;
5521     }
5522
5523     function parse(code, options) {
5524         var program, toString;
5525
5526         toString = String;
5527         if (typeof code !== 'string' && !(code instanceof String)) {
5528             code = toString(code);
5529         }
5530
5531         source = code;
5532         index = 0;
5533         lineNumber = (source.length > 0) ? 1 : 0;
5534         lineStart = 0;
5535         startIndex = index;
5536         startLineNumber = lineNumber;
5537         startLineStart = lineStart;
5538         length = source.length;
5539         lookahead = null;
5540         state = {
5541             allowIn: true,
5542             allowYield: true,
5543             labelSet: {},
5544             inFunctionBody: false,
5545             inIteration: false,
5546             inSwitch: false,
5547             lastCommentStart: -1,
5548             curlyStack: []
5549         };
5550         sourceType = 'script';
5551         strict = false;
5552
5553         extra = {};
5554         if (typeof options !== 'undefined') {
5555             extra.range = (typeof options.range === 'boolean') && options.range;
5556             extra.loc = (typeof options.loc === 'boolean') && options.loc;
5557             extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment;
5558
5559             if (extra.loc && options.source !== null && options.source !== undefined) {
5560                 extra.source = toString(options.source);
5561             }
5562
5563             if (typeof options.tokens === 'boolean' && options.tokens) {
5564                 extra.tokens = [];
5565             }
5566             if (typeof options.comment === 'boolean' && options.comment) {
5567                 extra.comments = [];
5568             }
5569             if (typeof options.tolerant === 'boolean' && options.tolerant) {
5570                 extra.errors = [];
5571             }
5572             if (extra.attachComment) {
5573                 extra.range = true;
5574                 extra.comments = [];
5575                 extra.bottomRightStack = [];
5576                 extra.trailingComments = [];
5577                 extra.leadingComments = [];
5578             }
5579             if (options.sourceType === 'module') {
5580                 // very restrictive condition for now
5581                 sourceType = options.sourceType;
5582                 strict = true;
5583             }
5584         }
5585
5586         try {
5587             program = parseProgram();
5588             if (typeof extra.comments !== 'undefined') {
5589                 program.comments = extra.comments;
5590             }
5591             if (typeof extra.tokens !== 'undefined') {
5592                 filterTokenLocation();
5593                 program.tokens = extra.tokens;
5594             }
5595             if (typeof extra.errors !== 'undefined') {
5596                 program.errors = extra.errors;
5597             }
5598         } catch (e) {
5599             throw e;
5600         } finally {
5601             extra = {};
5602         }
5603
5604         return program;
5605     }
5606
5607     // Sync with *.json manifests.
5608     exports.version = '2.5.0';
5609
5610     exports.tokenize = tokenize;
5611
5612     exports.parse = parse;
5613
5614     // Deep copy.
5615     /* istanbul ignore next */
5616     exports.Syntax = (function () {
5617         var name, types = {};
5618
5619         if (typeof Object.create === 'function') {
5620             types = Object.create(null);
5621         }
5622
5623         for (name in Syntax) {
5624             if (Syntax.hasOwnProperty(name)) {
5625                 types[name] = Syntax[name];
5626             }
5627         }
5628
5629         if (typeof Object.freeze === 'function') {
5630             Object.freeze(types);
5631         }
5632
5633         return types;
5634     }());
5635
5636 }));
5637 /* vim: set sw=4 ts=4 et tw=80 : */