DoYouEvenBench: Add Facebook's React TodoMVC test case
[WebKit-https.git] / PerformanceTests / DoYouEvenBench / todomvc / labs / architecture-examples / react / bower_components / react / JSXTransformer.js
1 /**
2  * JSXTransformer v0.4.0
3  */
4 (function(e){if("function"==typeof bootstrap)bootstrap("jsxtransformer",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeJSXTransformer=e}else"undefined"!=typeof window?window.JSXTransformer=e():global.JSXTransformer=e()})(function(){var define,ses,bootstrap,module,exports;
5 return (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
6 var Base62 = (function (my) {
7   my.chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
8
9   my.encode = function(i){
10     if (i === 0) {return '0'}
11     var s = ''
12     while (i > 0) {
13       s = this.chars[i % 62] + s
14       i = Math.floor(i/62)
15     }
16     return s
17   };
18   my.decode = function(a,b,c,d){
19     for (
20       b = c = (
21         a === (/\W|_|^$/.test(a += "") || a)
22       ) - 1;
23       d = a.charCodeAt(c++);
24     )
25     b = b * 62 + d - [, 48, 29, 87][d >> 5];
26     return b
27   };
28
29   return my;
30 }({}));
31
32 module.exports = Base62
33 },{}],2:[function(require,module,exports){
34 (function(process){function filter (xs, fn) {
35     var res = [];
36     for (var i = 0; i < xs.length; i++) {
37         if (fn(xs[i], i, xs)) res.push(xs[i]);
38     }
39     return res;
40 }
41
42 // resolves . and .. elements in a path array with directory names there
43 // must be no slashes, empty elements, or device names (c:\) in the array
44 // (so also no leading and trailing slashes - it does not distinguish
45 // relative and absolute paths)
46 function normalizeArray(parts, allowAboveRoot) {
47   // if the path tries to go above the root, `up` ends up > 0
48   var up = 0;
49   for (var i = parts.length; i >= 0; i--) {
50     var last = parts[i];
51     if (last == '.') {
52       parts.splice(i, 1);
53     } else if (last === '..') {
54       parts.splice(i, 1);
55       up++;
56     } else if (up) {
57       parts.splice(i, 1);
58       up--;
59     }
60   }
61
62   // if the path is allowed to go above the root, restore leading ..s
63   if (allowAboveRoot) {
64     for (; up--; up) {
65       parts.unshift('..');
66     }
67   }
68
69   return parts;
70 }
71
72 // Regex to split a filename into [*, dir, basename, ext]
73 // posix version
74 var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
75
76 // path.resolve([from ...], to)
77 // posix version
78 exports.resolve = function() {
79 var resolvedPath = '',
80     resolvedAbsolute = false;
81
82 for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
83   var path = (i >= 0)
84       ? arguments[i]
85       : process.cwd();
86
87   // Skip empty and invalid entries
88   if (typeof path !== 'string' || !path) {
89     continue;
90   }
91
92   resolvedPath = path + '/' + resolvedPath;
93   resolvedAbsolute = path.charAt(0) === '/';
94 }
95
96 // At this point the path should be resolved to a full absolute path, but
97 // handle relative paths to be safe (might happen when process.cwd() fails)
98
99 // Normalize the path
100 resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
101     return !!p;
102   }), !resolvedAbsolute).join('/');
103
104   return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
105 };
106
107 // path.normalize(path)
108 // posix version
109 exports.normalize = function(path) {
110 var isAbsolute = path.charAt(0) === '/',
111     trailingSlash = path.slice(-1) === '/';
112
113 // Normalize the path
114 path = normalizeArray(filter(path.split('/'), function(p) {
115     return !!p;
116   }), !isAbsolute).join('/');
117
118   if (!path && !isAbsolute) {
119     path = '.';
120   }
121   if (path && trailingSlash) {
122     path += '/';
123   }
124   
125   return (isAbsolute ? '/' : '') + path;
126 };
127
128
129 // posix version
130 exports.join = function() {
131   var paths = Array.prototype.slice.call(arguments, 0);
132   return exports.normalize(filter(paths, function(p, index) {
133     return p && typeof p === 'string';
134   }).join('/'));
135 };
136
137
138 exports.dirname = function(path) {
139   var dir = splitPathRe.exec(path)[1] || '';
140   var isWindows = false;
141   if (!dir) {
142     // No dirname
143     return '.';
144   } else if (dir.length === 1 ||
145       (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
146     // It is just a slash or a drive letter with a slash
147     return dir;
148   } else {
149     // It is a full dirname, strip trailing slash
150     return dir.substring(0, dir.length - 1);
151   }
152 };
153
154
155 exports.basename = function(path, ext) {
156   var f = splitPathRe.exec(path)[2] || '';
157   // TODO: make this comparison case-insensitive on windows?
158   if (ext && f.substr(-1 * ext.length) === ext) {
159     f = f.substr(0, f.length - ext.length);
160   }
161   return f;
162 };
163
164
165 exports.extname = function(path) {
166   return splitPathRe.exec(path)[3] || '';
167 };
168
169 exports.relative = function(from, to) {
170   from = exports.resolve(from).substr(1);
171   to = exports.resolve(to).substr(1);
172
173   function trim(arr) {
174     var start = 0;
175     for (; start < arr.length; start++) {
176       if (arr[start] !== '') break;
177     }
178
179     var end = arr.length - 1;
180     for (; end >= 0; end--) {
181       if (arr[end] !== '') break;
182     }
183
184     if (start > end) return [];
185     return arr.slice(start, end - start + 1);
186   }
187
188   var fromParts = trim(from.split('/'));
189   var toParts = trim(to.split('/'));
190
191   var length = Math.min(fromParts.length, toParts.length);
192   var samePartsLength = length;
193   for (var i = 0; i < length; i++) {
194     if (fromParts[i] !== toParts[i]) {
195       samePartsLength = i;
196       break;
197     }
198   }
199
200   var outputParts = [];
201   for (var i = samePartsLength; i < fromParts.length; i++) {
202     outputParts.push('..');
203   }
204
205   outputParts = outputParts.concat(toParts.slice(samePartsLength));
206
207   return outputParts.join('/');
208 };
209
210 })(require("__browserify_process"))
211 },{"__browserify_process":3}],3:[function(require,module,exports){
212 // shim for using process in browser
213
214 var process = module.exports = {};
215
216 process.nextTick = (function () {
217     var canSetImmediate = typeof window !== 'undefined'
218     && window.setImmediate;
219     var canPost = typeof window !== 'undefined'
220     && window.postMessage && window.addEventListener
221     ;
222
223     if (canSetImmediate) {
224         return function (f) { return window.setImmediate(f) };
225     }
226
227     if (canPost) {
228         var queue = [];
229         window.addEventListener('message', function (ev) {
230             if (ev.source === window && ev.data === 'process-tick') {
231                 ev.stopPropagation();
232                 if (queue.length > 0) {
233                     var fn = queue.shift();
234                     fn();
235                 }
236             }
237         }, true);
238
239         return function nextTick(fn) {
240             queue.push(fn);
241             window.postMessage('process-tick', '*');
242         };
243     }
244
245     return function nextTick(fn) {
246         setTimeout(fn, 0);
247     };
248 })();
249
250 process.title = 'browser';
251 process.browser = true;
252 process.env = {};
253 process.argv = [];
254
255 process.binding = function (name) {
256     throw new Error('process.binding is not supported');
257 }
258
259 // TODO(shtylman)
260 process.cwd = function () { return '/' };
261 process.chdir = function (dir) {
262     throw new Error('process.chdir is not supported');
263 };
264
265 },{}],4:[function(require,module,exports){
266 (function(){/*
267   Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
268   Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
269   Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
270   Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
271   Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
272   Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
273   Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
274   Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
275
276   Redistribution and use in source and binary forms, with or without
277   modification, are permitted provided that the following conditions are met:
278
279     * Redistributions of source code must retain the above copyright
280       notice, this list of conditions and the following disclaimer.
281     * Redistributions in binary form must reproduce the above copyright
282       notice, this list of conditions and the following disclaimer in the
283       documentation and/or other materials provided with the distribution.
284
285   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
286   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
287   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
288   ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
289   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
290   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
291   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
292   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
293   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
294   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295 */
296
297 /*jslint bitwise:true plusplus:true */
298 /*global esprima:true, define:true, exports:true, window: true,
299 throwError: true, generateStatement: true, peek: true,
300 parseAssignmentExpression: true, parseBlock: true,
301 parseClassExpression: true, parseClassDeclaration: true, parseExpression: true,
302 parseForStatement: true,
303 parseFunctionDeclaration: true, parseFunctionExpression: true,
304 parseFunctionSourceElements: true, parseVariableIdentifier: true,
305 parseImportSpecifier: true,
306 parseLeftHandSideExpression: true, parseParams: true, validateParam: true,
307 parseSpreadOrAssignmentExpression: true,
308 parseStatement: true, parseSourceElement: true, parseModuleBlock: true, parseConciseBody: true,
309 advanceXJSChild: true, isXJSIdentifierStart: true, isXJSIdentifierPart: true,
310 scanXJSStringLiteral: true, scanXJSIdentifier: true,
311 parseXJSAttributeValue: true, parseXJSChild: true, parseXJSElement: true, parseXJSExpressionContainer: true, parseXJSEmptyExpression: true,
312 parseYieldExpression: true
313 */
314
315 (function (root, factory) {
316     'use strict';
317
318     // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
319     // Rhino, and plain browser loading.
320     if (typeof define === 'function' && define.amd) {
321         define(['exports'], factory);
322     } else if (typeof exports !== 'undefined') {
323         factory(exports);
324     } else {
325         factory((root.esprima = {}));
326     }
327 }(this, function (exports) {
328     'use strict';
329
330     var Token,
331         TokenName,
332         FnExprTokens,
333         Syntax,
334         PropertyKind,
335         Messages,
336         Regex,
337         SyntaxTreeDelegate,
338         XHTMLEntities,
339         ClassPropertyType,
340         source,
341         strict,
342         index,
343         lineNumber,
344         lineStart,
345         length,
346         delegate,
347         lookahead,
348         state,
349         extra;
350
351     Token = {
352         BooleanLiteral: 1,
353         EOF: 2,
354         Identifier: 3,
355         Keyword: 4,
356         NullLiteral: 5,
357         NumericLiteral: 6,
358         Punctuator: 7,
359         StringLiteral: 8,
360         RegularExpression: 9,
361         Template: 10,
362         XJSIdentifier: 11,
363         XJSText: 12
364     };
365
366     TokenName = {};
367     TokenName[Token.BooleanLiteral] = 'Boolean';
368     TokenName[Token.EOF] = '<end>';
369     TokenName[Token.Identifier] = 'Identifier';
370     TokenName[Token.Keyword] = 'Keyword';
371     TokenName[Token.NullLiteral] = 'Null';
372     TokenName[Token.NumericLiteral] = 'Numeric';
373     TokenName[Token.Punctuator] = 'Punctuator';
374     TokenName[Token.StringLiteral] = 'String';
375     TokenName[Token.XJSIdentifier] = 'XJSIdentifier';
376     TokenName[Token.XJSText] = 'XJSText';
377     TokenName[Token.RegularExpression] = 'RegularExpression';
378
379     // A function following one of those tokens is an expression.
380     FnExprTokens = ["(", "{", "[", "in", "typeof", "instanceof", "new",
381                     "return", "case", "delete", "throw", "void",
382                     // assignment operators
383                     "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=",
384                     "&=", "|=", "^=", ",",
385                     // binary/unary operators
386                     "+", "-", "*", "/", "%", "++", "--", "<<", ">>", ">>>", "&",
387                     "|", "^", "!", "~", "&&", "||", "?", ":", "===", "==", ">=",
388                     "<=", "<", ">", "!=", "!=="];
389
390     Syntax = {
391         ArrayExpression: 'ArrayExpression',
392         ArrayPattern: 'ArrayPattern',
393         ArrowFunctionExpression: 'ArrowFunctionExpression',
394         AssignmentExpression: 'AssignmentExpression',
395         BinaryExpression: 'BinaryExpression',
396         BlockStatement: 'BlockStatement',
397         BreakStatement: 'BreakStatement',
398         CallExpression: 'CallExpression',
399         CatchClause: 'CatchClause',
400         ClassBody: 'ClassBody',
401         ClassDeclaration: 'ClassDeclaration',
402         ClassExpression: 'ClassExpression',
403         ClassHeritage: 'ClassHeritage',
404         ComprehensionBlock: 'ComprehensionBlock',
405         ComprehensionExpression: 'ComprehensionExpression',
406         ConditionalExpression: 'ConditionalExpression',
407         ContinueStatement: 'ContinueStatement',
408         DebuggerStatement: 'DebuggerStatement',
409         DoWhileStatement: 'DoWhileStatement',
410         EmptyStatement: 'EmptyStatement',
411         ExportDeclaration: 'ExportDeclaration',
412         ExportSpecifier: 'ExportSpecifier',
413         ExportSpecifierSet: 'ExportSpecifierSet',
414         ExpressionStatement: 'ExpressionStatement',
415         ForInStatement: 'ForInStatement',
416         ForOfStatement: 'ForOfStatement',
417         ForStatement: 'ForStatement',
418         FunctionDeclaration: 'FunctionDeclaration',
419         FunctionExpression: 'FunctionExpression',
420         Glob: 'Glob',
421         Identifier: 'Identifier',
422         IfStatement: 'IfStatement',
423         ImportDeclaration: 'ImportDeclaration',
424         ImportSpecifier: 'ImportSpecifier',
425         LabeledStatement: 'LabeledStatement',
426         Literal: 'Literal',
427         LogicalExpression: 'LogicalExpression',
428         MemberExpression: 'MemberExpression',
429         MethodDefinition: 'MethodDefinition',
430         ModuleDeclaration: 'ModuleDeclaration',
431         NewExpression: 'NewExpression',
432         ObjectExpression: 'ObjectExpression',
433         ObjectPattern: 'ObjectPattern',
434         Path:  'Path',
435         Program: 'Program',
436         Property: 'Property',
437         ReturnStatement: 'ReturnStatement',
438         SequenceExpression: 'SequenceExpression',
439         SpreadElement: 'SpreadElement',
440         SwitchCase: 'SwitchCase',
441         SwitchStatement: 'SwitchStatement',
442         TaggedTemplateExpression: 'TaggedTemplateExpression',
443         TemplateElement: 'TemplateElement',
444         TemplateLiteral: 'TemplateLiteral',
445         ThisExpression: 'ThisExpression',
446         ThrowStatement: 'ThrowStatement',
447         TryStatement: 'TryStatement',
448         UnaryExpression: 'UnaryExpression',
449         UpdateExpression: 'UpdateExpression',
450         VariableDeclaration: 'VariableDeclaration',
451         VariableDeclarator: 'VariableDeclarator',
452         WhileStatement: 'WhileStatement',
453         WithStatement: 'WithStatement',
454         XJSIdentifier: 'XJSIdentifier',
455         XJSEmptyExpression: 'XJSEmptyExpression',
456         XJSExpressionContainer: 'XJSExpressionContainer',
457         XJSElement: 'XJSElement',
458         XJSClosingElement: 'XJSClosingElement',
459         XJSOpeningElement: 'XJSOpeningElement',
460         XJSAttribute: 'XJSAttribute',
461         XJSText: 'XJSText',
462         YieldExpression: 'YieldExpression'
463     };
464
465     PropertyKind = {
466         Data: 1,
467         Get: 2,
468         Set: 4
469     };
470
471     ClassPropertyType = {
472         static: 'static',
473         prototype: 'prototype'
474     };
475
476     // Error messages should be identical to V8.
477     Messages = {
478         UnexpectedToken:  'Unexpected token %0',
479         UnexpectedNumber:  'Unexpected number',
480         UnexpectedString:  'Unexpected string',
481         UnexpectedIdentifier:  'Unexpected identifier',
482         UnexpectedReserved:  'Unexpected reserved word',
483         UnexpectedTemplate:  'Unexpected quasi %0',
484         UnexpectedEOS:  'Unexpected end of input',
485         NewlineAfterThrow:  'Illegal newline after throw',
486         InvalidRegExp: 'Invalid regular expression',
487         UnterminatedRegExp:  'Invalid regular expression: missing /',
488         InvalidLHSInAssignment:  'Invalid left-hand side in assignment',
489         InvalidLHSInFormalsList:  'Invalid left-hand side in formals list',
490         InvalidLHSInForIn:  'Invalid left-hand side in for-in',
491         MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
492         NoCatchOrFinally:  'Missing catch or finally after try',
493         UnknownLabel: 'Undefined label \'%0\'',
494         Redeclaration: '%0 \'%1\' has already been declared',
495         IllegalContinue: 'Illegal continue statement',
496         IllegalBreak: 'Illegal break statement',
497         IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition',
498         IllegalReturn: 'Illegal return statement',
499         IllegalYield: 'Illegal yield expression',
500         IllegalSpread: 'Illegal spread element',
501         StrictModeWith:  'Strict mode code may not include a with statement',
502         StrictCatchVariable:  'Catch variable may not be eval or arguments in strict mode',
503         StrictVarName:  'Variable name may not be eval or arguments in strict mode',
504         StrictParamName:  'Parameter name eval or arguments is not allowed in strict mode',
505         StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
506         ParameterAfterRestParameter: 'Rest parameter must be final parameter of an argument list',
507         ElementAfterSpreadElement: 'Spread must be the final element of an element list',
508         ObjectPatternAsRestParameter: 'Invalid rest parameter',
509         ObjectPatternAsSpread: 'Invalid spread argument',
510         StrictFunctionName:  'Function name may not be eval or arguments in strict mode',
511         StrictOctalLiteral:  'Octal literals are not allowed in strict mode.',
512         StrictDelete:  'Delete of an unqualified identifier in strict mode.',
513         StrictDuplicateProperty:  'Duplicate data property in object literal not allowed in strict mode',
514         AccessorDataProperty:  'Object literal may not have data and accessor property with the same name',
515         AccessorGetSet:  'Object literal may not have multiple get/set accessors with the same name',
516         StrictLHSAssignment:  'Assignment to eval or arguments is not allowed in strict mode',
517         StrictLHSPostfix:  'Postfix increment/decrement may not have eval or arguments operand in strict mode',
518         StrictLHSPrefix:  'Prefix increment/decrement may not have eval or arguments operand in strict mode',
519         StrictReservedWord:  'Use of future reserved word in strict mode',
520         NoFromAfterImport: 'Missing from after import',
521         NoYieldInGenerator: 'Missing yield in generator',
522         NoUnintializedConst: 'Const must be initialized',
523         ComprehensionRequiresBlock: 'Comprehension must have at least one block',
524         ComprehensionError:  'Comprehension Error',
525         EachNotAllowed:  'Each is not supported',
526         InvalidXJSTagName: 'XJS tag name can not be empty',
527         InvalidXJSAttributeValue: 'XJS value should be either an expression or a quoted XJS text',
528         ExpectedXJSClosingTag: 'Expected corresponding XJS closing tag for %0'
529     };
530
531     // See also tools/generate-unicode-regex.py.
532     Regex = {
533         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]'),
534         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]')
535     };
536
537     // Ensure the condition is true, otherwise throw an error.
538     // This is only to have a better contract semantic, i.e. another safety net
539     // to catch a logic error. The condition shall be fulfilled in normal case.
540     // Do NOT use this to enforce a certain condition on any user input.
541
542     function assert(condition, message) {
543         if (!condition) {
544             throw new Error('ASSERT: ' + message);
545         }
546     }
547
548     function isDecimalDigit(ch) {
549         return (ch >= 48 && ch <= 57);   // 0..9
550     }
551
552     function isHexDigit(ch) {
553         return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
554     }
555
556     function isOctalDigit(ch) {
557         return '01234567'.indexOf(ch) >= 0;
558     }
559
560
561     // 7.2 White Space
562
563     function isWhiteSpace(ch) {
564         return (ch === 32) ||  // space
565             (ch === 9) ||      // tab
566             (ch === 0xB) ||
567             (ch === 0xC) ||
568             (ch === 0xA0) ||
569             (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0);
570     }
571
572     // 7.3 Line Terminators
573
574     function isLineTerminator(ch) {
575         return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029);
576     }
577
578     // 7.6 Identifier Names and Identifiers
579
580     function isIdentifierStart(ch) {
581         return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)
582             (ch >= 65 && ch <= 90) ||         // A..Z
583             (ch >= 97 && ch <= 122) ||        // a..z
584             (ch === 92) ||                    // \ (backslash)
585             ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch)));
586     }
587
588     function isIdentifierPart(ch) {
589         return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)
590             (ch >= 65 && ch <= 90) ||         // A..Z
591             (ch >= 97 && ch <= 122) ||        // a..z
592             (ch >= 48 && ch <= 57) ||         // 0..9
593             (ch === 92) ||                    // \ (backslash)
594             ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch)));
595     }
596
597     // 7.6.1.2 Future Reserved Words
598
599     function isFutureReservedWord(id) {
600         switch (id) {
601         case 'class':
602         case 'enum':
603         case 'export':
604         case 'extends':
605         case 'import':
606         case 'super':
607             return true;
608         default:
609             return false;
610         }
611     }
612
613     function isStrictModeReservedWord(id) {
614         switch (id) {
615         case 'implements':
616         case 'interface':
617         case 'package':
618         case 'private':
619         case 'protected':
620         case 'public':
621         case 'static':
622         case 'yield':
623         case 'let':
624             return true;
625         default:
626             return false;
627         }
628     }
629
630     function isRestrictedWord(id) {
631         return id === 'eval' || id === 'arguments';
632     }
633
634     // 7.6.1.1 Keywords
635
636     function isKeyword(id) {
637         if (strict && isStrictModeReservedWord(id)) {
638             return true;
639         }
640
641         // 'const' is specialized as Keyword in V8.
642         // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next.
643         // Some others are from future reserved words.
644
645         switch (id.length) {
646         case 2:
647             return (id === 'if') || (id === 'in') || (id === 'do');
648         case 3:
649             return (id === 'var') || (id === 'for') || (id === 'new') ||
650                 (id === 'try') || (id === 'let');
651         case 4:
652             return (id === 'this') || (id === 'else') || (id === 'case') ||
653                 (id === 'void') || (id === 'with') || (id === 'enum');
654         case 5:
655             return (id === 'while') || (id === 'break') || (id === 'catch') ||
656                 (id === 'throw') || (id === 'const') || (id === 'yield') ||
657                 (id === 'class') || (id === 'super');
658         case 6:
659             return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
660                 (id === 'switch') || (id === 'export') || (id === 'import');
661         case 7:
662             return (id === 'default') || (id === 'finally') || (id === 'extends');
663         case 8:
664             return (id === 'function') || (id === 'continue') || (id === 'debugger');
665         case 10:
666             return (id === 'instanceof');
667         default:
668             return false;
669         }
670     }
671
672     // 7.4 Comments
673
674     function skipComment() {
675         var ch, blockComment, lineComment;
676
677         blockComment = false;
678         lineComment = false;
679
680         while (index < length) {
681             ch = source.charCodeAt(index);
682
683             if (lineComment) {
684                 ++index;
685                 if (isLineTerminator(ch)) {
686                     lineComment = false;
687                     if (ch === 13 && source.charCodeAt(index) === 10) {
688                         ++index;
689                     }
690                     ++lineNumber;
691                     lineStart = index;
692                 }
693             } else if (blockComment) {
694                 if (isLineTerminator(ch)) {
695                     if (ch === 13 && source.charCodeAt(index + 1) === 10) {
696                         ++index;
697                     }
698                     ++lineNumber;
699                     ++index;
700                     lineStart = index;
701                     if (index >= length) {
702                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
703                     }
704                 } else {
705                     ch = source.charCodeAt(index++);
706                     if (index >= length) {
707                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
708                     }
709                     // Block comment ends with '*/' (char #42, char #47).
710                     if (ch === 42) {
711                         ch = source.charCodeAt(index);
712                         if (ch === 47) {
713                             ++index;
714                             blockComment = false;
715                         }
716                     }
717                 }
718             } else if (ch === 47) {
719                 ch = source.charCodeAt(index + 1);
720                 // Line comment starts with '//' (char #47, char #47).
721                 if (ch === 47) {
722                     index += 2;
723                     lineComment = true;
724                 } else if (ch === 42) {
725                     // Block comment starts with '/*' (char #47, char #42).
726                     index += 2;
727                     blockComment = true;
728                     if (index >= length) {
729                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
730                     }
731                 } else {
732                     break;
733                 }
734             } else if (isWhiteSpace(ch)) {
735                 ++index;
736             } else if (isLineTerminator(ch)) {
737                 ++index;
738                 if (ch === 13 && source.charCodeAt(index) === 10) {
739                     ++index;
740                 }
741                 ++lineNumber;
742                 lineStart = index;
743             } else {
744                 break;
745             }
746         }
747     }
748
749     function scanHexEscape(prefix) {
750         var i, len, ch, code = 0;
751
752         len = (prefix === 'u') ? 4 : 2;
753         for (i = 0; i < len; ++i) {
754             if (index < length && isHexDigit(source[index])) {
755                 ch = source[index++];
756                 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
757             } else {
758                 return '';
759             }
760         }
761         return String.fromCharCode(code);
762     }
763
764     function scanUnicodeCodePointEscape() {
765         var ch, code, cu1, cu2;
766
767         ch = source[index];
768         code = 0;
769
770         // At least, one hex digit is required.
771         if (ch === '}') {
772             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
773         }
774
775         while (index < length) {
776             ch = source[index++];
777             if (!isHexDigit(ch)) {
778                 break;
779             }
780             code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
781         }
782
783         if (code > 0x10FFFF || ch !== '}') {
784             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
785         }
786
787         // UTF-16 Encoding
788         if (code <= 0xFFFF) {
789             return String.fromCharCode(code);
790         }
791         cu1 = ((code - 0x10000) >> 10) + 0xD800;
792         cu2 = ((code - 0x10000) & 1023) + 0xDC00;
793         return String.fromCharCode(cu1, cu2);
794     }
795
796     function getEscapedIdentifier() {
797         var ch, id;
798
799         ch = source.charCodeAt(index++);
800         id = String.fromCharCode(ch);
801
802         // '\u' (char #92, char #117) denotes an escaped character.
803         if (ch === 92) {
804             if (source.charCodeAt(index) !== 117) {
805                 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
806             }
807             ++index;
808             ch = scanHexEscape('u');
809             if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) {
810                 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
811             }
812             id = ch;
813         }
814
815         while (index < length) {
816             ch = source.charCodeAt(index);
817             if (!isIdentifierPart(ch)) {
818                 break;
819             }
820             ++index;
821             id += String.fromCharCode(ch);
822
823             // '\u' (char #92, char #117) denotes an escaped character.
824             if (ch === 92) {
825                 id = id.substr(0, id.length - 1);
826                 if (source.charCodeAt(index) !== 117) {
827                     throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
828                 }
829                 ++index;
830                 ch = scanHexEscape('u');
831                 if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) {
832                     throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
833                 }
834                 id += ch;
835             }
836         }
837
838         return id;
839     }
840
841     function getIdentifier() {
842         var start, ch;
843
844         start = index++;
845         while (index < length) {
846             ch = source.charCodeAt(index);
847             if (ch === 92) {
848                 // Blackslash (char #92) marks Unicode escape sequence.
849                 index = start;
850                 return getEscapedIdentifier();
851             }
852             if (isIdentifierPart(ch)) {
853                 ++index;
854             } else {
855                 break;
856             }
857         }
858
859         return source.slice(start, index);
860     }
861
862     function scanIdentifier() {
863         var start, id, type;
864
865         start = index;
866
867         // Backslash (char #92) starts an escaped character.
868         id = (source.charCodeAt(index) === 92) ? getEscapedIdentifier() : getIdentifier();
869
870         // There is no keyword or literal with only one character.
871         // Thus, it must be an identifier.
872         if (id.length === 1) {
873             type = Token.Identifier;
874         } else if (isKeyword(id)) {
875             type = Token.Keyword;
876         } else if (id === 'null') {
877             type = Token.NullLiteral;
878         } else if (id === 'true' || id === 'false') {
879             type = Token.BooleanLiteral;
880         } else {
881             type = Token.Identifier;
882         }
883
884         return {
885             type: type,
886             value: id,
887             lineNumber: lineNumber,
888             lineStart: lineStart,
889             range: [start, index]
890         };
891     }
892
893
894     // 7.7 Punctuators
895
896     function scanPunctuator() {
897         var start = index,
898             code = source.charCodeAt(index),
899             code2,
900             ch1 = source[index],
901             ch2,
902             ch3,
903             ch4;
904
905         switch (code) {
906         // Check for most common single-character punctuators.
907         case 40:   // ( open bracket
908         case 41:   // ) close bracket
909         case 59:   // ; semicolon
910         case 44:   // , comma
911         case 123:  // { open curly brace
912         case 125:  // } close curly brace
913         case 91:   // [
914         case 93:   // ]
915         case 58:   // :
916         case 63:   // ?
917         case 126:  // ~
918             ++index;
919             if (extra.tokenize) {
920                 if (code === 40) {
921                     extra.openParenToken = extra.tokens.length;
922                 } else if (code === 123) {
923                     extra.openCurlyToken = extra.tokens.length;
924                 }
925             }
926             return {
927                 type: Token.Punctuator,
928                 value: String.fromCharCode(code),
929                 lineNumber: lineNumber,
930                 lineStart: lineStart,
931                 range: [start, index]
932             };
933
934         default:
935             code2 = source.charCodeAt(index + 1);
936
937             // '=' (char #61) marks an assignment or comparison operator.
938             if (code2 === 61) {
939                 switch (code) {
940                 case 37:  // %
941                 case 38:  // &
942                 case 42:  // *:
943                 case 43:  // +
944                 case 45:  // -
945                 case 47:  // /
946                 case 60:  // <
947                 case 62:  // >
948                 case 94:  // ^
949                 case 124: // |
950                     index += 2;
951                     return {
952                         type: Token.Punctuator,
953                         value: String.fromCharCode(code) + String.fromCharCode(code2),
954                         lineNumber: lineNumber,
955                         lineStart: lineStart,
956                         range: [start, index]
957                     };
958
959                 case 33: // !
960                 case 61: // =
961                     index += 2;
962
963                     // !== and ===
964                     if (source.charCodeAt(index) === 61) {
965                         ++index;
966                     }
967                     return {
968                         type: Token.Punctuator,
969                         value: source.slice(start, index),
970                         lineNumber: lineNumber,
971                         lineStart: lineStart,
972                         range: [start, index]
973                     };
974                 default:
975                     break;
976                 }
977             }
978             break;
979         }
980
981         // Peek more characters.
982
983         ch2 = source[index + 1];
984         ch3 = source[index + 2];
985         ch4 = source[index + 3];
986
987         // 4-character punctuator: >>>=
988
989         if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
990             if (ch4 === '=') {
991                 index += 4;
992                 return {
993                     type: Token.Punctuator,
994                     value: '>>>=',
995                     lineNumber: lineNumber,
996                     lineStart: lineStart,
997                     range: [start, index]
998                 };
999             }
1000         }
1001
1002         // 3-character punctuators: === !== >>> <<= >>=
1003
1004         if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
1005             index += 3;
1006             return {
1007                 type: Token.Punctuator,
1008                 value: '>>>',
1009                 lineNumber: lineNumber,
1010                 lineStart: lineStart,
1011                 range: [start, index]
1012             };
1013         }
1014
1015         if (ch1 === '<' && ch2 === '<' && ch3 === '=') {
1016             index += 3;
1017             return {
1018                 type: Token.Punctuator,
1019                 value: '<<=',
1020                 lineNumber: lineNumber,
1021                 lineStart: lineStart,
1022                 range: [start, index]
1023             };
1024         }
1025
1026         if (ch1 === '>' && ch2 === '>' && ch3 === '=') {
1027             index += 3;
1028             return {
1029                 type: Token.Punctuator,
1030                 value: '>>=',
1031                 lineNumber: lineNumber,
1032                 lineStart: lineStart,
1033                 range: [start, index]
1034             };
1035         }
1036
1037         if (ch1 === '.' && ch2 === '.' && ch3 === '.') {
1038             index += 3;
1039             return {
1040                 type: Token.Punctuator,
1041                 value: '...',
1042                 lineNumber: lineNumber,
1043                 lineStart: lineStart,
1044                 range: [start, index]
1045             };
1046         }
1047
1048         // Other 2-character punctuators: ++ -- << >> && ||
1049
1050         if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) {
1051             index += 2;
1052             return {
1053                 type: Token.Punctuator,
1054                 value: ch1 + ch2,
1055                 lineNumber: lineNumber,
1056                 lineStart: lineStart,
1057                 range: [start, index]
1058             };
1059         }
1060
1061         if (ch1 === '=' && ch2 === '>') {
1062             index += 2;
1063             return {
1064                 type: Token.Punctuator,
1065                 value: '=>',
1066                 lineNumber: lineNumber,
1067                 lineStart: lineStart,
1068                 range: [start, index]
1069             };
1070         }
1071
1072         if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
1073             ++index;
1074             return {
1075                 type: Token.Punctuator,
1076                 value: ch1,
1077                 lineNumber: lineNumber,
1078                 lineStart: lineStart,
1079                 range: [start, index]
1080             };
1081         }
1082
1083         if (ch1 === '.') {
1084             ++index;
1085             return {
1086                 type: Token.Punctuator,
1087                 value: ch1,
1088                 lineNumber: lineNumber,
1089                 lineStart: lineStart,
1090                 range: [start, index]
1091             };
1092         }
1093
1094         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1095     }
1096
1097     // 7.8.3 Numeric Literals
1098
1099     function scanHexLiteral(start) {
1100         var number = '';
1101
1102         while (index < length) {
1103             if (!isHexDigit(source[index])) {
1104                 break;
1105             }
1106             number += source[index++];
1107         }
1108
1109         if (number.length === 0) {
1110             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1111         }
1112
1113         if (isIdentifierStart(source.charCodeAt(index))) {
1114             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1115         }
1116
1117         return {
1118             type: Token.NumericLiteral,
1119             value: parseInt('0x' + number, 16),
1120             lineNumber: lineNumber,
1121             lineStart: lineStart,
1122             range: [start, index]
1123         };
1124     }
1125
1126     function scanOctalLiteral(prefix, start) {
1127         var number, octal;
1128
1129         if (isOctalDigit(prefix)) {
1130             octal = true;
1131             number = '0' + source[index++];
1132         } else {
1133             octal = false;
1134             ++index;
1135             number = '';
1136         }
1137
1138         while (index < length) {
1139             if (!isOctalDigit(source[index])) {
1140                 break;
1141             }
1142             number += source[index++];
1143         }
1144
1145         if (!octal && number.length === 0) {
1146             // only 0o or 0O
1147             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1148         }
1149
1150         if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
1151             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1152         }
1153
1154         return {
1155             type: Token.NumericLiteral,
1156             value: parseInt(number, 8),
1157             octal: octal,
1158             lineNumber: lineNumber,
1159             lineStart: lineStart,
1160             range: [start, index]
1161         };
1162     }
1163
1164     function scanNumericLiteral() {
1165         var number, start, ch, octal;
1166
1167         ch = source[index];
1168         assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
1169             'Numeric literal must start with a decimal digit or a decimal point');
1170
1171         start = index;
1172         number = '';
1173         if (ch !== '.') {
1174             number = source[index++];
1175             ch = source[index];
1176
1177             // Hex number starts with '0x'.
1178             // Octal number starts with '0'.
1179             // Octal number in ES6 starts with '0o'.
1180             // Binary number in ES6 starts with '0b'.
1181             if (number === '0') {
1182                 if (ch === 'x' || ch === 'X') {
1183                     ++index;
1184                     return scanHexLiteral(start);
1185                 }
1186                 if (ch === 'b' || ch === 'B') {
1187                     ++index;
1188                     number = '';
1189
1190                     while (index < length) {
1191                         ch = source[index];
1192                         if (ch !== '0' && ch !== '1') {
1193                             break;
1194                         }
1195                         number += source[index++];
1196                     }
1197
1198                     if (number.length === 0) {
1199                         // only 0b or 0B
1200                         throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1201                     }
1202
1203                     if (index < length) {
1204                         ch = source.charCodeAt(index);
1205                         if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
1206                             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1207                         }
1208                     }
1209                     return {
1210                         type: Token.NumericLiteral,
1211                         value: parseInt(number, 2),
1212                         lineNumber: lineNumber,
1213                         lineStart: lineStart,
1214                         range: [start, index]
1215                     };
1216                 }
1217                 if (ch === 'o' || ch === 'O' || isOctalDigit(ch)) {
1218                     return scanOctalLiteral(ch, start);
1219                 }
1220                 // decimal number starts with '0' such as '09' is illegal.
1221                 if (ch && isDecimalDigit(ch.charCodeAt(0))) {
1222                     throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1223                 }
1224             }
1225
1226             while (isDecimalDigit(source.charCodeAt(index))) {
1227                 number += source[index++];
1228             }
1229             ch = source[index];
1230         }
1231
1232         if (ch === '.') {
1233             number += source[index++];
1234             while (isDecimalDigit(source.charCodeAt(index))) {
1235                 number += source[index++];
1236             }
1237             ch = source[index];
1238         }
1239
1240         if (ch === 'e' || ch === 'E') {
1241             number += source[index++];
1242
1243             ch = source[index];
1244             if (ch === '+' || ch === '-') {
1245                 number += source[index++];
1246             }
1247             if (isDecimalDigit(source.charCodeAt(index))) {
1248                 while (isDecimalDigit(source.charCodeAt(index))) {
1249                     number += source[index++];
1250                 }
1251             } else {
1252                 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1253             }
1254         }
1255
1256         if (isIdentifierStart(source.charCodeAt(index))) {
1257             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1258         }
1259
1260         return {
1261             type: Token.NumericLiteral,
1262             value: parseFloat(number),
1263             lineNumber: lineNumber,
1264             lineStart: lineStart,
1265             range: [start, index]
1266         };
1267     }
1268
1269     // 7.8.4 String Literals
1270
1271     function scanStringLiteral() {
1272         var str = '', quote, start, ch, code, unescaped, restore, octal = false;
1273
1274         quote = source[index];
1275         assert((quote === '\'' || quote === '"'),
1276             'String literal must starts with a quote');
1277
1278         start = index;
1279         ++index;
1280
1281         while (index < length) {
1282             ch = source[index++];
1283
1284             if (ch === quote) {
1285                 quote = '';
1286                 break;
1287             } else if (ch === '\\') {
1288                 ch = source[index++];
1289                 if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
1290                     switch (ch) {
1291                     case 'n':
1292                         str += '\n';
1293                         break;
1294                     case 'r':
1295                         str += '\r';
1296                         break;
1297                     case 't':
1298                         str += '\t';
1299                         break;
1300                     case 'u':
1301                     case 'x':
1302                         if (source[index] === '{') {
1303                             ++index;
1304                             str += scanUnicodeCodePointEscape();
1305                         } else {
1306                             restore = index;
1307                             unescaped = scanHexEscape(ch);
1308                             if (unescaped) {
1309                                 str += unescaped;
1310                             } else {
1311                                 index = restore;
1312                                 str += ch;
1313                             }
1314                         }
1315                         break;
1316                     case 'b':
1317                         str += '\b';
1318                         break;
1319                     case 'f':
1320                         str += '\f';
1321                         break;
1322                     case 'v':
1323                         str += '\x0B';
1324                         break;
1325
1326                     default:
1327                         if (isOctalDigit(ch)) {
1328                             code = '01234567'.indexOf(ch);
1329
1330                             // \0 is not octal escape sequence
1331                             if (code !== 0) {
1332                                 octal = true;
1333                             }
1334
1335                             if (index < length && isOctalDigit(source[index])) {
1336                                 octal = true;
1337                                 code = code * 8 + '01234567'.indexOf(source[index++]);
1338
1339                                 // 3 digits are only allowed when string starts
1340                                 // with 0, 1, 2, 3
1341                                 if ('0123'.indexOf(ch) >= 0 &&
1342                                         index < length &&
1343                                         isOctalDigit(source[index])) {
1344                                     code = code * 8 + '01234567'.indexOf(source[index++]);
1345                                 }
1346                             }
1347                             str += String.fromCharCode(code);
1348                         } else {
1349                             str += ch;
1350                         }
1351                         break;
1352                     }
1353                 } else {
1354                     ++lineNumber;
1355                     if (ch ===  '\r' && source[index] === '\n') {
1356                         ++index;
1357                     }
1358                 }
1359             } else if (isLineTerminator(ch.charCodeAt(0))) {
1360                 break;
1361             } else {
1362                 str += ch;
1363             }
1364         }
1365
1366         if (quote !== '') {
1367             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1368         }
1369
1370         return {
1371             type: Token.StringLiteral,
1372             value: str,
1373             octal: octal,
1374             lineNumber: lineNumber,
1375             lineStart: lineStart,
1376             range: [start, index]
1377         };
1378     }
1379
1380     function scanTemplate() {
1381         var cooked = '', ch, start, terminated, tail, restore, unescaped, code, octal;
1382
1383         terminated = false;
1384         tail = false;
1385         start = index;
1386
1387         ++index;
1388
1389         while (index < length) {
1390             ch = source[index++];
1391             if (ch === '`') {
1392                 tail = true;
1393                 terminated = true;
1394                 break;
1395             } else if (ch === '$') {
1396                 if (source[index] === '{') {
1397                     ++index;
1398                     terminated = true;
1399                     break;
1400                 }
1401                 cooked += ch;
1402             } else if (ch === '\\') {
1403                 ch = source[index++];
1404                 if (!isLineTerminator(ch.charCodeAt(0))) {
1405                     switch (ch) {
1406                     case 'n':
1407                         cooked += '\n';
1408                         break;
1409                     case 'r':
1410                         cooked += '\r';
1411                         break;
1412                     case 't':
1413                         cooked += '\t';
1414                         break;
1415                     case 'u':
1416                     case 'x':
1417                         if (source[index] === '{') {
1418                             ++index;
1419                             cooked += scanUnicodeCodePointEscape();
1420                         } else {
1421                             restore = index;
1422                             unescaped = scanHexEscape(ch);
1423                             if (unescaped) {
1424                                 cooked += unescaped;
1425                             } else {
1426                                 index = restore;
1427                                 cooked += ch;
1428                             }
1429                         }
1430                         break;
1431                     case 'b':
1432                         cooked += '\b';
1433                         break;
1434                     case 'f':
1435                         cooked += '\f';
1436                         break;
1437                     case 'v':
1438                         cooked += '\v';
1439                         break;
1440
1441                     default:
1442                         if (isOctalDigit(ch)) {
1443                             code = '01234567'.indexOf(ch);
1444
1445                             // \0 is not octal escape sequence
1446                             if (code !== 0) {
1447                                 octal = true;
1448                             }
1449
1450                             if (index < length && isOctalDigit(source[index])) {
1451                                 octal = true;
1452                                 code = code * 8 + '01234567'.indexOf(source[index++]);
1453
1454                                 // 3 digits are only allowed when string starts
1455                                 // with 0, 1, 2, 3
1456                                 if ('0123'.indexOf(ch) >= 0 &&
1457                                         index < length &&
1458                                         isOctalDigit(source[index])) {
1459                                     code = code * 8 + '01234567'.indexOf(source[index++]);
1460                                 }
1461                             }
1462                             cooked += String.fromCharCode(code);
1463                         } else {
1464                             cooked += ch;
1465                         }
1466                         break;
1467                     }
1468                 } else {
1469                     ++lineNumber;
1470                     if (ch ===  '\r' && source[index] === '\n') {
1471                         ++index;
1472                     }
1473                 }
1474             } else if (isLineTerminator(ch.charCodeAt(0))) {
1475                 ++lineNumber;
1476                 if (ch ===  '\r' && source[index] === '\n') {
1477                     ++index;
1478                 }
1479             } else {
1480                 cooked += ch;
1481             }
1482         }
1483
1484         if (!terminated) {
1485             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1486         }
1487
1488         return {
1489             type: Token.Template,
1490             value: {
1491                 cooked: cooked,
1492                 raw: source.slice(start + 1, index - ((tail) ? 1 : 2))
1493             },
1494             tail: tail,
1495             octal: octal,
1496             lineNumber: lineNumber,
1497             lineStart: lineStart,
1498             range: [start, index]
1499         };
1500     }
1501
1502     function scanTemplateElement(option) {
1503         var startsWith, template;
1504
1505         lookahead = null;
1506         skipComment();
1507
1508         startsWith = (option.head) ? '`' : '}';
1509
1510         if (source[index] !== startsWith) {
1511             throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1512         }
1513
1514         template = scanTemplate();
1515
1516         peek();
1517
1518         return template;
1519     }
1520
1521     function scanRegExp() {
1522         var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false;
1523
1524         lookahead = null;
1525         skipComment();
1526
1527         start = index;
1528         ch = source[index];
1529         assert(ch === '/', 'Regular expression literal must start with a slash');
1530         str = source[index++];
1531
1532         while (index < length) {
1533             ch = source[index++];
1534             str += ch;
1535             if (classMarker) {
1536                 if (ch === ']') {
1537                     classMarker = false;
1538                 }
1539             } else {
1540                 if (ch === '\\') {
1541                     ch = source[index++];
1542                     // ECMA-262 7.8.5
1543                     if (isLineTerminator(ch.charCodeAt(0))) {
1544                         throwError({}, Messages.UnterminatedRegExp);
1545                     }
1546                     str += ch;
1547                 } else if (ch === '/') {
1548                     terminated = true;
1549                     break;
1550                 } else if (ch === '[') {
1551                     classMarker = true;
1552                 } else if (isLineTerminator(ch.charCodeAt(0))) {
1553                     throwError({}, Messages.UnterminatedRegExp);
1554                 }
1555             }
1556         }
1557
1558         if (!terminated) {
1559             throwError({}, Messages.UnterminatedRegExp);
1560         }
1561
1562         // Exclude leading and trailing slash.
1563         pattern = str.substr(1, str.length - 2);
1564
1565         flags = '';
1566         while (index < length) {
1567             ch = source[index];
1568             if (!isIdentifierPart(ch.charCodeAt(0))) {
1569                 break;
1570             }
1571
1572             ++index;
1573             if (ch === '\\' && index < length) {
1574                 ch = source[index];
1575                 if (ch === 'u') {
1576                     ++index;
1577                     restore = index;
1578                     ch = scanHexEscape('u');
1579                     if (ch) {
1580                         flags += ch;
1581                         for (str += '\\u'; restore < index; ++restore) {
1582                             str += source[restore];
1583                         }
1584                     } else {
1585                         index = restore;
1586                         flags += 'u';
1587                         str += '\\u';
1588                     }
1589                 } else {
1590                     str += '\\';
1591                 }
1592             } else {
1593                 flags += ch;
1594                 str += ch;
1595             }
1596         }
1597
1598         try {
1599             value = new RegExp(pattern, flags);
1600         } catch (e) {
1601             throwError({}, Messages.InvalidRegExp);
1602         }
1603
1604         peek();
1605
1606
1607         if (extra.tokenize) {
1608             return {
1609                 type: Token.RegularExpression,
1610                 value: value,
1611                 lineNumber: lineNumber,
1612                 lineStart: lineStart,
1613                 range: [start, index]
1614             };
1615         }
1616         return {
1617             literal: str,
1618             value: value,
1619             range: [start, index]
1620         };
1621     }
1622
1623     function isIdentifierName(token) {
1624         return token.type === Token.Identifier ||
1625             token.type === Token.Keyword ||
1626             token.type === Token.BooleanLiteral ||
1627             token.type === Token.NullLiteral;
1628     }
1629
1630     function advanceSlash() {
1631         var prevToken,
1632             checkToken;
1633         // Using the following algorithm:
1634         // https://github.com/mozilla/sweet.js/wiki/design
1635         prevToken = extra.tokens[extra.tokens.length - 1];
1636         if (!prevToken) {
1637             // Nothing before that: it cannot be a division.
1638             return scanRegExp();
1639         }
1640         if (prevToken.type === "Punctuator") {
1641             if (prevToken.value === ")") {
1642                 checkToken = extra.tokens[extra.openParenToken - 1];
1643                 if (checkToken &&
1644                         checkToken.type === "Keyword" &&
1645                         (checkToken.value === "if" ||
1646                          checkToken.value === "while" ||
1647                          checkToken.value === "for" ||
1648                          checkToken.value === "with")) {
1649                     return scanRegExp();
1650                 }
1651                 return scanPunctuator();
1652             }
1653             if (prevToken.value === "}") {
1654                 // Dividing a function by anything makes little sense,
1655                 // but we have to check for that.
1656                 if (extra.tokens[extra.openCurlyToken - 3] &&
1657                         extra.tokens[extra.openCurlyToken - 3].type === "Keyword") {
1658                     // Anonymous function.
1659                     checkToken = extra.tokens[extra.openCurlyToken - 4];
1660                     if (!checkToken) {
1661                         return scanPunctuator();
1662                     }
1663                 } else if (extra.tokens[extra.openCurlyToken - 4] &&
1664                         extra.tokens[extra.openCurlyToken - 4].type === "Keyword") {
1665                     // Named function.
1666                     checkToken = extra.tokens[extra.openCurlyToken - 5];
1667                     if (!checkToken) {
1668                         return scanRegExp();
1669                     }
1670                 } else {
1671                     return scanPunctuator();
1672                 }
1673                 // checkToken determines whether the function is
1674                 // a declaration or an expression.
1675                 if (FnExprTokens.indexOf(checkToken.value) >= 0) {
1676                     // It is an expression.
1677                     return scanPunctuator();
1678                 }
1679                 // It is a declaration.
1680                 return scanRegExp();
1681             }
1682             return scanRegExp();
1683         }
1684         if (prevToken.type === "Keyword") {
1685             return scanRegExp();
1686         }
1687         return scanPunctuator();
1688     }
1689
1690     function advance() {
1691         var ch;
1692
1693         if (state.inXJSChild) {
1694             return advanceXJSChild();
1695         }
1696
1697         skipComment();
1698
1699         if (index >= length) {
1700             return {
1701                 type: Token.EOF,
1702                 lineNumber: lineNumber,
1703                 lineStart: lineStart,
1704                 range: [index, index]
1705             };
1706         }
1707
1708         ch = source.charCodeAt(index);
1709
1710         // Very common: ( and ) and ;
1711         if (ch === 40 || ch === 41 || ch === 58) {
1712             return scanPunctuator();
1713         }
1714
1715         // String literal starts with single quote (#39) or double quote (#34).
1716         if (ch === 39 || ch === 34) {
1717             if (state.inXJSTag) {
1718                 return scanXJSStringLiteral();
1719             }
1720             return scanStringLiteral();
1721         }
1722
1723         if (state.inXJSTag && isXJSIdentifierStart(ch)) {
1724             return scanXJSIdentifier();
1725         }
1726
1727         if (ch === 96) {
1728             return scanTemplate();
1729         }
1730         if (isIdentifierStart(ch)) {
1731             return scanIdentifier();
1732         }
1733
1734         // Dot (.) char #46 can also start a floating-point number, hence the need
1735         // to check the next character.
1736         if (ch === 46) {
1737             if (isDecimalDigit(source.charCodeAt(index + 1))) {
1738                 return scanNumericLiteral();
1739             }
1740             return scanPunctuator();
1741         }
1742
1743         if (isDecimalDigit(ch)) {
1744             return scanNumericLiteral();
1745         }
1746
1747         // Slash (/) char #47 can also start a regex.
1748         if (extra.tokenize && ch === 47) {
1749             return advanceSlash();
1750         }
1751
1752         return scanPunctuator();
1753     }
1754
1755     function lex() {
1756         var token;
1757
1758         token = lookahead;
1759         index = token.range[1];
1760         lineNumber = token.lineNumber;
1761         lineStart = token.lineStart;
1762
1763         lookahead = advance();
1764
1765         index = token.range[1];
1766         lineNumber = token.lineNumber;
1767         lineStart = token.lineStart;
1768
1769         return token;
1770     }
1771
1772     function peek() {
1773         var pos, line, start;
1774
1775         pos = index;
1776         line = lineNumber;
1777         start = lineStart;
1778         lookahead = advance();
1779         index = pos;
1780         lineNumber = line;
1781         lineStart = start;
1782     }
1783
1784     function lookahead2() {
1785         var adv, pos, line, start, result;
1786
1787         // If we are collecting the tokens, don't grab the next one yet.
1788         adv = (typeof extra.advance === 'function') ? extra.advance : advance;
1789
1790         pos = index;
1791         line = lineNumber;
1792         start = lineStart;
1793
1794         // Scan for the next immediate token.
1795         if (lookahead === null) {
1796             lookahead = adv();
1797         }
1798         index = lookahead.range[1];
1799         lineNumber = lookahead.lineNumber;
1800         lineStart = lookahead.lineStart;
1801
1802         // Grab the token right after.
1803         result = adv();
1804         index = pos;
1805         lineNumber = line;
1806         lineStart = start;
1807
1808         return result;
1809     }
1810
1811     SyntaxTreeDelegate = {
1812
1813         name: 'SyntaxTree',
1814
1815         postProcess: function (node) {
1816             return node;
1817         },
1818
1819         createArrayExpression: function (elements) {
1820             return {
1821                 type: Syntax.ArrayExpression,
1822                 elements: elements
1823             };
1824         },
1825
1826         createAssignmentExpression: function (operator, left, right) {
1827             return {
1828                 type: Syntax.AssignmentExpression,
1829                 operator: operator,
1830                 left: left,
1831                 right: right
1832             };
1833         },
1834
1835         createBinaryExpression: function (operator, left, right) {
1836             var type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression :
1837                         Syntax.BinaryExpression;
1838             return {
1839                 type: type,
1840                 operator: operator,
1841                 left: left,
1842                 right: right
1843             };
1844         },
1845
1846         createBlockStatement: function (body) {
1847             return {
1848                 type: Syntax.BlockStatement,
1849                 body: body
1850             };
1851         },
1852
1853         createBreakStatement: function (label) {
1854             return {
1855                 type: Syntax.BreakStatement,
1856                 label: label
1857             };
1858         },
1859
1860         createCallExpression: function (callee, args) {
1861             return {
1862                 type: Syntax.CallExpression,
1863                 callee: callee,
1864                 'arguments': args
1865             };
1866         },
1867
1868         createCatchClause: function (param, body) {
1869             return {
1870                 type: Syntax.CatchClause,
1871                 param: param,
1872                 body: body
1873             };
1874         },
1875
1876         createConditionalExpression: function (test, consequent, alternate) {
1877             return {
1878                 type: Syntax.ConditionalExpression,
1879                 test: test,
1880                 consequent: consequent,
1881                 alternate: alternate
1882             };
1883         },
1884
1885         createContinueStatement: function (label) {
1886             return {
1887                 type: Syntax.ContinueStatement,
1888                 label: label
1889             };
1890         },
1891
1892         createDebuggerStatement: function () {
1893             return {
1894                 type: Syntax.DebuggerStatement
1895             };
1896         },
1897
1898         createDoWhileStatement: function (body, test) {
1899             return {
1900                 type: Syntax.DoWhileStatement,
1901                 body: body,
1902                 test: test
1903             };
1904         },
1905
1906         createEmptyStatement: function () {
1907             return {
1908                 type: Syntax.EmptyStatement
1909             };
1910         },
1911
1912         createExpressionStatement: function (expression) {
1913             return {
1914                 type: Syntax.ExpressionStatement,
1915                 expression: expression
1916             };
1917         },
1918
1919         createForStatement: function (init, test, update, body) {
1920             return {
1921                 type: Syntax.ForStatement,
1922                 init: init,
1923                 test: test,
1924                 update: update,
1925                 body: body
1926             };
1927         },
1928
1929         createForInStatement: function (left, right, body) {
1930             return {
1931                 type: Syntax.ForInStatement,
1932                 left: left,
1933                 right: right,
1934                 body: body,
1935                 each: false
1936             };
1937         },
1938
1939         createForOfStatement: function (left, right, body) {
1940             return {
1941                 type: Syntax.ForOfStatement,
1942                 left: left,
1943                 right: right,
1944                 body: body,
1945             };
1946         },
1947
1948         createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression) {
1949             return {
1950                 type: Syntax.FunctionDeclaration,
1951                 id: id,
1952                 params: params,
1953                 defaults: defaults,
1954                 body: body,
1955                 rest: rest,
1956                 generator: generator,
1957                 expression: expression
1958             };
1959         },
1960
1961         createFunctionExpression: function (id, params, defaults, body, rest, generator, expression) {
1962             return {
1963                 type: Syntax.FunctionExpression,
1964                 id: id,
1965                 params: params,
1966                 defaults: defaults,
1967                 body: body,
1968                 rest: rest,
1969                 generator: generator,
1970                 expression: expression
1971             };
1972         },
1973
1974         createIdentifier: function (name) {
1975             return {
1976                 type: Syntax.Identifier,
1977                 name: name
1978             };
1979         },
1980
1981         createXJSAttribute: function (name, value) {
1982             return {
1983                 type: Syntax.XJSAttribute,
1984                 name: name,
1985                 value: value
1986             };
1987         },
1988
1989         createXJSIdentifier: function (name, namespace) {
1990             return {
1991                 type: Syntax.XJSIdentifier,
1992                 name: name,
1993                 namespace: namespace
1994             };
1995         },
1996
1997         createXJSElement: function (openingElement, closingElement, children) {
1998             return {
1999                 type: Syntax.XJSElement,
2000                 name: openingElement.name,
2001                 selfClosing: openingElement.selfClosing,
2002                 openingElement: openingElement,
2003                 closingElement: closingElement,
2004                 attributes: openingElement.attributes,
2005                 children: children
2006             };
2007         },
2008
2009         createXJSEmptyExpression: function () {
2010             return {
2011                 type: Syntax.XJSEmptyExpression
2012             };
2013         },
2014
2015         createXJSExpressionContainer: function (expression) {
2016             return {
2017                 type: Syntax.XJSExpressionContainer,
2018                 expression: expression
2019             };
2020         },
2021
2022         createXJSOpeningElement: function (name, attributes, selfClosing) {
2023             return {
2024                 type: Syntax.XJSOpeningElement,
2025                 name: name,
2026                 selfClosing: selfClosing,
2027                 attributes: attributes
2028             };
2029         },
2030
2031         createXJSClosingElement: function (name) {
2032             return {
2033                 type: Syntax.XJSClosingElement,
2034                 name: name
2035             };
2036         },
2037
2038         createIfStatement: function (test, consequent, alternate) {
2039             return {
2040                 type: Syntax.IfStatement,
2041                 test: test,
2042                 consequent: consequent,
2043                 alternate: alternate
2044             };
2045         },
2046
2047         createLabeledStatement: function (label, body) {
2048             return {
2049                 type: Syntax.LabeledStatement,
2050                 label: label,
2051                 body: body
2052             };
2053         },
2054
2055         createLiteral: function (token) {
2056             return {
2057                 type: Syntax.Literal,
2058                 value: token.value,
2059                 raw: source.slice(token.range[0], token.range[1])
2060             };
2061         },
2062
2063         createMemberExpression: function (accessor, object, property) {
2064             return {
2065                 type: Syntax.MemberExpression,
2066                 computed: accessor === '[',
2067                 object: object,
2068                 property: property
2069             };
2070         },
2071
2072         createNewExpression: function (callee, args) {
2073             return {
2074                 type: Syntax.NewExpression,
2075                 callee: callee,
2076                 'arguments': args
2077             };
2078         },
2079
2080         createObjectExpression: function (properties) {
2081             return {
2082                 type: Syntax.ObjectExpression,
2083                 properties: properties
2084             };
2085         },
2086
2087         createPostfixExpression: function (operator, argument) {
2088             return {
2089                 type: Syntax.UpdateExpression,
2090                 operator: operator,
2091                 argument: argument,
2092                 prefix: false
2093             };
2094         },
2095
2096         createProgram: function (body) {
2097             return {
2098                 type: Syntax.Program,
2099                 body: body
2100             };
2101         },
2102
2103         createProperty: function (kind, key, value, method, shorthand) {
2104             return {
2105                 type: Syntax.Property,
2106                 key: key,
2107                 value: value,
2108                 kind: kind,
2109                 method: method,
2110                 shorthand: shorthand
2111             };
2112         },
2113
2114         createReturnStatement: function (argument) {
2115             return {
2116                 type: Syntax.ReturnStatement,
2117                 argument: argument
2118             };
2119         },
2120
2121         createSequenceExpression: function (expressions) {
2122             return {
2123                 type: Syntax.SequenceExpression,
2124                 expressions: expressions
2125             };
2126         },
2127
2128         createSwitchCase: function (test, consequent) {
2129             return {
2130                 type: Syntax.SwitchCase,
2131                 test: test,
2132                 consequent: consequent
2133             };
2134         },
2135
2136         createSwitchStatement: function (discriminant, cases) {
2137             return {
2138                 type: Syntax.SwitchStatement,
2139                 discriminant: discriminant,
2140                 cases: cases
2141             };
2142         },
2143
2144         createThisExpression: function () {
2145             return {
2146                 type: Syntax.ThisExpression
2147             };
2148         },
2149
2150         createThrowStatement: function (argument) {
2151             return {
2152                 type: Syntax.ThrowStatement,
2153                 argument: argument
2154             };
2155         },
2156
2157         createTryStatement: function (block, guardedHandlers, handlers, finalizer) {
2158             return {
2159                 type: Syntax.TryStatement,
2160                 block: block,
2161                 guardedHandlers: guardedHandlers,
2162                 handlers: handlers,
2163                 finalizer: finalizer
2164             };
2165         },
2166
2167         createUnaryExpression: function (operator, argument) {
2168             if (operator === '++' || operator === '--') {
2169                 return {
2170                     type: Syntax.UpdateExpression,
2171                     operator: operator,
2172                     argument: argument,
2173                     prefix: true
2174                 };
2175             }
2176             return {
2177                 type: Syntax.UnaryExpression,
2178                 operator: operator,
2179                 argument: argument
2180             };
2181         },
2182
2183         createVariableDeclaration: function (declarations, kind) {
2184             return {
2185                 type: Syntax.VariableDeclaration,
2186                 declarations: declarations,
2187                 kind: kind
2188             };
2189         },
2190
2191         createVariableDeclarator: function (id, init) {
2192             return {
2193                 type: Syntax.VariableDeclarator,
2194                 id: id,
2195                 init: init
2196             };
2197         },
2198
2199         createWhileStatement: function (test, body) {
2200             return {
2201                 type: Syntax.WhileStatement,
2202                 test: test,
2203                 body: body
2204             };
2205         },
2206
2207         createWithStatement: function (object, body) {
2208             return {
2209                 type: Syntax.WithStatement,
2210                 object: object,
2211                 body: body
2212             };
2213         },
2214
2215         createTemplateElement: function (value, tail) {
2216             return {
2217                 type: Syntax.TemplateElement,
2218                 value: value,
2219                 tail: tail
2220             };
2221         },
2222
2223         createTemplateLiteral: function (quasis, expressions) {
2224             return {
2225                 type: Syntax.TemplateLiteral,
2226                 quasis: quasis,
2227                 expressions: expressions
2228             };
2229         },
2230
2231         createSpreadElement: function (argument) {
2232             return {
2233                 type: Syntax.SpreadElement,
2234                 argument: argument
2235             };
2236         },
2237
2238         createTaggedTemplateExpression: function (tag, quasi) {
2239             return {
2240                 type: Syntax.TaggedTemplateExpression,
2241                 tag: tag,
2242                 quasi: quasi
2243             };
2244         },
2245
2246         createArrowFunctionExpression: function (params, defaults, body, rest, expression) {
2247             return {
2248                 type: Syntax.ArrowFunctionExpression,
2249                 id: null,
2250                 params: params,
2251                 defaults: defaults,
2252                 body: body,
2253                 rest: rest,
2254                 generator: false,
2255                 expression: expression
2256             };
2257         },
2258
2259         createMethodDefinition: function (propertyType, kind, key, value) {
2260             return {
2261                 type: Syntax.MethodDefinition,
2262                 key: key,
2263                 value: value,
2264                 kind: kind,
2265                 'static': propertyType === ClassPropertyType.static
2266             };
2267         },
2268
2269         createClassBody: function (body) {
2270             return {
2271                 type: Syntax.ClassBody,
2272                 body: body
2273             };
2274         },
2275
2276         createClassExpression: function (id, superClass, body) {
2277             return {
2278                 type: Syntax.ClassExpression,
2279                 id: id,
2280                 superClass: superClass,
2281                 body: body
2282             };
2283         },
2284
2285         createClassDeclaration: function (id, superClass, body) {
2286             return {
2287                 type: Syntax.ClassDeclaration,
2288                 id: id,
2289                 superClass: superClass,
2290                 body: body
2291             };
2292         },
2293
2294         createPath: function (body) {
2295             return {
2296                 type: Syntax.Path,
2297                 body: body
2298             };
2299         },
2300
2301         createGlob: function () {
2302             return {
2303                 type: Syntax.Glob
2304             };
2305         },
2306
2307         createExportSpecifier: function (id, from) {
2308             return {
2309                 type: Syntax.ExportSpecifier,
2310                 id: id,
2311                 from: from
2312             };
2313         },
2314
2315         createExportSpecifierSet: function (specifiers) {
2316             return {
2317                 type: Syntax.ExportSpecifierSet,
2318                 specifiers: specifiers
2319             };
2320         },
2321
2322         createExportDeclaration: function (declaration, specifiers) {
2323             return {
2324                 type: Syntax.ExportDeclaration,
2325                 declaration: declaration,
2326                 specifiers: specifiers
2327             };
2328         },
2329
2330         createImportSpecifier: function (id, from) {
2331             return {
2332                 type: Syntax.ImportSpecifier,
2333                 id: id,
2334                 from: from
2335             };
2336         },
2337
2338         createImportDeclaration: function (specifiers, from) {
2339             return {
2340                 type: Syntax.ImportDeclaration,
2341                 specifiers: specifiers,
2342                 from: from
2343             };
2344         },
2345
2346         createYieldExpression: function (argument, delegate) {
2347             return {
2348                 type: Syntax.YieldExpression,
2349                 argument: argument,
2350                 delegate: delegate
2351             };
2352         },
2353
2354         createModuleDeclaration: function (id, from, body) {
2355             return {
2356                 type: Syntax.ModuleDeclaration,
2357                 id: id,
2358                 from: from,
2359                 body: body
2360             };
2361         }
2362
2363
2364     };
2365
2366     // Return true if there is a line terminator before the next token.
2367
2368     function peekLineTerminator() {
2369         var pos, line, start, found;
2370
2371         pos = index;
2372         line = lineNumber;
2373         start = lineStart;
2374         skipComment();
2375         found = lineNumber !== line;
2376         index = pos;
2377         lineNumber = line;
2378         lineStart = start;
2379
2380         return found;
2381     }
2382
2383     // Throw an exception
2384
2385     function throwError(token, messageFormat) {
2386         var error,
2387             args = Array.prototype.slice.call(arguments, 2),
2388             msg = messageFormat.replace(
2389                 /%(\d)/g,
2390                 function (whole, index) {
2391                     assert(index < args.length, 'Message reference must be in range');
2392                     return args[index];
2393                 }
2394             );
2395
2396         if (typeof token.lineNumber === 'number') {
2397             error = new Error('Line ' + token.lineNumber + ': ' + msg);
2398             error.index = token.range[0];
2399             error.lineNumber = token.lineNumber;
2400             error.column = token.range[0] - lineStart + 1;
2401         } else {
2402             error = new Error('Line ' + lineNumber + ': ' + msg);
2403             error.index = index;
2404             error.lineNumber = lineNumber;
2405             error.column = index - lineStart + 1;
2406         }
2407
2408         error.description = msg;
2409         throw error;
2410     }
2411
2412     function throwErrorTolerant() {
2413         try {
2414             throwError.apply(null, arguments);
2415         } catch (e) {
2416             if (extra.errors) {
2417                 extra.errors.push(e);
2418             } else {
2419                 throw e;
2420             }
2421         }
2422     }
2423
2424
2425     // Throw an exception because of the token.
2426
2427     function throwUnexpected(token) {
2428         if (token.type === Token.EOF) {
2429             throwError(token, Messages.UnexpectedEOS);
2430         }
2431
2432         if (token.type === Token.NumericLiteral) {
2433             throwError(token, Messages.UnexpectedNumber);
2434         }
2435
2436         if (token.type === Token.StringLiteral) {
2437             throwError(token, Messages.UnexpectedString);
2438         }
2439
2440         if (token.type === Token.Identifier) {
2441             throwError(token, Messages.UnexpectedIdentifier);
2442         }
2443
2444         if (token.type === Token.Keyword) {
2445             if (isFutureReservedWord(token.value)) {
2446                 throwError(token, Messages.UnexpectedReserved);
2447             } else if (strict && isStrictModeReservedWord(token.value)) {
2448                 throwErrorTolerant(token, Messages.StrictReservedWord);
2449                 return;
2450             }
2451             throwError(token, Messages.UnexpectedToken, token.value);
2452         }
2453
2454         if (token.type === Token.Template) {
2455             throwError(token, Messages.UnexpectedTemplate, token.value.raw);
2456         }
2457
2458         // BooleanLiteral, NullLiteral, or Punctuator.
2459         throwError(token, Messages.UnexpectedToken, token.value);
2460     }
2461
2462     // Expect the next token to match the specified punctuator.
2463     // If not, an exception will be thrown.
2464
2465     function expect(value) {
2466         var token = lex();
2467         if (token.type !== Token.Punctuator || token.value !== value) {
2468             throwUnexpected(token);
2469         }
2470     }
2471
2472     // Expect the next token to match the specified keyword.
2473     // If not, an exception will be thrown.
2474
2475     function expectKeyword(keyword) {
2476         var token = lex();
2477         if (token.type !== Token.Keyword || token.value !== keyword) {
2478             throwUnexpected(token);
2479         }
2480     }
2481
2482     // Return true if the next token matches the specified punctuator.
2483
2484     function match(value) {
2485         return lookahead.type === Token.Punctuator && lookahead.value === value;
2486     }
2487
2488     // Return true if the next token matches the specified keyword
2489
2490     function matchKeyword(keyword) {
2491         return lookahead.type === Token.Keyword && lookahead.value === keyword;
2492     }
2493
2494
2495     // Return true if the next token matches the specified contextual keyword
2496
2497     function matchContextualKeyword(keyword) {
2498         return lookahead.type === Token.Identifier && lookahead.value === keyword;
2499     }
2500
2501     // Return true if the next token is an assignment operator
2502
2503     function matchAssign() {
2504         var op;
2505
2506         if (lookahead.type !== Token.Punctuator) {
2507             return false;
2508         }
2509         op = lookahead.value;
2510         return op === '=' ||
2511             op === '*=' ||
2512             op === '/=' ||
2513             op === '%=' ||
2514             op === '+=' ||
2515             op === '-=' ||
2516             op === '<<=' ||
2517             op === '>>=' ||
2518             op === '>>>=' ||
2519             op === '&=' ||
2520             op === '^=' ||
2521             op === '|=';
2522     }
2523
2524     function consumeSemicolon() {
2525         var line;
2526
2527         // Catch the very common case first: immediately a semicolon (char #59).
2528         if (source.charCodeAt(index) === 59) {
2529             lex();
2530             return;
2531         }
2532
2533         line = lineNumber;
2534         skipComment();
2535         if (lineNumber !== line) {
2536             return;
2537         }
2538
2539         if (match(';')) {
2540             lex();
2541             return;
2542         }
2543
2544         if (lookahead.type !== Token.EOF && !match('}')) {
2545             throwUnexpected(lookahead);
2546         }
2547     }
2548
2549     // Return true if provided expression is LeftHandSideExpression
2550
2551     function isLeftHandSide(expr) {
2552         return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
2553     }
2554
2555     function isAssignableLeftHandSide(expr) {
2556         return isLeftHandSide(expr) || expr.type === Syntax.ObjectPattern || expr.type === Syntax.ArrayPattern;
2557     }
2558
2559     // 11.1.4 Array Initialiser
2560
2561     function parseArrayInitialiser() {
2562         var elements = [], blocks = [], filter = null, tmp, possiblecomprehension = true, body;
2563
2564         expect('[');
2565         while (!match(']')) {
2566             if (lookahead.value === 'for' &&
2567                     lookahead.type === Token.Keyword) {
2568                 if (!possiblecomprehension) {
2569                     throwError({}, Messages.ComprehensionError);
2570                 }
2571                 matchKeyword('for');
2572                 tmp = parseForStatement({ignore_body: true});
2573                 tmp.of = tmp.type === Syntax.ForOfStatement;
2574                 tmp.type = Syntax.ComprehensionBlock;
2575                 if (tmp.left.kind) { // can't be let or const
2576                     throwError({}, Messages.ComprehensionError);
2577                 }
2578                 blocks.push(tmp);
2579             } else if (lookahead.value === 'if' &&
2580                            lookahead.type === Token.Keyword) {
2581                 if (!possiblecomprehension) {
2582                     throwError({}, Messages.ComprehensionError);
2583                 }
2584                 expectKeyword('if');
2585                 expect('(');
2586                 filter = parseExpression();
2587                 expect(')');
2588             } else if (lookahead.value === ',' &&
2589                            lookahead.type === Token.Punctuator) {
2590                 possiblecomprehension = false; // no longer allowed.
2591                 lex();
2592                 elements.push(null);
2593             } else {
2594                 tmp = parseSpreadOrAssignmentExpression();
2595                 elements.push(tmp);
2596                 if (tmp && tmp.type === Syntax.SpreadElement) {
2597                     if (!match(']')) {
2598                         throwError({}, Messages.ElementAfterSpreadElement);
2599                     }
2600                 } else if (!(match(']') || matchKeyword('for') || matchKeyword('if'))) {