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