Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / esprima / esprima.js
1 /*
2   Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
3   Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
4   Copyright (C) 2013 Mathias Bynens <mathias@qiwi.be>
5   Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
6   Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
7   Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
8   Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
9   Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
10   Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
11   Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
12
13   Redistribution and use in source and binary forms, with or without
14   modification, are permitted provided that the following conditions are met:
15
16     * Redistributions of source code must retain the above copyright
17       notice, this list of conditions and the following disclaimer.
18     * Redistributions in binary form must reproduce the above copyright
19       notice, this list of conditions and the following disclaimer in the
20       documentation and/or other materials provided with the distribution.
21
22   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25   ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
26   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*jslint bitwise:true plusplus:true */
35 /*global esprima:true, define:true, exports:true, window: true,
36 throwErrorTolerant: true,
37 throwError: true, generateStatement: true, peek: true,
38 parseAssignmentExpression: true, parseBlock: true, parseExpression: true,
39 parseFunctionDeclaration: true, parseFunctionExpression: true,
40 parseFunctionSourceElements: true, parseVariableIdentifier: true,
41 parseLeftHandSideExpression: true,
42 parseUnaryExpression: true,
43 parseStatement: true, parseSourceElement: true */
44
45 (function (root, factory) {
46     'use strict';
47
48     // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
49     // Rhino, and plain browser loading.
50
51     /* istanbul ignore next */
52     if (typeof define === 'function' && define.amd) {
53         define(['exports'], factory);
54     } else if (typeof exports !== 'undefined') {
55         factory(exports);
56     } else {
57         factory((root.esprima = {}));
58     }
59 }(this, function (exports) {
60     'use strict';
61
62     var Token,
63         TokenName,
64         FnExprTokens,
65         Syntax,
66         PropertyKind,
67         Messages,
68         Regex,
69         SyntaxTreeDelegate,
70         source,
71         strict,
72         index,
73         lineNumber,
74         lineStart,
75         length,
76         delegate,
77         lookahead,
78         state,
79         extra;
80
81     Token = {
82         BooleanLiteral: 1,
83         EOF: 2,
84         Identifier: 3,
85         Keyword: 4,
86         NullLiteral: 5,
87         NumericLiteral: 6,
88         Punctuator: 7,
89         StringLiteral: 8,
90         RegularExpression: 9
91     };
92
93     TokenName = {};
94     TokenName[Token.BooleanLiteral] = 'Boolean';
95     TokenName[Token.EOF] = '<end>';
96     TokenName[Token.Identifier] = 'Identifier';
97     TokenName[Token.Keyword] = 'Keyword';
98     TokenName[Token.NullLiteral] = 'Null';
99     TokenName[Token.NumericLiteral] = 'Numeric';
100     TokenName[Token.Punctuator] = 'Punctuator';
101     TokenName[Token.StringLiteral] = 'String';
102     TokenName[Token.RegularExpression] = 'RegularExpression';
103
104     // A function following one of those tokens is an expression.
105     FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
106                     'return', 'case', 'delete', 'throw', 'void',
107                     // assignment operators
108                     '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=',
109                     '&=', '|=', '^=', ',',
110                     // binary/unary operators
111                     '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&',
112                     '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=',
113                     '<=', '<', '>', '!=', '!=='];
114
115     Syntax = {
116         AssignmentExpression: 'AssignmentExpression',
117         ArrayExpression: 'ArrayExpression',
118         BlockStatement: 'BlockStatement',
119         BinaryExpression: 'BinaryExpression',
120         BreakStatement: 'BreakStatement',
121         CallExpression: 'CallExpression',
122         CatchClause: 'CatchClause',
123         ConditionalExpression: 'ConditionalExpression',
124         ContinueStatement: 'ContinueStatement',
125         DoWhileStatement: 'DoWhileStatement',
126         DebuggerStatement: 'DebuggerStatement',
127         EmptyStatement: 'EmptyStatement',
128         ExpressionStatement: 'ExpressionStatement',
129         ForStatement: 'ForStatement',
130         ForInStatement: 'ForInStatement',
131         FunctionDeclaration: 'FunctionDeclaration',
132         FunctionExpression: 'FunctionExpression',
133         Identifier: 'Identifier',
134         IfStatement: 'IfStatement',
135         Literal: 'Literal',
136         LabeledStatement: 'LabeledStatement',
137         LogicalExpression: 'LogicalExpression',
138         MemberExpression: 'MemberExpression',
139         NewExpression: 'NewExpression',
140         ObjectExpression: 'ObjectExpression',
141         Program: 'Program',
142         Property: 'Property',
143         ReturnStatement: 'ReturnStatement',
144         SequenceExpression: 'SequenceExpression',
145         SwitchStatement: 'SwitchStatement',
146         SwitchCase: 'SwitchCase',
147         ThisExpression: 'ThisExpression',
148         ThrowStatement: 'ThrowStatement',
149         TryStatement: 'TryStatement',
150         UnaryExpression: 'UnaryExpression',
151         UpdateExpression: 'UpdateExpression',
152         VariableDeclaration: 'VariableDeclaration',
153         VariableDeclarator: 'VariableDeclarator',
154         WhileStatement: 'WhileStatement',
155         WithStatement: 'WithStatement'
156     };
157
158     PropertyKind = {
159         Data: 1,
160         Get: 2,
161         Set: 4
162     };
163
164     // Error messages should be identical to V8.
165     Messages = {
166         UnexpectedToken:  'Unexpected token %0',
167         UnexpectedNumber:  'Unexpected number',
168         UnexpectedString:  'Unexpected string',
169         UnexpectedIdentifier:  'Unexpected identifier',
170         UnexpectedReserved:  'Unexpected reserved word',
171         UnexpectedEOS:  'Unexpected end of input',
172         NewlineAfterThrow:  'Illegal newline after throw',
173         InvalidRegExp: 'Invalid regular expression',
174         UnterminatedRegExp:  'Invalid regular expression: missing /',
175         InvalidLHSInAssignment:  'Invalid left-hand side in assignment',
176         InvalidLHSInForIn:  'Invalid left-hand side in for-in',
177         MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
178         NoCatchOrFinally:  'Missing catch or finally after try',
179         UnknownLabel: 'Undefined label \'%0\'',
180         Redeclaration: '%0 \'%1\' has already been declared',
181         IllegalContinue: 'Illegal continue statement',
182         IllegalBreak: 'Illegal break statement',
183         IllegalReturn: 'Illegal return statement',
184         StrictModeWith:  'Strict mode code may not include a with statement',
185         StrictCatchVariable:  'Catch variable may not be eval or arguments in strict mode',
186         StrictVarName:  'Variable name may not be eval or arguments in strict mode',
187         StrictParamName:  'Parameter name eval or arguments is not allowed in strict mode',
188         StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
189         StrictFunctionName:  'Function name may not be eval or arguments in strict mode',
190         StrictOctalLiteral:  'Octal literals are not allowed in strict mode.',
191         StrictDelete:  'Delete of an unqualified identifier in strict mode.',
192         StrictDuplicateProperty:  'Duplicate data property in object literal not allowed in strict mode',
193         AccessorDataProperty:  'Object literal may not have data and accessor property with the same name',
194         AccessorGetSet:  'Object literal may not have multiple get/set accessors with the same name',
195         StrictLHSAssignment:  'Assignment to eval or arguments is not allowed in strict mode',
196         StrictLHSPostfix:  'Postfix increment/decrement may not have eval or arguments operand in strict mode',
197         StrictLHSPrefix:  'Prefix increment/decrement may not have eval or arguments operand in strict mode',
198         StrictReservedWord:  'Use of future reserved word in strict mode'
199     };
200
201     // See also tools/generate-unicode-regex.py.
202     Regex = {
203         NonAsciiIdentifierStart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]'),
204         NonAsciiIdentifierPart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0\u08A2-\u08AC\u08E4-\u08FE\u0900-\u0963\u0966-\u096F\u0971-\u0977\u0979-\u097F\u0981-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C01-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C82\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191C\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1D00-\u1DE6\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA697\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7B\uAA80-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE26\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]')
205     };
206
207     // Ensure the condition is true, otherwise throw an error.
208     // This is only to have a better contract semantic, i.e. another safety net
209     // to catch a logic error. The condition shall be fulfilled in normal case.
210     // Do NOT use this to enforce a certain condition on any user input.
211
212     function assert(condition, message) {
213         /* istanbul ignore if */
214         if (!condition) {
215             throw new Error('ASSERT: ' + message);
216         }
217     }
218
219     function isDecimalDigit(ch) {
220         return (ch >= 48 && ch <= 57);   // 0..9
221     }
222
223     function isHexDigit(ch) {
224         return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
225     }
226
227     function isOctalDigit(ch) {
228         return '01234567'.indexOf(ch) >= 0;
229     }
230
231
232     // 7.2 White Space
233
234     function isWhiteSpace(ch) {
235         return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) ||
236             (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0);
237     }
238
239     // 7.3 Line Terminators
240
241     function isLineTerminator(ch) {
242         return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029);
243     }
244
245     // 7.6 Identifier Names and Identifiers
246
247     function isIdentifierStart(ch) {
248         return (ch === 0x24) || (ch === 0x5F) ||  // $ (dollar) and _ (underscore)
249             (ch >= 0x41 && ch <= 0x5A) ||         // A..Z
250             (ch >= 0x61 && ch <= 0x7A) ||         // a..z
251             (ch === 0x5C) ||                      // \ (backslash)
252             ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch)));
253     }
254
255     function isIdentifierPart(ch) {
256         return (ch === 0x24) || (ch === 0x5F) ||  // $ (dollar) and _ (underscore)
257             (ch >= 0x41 && ch <= 0x5A) ||         // A..Z
258             (ch >= 0x61 && ch <= 0x7A) ||         // a..z
259             (ch >= 0x30 && ch <= 0x39) ||         // 0..9
260             (ch === 0x5C) ||                      // \ (backslash)
261             ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch)));
262     }
263
264     // 7.6.1.2 Future Reserved Words
265
266     function isFutureReservedWord(id) {
267         switch (id) {
268         case 'class':
269         case 'enum':
270         case 'export':
271         case 'extends':
272         case 'import':
273         case 'super':
274             return true;
275         default:
276             return false;
277         }
278     }
279
280     function isStrictModeReservedWord(id) {
281         switch (id) {
282         case 'implements':
283         case 'interface':
284         case 'package':
285         case 'private':
286         case 'protected':
287         case 'public':
288         case 'static':
289         case 'yield':
290         case 'let':
291             return true;
292         default:
293             return false;
294         }
295     }
296
297     function isRestrictedWord(id) {
298         return id === 'eval' || id === 'arguments';
299     }
300
301     // 7.6.1.1 Keywords
302
303     function isKeyword(id) {
304         if (strict && isStrictModeReservedWord(id)) {
305             return true;
306         }
307
308         // 'const' is specialized as Keyword in V8.
309         // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next.
310         // Some others are from future reserved words.
311
312         switch (id.length) {
313         case 2:
314             return (id === 'if') || (id === 'in') || (id === 'do');
315         case 3:
316             return (id === 'var') || (id === 'for') || (id === 'new') ||
317                 (id === 'try') || (id === 'let');
318         case 4:
319             return (id === 'this') || (id === 'else') || (id === 'case') ||
320                 (id === 'void') || (id === 'with') || (id === 'enum');
321         case 5:
322             return (id === 'while') || (id === 'break') || (id === 'catch') ||
323                 (id === 'throw') || (id === 'const') || (id === 'yield') ||
324                 (id === 'class') || (id === 'super');
325         case 6:
326             return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
327                 (id === 'switch') || (id === 'export') || (id === 'import');
328         case 7:
329             return (id === 'default') || (id === 'finally') || (id === 'extends');
330         case 8:
331             return (id === 'function') || (id === 'continue') || (id === 'debugger');
332         case 10:
333             return (id === 'instanceof');
334         default:
335             return false;
336         }
337     }
338
339     // 7.4 Comments
340
341     function addComment(type, value, start, end, loc) {
342         var comment, attacher;
343
344         assert(typeof start === 'number', 'Comment must have valid position');
345
346         // Because the way the actual token is scanned, often the comments
347         // (if any) are skipped twice during the lexical analysis.
348         // Thus, we need to skip adding a comment if the comment array already
349         // handled it.
350         if (state.lastCommentStart >= start) {
351             return;
352         }
353         state.lastCommentStart = start;
354
355         comment = {
356             type: type,
357             value: value
358         };
359         if (extra.range) {
360             comment.range = [start, end];
361         }
362         if (extra.loc) {
363             comment.loc = loc;
364         }
365         extra.comments.push(comment);
366         if (extra.attachComment) {
367             extra.leadingComments.push(comment);
368             extra.trailingComments.push(comment);
369         }
370     }
371
372     function skipSingleLineComment(offset) {
373         var start, loc, ch, comment;
374
375         start = index - offset;
376         loc = {
377             start: {
378                 line: lineNumber,
379                 column: index - lineStart - offset
380             }
381         };
382
383         while (index < length) {
384             ch = source.charCodeAt(index);
385             ++index;
386             if (isLineTerminator(ch)) {
387                 if (extra.comments) {
388                     comment = source.slice(start + offset, index - 1);
389                     loc.end = {
390                         line: lineNumber,
391                         column: index - lineStart - 1
392                     };
393                     addComment('Line', comment, start, index - 1, loc);
394                 }
395                 if (ch === 13 && source.charCodeAt(index) === 10) {
396                     ++index;
397                 }
398                 ++lineNumber;
399                 lineStart = index;
400                 return;
401             }
402         }
403
404         if (extra.comments) {
405             comment = source.slice(start + offset, index);
406             loc.end = {
407                 line: lineNumber,
408                 column: index - lineStart
409             };
410             addComment('Line', comment, start, index, loc);
411         }
412     }
413
414     function skipMultiLineComment() {
415         var start, loc, ch, comment;
416
417         if (extra.comments) {
418             start = index - 2;
419             loc = {
420                 start: {
421                     line: lineNumber,
422                     column: index - lineStart - 2
423                 }
424             };
425         }
426
427         while (index < length) {
428             ch = source.charCodeAt(index);
429             if (isLineTerminator(ch)) {
430                 if (ch === 0x0D && source.charCodeAt(index + 1) === 0x0A) {
431                     ++index;
432                 }
433                 ++lineNumber;
434                 ++index;
435                 lineStart = index;
436                 if (index >= length) {
437                     throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
438                 }
439             } else if (ch === 0x2A) {
440                 // Block comment ends with '*/'.
441                 if (source.charCodeAt(index + 1) === 0x2F) {
442                     ++index;
443                     ++index;
444                     if (extra.comments) {
445                         comment = source.slice(start + 2, index - 2);
446                         loc.end = {
447                             line: lineNumber,
448                             column: index - lineStart
449                         };
450                         addComment('Block', comment, start, index, loc);
451                     }
452                     return;
453                 }
454                 ++index;
455             } else {
456                 ++index;
457             }
458         }
459
460         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
461     }
462
463     function skipComment() {
464         var ch, start;
465
466         start = (index === 0);
467         while (index < length) {
468             ch = source.charCodeAt(index);
469
470             if (isWhiteSpace(ch)) {
471                 ++index;
472             } else if (isLineTerminator(ch)) {
473                 ++index;
474                 if (ch === 0x0D && source.charCodeAt(index) === 0x0A) {
475                     ++index;
476                 }
477                 ++lineNumber;
478                 lineStart = index;
479                 start = true;
480             } else if (ch === 0x2F) { // U+002F is '/'
481                 ch = source.charCodeAt(index + 1);
482                 if (ch === 0x2F) {
483                     ++index;
484                     ++index;
485                     skipSingleLineComment(2);
486                     start = true;
487                 } else if (ch === 0x2A) {  // U+002A is '*'
488                     ++index;
489                     ++index;
490                     skipMultiLineComment();
491                 } else {
492                     break;
493                 }
494             } else if (start && ch === 0x2D) { // U+002D is '-'
495                 // U+003E is '>'
496                 if ((source.charCodeAt(index + 1) === 0x2D) && (source.charCodeAt(index + 2) === 0x3E)) {
497                     // '-->' is a single-line comment
498                     index += 3;
499                     skipSingleLineComment(3);
500                 } else {
501                     break;
502                 }
503             } else if (ch === 0x3C) { // U+003C is '<'
504                 if (source.slice(index + 1, index + 4) === '!--') {
505                     ++index; // `<`
506                     ++index; // `!`
507                     ++index; // `-`
508                     ++index; // `-`
509                     skipSingleLineComment(4);
510                 } else {
511                     break;
512                 }
513             } else {
514                 break;
515             }
516         }
517     }
518
519     function scanHexEscape(prefix) {
520         var i, len, ch, code = 0;
521
522         len = (prefix === 'u') ? 4 : 2;
523         for (i = 0; i < len; ++i) {
524             if (index < length && isHexDigit(source[index])) {
525                 ch = source[index++];
526                 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
527             } else {
528                 return '';
529             }
530         }
531         return String.fromCharCode(code);
532     }
533
534     function getEscapedIdentifier() {
535         var ch, id;
536
537         ch = source.charCodeAt(index++);
538         id = String.fromCharCode(ch);
539
540         // '\u' (U+005C, U+0075) denotes an escaped character.
541         if (ch === 0x5C) {
542             if (source.charCodeAt(index) !== 0x75) {
543                 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
544             }
545             ++index;
546             ch = scanHexEscape('u');
547             if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) {
548                 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
549             }
550             id = ch;
551         }
552
553         while (index < length) {
554             ch = source.charCodeAt(index);
555             if (!isIdentifierPart(ch)) {
556                 break;
557             }
558             ++index;
559             id += String.fromCharCode(ch);
560
561             // '\u' (U+005C, U+0075) denotes an escaped character.
562             if (ch === 0x5C) {
563                 id = id.substr(0, id.length - 1);
564                 if (source.charCodeAt(index) !== 0x75) {
565                     throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
566                 }
567                 ++index;
568                 ch = scanHexEscape('u');
569                 if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) {
570                     throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
571                 }
572                 id += ch;
573             }
574         }
575
576         return id;
577     }
578
579     function getIdentifier() {
580         var start, ch;
581
582         start = index++;
583         while (index < length) {
584             ch = source.charCodeAt(index);
585             if (ch === 0x5C) {
586                 // Blackslash (U+005C) marks Unicode escape sequence.
587                 index = start;
588                 return getEscapedIdentifier();
589             }
590             if (isIdentifierPart(ch)) {
591                 ++index;
592             } else {
593                 break;
594             }
595         }
596
597         return source.slice(start, index);
598     }
599
600     function scanIdentifier() {
601         var start, id, type;
602
603         start = index;
604
605         // Backslash (U+005C) starts an escaped character.
606         id = (source.charCodeAt(index) === 0x5C) ? getEscapedIdentifier() : getIdentifier();
607
608         // There is no keyword or literal with only one character.
609         // Thus, it must be an identifier.
610         if (id.length === 1) {
611             type = Token.Identifier;
612         } else if (isKeyword(id)) {
613             type = Token.Keyword;
614         } else if (id === 'null') {
615             type = Token.NullLiteral;
616         } else if (id === 'true' || id === 'false') {
617             type = Token.BooleanLiteral;
618         } else {
619             type = Token.Identifier;
620         }
621
622         return {
623             type: type,
624             value: id,
625             lineNumber: lineNumber,
626             lineStart: lineStart,
627             start: start,
628             end: index
629         };
630     }
631
632
633     // 7.7 Punctuators
634
635     function scanPunctuator() {
636         var start = index,
637             code = source.charCodeAt(index),
638             code2,
639             ch1 = source[index],
640             ch2,
641             ch3,
642             ch4;
643
644         switch (code) {
645
646         // Check for most common single-character punctuators.
647         case 0x2E:  // . dot
648         case 0x28:  // ( open bracket
649         case 0x29:  // ) close bracket
650         case 0x3B:  // ; semicolon
651         case 0x2C:  // , comma
652         case 0x7B:  // { open curly brace
653         case 0x7D:  // } close curly brace
654         case 0x5B:  // [
655         case 0x5D:  // ]
656         case 0x3A:  // :
657         case 0x3F:  // ?
658         case 0x7E:  // ~
659             ++index;
660             if (extra.tokenize) {
661                 if (code === 0x28) {
662                     extra.openParenToken = extra.tokens.length;
663                 } else if (code === 0x7B) {
664                     extra.openCurlyToken = extra.tokens.length;
665                 }
666             }
667             return {
668                 type: Token.Punctuator,
669                 value: String.fromCharCode(code),
670                 lineNumber: lineNumber,
671                 lineStart: lineStart,
672                 start: start,
673                 end: index
674             };
675
676         default:
677             code2 = source.charCodeAt(index + 1);
678
679             // '=' (U+003D) marks an assignment or comparison operator.
680             if (code2 === 0x3D) {
681                 switch (code) {
682                 case 0x2B:  // +
683                 case 0x2D:  // -
684                 case 0x2F:  // /
685                 case 0x3C:  // <
686                 case 0x3E:  // >
687                 case 0x5E:  // ^
688                 case 0x7C:  // |
689                 case 0x25:  // %
690                 case 0x26:  // &
691                 case 0x2A:  // *
692                     index += 2;
693                     return {
694                         type: Token.Punctuator,
695                         value: String.fromCharCode(code) + String.fromCharCode(code2),
696                         lineNumber: lineNumber,
697                         lineStart: lineStart,
698                         start: start,
699                         end: index
700                     };
701
702                 case 0x21: // !
703                 case 0x3D: // =
704                     index += 2;
705
706                     // !== and ===
707                     if (source.charCodeAt(index) === 0x3D) {
708                         ++index;
709                     }
710                     return {
711                         type: Token.Punctuator,
712                         value: source.slice(start, index),
713                         lineNumber: lineNumber,
714                         lineStart: lineStart,
715                         start: start,
716                         end: index
717                     };
718                 }
719             }
720         }
721
722         // 4-character punctuator: >>>=
723
724         ch4 = source.substr(index, 4);
725
726         if (ch4 === '>>>=') {
727             index += 4;
728             return {
729                 type: Token.Punctuator,
730                 value: ch4,
731                 lineNumber: lineNumber,
732                 lineStart: lineStart,
733                 start: start,
734                 end: index
735             };
736         }
737
738         // 3-character punctuators: === !== >>> <<= >>=
739
740         ch3 = ch4.substr(0, 3);
741
742         if (ch3 === '>>>' || ch3 === '<<=' || ch3 === '>>=') {
743             index += 3;
744             return {
745                 type: Token.Punctuator,
746                 value: ch3,
747                 lineNumber: lineNumber,
748                 lineStart: lineStart,
749                 start: start,
750                 end: index
751             };
752         }
753
754         // Other 2-character punctuators: ++ -- << >> && ||
755         ch2 = ch3.substr(0, 2);
756
757         if ((ch1 === ch2[1] && ('+-<>&|'.indexOf(ch1) >= 0)) || ch2 === '=>') {
758             index += 2;
759             return {
760                 type: Token.Punctuator,
761                 value: ch2,
762                 lineNumber: lineNumber,
763                 lineStart: lineStart,
764                 start: start,
765                 end: index
766             };
767         }
768
769         // 1-character punctuators: < > = ! + - * % & | ^ /
770         if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
771             ++index;
772             return {
773                 type: Token.Punctuator,
774                 value: ch1,
775                 lineNumber: lineNumber,
776                 lineStart: lineStart,
777                 start: start,
778                 end: index
779             };
780         }
781
782         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
783     }
784
785     // 7.8.3 Numeric Literals
786
787     function scanHexLiteral(start) {
788         var number = '';
789
790         while (index < length) {
791             if (!isHexDigit(source[index])) {
792                 break;
793             }
794             number += source[index++];
795         }
796
797         if (number.length === 0) {
798             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
799         }
800
801         if (isIdentifierStart(source.charCodeAt(index))) {
802             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
803         }
804
805         return {
806             type: Token.NumericLiteral,
807             value: parseInt('0x' + number, 16),
808             lineNumber: lineNumber,
809             lineStart: lineStart,
810             start: start,
811             end: index
812         };
813     }
814
815     function scanOctalLiteral(start) {
816         var number = '0' + source[index++];
817         while (index < length) {
818             if (!isOctalDigit(source[index])) {
819                 break;
820             }
821             number += source[index++];
822         }
823
824         if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
825             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
826         }
827
828         return {
829             type: Token.NumericLiteral,
830             value: parseInt(number, 8),
831             octal: true,
832             lineNumber: lineNumber,
833             lineStart: lineStart,
834             start: start,
835             end: index
836         };
837     }
838
839     function isImplicitOctalLiteral() {
840         var i, ch;
841
842         // Implicit octal, unless there is a non-octal digit.
843         // (Annex B.1.1 on Numeric Literals)
844         for (i = index + 1; i < length; ++i) {
845             ch = source[i];
846             if (ch === '8' || ch === '9') {
847                 return false;
848             }
849             if (!isOctalDigit(ch)) {
850                 return true;
851             }
852         }
853
854         return true;
855     }
856
857     function scanNumericLiteral() {
858         var number, start, ch;
859
860         ch = source[index];
861         assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
862             'Numeric literal must start with a decimal digit or a decimal point');
863
864         start = index;
865         number = '';
866         if (ch !== '.') {
867             number = source[index++];
868             ch = source[index];
869
870             // Hex number starts with '0x'.
871             // Octal number starts with '0'.
872             if (number === '0') {
873                 if (ch === 'x' || ch === 'X') {
874                     ++index;
875                     return scanHexLiteral(start);
876                 }
877                 if (isOctalDigit(ch)) {
878                     if (isImplicitOctalLiteral()) {
879                         return scanOctalLiteral(start);
880                     }
881                 }
882             }
883
884             while (isDecimalDigit(source.charCodeAt(index))) {
885                 number += source[index++];
886             }
887             ch = source[index];
888         }
889
890         if (ch === '.') {
891             number += source[index++];
892             while (isDecimalDigit(source.charCodeAt(index))) {
893                 number += source[index++];
894             }
895             ch = source[index];
896         }
897
898         if (ch === 'e' || ch === 'E') {
899             number += source[index++];
900
901             ch = source[index];
902             if (ch === '+' || ch === '-') {
903                 number += source[index++];
904             }
905             if (isDecimalDigit(source.charCodeAt(index))) {
906                 while (isDecimalDigit(source.charCodeAt(index))) {
907                     number += source[index++];
908                 }
909             } else {
910                 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
911             }
912         }
913
914         if (isIdentifierStart(source.charCodeAt(index))) {
915             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
916         }
917
918         return {
919             type: Token.NumericLiteral,
920             value: parseFloat(number),
921             lineNumber: lineNumber,
922             lineStart: lineStart,
923             start: start,
924             end: index
925         };
926     }
927
928     // 7.8.4 String Literals
929
930     function scanStringLiteral() {
931         var str = '', quote, start, ch, code, unescaped, restore, octal = false, startLineNumber, startLineStart;
932         startLineNumber = lineNumber;
933         startLineStart = lineStart;
934
935         quote = source[index];
936         assert((quote === '\'' || quote === '"'),
937             'String literal must starts with a quote');
938
939         start = index;
940         ++index;
941
942         while (index < length) {
943             ch = source[index++];
944
945             if (ch === quote) {
946                 quote = '';
947                 break;
948             } else if (ch === '\\') {
949                 ch = source[index++];
950                 if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
951                     switch (ch) {
952                     case 'u':
953                     case 'x':
954                         restore = index;
955                         unescaped = scanHexEscape(ch);
956                         if (unescaped) {
957                             str += unescaped;
958                         } else {
959                             index = restore;
960                             str += ch;
961                         }
962                         break;
963                     case 'n':
964                         str += '\n';
965                         break;
966                     case 'r':
967                         str += '\r';
968                         break;
969                     case 't':
970                         str += '\t';
971                         break;
972                     case 'b':
973                         str += '\b';
974                         break;
975                     case 'f':
976                         str += '\f';
977                         break;
978                     case 'v':
979                         str += '\x0B';
980                         break;
981
982                     default:
983                         if (isOctalDigit(ch)) {
984                             code = '01234567'.indexOf(ch);
985
986                             // \0 is not octal escape sequence
987                             if (code !== 0) {
988                                 octal = true;
989                             }
990
991                             if (index < length && isOctalDigit(source[index])) {
992                                 octal = true;
993                                 code = code * 8 + '01234567'.indexOf(source[index++]);
994
995                                 // 3 digits are only allowed when string starts
996                                 // with 0, 1, 2, 3
997                                 if ('0123'.indexOf(ch) >= 0 &&
998                                         index < length &&
999                                         isOctalDigit(source[index])) {
1000                                     code = code * 8 + '01234567'.indexOf(source[index++]);
1001                                 }
1002                             }
1003                             str += String.fromCharCode(code);
1004                         } else {
1005                             str += ch;
1006                         }
1007                         break;
1008                     }
1009                 } else {
1010                     ++lineNumber;
1011                     if (ch ===  '\r' && source[index] === '\n') {
1012                         ++index;
1013                     }
1014                     lineStart = index;
1015                 }
1016             } else if (isLineTerminator(ch.charCodeAt(0))) {
1017                 break;
1018             } else {
1019                 str += ch;
1020             }
1021         }
1022
1023         if (quote !== '') {
1024             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1025         }
1026
1027         return {
1028             type: Token.StringLiteral,
1029             value: str,
1030             octal: octal,
1031             startLineNumber: startLineNumber,
1032             startLineStart: startLineStart,
1033             lineNumber: lineNumber,
1034             lineStart: lineStart,
1035             start: start,
1036             end: index
1037         };
1038     }
1039
1040     function testRegExp(pattern, flags) {
1041         var value;
1042         try {
1043             value = new RegExp(pattern, flags);
1044         } catch (e) {
1045             throwError({}, Messages.InvalidRegExp);
1046         }
1047         return value;
1048     }
1049
1050     function scanRegExpBody() {
1051         var ch, str, classMarker, terminated, body;
1052
1053         ch = source[index];
1054         assert(ch === '/', 'Regular expression literal must start with a slash');
1055         str = source[index++];
1056
1057         classMarker = false;
1058         terminated = false;
1059         while (index < length) {
1060             ch = source[index++];
1061             str += ch;
1062             if (ch === '\\') {
1063                 ch = source[index++];
1064                 // ECMA-262 7.8.5
1065                 if (isLineTerminator(ch.charCodeAt(0))) {
1066                     throwError({}, Messages.UnterminatedRegExp);
1067                 }
1068                 str += ch;
1069             } else if (isLineTerminator(ch.charCodeAt(0))) {
1070                 throwError({}, Messages.UnterminatedRegExp);
1071             } else if (classMarker) {
1072                 if (ch === ']') {
1073                     classMarker = false;
1074                 }
1075             } else {
1076                 if (ch === '/') {
1077                     terminated = true;
1078                     break;
1079                 } else if (ch === '[') {
1080                     classMarker = true;
1081                 }
1082             }
1083         }
1084
1085         if (!terminated) {
1086             throwError({}, Messages.UnterminatedRegExp);
1087         }
1088
1089         // Exclude leading and trailing slash.
1090         body = str.substr(1, str.length - 2);
1091         return {
1092             value: body,
1093             literal: str
1094         };
1095     }
1096
1097     function scanRegExpFlags() {
1098         var ch, str, flags, restore;
1099
1100         str = '';
1101         flags = '';
1102         while (index < length) {
1103             ch = source[index];
1104             if (!isIdentifierPart(ch.charCodeAt(0))) {
1105                 break;
1106             }
1107
1108             ++index;
1109             if (ch === '\\' && index < length) {
1110                 ch = source[index];
1111                 if (ch === 'u') {
1112                     ++index;
1113                     restore = index;
1114                     ch = scanHexEscape('u');
1115                     if (ch) {
1116                         flags += ch;
1117                         for (str += '\\u'; restore < index; ++restore) {
1118                             str += source[restore];
1119                         }
1120                     } else {
1121                         index = restore;
1122                         flags += 'u';
1123                         str += '\\u';
1124                     }
1125                     throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
1126                 } else {
1127                     str += '\\';
1128                     throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
1129                 }
1130             } else {
1131                 flags += ch;
1132                 str += ch;
1133             }
1134         }
1135
1136         return {
1137             value: flags,
1138             literal: str
1139         };
1140     }
1141
1142     function scanRegExp() {
1143         var start, body, flags, pattern, value;
1144
1145         lookahead = null;
1146         skipComment();
1147         start = index;
1148
1149         body = scanRegExpBody();
1150         flags = scanRegExpFlags();
1151         value = testRegExp(body.value, flags.value);
1152
1153         if (extra.tokenize) {
1154             return {
1155                 type: Token.RegularExpression,
1156                 value: value,
1157                 lineNumber: lineNumber,
1158                 lineStart: lineStart,
1159                 start: start,
1160                 end: index
1161             };
1162         }
1163
1164         return {
1165             literal: body.literal + flags.literal,
1166             value: value,
1167             start: start,
1168             end: index
1169         };
1170     }
1171
1172     function collectRegex() {
1173         var pos, loc, regex, token;
1174
1175         skipComment();
1176
1177         pos = index;
1178         loc = {
1179             start: {
1180                 line: lineNumber,
1181                 column: index - lineStart
1182             }
1183         };
1184
1185         regex = scanRegExp();
1186         loc.end = {
1187             line: lineNumber,
1188             column: index - lineStart
1189         };
1190
1191         /* istanbul ignore next */
1192         if (!extra.tokenize) {
1193             // Pop the previous token, which is likely '/' or '/='
1194             if (extra.tokens.length > 0) {
1195                 token = extra.tokens[extra.tokens.length - 1];
1196                 if (token.range[0] === pos && token.type === 'Punctuator') {
1197                     if (token.value === '/' || token.value === '/=') {
1198                         extra.tokens.pop();
1199                     }
1200                 }
1201             }
1202
1203             extra.tokens.push({
1204                 type: 'RegularExpression',
1205                 value: regex.literal,
1206                 range: [pos, index],
1207                 loc: loc
1208             });
1209         }
1210
1211         return regex;
1212     }
1213
1214     function isIdentifierName(token) {
1215         return token.type === Token.Identifier ||
1216             token.type === Token.Keyword ||
1217             token.type === Token.BooleanLiteral ||
1218             token.type === Token.NullLiteral;
1219     }
1220
1221     function advanceSlash() {
1222         var prevToken,
1223             checkToken;
1224         // Using the following algorithm:
1225         // https://github.com/mozilla/sweet.js/wiki/design
1226         prevToken = extra.tokens[extra.tokens.length - 1];
1227         if (!prevToken) {
1228             // Nothing before that: it cannot be a division.
1229             return collectRegex();
1230         }
1231         if (prevToken.type === 'Punctuator') {
1232             if (prevToken.value === ']') {
1233                 return scanPunctuator();
1234             }
1235             if (prevToken.value === ')') {
1236                 checkToken = extra.tokens[extra.openParenToken - 1];
1237                 if (checkToken &&
1238                         checkToken.type === 'Keyword' &&
1239                         (checkToken.value === 'if' ||
1240                          checkToken.value === 'while' ||
1241                          checkToken.value === 'for' ||
1242                          checkToken.value === 'with')) {
1243                     return collectRegex();
1244                 }
1245                 return scanPunctuator();
1246             }
1247             if (prevToken.value === '}') {
1248                 // Dividing a function by anything makes little sense,
1249                 // but we have to check for that.
1250                 if (extra.tokens[extra.openCurlyToken - 3] &&
1251                         extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') {
1252                     // Anonymous function.
1253                     checkToken = extra.tokens[extra.openCurlyToken - 4];
1254                     if (!checkToken) {
1255                         return scanPunctuator();
1256                     }
1257                 } else if (extra.tokens[extra.openCurlyToken - 4] &&
1258                         extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') {
1259                     // Named function.
1260                     checkToken = extra.tokens[extra.openCurlyToken - 5];
1261                     if (!checkToken) {
1262                         return collectRegex();
1263                     }
1264                 } else {
1265                     return scanPunctuator();
1266                 }
1267                 // checkToken determines whether the function is
1268                 // a declaration or an expression.
1269                 if (FnExprTokens.indexOf(checkToken.value) >= 0) {
1270                     // It is an expression.
1271                     return scanPunctuator();
1272                 }
1273                 // It is a declaration.
1274                 return collectRegex();
1275             }
1276             return collectRegex();
1277         }
1278         if (prevToken.type === 'Keyword' && prevToken.value !== 'this') {
1279             return collectRegex();
1280         }
1281         return scanPunctuator();
1282     }
1283
1284     function advance() {
1285         var ch;
1286
1287         skipComment();
1288
1289         if (index >= length) {
1290             return {
1291                 type: Token.EOF,
1292                 lineNumber: lineNumber,
1293                 lineStart: lineStart,
1294                 start: index,
1295                 end: index
1296             };
1297         }
1298
1299         ch = source.charCodeAt(index);
1300
1301         if (isIdentifierStart(ch)) {
1302             return scanIdentifier();
1303         }
1304
1305         // Very common: ( and ) and ;
1306         if (ch === 0x28 || ch === 0x29 || ch === 0x3B) {
1307             return scanPunctuator();
1308         }
1309
1310         // String literal starts with single quote (U+0027) or double quote (U+0022).
1311         if (ch === 0x27 || ch === 0x22) {
1312             return scanStringLiteral();
1313         }
1314
1315
1316         // Dot (.) U+002E can also start a floating-point number, hence the need
1317         // to check the next character.
1318         if (ch === 0x2E) {
1319             if (isDecimalDigit(source.charCodeAt(index + 1))) {
1320                 return scanNumericLiteral();
1321             }
1322             return scanPunctuator();
1323         }
1324
1325         if (isDecimalDigit(ch)) {
1326             return scanNumericLiteral();
1327         }
1328
1329         // Slash (/) U+002F can also start a regex.
1330         if (extra.tokenize && ch === 0x2F) {
1331             return advanceSlash();
1332         }
1333
1334         return scanPunctuator();
1335     }
1336
1337     function collectToken() {
1338         var loc, token, range, value;
1339
1340         skipComment();
1341         loc = {
1342             start: {
1343                 line: lineNumber,
1344                 column: index - lineStart
1345             }
1346         };
1347
1348         token = advance();
1349         loc.end = {
1350             line: lineNumber,
1351             column: index - lineStart
1352         };
1353
1354         if (token.type !== Token.EOF) {
1355             value = source.slice(token.start, token.end);
1356             extra.tokens.push({
1357                 type: TokenName[token.type],
1358                 value: value,
1359                 range: [token.start, token.end],
1360                 loc: loc
1361             });
1362         }
1363
1364         return token;
1365     }
1366
1367     function lex() {
1368         var token;
1369
1370         token = lookahead;
1371         index = token.end;
1372         lineNumber = token.lineNumber;
1373         lineStart = token.lineStart;
1374
1375         lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
1376
1377         index = token.end;
1378         lineNumber = token.lineNumber;
1379         lineStart = token.lineStart;
1380
1381         return token;
1382     }
1383
1384     function peek() {
1385         var pos, line, start;
1386
1387         pos = index;
1388         line = lineNumber;
1389         start = lineStart;
1390         lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
1391         index = pos;
1392         lineNumber = line;
1393         lineStart = start;
1394     }
1395
1396     function Position(line, column) {
1397         this.line = line;
1398         this.column = column;
1399     }
1400
1401     function SourceLocation(startLine, startColumn, line, column) {
1402         this.start = new Position(startLine, startColumn);
1403         this.end = new Position(line, column);
1404     }
1405
1406     SyntaxTreeDelegate = {
1407
1408         name: 'SyntaxTree',
1409
1410         processComment: function (node) {
1411             var lastChild, trailingComments;
1412
1413             if (node.type === Syntax.Program) {
1414                 if (node.body.length > 0) {
1415                     return;
1416                 }
1417             }
1418
1419             if (extra.trailingComments.length > 0) {
1420                 if (extra.trailingComments[0].range[0] >= node.range[1]) {
1421                     trailingComments = extra.trailingComments;
1422                     extra.trailingComments = [];
1423                 } else {
1424                     extra.trailingComments.length = 0;
1425                 }
1426             } else {
1427                 if (extra.bottomRightStack.length > 0 &&
1428                         extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments &&
1429                         extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments[0].range[0] >= node.range[1]) {
1430                     trailingComments = extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments;
1431                     delete extra.bottomRightStack[extra.bottomRightStack.length - 1].trailingComments;
1432                 }
1433             }
1434
1435             // Eating the stack.
1436             while (extra.bottomRightStack.length > 0 && extra.bottomRightStack[extra.bottomRightStack.length - 1].range[0] >= node.range[0]) {
1437                 lastChild = extra.bottomRightStack.pop();
1438             }
1439
1440             if (lastChild) {
1441                 if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= node.range[0]) {
1442                     node.leadingComments = lastChild.leadingComments;
1443                     delete lastChild.leadingComments;
1444                 }
1445             } else if (extra.leadingComments.length > 0 && extra.leadingComments[extra.leadingComments.length - 1].range[1] <= node.range[0]) {
1446                 node.leadingComments = extra.leadingComments;
1447                 extra.leadingComments = [];
1448             }
1449
1450
1451             if (trailingComments) {
1452                 node.trailingComments = trailingComments;
1453             }
1454
1455             extra.bottomRightStack.push(node);
1456         },
1457
1458         markEnd: function (node, startToken) {
1459             if (extra.range) {
1460                 node.range = [startToken.start, index];
1461             }
1462             if (extra.loc) {
1463                 node.loc = new SourceLocation(
1464                     startToken.startLineNumber === undefined ?  startToken.lineNumber : startToken.startLineNumber,
1465                     startToken.start - (startToken.startLineStart === undefined ?  startToken.lineStart : startToken.startLineStart),
1466                     lineNumber,
1467                     index - lineStart
1468                 );
1469                 this.postProcess(node);
1470             }
1471
1472             if (extra.attachComment) {
1473                 this.processComment(node);
1474             }
1475             return node;
1476         },
1477
1478         postProcess: function (node) {
1479             if (extra.source) {
1480                 node.loc.source = extra.source;
1481             }
1482             return node;
1483         },
1484
1485         createArrayExpression: function (elements) {
1486             return {
1487                 type: Syntax.ArrayExpression,
1488                 elements: elements
1489             };
1490         },
1491
1492         createAssignmentExpression: function (operator, left, right) {
1493             return {
1494                 type: Syntax.AssignmentExpression,
1495                 operator: operator,
1496                 left: left,
1497                 right: right
1498             };
1499         },
1500
1501         createBinaryExpression: function (operator, left, right) {
1502             var type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression :
1503                         Syntax.BinaryExpression;
1504             return {
1505                 type: type,
1506                 operator: operator,
1507                 left: left,
1508                 right: right
1509             };
1510         },
1511
1512         createBlockStatement: function (body) {
1513             return {
1514                 type: Syntax.BlockStatement,
1515                 body: body
1516             };
1517         },
1518
1519         createBreakStatement: function (label) {
1520             return {
1521                 type: Syntax.BreakStatement,
1522                 label: label
1523             };
1524         },
1525
1526         createCallExpression: function (callee, args) {
1527             return {
1528                 type: Syntax.CallExpression,
1529                 callee: callee,
1530                 'arguments': args
1531             };
1532         },
1533
1534         createCatchClause: function (param, body) {
1535             return {
1536                 type: Syntax.CatchClause,
1537                 param: param,
1538                 body: body
1539             };
1540         },
1541
1542         createConditionalExpression: function (test, consequent, alternate) {
1543             return {
1544                 type: Syntax.ConditionalExpression,
1545                 test: test,
1546                 consequent: consequent,
1547                 alternate: alternate
1548             };
1549         },
1550
1551         createContinueStatement: function (label) {
1552             return {
1553                 type: Syntax.ContinueStatement,
1554                 label: label
1555             };
1556         },
1557
1558         createDebuggerStatement: function () {
1559             return {
1560                 type: Syntax.DebuggerStatement
1561             };
1562         },
1563
1564         createDoWhileStatement: function (body, test) {
1565             return {
1566                 type: Syntax.DoWhileStatement,
1567                 body: body,
1568                 test: test
1569             };
1570         },
1571
1572         createEmptyStatement: function () {
1573             return {
1574                 type: Syntax.EmptyStatement
1575             };
1576         },
1577
1578         createExpressionStatement: function (expression) {
1579             return {
1580                 type: Syntax.ExpressionStatement,
1581                 expression: expression
1582             };
1583         },
1584
1585         createForStatement: function (init, test, update, body) {
1586             return {
1587                 type: Syntax.ForStatement,
1588                 init: init,
1589                 test: test,
1590                 update: update,
1591                 body: body
1592             };
1593         },
1594
1595         createForInStatement: function (left, right, body) {
1596             return {
1597                 type: Syntax.ForInStatement,
1598                 left: left,
1599                 right: right,
1600                 body: body,
1601                 each: false
1602             };
1603         },
1604
1605         createFunctionDeclaration: function (id, params, defaults, body) {
1606             return {
1607                 type: Syntax.FunctionDeclaration,
1608                 id: id,
1609                 params: params,
1610                 defaults: defaults,
1611                 body: body,
1612                 rest: null,
1613                 generator: false,
1614                 expression: false
1615             };
1616         },
1617
1618         createFunctionExpression: function (id, params, defaults, body) {
1619             return {
1620                 type: Syntax.FunctionExpression,
1621                 id: id,
1622                 params: params,
1623                 defaults: defaults,
1624                 body: body,
1625                 rest: null,
1626                 generator: false,
1627                 expression: false
1628             };
1629         },
1630
1631         createIdentifier: function (name) {
1632             return {
1633                 type: Syntax.Identifier,
1634                 name: name
1635             };
1636         },
1637
1638         createIfStatement: function (test, consequent, alternate) {
1639             return {
1640                 type: Syntax.IfStatement,
1641                 test: test,
1642                 consequent: consequent,
1643                 alternate: alternate
1644             };
1645         },
1646
1647         createLabeledStatement: function (label, body) {
1648             return {
1649                 type: Syntax.LabeledStatement,
1650                 label: label,
1651                 body: body
1652             };
1653         },
1654
1655         createLiteral: function (token) {
1656             return {
1657                 type: Syntax.Literal,
1658                 value: token.value,
1659                 raw: source.slice(token.start, token.end)
1660             };
1661         },
1662
1663         createMemberExpression: function (accessor, object, property) {
1664             return {
1665                 type: Syntax.MemberExpression,
1666                 computed: accessor === '[',
1667                 object: object,
1668                 property: property
1669             };
1670         },
1671
1672         createNewExpression: function (callee, args) {
1673             return {
1674                 type: Syntax.NewExpression,
1675                 callee: callee,
1676                 'arguments': args
1677             };
1678         },
1679
1680         createObjectExpression: function (properties) {
1681             return {
1682                 type: Syntax.ObjectExpression,
1683                 properties: properties
1684             };
1685         },
1686
1687         createPostfixExpression: function (operator, argument) {
1688             return {
1689                 type: Syntax.UpdateExpression,
1690                 operator: operator,
1691                 argument: argument,
1692                 prefix: false
1693             };
1694         },
1695
1696         createProgram: function (body) {
1697             return {
1698                 type: Syntax.Program,
1699                 body: body
1700             };
1701         },
1702
1703         createProperty: function (kind, key, value) {
1704             return {
1705                 type: Syntax.Property,
1706                 key: key,
1707                 value: value,
1708                 kind: kind
1709             };
1710         },
1711
1712         createReturnStatement: function (argument) {
1713             return {
1714                 type: Syntax.ReturnStatement,
1715                 argument: argument
1716             };
1717         },
1718
1719         createSequenceExpression: function (expressions) {
1720             return {
1721                 type: Syntax.SequenceExpression,
1722                 expressions: expressions
1723             };
1724         },
1725
1726         createSwitchCase: function (test, consequent) {
1727             return {
1728                 type: Syntax.SwitchCase,
1729                 test: test,
1730                 consequent: consequent
1731             };
1732         },
1733
1734         createSwitchStatement: function (discriminant, cases) {
1735             return {
1736                 type: Syntax.SwitchStatement,
1737                 discriminant: discriminant,
1738                 cases: cases
1739             };
1740         },
1741
1742         createThisExpression: function () {
1743             return {
1744                 type: Syntax.ThisExpression
1745             };
1746         },
1747
1748         createThrowStatement: function (argument) {
1749             return {
1750                 type: Syntax.ThrowStatement,
1751                 argument: argument
1752             };
1753         },
1754
1755         createTryStatement: function (block, guardedHandlers, handlers, finalizer) {
1756             return {
1757                 type: Syntax.TryStatement,
1758                 block: block,
1759                 guardedHandlers: guardedHandlers,
1760                 handlers: handlers,
1761                 finalizer: finalizer
1762             };
1763         },
1764
1765         createUnaryExpression: function (operator, argument) {
1766             if (operator === '++' || operator === '--') {
1767                 return {
1768                     type: Syntax.UpdateExpression,
1769                     operator: operator,
1770                     argument: argument,
1771                     prefix: true
1772                 };
1773             }
1774             return {
1775                 type: Syntax.UnaryExpression,
1776                 operator: operator,
1777                 argument: argument,
1778                 prefix: true
1779             };
1780         },
1781
1782         createVariableDeclaration: function (declarations, kind) {
1783             return {
1784                 type: Syntax.VariableDeclaration,
1785                 declarations: declarations,
1786                 kind: kind
1787             };
1788         },
1789
1790         createVariableDeclarator: function (id, init) {
1791             return {
1792                 type: Syntax.VariableDeclarator,
1793                 id: id,
1794                 init: init
1795             };
1796         },
1797
1798         createWhileStatement: function (test, body) {
1799             return {
1800                 type: Syntax.WhileStatement,
1801                 test: test,
1802                 body: body
1803             };
1804         },
1805
1806         createWithStatement: function (object, body) {
1807             return {
1808                 type: Syntax.WithStatement,
1809                 object: object,
1810                 body: body
1811             };
1812         }
1813     };
1814
1815     // Return true if there is a line terminator before the next token.
1816
1817     function peekLineTerminator() {
1818         var pos, line, start, found;
1819
1820         pos = index;
1821         line = lineNumber;
1822         start = lineStart;
1823         skipComment();
1824         found = lineNumber !== line;
1825         index = pos;
1826         lineNumber = line;
1827         lineStart = start;
1828
1829         return found;
1830     }
1831
1832     // Throw an exception
1833
1834     function throwError(token, messageFormat) {
1835         var error,
1836             args = Array.prototype.slice.call(arguments, 2),
1837             msg = messageFormat.replace(
1838                 /%(\d)/g,
1839                 function (whole, index) {
1840                     assert(index < args.length, 'Message reference must be in range');
1841                     return args[index];
1842                 }
1843             );
1844
1845         if (typeof token.lineNumber === 'number') {
1846             error = new Error('Line ' + token.lineNumber + ': ' + msg);
1847             error.index = token.start;
1848             error.lineNumber = token.lineNumber;
1849             error.column = token.start - lineStart + 1;
1850         } else {
1851             error = new Error('Line ' + lineNumber + ': ' + msg);
1852             error.index = index;
1853             error.lineNumber = lineNumber;
1854             error.column = index - lineStart + 1;
1855         }
1856
1857         error.description = msg;
1858         throw error;
1859     }
1860
1861     function throwErrorTolerant() {
1862         try {
1863             throwError.apply(null, arguments);
1864         } catch (e) {
1865             if (extra.errors) {
1866                 extra.errors.push(e);
1867             } else {
1868                 throw e;
1869             }
1870         }
1871     }
1872
1873
1874     // Throw an exception because of the token.
1875
1876     function throwUnexpected(token) {
1877         if (token.type === Token.EOF) {
1878             throwError(token, Messages.UnexpectedEOS);
1879         }
1880
1881         if (token.type === Token.NumericLiteral) {
1882             throwError(token, Messages.UnexpectedNumber);
1883         }
1884
1885         if (token.type === Token.StringLiteral) {
1886             throwError(token, Messages.UnexpectedString);
1887         }
1888
1889         if (token.type === Token.Identifier) {
1890             throwError(token, Messages.UnexpectedIdentifier);
1891         }
1892
1893         if (token.type === Token.Keyword) {
1894             if (isFutureReservedWord(token.value)) {
1895                 throwError(token, Messages.UnexpectedReserved);
1896             } else if (strict && isStrictModeReservedWord(token.value)) {
1897                 throwErrorTolerant(token, Messages.StrictReservedWord);
1898                 return;
1899             }
1900             throwError(token, Messages.UnexpectedToken, token.value);
1901         }
1902
1903         // BooleanLiteral, NullLiteral, or Punctuator.
1904         throwError(token, Messages.UnexpectedToken, token.value);
1905     }
1906
1907     // Expect the next token to match the specified punctuator.
1908     // If not, an exception will be thrown.
1909
1910     function expect(value) {
1911         var token = lex();
1912         if (token.type !== Token.Punctuator || token.value !== value) {
1913             throwUnexpected(token);
1914         }
1915     }
1916
1917     // Expect the next token to match the specified keyword.
1918     // If not, an exception will be thrown.
1919
1920     function expectKeyword(keyword) {
1921         var token = lex();
1922         if (token.type !== Token.Keyword || token.value !== keyword) {
1923             throwUnexpected(token);
1924         }
1925     }
1926
1927     // Return true if the next token matches the specified punctuator.
1928
1929     function match(value) {
1930         return lookahead.type === Token.Punctuator && lookahead.value === value;
1931     }
1932
1933     // Return true if the next token matches the specified keyword
1934
1935     function matchKeyword(keyword) {
1936         return lookahead.type === Token.Keyword && lookahead.value === keyword;
1937     }
1938
1939     // Return true if the next token is an assignment operator
1940
1941     function matchAssign() {
1942         var op;
1943
1944         if (lookahead.type !== Token.Punctuator) {
1945             return false;
1946         }
1947         op = lookahead.value;
1948         return op === '=' ||
1949             op === '*=' ||
1950             op === '/=' ||
1951             op === '%=' ||
1952             op === '+=' ||
1953             op === '-=' ||
1954             op === '<<=' ||
1955             op === '>>=' ||
1956             op === '>>>=' ||
1957             op === '&=' ||
1958             op === '^=' ||
1959             op === '|=';
1960     }
1961
1962     function consumeSemicolon() {
1963         var line, oldIndex = index, oldLineNumber = lineNumber,
1964             oldLineStart = lineStart, oldLookahead = lookahead;
1965
1966         // Catch the very common case first: immediately a semicolon (U+003B).
1967         if (source.charCodeAt(index) === 0x3B || match(';')) {
1968             lex();
1969             return;
1970         }
1971
1972         line = lineNumber;
1973         skipComment();
1974         if (lineNumber !== line) {
1975             index = oldIndex;
1976             lineNumber = oldLineNumber;
1977             lineStart = oldLineStart;
1978             lookahead = oldLookahead;
1979             return;
1980         }
1981
1982         if (lookahead.type !== Token.EOF && !match('}')) {
1983             throwUnexpected(lookahead);
1984         }
1985     }
1986
1987     // Return true if provided expression is LeftHandSideExpression
1988
1989     function isLeftHandSide(expr) {
1990         return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
1991     }
1992
1993     // 11.1.4 Array Initialiser
1994
1995     function parseArrayInitialiser() {
1996         var elements = [], startToken;
1997
1998         startToken = lookahead;
1999         expect('[');
2000
2001         while (!match(']')) {
2002             if (match(',')) {
2003                 lex();
2004                 elements.push(null);
2005             } else {
2006                 elements.push(parseAssignmentExpression());
2007
2008                 if (!match(']')) {
2009                     expect(',');
2010                 }
2011             }
2012         }
2013
2014         lex();
2015
2016         return delegate.markEnd(delegate.createArrayExpression(elements), startToken);
2017     }
2018
2019     // 11.1.5 Object Initialiser
2020
2021     function parsePropertyFunction(param, first) {
2022         var previousStrict, body, startToken;
2023
2024         previousStrict = strict;
2025         startToken = lookahead;
2026         body = parseFunctionSourceElements();
2027         if (first && strict && isRestrictedWord(param[0].name)) {
2028             throwErrorTolerant(first, Messages.StrictParamName);
2029         }
2030         strict = previousStrict;
2031         return delegate.markEnd(delegate.createFunctionExpression(null, param, [], body), startToken);
2032     }
2033
2034     function parseObjectPropertyKey() {
2035         var token, startToken;
2036
2037         startToken = lookahead;
2038         token = lex();
2039
2040         // Note: This function is called only from parseObjectProperty(), where
2041         // EOF and Punctuator tokens are already filtered out.
2042
2043         if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
2044             if (strict && token.octal) {
2045                 throwErrorTolerant(token, Messages.StrictOctalLiteral);
2046             }
2047             return delegate.markEnd(delegate.createLiteral(token), startToken);
2048         }
2049
2050         return delegate.markEnd(delegate.createIdentifier(token.value), startToken);
2051     }
2052
2053     function parseObjectProperty() {
2054         var token, key, id, value, param, startToken;
2055
2056         token = lookahead;
2057         startToken = lookahead;
2058
2059         if (token.type === Token.Identifier) {
2060
2061             id = parseObjectPropertyKey();
2062
2063             // Property Assignment: Getter and Setter.
2064
2065             if (token.value === 'get' && !match(':')) {
2066                 key = parseObjectPropertyKey();
2067                 expect('(');
2068                 expect(')');
2069                 value = parsePropertyFunction([]);
2070                 return delegate.markEnd(delegate.createProperty('get', key, value), startToken);
2071             }
2072             if (token.value === 'set' && !match(':')) {
2073                 key = parseObjectPropertyKey();
2074                 expect('(');
2075                 token = lookahead;
2076                 if (token.type !== Token.Identifier) {
2077                     expect(')');
2078                     throwErrorTolerant(token, Messages.UnexpectedToken, token.value);
2079                     value = parsePropertyFunction([]);
2080                 } else {
2081                     param = [ parseVariableIdentifier() ];
2082                     expect(')');
2083                     value = parsePropertyFunction(param, token);
2084                 }
2085                 return delegate.markEnd(delegate.createProperty('set', key, value), startToken);
2086             }
2087             expect(':');
2088             value = parseAssignmentExpression();
2089             return delegate.markEnd(delegate.createProperty('init', id, value), startToken);
2090         }
2091         if (token.type === Token.EOF || token.type === Token.Punctuator) {
2092             throwUnexpected(token);
2093         } else {
2094             key = parseObjectPropertyKey();
2095             expect(':');
2096             value = parseAssignmentExpression();
2097             return delegate.markEnd(delegate.createProperty('init', key, value), startToken);
2098         }
2099     }
2100
2101     function parseObjectInitialiser() {
2102         var properties = [], property, name, key, kind, map = {}, toString = String, startToken;
2103
2104         startToken = lookahead;
2105
2106         expect('{');
2107
2108         while (!match('}')) {
2109             property = parseObjectProperty();
2110
2111             if (property.key.type === Syntax.Identifier) {
2112                 name = property.key.name;
2113             } else {
2114                 name = toString(property.key.value);
2115             }
2116             kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
2117
2118             key = '$' + name;
2119             if (Object.prototype.hasOwnProperty.call(map, key)) {
2120                 if (map[key] === PropertyKind.Data) {
2121                     if (strict && kind === PropertyKind.Data) {
2122                         throwErrorTolerant({}, Messages.StrictDuplicateProperty);
2123                     } else if (kind !== PropertyKind.Data) {
2124                         throwErrorTolerant({}, Messages.AccessorDataProperty);
2125                     }
2126                 } else {
2127                     if (kind === PropertyKind.Data) {
2128                         throwErrorTolerant({}, Messages.AccessorDataProperty);
2129                     } else if (map[key] & kind) {
2130                         throwErrorTolerant({}, Messages.AccessorGetSet);
2131                     }
2132                 }
2133                 map[key] |= kind;
2134             } else {
2135                 map[key] = kind;
2136             }
2137
2138             properties.push(property);
2139
2140             if (!match('}')) {
2141                 expect(',');
2142             }
2143         }
2144
2145         expect('}');
2146
2147         return delegate.markEnd(delegate.createObjectExpression(properties), startToken);
2148     }
2149
2150     // 11.1.6 The Grouping Operator
2151
2152     function parseGroupExpression() {
2153         var expr;
2154
2155         expect('(');
2156
2157         expr = parseExpression();
2158
2159         expect(')');
2160
2161         return expr;
2162     }
2163
2164
2165     // 11.1 Primary Expressions
2166
2167     function parsePrimaryExpression() {
2168         var type, token, expr, startToken;
2169
2170         if (match('(')) {
2171             return parseGroupExpression();
2172         }
2173
2174         if (match('[')) {
2175             return parseArrayInitialiser();
2176         }
2177
2178         if (match('{')) {
2179             return parseObjectInitialiser();
2180         }
2181
2182         type = lookahead.type;
2183         startToken = lookahead;
2184
2185         if (type === Token.Identifier) {
2186             expr =  delegate.createIdentifier(lex().value);
2187         } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
2188             if (strict && lookahead.octal) {
2189                 throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
2190             }
2191             expr = delegate.createLiteral(lex());
2192         } else if (type === Token.Keyword) {
2193             if (matchKeyword('function')) {
2194                 return parseFunctionExpression();
2195             }
2196             if (matchKeyword('this')) {
2197                 lex();
2198                 expr = delegate.createThisExpression();
2199             } else {
2200                 throwUnexpected(lex());
2201             }
2202         } else if (type === Token.BooleanLiteral) {
2203             token = lex();
2204             token.value = (token.value === 'true');
2205             expr = delegate.createLiteral(token);
2206         } else if (type === Token.NullLiteral) {
2207             token = lex();
2208             token.value = null;
2209             expr = delegate.createLiteral(token);
2210         } else if (match('/') || match('/=')) {
2211             if (typeof extra.tokens !== 'undefined') {
2212                 expr = delegate.createLiteral(collectRegex());
2213             } else {
2214                 expr = delegate.createLiteral(scanRegExp());
2215             }
2216             peek();
2217         } else {
2218             throwUnexpected(lex());
2219         }
2220
2221         return delegate.markEnd(expr, startToken);
2222     }
2223
2224     // 11.2 Left-Hand-Side Expressions
2225
2226     function parseArguments() {
2227         var args = [];
2228
2229         expect('(');
2230
2231         if (!match(')')) {
2232             while (index < length) {
2233                 args.push(parseAssignmentExpression());
2234                 if (match(')')) {
2235                     break;
2236                 }
2237                 expect(',');
2238             }
2239         }
2240
2241         expect(')');
2242
2243         return args;
2244     }
2245
2246     function parseNonComputedProperty() {
2247         var token, startToken;
2248
2249         startToken = lookahead;
2250         token = lex();
2251
2252         if (!isIdentifierName(token)) {
2253             throwUnexpected(token);
2254         }
2255
2256         return delegate.markEnd(delegate.createIdentifier(token.value), startToken);
2257     }
2258
2259     function parseNonComputedMember() {
2260         expect('.');
2261
2262         return parseNonComputedProperty();
2263     }
2264
2265     function parseComputedMember() {
2266         var expr;
2267
2268         expect('[');
2269
2270         expr = parseExpression();
2271
2272         expect(']');
2273
2274         return expr;
2275     }
2276
2277     function parseNewExpression() {
2278         var callee, args, startToken;
2279
2280         startToken = lookahead;
2281         expectKeyword('new');
2282         callee = parseLeftHandSideExpression();
2283         args = match('(') ? parseArguments() : [];
2284
2285         return delegate.markEnd(delegate.createNewExpression(callee, args), startToken);
2286     }
2287
2288     function parseLeftHandSideExpressionAllowCall() {
2289         var expr, args, property, startToken, previousAllowIn = state.allowIn;
2290
2291         startToken = lookahead;
2292         state.allowIn = true;
2293         expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
2294
2295         for (;;) {
2296             if (match('.')) {
2297                 property = parseNonComputedMember();
2298                 expr = delegate.createMemberExpression('.', expr, property);
2299             } else if (match('(')) {
2300                 args = parseArguments();
2301                 expr = delegate.createCallExpression(expr, args);
2302             } else if (match('[')) {
2303                 property = parseComputedMember();
2304                 expr = delegate.createMemberExpression('[', expr, property);
2305             } else {
2306                 break;
2307             }
2308             delegate.markEnd(expr, startToken);
2309         }
2310         state.allowIn = previousAllowIn;
2311
2312         return expr;
2313     }
2314
2315     function parseLeftHandSideExpression() {
2316         var expr, property, startToken;
2317         assert(state.allowIn, 'callee of new expression always allow in keyword.');
2318
2319         startToken = lookahead;
2320
2321         expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
2322
2323         while (match('.') || match('[')) {
2324             if (match('[')) {
2325                 property = parseComputedMember();
2326                 expr = delegate.createMemberExpression('[', expr, property);
2327             } else {
2328                 property = parseNonComputedMember();
2329                 expr = delegate.createMemberExpression('.', expr, property);
2330             }
2331             delegate.markEnd(expr, startToken);
2332         }
2333         return expr;
2334     }
2335
2336     // 11.3 Postfix Expressions
2337
2338     function parsePostfixExpression() {
2339         var expr, token, startToken = lookahead;
2340
2341         expr = parseLeftHandSideExpressionAllowCall();
2342
2343         if (lookahead.type === Token.Punctuator) {
2344             if ((match('++') || match('--')) && !peekLineTerminator()) {
2345                 // 11.3.1, 11.3.2
2346                 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
2347                     throwErrorTolerant({}, Messages.StrictLHSPostfix);
2348                 }
2349
2350                 if (!isLeftHandSide(expr)) {
2351                     throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
2352                 }
2353
2354                 token = lex();
2355                 expr = delegate.markEnd(delegate.createPostfixExpression(token.value, expr), startToken);
2356             }
2357         }
2358
2359         return expr;
2360     }
2361
2362     // 11.4 Unary Operators
2363
2364     function parseUnaryExpression() {
2365         var token, expr, startToken;
2366
2367         if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
2368             expr = parsePostfixExpression();
2369         } else if (match('++') || match('--')) {
2370             startToken = lookahead;
2371             token = lex();
2372             expr = parseUnaryExpression();
2373             // 11.4.4, 11.4.5
2374             if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
2375                 throwErrorTolerant({}, Messages.StrictLHSPrefix);
2376             }
2377
2378             if (!isLeftHandSide(expr)) {
2379                 throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
2380             }
2381
2382             expr = delegate.createUnaryExpression(token.value, expr);
2383             expr = delegate.markEnd(expr, startToken);
2384         } else if (match('+') || match('-') || match('~') || match('!')) {
2385             startToken = lookahead;
2386             token = lex();
2387             expr = parseUnaryExpression();
2388             expr = delegate.createUnaryExpression(token.value, expr);
2389             expr = delegate.markEnd(expr, startToken);
2390         } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
2391             startToken = lookahead;
2392             token = lex();
2393             expr = parseUnaryExpression();
2394             expr = delegate.createUnaryExpression(token.value, expr);
2395             expr = delegate.markEnd(expr, startToken);
2396             if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
2397                 throwErrorTolerant({}, Messages.StrictDelete);
2398             }
2399         } else {
2400             expr = parsePostfixExpression();
2401         }
2402
2403         return expr;
2404     }
2405
2406     function binaryPrecedence(token, allowIn) {
2407         var prec = 0;
2408
2409         if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
2410             return 0;
2411         }
2412
2413         switch (token.value) {
2414         case '||':
2415             prec = 1;
2416             break;
2417
2418         case '&&':
2419             prec = 2;
2420             break;
2421
2422         case '|':
2423             prec = 3;
2424             break;
2425
2426         case '^':
2427             prec = 4;
2428             break;
2429
2430         case '&':
2431             prec = 5;
2432             break;
2433
2434         case '==':
2435         case '!=':
2436         case '===':
2437         case '!==':
2438             prec = 6;
2439             break;
2440
2441         case '<':
2442         case '>':
2443         case '<=':
2444         case '>=':
2445         case 'instanceof':
2446             prec = 7;
2447             break;
2448
2449         case 'in':
2450             prec = allowIn ? 7 : 0;
2451             break;
2452
2453         case '<<':
2454         case '>>':
2455         case '>>>':
2456             prec = 8;
2457             break;
2458
2459         case '+':
2460         case '-':
2461             prec = 9;
2462             break;
2463
2464         case '*':
2465         case '/':
2466         case '%':
2467             prec = 11;
2468             break;
2469
2470         default:
2471             break;
2472         }
2473
2474         return prec;
2475     }
2476
2477     // 11.5 Multiplicative Operators
2478     // 11.6 Additive Operators
2479     // 11.7 Bitwise Shift Operators
2480     // 11.8 Relational Operators
2481     // 11.9 Equality Operators
2482     // 11.10 Binary Bitwise Operators
2483     // 11.11 Binary Logical Operators
2484
2485     function parseBinaryExpression() {
2486         var marker, markers, expr, token, prec, stack, right, operator, left, i;
2487
2488         marker = lookahead;
2489         left = parseUnaryExpression();
2490
2491         token = lookahead;
2492         prec = binaryPrecedence(token, state.allowIn);
2493         if (prec === 0) {
2494             return left;
2495         }
2496         token.prec = prec;
2497         lex();
2498
2499         markers = [marker, lookahead];
2500         right = parseUnaryExpression();
2501
2502         stack = [left, token, right];
2503
2504         while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) {
2505
2506             // Reduce: make a binary expression from the three topmost entries.
2507             while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
2508                 right = stack.pop();
2509                 operator = stack.pop().value;
2510                 left = stack.pop();
2511                 expr = delegate.createBinaryExpression(operator, left, right);
2512                 markers.pop();
2513                 marker = markers[markers.length - 1];
2514                 delegate.markEnd(expr, marker);
2515                 stack.push(expr);
2516             }
2517
2518             // Shift.
2519             token = lex();
2520             token.prec = prec;
2521             stack.push(token);
2522             markers.push(lookahead);
2523             expr = parseUnaryExpression();
2524             stack.push(expr);
2525         }
2526
2527         // Final reduce to clean-up the stack.
2528         i = stack.length - 1;
2529         expr = stack[i];
2530         markers.pop();
2531         while (i > 1) {
2532             expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
2533             i -= 2;
2534             marker = markers.pop();
2535             delegate.markEnd(expr, marker);
2536         }
2537
2538         return expr;
2539     }
2540
2541
2542     // 11.12 Conditional Operator
2543
2544     function parseConditionalExpression() {
2545         var expr, previousAllowIn, consequent, alternate, startToken;
2546
2547         startToken = lookahead;
2548
2549         expr = parseBinaryExpression();
2550
2551         if (match('?')) {
2552             lex();
2553             previousAllowIn = state.allowIn;
2554             state.allowIn = true;
2555             consequent = parseAssignmentExpression();
2556             state.allowIn = previousAllowIn;
2557             expect(':');
2558             alternate = parseAssignmentExpression();
2559
2560             expr = delegate.createConditionalExpression(expr, consequent, alternate);
2561             delegate.markEnd(expr, startToken);
2562         }
2563
2564         return expr;
2565     }
2566
2567     // 11.13 Assignment Operators
2568
2569     function parseAssignmentExpression() {
2570         var token, left, right, node, startToken;
2571
2572         token = lookahead;
2573         startToken = lookahead;
2574
2575         node = left = parseConditionalExpression();
2576
2577         if (matchAssign()) {
2578             // LeftHandSideExpression
2579             if (!isLeftHandSide(left)) {
2580                 throwErrorTolerant({}, Messages.InvalidLHSInAssignment);
2581             }
2582
2583             // 11.13.1
2584             if (strict && left.type === Syntax.Identifier && isRestrictedWord(left.name)) {
2585                 throwErrorTolerant(token, Messages.StrictLHSAssignment);
2586             }
2587
2588             token = lex();
2589             right = parseAssignmentExpression();
2590             node = delegate.markEnd(delegate.createAssignmentExpression(token.value, left, right), startToken);
2591         }
2592
2593         return node;
2594     }
2595
2596     // 11.14 Comma Operator
2597
2598     function parseExpression() {
2599         var expr, startToken = lookahead;
2600
2601         expr = parseAssignmentExpression();
2602
2603         if (match(',')) {
2604             expr = delegate.createSequenceExpression([ expr ]);
2605
2606             while (index < length) {
2607                 if (!match(',')) {
2608                     break;
2609                 }
2610                 lex();
2611                 expr.expressions.push(parseAssignmentExpression());
2612             }
2613
2614             delegate.markEnd(expr, startToken);
2615         }
2616
2617         return expr;
2618     }
2619
2620     // 12.1 Block
2621
2622     function parseStatementList() {
2623         var list = [],
2624             statement;
2625
2626         while (index < length) {
2627             if (match('}')) {
2628                 break;
2629             }
2630             statement = parseSourceElement();
2631             if (typeof statement === 'undefined') {
2632                 break;
2633             }
2634             list.push(statement);
2635         }
2636
2637         return list;
2638     }
2639
2640     function parseBlock() {
2641         var block, startToken;
2642
2643         startToken = lookahead;
2644         expect('{');
2645
2646         block = parseStatementList();
2647
2648         expect('}');
2649
2650         return delegate.markEnd(delegate.createBlockStatement(block), startToken);
2651     }
2652
2653     // 12.2 Variable Statement
2654
2655     function parseVariableIdentifier() {
2656         var token, startToken;
2657
2658         startToken = lookahead;
2659         token = lex();
2660
2661         if (token.type !== Token.Identifier) {
2662             throwUnexpected(token);
2663         }
2664
2665         return delegate.markEnd(delegate.createIdentifier(token.value), startToken);
2666     }
2667
2668     function parseVariableDeclaration(kind) {
2669         var init = null, id, startToken;
2670
2671         startToken = lookahead;
2672         id = parseVariableIdentifier();
2673
2674         // 12.2.1
2675         if (strict && isRestrictedWord(id.name)) {
2676             throwErrorTolerant({}, Messages.StrictVarName);
2677         }
2678
2679         if (kind === 'const') {
2680             expect('=');
2681             init = parseAssignmentExpression();
2682         } else if (match('=')) {
2683             lex();
2684             init = parseAssignmentExpression();
2685         }
2686
2687         return delegate.markEnd(delegate.createVariableDeclarator(id, init), startToken);
2688     }
2689
2690     function parseVariableDeclarationList(kind) {
2691         var list = [];
2692
2693         do {
2694             list.push(parseVariableDeclaration(kind));
2695             if (!match(',')) {
2696                 break;
2697             }
2698             lex();
2699         } while (index < length);
2700
2701         return list;
2702     }
2703
2704     function parseVariableStatement() {
2705         var declarations;
2706
2707         expectKeyword('var');
2708
2709         declarations = parseVariableDeclarationList();
2710
2711         consumeSemicolon();
2712
2713         return delegate.createVariableDeclaration(declarations, 'var');
2714     }
2715
2716     // kind may be `const` or `let`
2717     // Both are experimental and not in the specification yet.
2718     // see http://wiki.ecmascript.org/doku.php?id=harmony:const
2719     // and http://wiki.ecmascript.org/doku.php?id=harmony:let
2720     function parseConstLetDeclaration(kind) {
2721         var declarations, startToken;
2722
2723         startToken = lookahead;
2724
2725         expectKeyword(kind);
2726
2727         declarations = parseVariableDeclarationList(kind);
2728
2729         consumeSemicolon();
2730
2731         return delegate.markEnd(delegate.createVariableDeclaration(declarations, kind), startToken);
2732     }
2733
2734     // 12.3 Empty Statement
2735
2736     function parseEmptyStatement() {
2737         expect(';');
2738         return delegate.createEmptyStatement();
2739     }
2740
2741     // 12.4 Expression Statement
2742
2743     function parseExpressionStatement() {
2744         var expr = parseExpression();
2745         consumeSemicolon();
2746         return delegate.createExpressionStatement(expr);
2747     }
2748
2749     // 12.5 If statement
2750
2751     function parseIfStatement() {
2752         var test, consequent, alternate;
2753
2754         expectKeyword('if');
2755
2756         expect('(');
2757
2758         test = parseExpression();
2759
2760         expect(')');
2761
2762         consequent = parseStatement();
2763
2764         if (matchKeyword('else')) {
2765             lex();
2766             alternate = parseStatement();
2767         } else {
2768             alternate = null;
2769         }
2770
2771         return delegate.createIfStatement(test, consequent, alternate);
2772     }
2773
2774     // 12.6 Iteration Statements
2775
2776     function parseDoWhileStatement() {
2777         var body, test, oldInIteration;
2778
2779         expectKeyword('do');
2780
2781         oldInIteration = state.inIteration;
2782         state.inIteration = true;
2783
2784         body = parseStatement();
2785
2786         state.inIteration = oldInIteration;
2787
2788         expectKeyword('while');
2789
2790         expect('(');
2791
2792         test = parseExpression();
2793
2794         expect(')');
2795
2796         if (match(';')) {
2797             lex();
2798         }
2799
2800         return delegate.createDoWhileStatement(body, test);
2801     }
2802
2803     function parseWhileStatement() {
2804         var test, body, oldInIteration;
2805
2806         expectKeyword('while');
2807
2808         expect('(');
2809
2810         test = parseExpression();
2811
2812         expect(')');
2813
2814         oldInIteration = state.inIteration;
2815         state.inIteration = true;
2816
2817         body = parseStatement();
2818
2819         state.inIteration = oldInIteration;
2820
2821         return delegate.createWhileStatement(test, body);
2822     }
2823
2824     function parseForVariableDeclaration() {
2825         var token, declarations, startToken;
2826
2827         startToken = lookahead;
2828         token = lex();
2829         declarations = parseVariableDeclarationList();
2830
2831         return delegate.markEnd(delegate.createVariableDeclaration(declarations, token.value), startToken);
2832     }
2833
2834     function parseForStatement() {
2835         var init, test, update, left, right, body, oldInIteration, previousAllowIn = state.allowIn;
2836
2837         init = test = update = null;
2838
2839         expectKeyword('for');
2840
2841         expect('(');
2842
2843         if (match(';')) {
2844             lex();
2845         } else {
2846             if (matchKeyword('var') || matchKeyword('let')) {
2847                 state.allowIn = false;
2848                 init = parseForVariableDeclaration();
2849                 state.allowIn = previousAllowIn;
2850
2851                 if (init.declarations.length === 1 && matchKeyword('in')) {
2852                     lex();
2853                     left = init;
2854                     right = parseExpression();
2855                     init = null;
2856                 }
2857             } else {
2858                 state.allowIn = false;
2859                 init = parseExpression();
2860                 state.allowIn = previousAllowIn;
2861
2862                 if (matchKeyword('in')) {
2863                     // LeftHandSideExpression
2864                     if (!isLeftHandSide(init)) {
2865                         throwErrorTolerant({}, Messages.InvalidLHSInForIn);
2866                     }
2867
2868                     lex();
2869                     left = init;
2870                     right = parseExpression();
2871                     init = null;
2872                 }
2873             }
2874
2875             if (typeof left === 'undefined') {
2876                 expect(';');
2877             }
2878         }
2879
2880         if (typeof left === 'undefined') {
2881
2882             if (!match(';')) {
2883                 test = parseExpression();
2884             }
2885             expect(';');
2886
2887             if (!match(')')) {
2888                 update = parseExpression();
2889             }
2890         }
2891
2892         expect(')');
2893
2894         oldInIteration = state.inIteration;
2895         state.inIteration = true;
2896
2897         body = parseStatement();
2898
2899         state.inIteration = oldInIteration;
2900
2901         return (typeof left === 'undefined') ?
2902                 delegate.createForStatement(init, test, update, body) :
2903                 delegate.createForInStatement(left, right, body);
2904     }
2905
2906     // 12.7 The continue statement
2907
2908     function parseContinueStatement() {
2909         var label = null, key;
2910
2911         expectKeyword('continue');
2912
2913         // Optimize the most common form: 'continue;'.
2914         if (source.charCodeAt(index) === 0x3B) {
2915             lex();
2916
2917             if (!state.inIteration) {
2918                 throwError({}, Messages.IllegalContinue);
2919             }
2920
2921             return delegate.createContinueStatement(null);
2922         }
2923
2924         if (peekLineTerminator()) {
2925             if (!state.inIteration) {
2926                 throwError({}, Messages.IllegalContinue);
2927             }
2928
2929             return delegate.createContinueStatement(null);
2930         }
2931
2932         if (lookahead.type === Token.Identifier) {
2933             label = parseVariableIdentifier();
2934
2935             key = '$' + label.name;
2936             if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
2937                 throwError({}, Messages.UnknownLabel, label.name);
2938             }
2939         }
2940
2941         consumeSemicolon();
2942
2943         if (label === null && !state.inIteration) {
2944             throwError({}, Messages.IllegalContinue);
2945         }
2946
2947         return delegate.createContinueStatement(label);
2948     }
2949
2950     // 12.8 The break statement
2951
2952     function parseBreakStatement() {
2953         var label = null, key;
2954
2955         expectKeyword('break');
2956
2957         // Catch the very common case first: immediately a semicolon (U+003B).
2958         if (source.charCodeAt(index) === 0x3B) {
2959             lex();
2960
2961             if (!(state.inIteration || state.inSwitch)) {
2962                 throwError({}, Messages.IllegalBreak);
2963             }
2964
2965             return delegate.createBreakStatement(null);
2966         }
2967
2968         if (peekLineTerminator()) {
2969             if (!(state.inIteration || state.inSwitch)) {
2970                 throwError({}, Messages.IllegalBreak);
2971             }
2972
2973             return delegate.createBreakStatement(null);
2974         }
2975
2976         if (lookahead.type === Token.Identifier) {
2977             label = parseVariableIdentifier();
2978
2979             key = '$' + label.name;
2980             if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
2981                 throwError({}, Messages.UnknownLabel, label.name);
2982             }
2983         }
2984
2985         consumeSemicolon();
2986
2987         if (label === null && !(state.inIteration || state.inSwitch)) {
2988             throwError({}, Messages.IllegalBreak);
2989         }
2990
2991         return delegate.createBreakStatement(label);
2992     }
2993
2994     // 12.9 The return statement
2995
2996     function parseReturnStatement() {
2997         var argument = null;
2998
2999         expectKeyword('return');
3000
3001         if (!state.inFunctionBody) {
3002             throwErrorTolerant({}, Messages.IllegalReturn);
3003         }
3004
3005         // 'return' followed by a space and an identifier is very common.
3006         if (source.charCodeAt(index) === 0x20) {
3007             if (isIdentifierStart(source.charCodeAt(index + 1))) {
3008                 argument = parseExpression();
3009                 consumeSemicolon();
3010                 return delegate.createReturnStatement(argument);
3011             }
3012         }
3013
3014         if (peekLineTerminator()) {
3015             return delegate.createReturnStatement(null);
3016         }
3017
3018         if (!match(';')) {
3019             if (!match('}') && lookahead.type !== Token.EOF) {
3020                 argument = parseExpression();
3021             }
3022         }
3023
3024         consumeSemicolon();
3025
3026         return delegate.createReturnStatement(argument);
3027     }
3028
3029     // 12.10 The with statement
3030
3031     function parseWithStatement() {
3032         var object, body;
3033
3034         if (strict) {
3035             // TODO(ikarienator): Should we update the test cases instead?
3036             skipComment();
3037             throwErrorTolerant({}, Messages.StrictModeWith);
3038         }
3039
3040         expectKeyword('with');
3041
3042         expect('(');
3043
3044         object = parseExpression();
3045
3046         expect(')');
3047
3048         body = parseStatement();
3049
3050         return delegate.createWithStatement(object, body);
3051     }
3052
3053     // 12.10 The swith statement
3054
3055     function parseSwitchCase() {
3056         var test, consequent = [], statement, startToken;
3057
3058         startToken = lookahead;
3059         if (matchKeyword('default')) {
3060             lex();
3061             test = null;
3062         } else {
3063             expectKeyword('case');
3064             test = parseExpression();
3065         }
3066         expect(':');
3067
3068         while (index < length) {
3069             if (match('}') || matchKeyword('default') || matchKeyword('case')) {
3070                 break;
3071             }
3072             statement = parseStatement();
3073             consequent.push(statement);
3074         }
3075
3076         return delegate.markEnd(delegate.createSwitchCase(test, consequent), startToken);
3077     }
3078
3079     function parseSwitchStatement() {
3080         var discriminant, cases, clause, oldInSwitch, defaultFound;
3081
3082         expectKeyword('switch');
3083
3084         expect('(');
3085
3086         discriminant = parseExpression();
3087
3088         expect(')');
3089
3090         expect('{');
3091
3092         cases = [];
3093
3094         if (match('}')) {
3095             lex();
3096             return delegate.createSwitchStatement(discriminant, cases);
3097         }
3098
3099         oldInSwitch = state.inSwitch;
3100         state.inSwitch = true;
3101         defaultFound = false;
3102
3103         while (index < length) {
3104             if (match('}')) {
3105                 break;
3106             }
3107             clause = parseSwitchCase();
3108             if (clause.test === null) {
3109                 if (defaultFound) {
3110                     throwError({}, Messages.MultipleDefaultsInSwitch);
3111                 }
3112                 defaultFound = true;
3113             }
3114             cases.push(clause);
3115         }
3116
3117         state.inSwitch = oldInSwitch;
3118
3119         expect('}');
3120
3121         return delegate.createSwitchStatement(discriminant, cases);
3122     }
3123
3124     // 12.13 The throw statement
3125
3126     function parseThrowStatement() {
3127         var argument;
3128
3129         expectKeyword('throw');
3130
3131         if (peekLineTerminator()) {
3132             throwError({}, Messages.NewlineAfterThrow);
3133         }
3134
3135         argument = parseExpression();
3136
3137         consumeSemicolon();
3138
3139         return delegate.createThrowStatement(argument);
3140     }
3141
3142     // 12.14 The try statement
3143
3144     function parseCatchClause() {
3145         var param, body, startToken;
3146
3147         startToken = lookahead;
3148         expectKeyword('catch');
3149
3150         expect('(');
3151         if (match(')')) {
3152             throwUnexpected(lookahead);
3153         }
3154
3155         param = parseVariableIdentifier();
3156         // 12.14.1
3157         if (strict && isRestrictedWord(param.name)) {
3158             throwErrorTolerant({}, Messages.StrictCatchVariable);
3159         }
3160
3161         expect(')');
3162         body = parseBlock();
3163         return delegate.markEnd(delegate.createCatchClause(param, body), startToken);
3164     }
3165
3166     function parseTryStatement() {
3167         var block, handlers = [], finalizer = null;
3168
3169         expectKeyword('try');
3170
3171         block = parseBlock();
3172
3173         if (matchKeyword('catch')) {
3174             handlers.push(parseCatchClause());
3175         }
3176
3177         if (matchKeyword('finally')) {
3178             lex();
3179             finalizer = parseBlock();
3180         }
3181
3182         if (handlers.length === 0 && !finalizer) {
3183             throwError({}, Messages.NoCatchOrFinally);
3184         }
3185
3186         return delegate.createTryStatement(block, [], handlers, finalizer);
3187     }
3188
3189     // 12.15 The debugger statement
3190
3191     function parseDebuggerStatement() {
3192         expectKeyword('debugger');
3193
3194         consumeSemicolon();
3195
3196         return delegate.createDebuggerStatement();
3197     }
3198
3199     // 12 Statements
3200
3201     function parseStatement() {
3202         var type = lookahead.type,
3203             expr,
3204             labeledBody,
3205             key,
3206             startToken;
3207
3208         if (type === Token.EOF) {
3209             throwUnexpected(lookahead);
3210         }
3211
3212         if (type === Token.Punctuator && lookahead.value === '{') {
3213             return parseBlock();
3214         }
3215
3216         startToken = lookahead;
3217
3218         if (type === Token.Punctuator) {
3219             switch (lookahead.value) {
3220             case ';':
3221                 return delegate.markEnd(parseEmptyStatement(), startToken);
3222             case '(':
3223                 return delegate.markEnd(parseExpressionStatement(), startToken);
3224             default:
3225                 break;
3226             }
3227         }
3228
3229         if (type === Token.Keyword) {
3230             switch (lookahead.value) {
3231             case 'break':
3232                 return delegate.markEnd(parseBreakStatement(), startToken);
3233             case 'continue':
3234                 return delegate.markEnd(parseContinueStatement(), startToken);
3235             case 'debugger':
3236                 return delegate.markEnd(parseDebuggerStatement(), startToken);
3237             case 'do':
3238                 return delegate.markEnd(parseDoWhileStatement(), startToken);
3239             case 'for':
3240                 return delegate.markEnd(parseForStatement(), startToken);
3241             case 'function':
3242                 return delegate.markEnd(parseFunctionDeclaration(), startToken);
3243             case 'if':
3244                 return delegate.markEnd(parseIfStatement(), startToken);
3245             case 'return':
3246                 return delegate.markEnd(parseReturnStatement(), startToken);
3247             case 'switch':
3248                 return delegate.markEnd(parseSwitchStatement(), startToken);
3249             case 'throw':
3250                 return delegate.markEnd(parseThrowStatement(), startToken);
3251             case 'try':
3252                 return delegate.markEnd(parseTryStatement(), startToken);
3253             case 'var':
3254                 return delegate.markEnd(parseVariableStatement(), startToken);
3255             case 'while':
3256                 return delegate.markEnd(parseWhileStatement(), startToken);
3257             case 'with':
3258                 return delegate.markEnd(parseWithStatement(), startToken);
3259             default:
3260                 break;
3261             }
3262         }
3263
3264         expr = parseExpression();
3265
3266         // 12.12 Labelled Statements
3267         if ((expr.type === Syntax.Identifier) && match(':')) {
3268             lex();
3269
3270             key = '$' + expr.name;
3271             if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
3272                 throwError({}, Messages.Redeclaration, 'Label', expr.name);
3273             }
3274
3275             state.labelSet[key] = true;
3276             labeledBody = parseStatement();
3277             delete state.labelSet[key];
3278             return delegate.markEnd(delegate.createLabeledStatement(expr, labeledBody), startToken);
3279         }
3280
3281         consumeSemicolon();
3282
3283         return delegate.markEnd(delegate.createExpressionStatement(expr), startToken);
3284     }
3285
3286     // 13 Function Definition
3287
3288     function parseFunctionSourceElements() {
3289         var sourceElement, sourceElements = [], token, directive, firstRestricted,
3290             oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, startToken;
3291
3292         startToken = lookahead;
3293         expect('{');
3294
3295         while (index < length) {
3296             if (lookahead.type !== Token.StringLiteral) {
3297                 break;
3298             }
3299             token = lookahead;
3300
3301             sourceElement = parseSourceElement();
3302             sourceElements.push(sourceElement);
3303             if (sourceElement.expression.type !== Syntax.Literal) {
3304                 // this is not directive
3305                 break;
3306             }
3307             directive = source.slice(token.start + 1, token.end - 1);
3308             if (directive === 'use strict') {
3309                 strict = true;
3310                 if (firstRestricted) {
3311                     throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
3312                 }
3313             } else {
3314                 if (!firstRestricted && token.octal) {
3315                     firstRestricted = token;
3316                 }
3317             }
3318         }
3319
3320         oldLabelSet = state.labelSet;
3321         oldInIteration = state.inIteration;
3322         oldInSwitch = state.inSwitch;
3323         oldInFunctionBody = state.inFunctionBody;
3324
3325         state.labelSet = {};
3326         state.inIteration = false;
3327         state.inSwitch = false;
3328         state.inFunctionBody = true;
3329
3330         while (index < length) {
3331             if (match('}')) {
3332                 break;
3333             }
3334             sourceElement = parseSourceElement();
3335             if (typeof sourceElement === 'undefined') {
3336                 break;
3337             }
3338             sourceElements.push(sourceElement);
3339         }
3340
3341         expect('}');
3342
3343         state.labelSet = oldLabelSet;
3344         state.inIteration = oldInIteration;
3345         state.inSwitch = oldInSwitch;
3346         state.inFunctionBody = oldInFunctionBody;
3347
3348         return delegate.markEnd(delegate.createBlockStatement(sourceElements), startToken);
3349     }
3350
3351     function parseParams(firstRestricted) {
3352         var param, params = [], token, stricted, paramSet, key, message;
3353         expect('(');
3354
3355         if (!match(')')) {
3356             paramSet = {};
3357             while (index < length) {
3358                 token = lookahead;
3359                 param = parseVariableIdentifier();
3360                 key = '$' + token.value;
3361                 if (strict) {
3362                     if (isRestrictedWord(token.value)) {
3363                         stricted = token;
3364                         message = Messages.StrictParamName;
3365                     }
3366                     if (Object.prototype.hasOwnProperty.call(paramSet, key)) {
3367                         stricted = token;
3368                         message = Messages.StrictParamDupe;
3369                     }
3370                 } else if (!firstRestricted) {
3371                     if (isRestrictedWord(token.value)) {
3372                         firstRestricted = token;
3373                         message = Messages.StrictParamName;
3374                     } else if (isStrictModeReservedWord(token.value)) {
3375                         firstRestricted = token;
3376                         message = Messages.StrictReservedWord;
3377                     } else if (Object.prototype.hasOwnProperty.call(paramSet, key)) {
3378                         firstRestricted = token;
3379                         message = Messages.StrictParamDupe;
3380                     }
3381                 }
3382                 params.push(param);
3383                 paramSet[key] = true;
3384                 if (match(')')) {
3385                     break;
3386                 }
3387                 expect(',');
3388             }
3389         }
3390
3391         expect(')');
3392
3393         return {
3394             params: params,
3395             stricted: stricted,
3396             firstRestricted: firstRestricted,
3397             message: message
3398         };
3399     }
3400
3401     function parseFunctionDeclaration() {
3402         var id, params = [], body, token, stricted, tmp, firstRestricted, message, previousStrict, startToken;
3403
3404         startToken = lookahead;
3405
3406         expectKeyword('function');
3407         token = lookahead;
3408         id = parseVariableIdentifier();
3409         if (strict) {
3410             if (isRestrictedWord(token.value)) {
3411                 throwErrorTolerant(token, Messages.StrictFunctionName);
3412             }
3413         } else {
3414             if (isRestrictedWord(token.value)) {
3415                 firstRestricted = token;
3416                 message = Messages.StrictFunctionName;
3417             } else if (isStrictModeReservedWord(token.value)) {
3418                 firstRestricted = token;
3419                 message = Messages.StrictReservedWord;
3420             }
3421         }
3422
3423         tmp = parseParams(firstRestricted);
3424         params = tmp.params;
3425         stricted = tmp.stricted;
3426         firstRestricted = tmp.firstRestricted;
3427         if (tmp.message) {
3428             message = tmp.message;
3429         }
3430
3431         previousStrict = strict;
3432         body = parseFunctionSourceElements();
3433         if (strict && firstRestricted) {
3434             throwError(firstRestricted, message);
3435         }
3436         if (strict && stricted) {
3437             throwErrorTolerant(stricted, message);
3438         }
3439         strict = previousStrict;
3440
3441         return delegate.markEnd(delegate.createFunctionDeclaration(id, params, [], body), startToken);
3442     }
3443
3444     function parseFunctionExpression() {
3445         var token, id = null, stricted, firstRestricted, message, tmp, params = [], body, previousStrict, startToken;
3446
3447         startToken = lookahead;
3448         expectKeyword('function');
3449
3450         if (!match('(')) {
3451             token = lookahead;
3452             id = parseVariableIdentifier();
3453             if (strict) {
3454                 if (isRestrictedWord(token.value)) {
3455                     throwErrorTolerant(token, Messages.StrictFunctionName);
3456                 }
3457             } else {
3458                 if (isRestrictedWord(token.value)) {
3459                     firstRestricted = token;
3460                     message = Messages.StrictFunctionName;
3461                 } else if (isStrictModeReservedWord(token.value)) {
3462                     firstRestricted = token;
3463                     message = Messages.StrictReservedWord;
3464                 }
3465             }
3466         }
3467
3468         tmp = parseParams(firstRestricted);
3469         params = tmp.params;
3470         stricted = tmp.stricted;
3471         firstRestricted = tmp.firstRestricted;
3472         if (tmp.message) {
3473             message = tmp.message;
3474         }
3475
3476         previousStrict = strict;
3477         body = parseFunctionSourceElements();
3478         if (strict && firstRestricted) {
3479             throwError(firstRestricted, message);
3480         }
3481         if (strict && stricted) {
3482             throwErrorTolerant(stricted, message);
3483         }
3484         strict = previousStrict;
3485
3486         return delegate.markEnd(delegate.createFunctionExpression(id, params, [], body), startToken);
3487     }
3488
3489     // 14 Program
3490
3491     function parseSourceElement() {
3492         if (lookahead.type === Token.Keyword) {
3493             switch (lookahead.value) {
3494             case 'const':
3495             case 'let':
3496                 return parseConstLetDeclaration(lookahead.value);
3497             case 'function':
3498                 return parseFunctionDeclaration();
3499             default:
3500                 return parseStatement();
3501             }
3502         }
3503
3504         if (lookahead.type !== Token.EOF) {
3505             return parseStatement();
3506         }
3507     }
3508
3509     function parseSourceElements() {
3510         var sourceElement, sourceElements = [], token, directive, firstRestricted;
3511
3512         while (index < length) {
3513             token = lookahead;
3514             if (token.type !== Token.StringLiteral) {
3515                 break;
3516             }
3517
3518             sourceElement = parseSourceElement();
3519             sourceElements.push(sourceElement);
3520             if (sourceElement.expression.type !== Syntax.Literal) {
3521                 // this is not directive
3522                 break;
3523             }
3524             directive = source.slice(token.start + 1, token.end - 1);
3525             if (directive === 'use strict') {
3526                 strict = true;
3527                 if (firstRestricted) {
3528                     throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
3529                 }
3530             } else {
3531                 if (!firstRestricted && token.octal) {
3532                     firstRestricted = token;
3533                 }
3534             }
3535         }
3536
3537         while (index < length) {
3538             sourceElement = parseSourceElement();
3539             /* istanbul ignore if */
3540             if (typeof sourceElement === 'undefined') {
3541                 break;
3542             }
3543             sourceElements.push(sourceElement);
3544         }
3545         return sourceElements;
3546     }
3547
3548     function parseProgram() {
3549         var body, startToken;
3550
3551         skipComment();
3552         peek();
3553         startToken = lookahead;
3554         strict = false;
3555
3556         body = parseSourceElements();
3557         return delegate.markEnd(delegate.createProgram(body), startToken);
3558     }
3559
3560     function filterTokenLocation() {
3561         var i, entry, token, tokens = [];
3562
3563         for (i = 0; i < extra.tokens.length; ++i) {
3564             entry = extra.tokens[i];
3565             token = {
3566                 type: entry.type,
3567                 value: entry.value
3568             };
3569             if (extra.range) {
3570                 token.range = entry.range;
3571             }
3572             if (extra.loc) {
3573                 token.loc = entry.loc;
3574             }
3575             tokens.push(token);
3576         }
3577
3578         extra.tokens = tokens;
3579     }
3580
3581     function tokenize(code, options) {
3582         var toString,
3583             token,
3584             tokens;
3585
3586         toString = String;
3587         if (typeof code !== 'string' && !(code instanceof String)) {
3588             code = toString(code);
3589         }
3590
3591         delegate = SyntaxTreeDelegate;
3592         source = code;
3593         index = 0;
3594         lineNumber = (source.length > 0) ? 1 : 0;
3595         lineStart = 0;
3596         length = source.length;
3597         lookahead = null;
3598         state = {
3599             allowIn: true,
3600             labelSet: {},
3601             inFunctionBody: false,
3602             inIteration: false,
3603             inSwitch: false,
3604             lastCommentStart: -1
3605         };
3606
3607         extra = {};
3608
3609         // Options matching.
3610         options = options || {};
3611
3612         // Of course we collect tokens here.
3613         options.tokens = true;
3614         extra.tokens = [];
3615         extra.tokenize = true;
3616         // The following two fields are necessary to compute the Regex tokens.
3617         extra.openParenToken = -1;
3618         extra.openCurlyToken = -1;
3619
3620         extra.range = (typeof options.range === 'boolean') && options.range;
3621         extra.loc = (typeof options.loc === 'boolean') && options.loc;
3622
3623         if (typeof options.comment === 'boolean' && options.comment) {
3624             extra.comments = [];
3625         }
3626         if (typeof options.tolerant === 'boolean' && options.tolerant) {
3627             extra.errors = [];
3628         }
3629
3630         try {
3631             peek();
3632             if (lookahead.type === Token.EOF) {
3633                 return extra.tokens;
3634             }
3635
3636             token = lex();
3637             while (lookahead.type !== Token.EOF) {
3638                 try {
3639                     token = lex();
3640                 } catch (lexError) {
3641                     token = lookahead;
3642                     if (extra.errors) {
3643                         extra.errors.push(lexError);
3644                         // We have to break on the first error
3645                         // to avoid infinite loops.
3646                         break;
3647                     } else {
3648                         throw lexError;
3649                     }
3650                 }
3651             }
3652
3653             filterTokenLocation();
3654             tokens = extra.tokens;
3655             if (typeof extra.comments !== 'undefined') {
3656                 tokens.comments = extra.comments;
3657             }
3658             if (typeof extra.errors !== 'undefined') {
3659                 tokens.errors = extra.errors;
3660             }
3661         } catch (e) {
3662             throw e;
3663         } finally {
3664             extra = {};
3665         }
3666         return tokens;
3667     }
3668
3669     function parse(code, options) {
3670         var program, toString;
3671
3672         toString = String;
3673         if (typeof code !== 'string' && !(code instanceof String)) {
3674             code = toString(code);
3675         }
3676
3677         delegate = SyntaxTreeDelegate;
3678         source = code;
3679         index = 0;
3680         lineNumber = (source.length > 0) ? 1 : 0;
3681         lineStart = 0;
3682         length = source.length;
3683         lookahead = null;
3684         state = {
3685             allowIn: true,
3686             labelSet: {},
3687             inFunctionBody: false,
3688             inIteration: false,
3689             inSwitch: false,
3690             lastCommentStart: -1
3691         };
3692
3693         extra = {};
3694         if (typeof options !== 'undefined') {
3695             extra.range = (typeof options.range === 'boolean') && options.range;
3696             extra.loc = (typeof options.loc === 'boolean') && options.loc;
3697             extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment;
3698
3699             if (extra.loc && options.source !== null && options.source !== undefined) {
3700                 extra.source = toString(options.source);
3701             }
3702
3703             if (typeof options.tokens === 'boolean' && options.tokens) {
3704                 extra.tokens = [];
3705             }
3706             if (typeof options.comment === 'boolean' && options.comment) {
3707                 extra.comments = [];
3708             }
3709             if (typeof options.tolerant === 'boolean' && options.tolerant) {
3710                 extra.errors = [];
3711             }
3712             if (extra.attachComment) {
3713                 extra.range = true;
3714                 extra.comments = [];
3715                 extra.bottomRightStack = [];
3716                 extra.trailingComments = [];
3717                 extra.leadingComments = [];
3718             }
3719         }
3720
3721         try {
3722             program = parseProgram();
3723             if (typeof extra.comments !== 'undefined') {
3724                 program.comments = extra.comments;
3725             }
3726             if (typeof extra.tokens !== 'undefined') {
3727                 filterTokenLocation();
3728                 program.tokens = extra.tokens;
3729             }
3730             if (typeof extra.errors !== 'undefined') {
3731                 program.errors = extra.errors;
3732             }
3733         } catch (e) {
3734             throw e;
3735         } finally {
3736             extra = {};
3737         }
3738
3739         return program;
3740     }
3741
3742     // Sync with *.json manifests.
3743     exports.version = '1.2.5';
3744
3745     exports.tokenize = tokenize;
3746
3747     exports.parse = parse;
3748
3749     // Deep copy.
3750    /* istanbul ignore next */
3751     exports.Syntax = (function () {
3752         var name, types = {};
3753
3754         if (typeof Object.create === 'function') {
3755             types = Object.create(null);
3756         }
3757
3758         for (name in Syntax) {
3759             if (Syntax.hasOwnProperty(name)) {
3760                 types[name] = Syntax[name];
3761             }
3762         }
3763
3764         if (typeof Object.freeze === 'function') {
3765             Object.freeze(types);
3766         }
3767
3768         return types;
3769     }());
3770
3771 }));
3772 /* vim: set sw=4 ts=4 et tw=80 : */