jsduck 4.0.beta2 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,5 +3,4 @@ template/extjs
3
3
  template/resources/css
4
4
  template/resources/sass/.sass-cache
5
5
  template-min/
6
- esprima/
7
6
  sdk-vars.rb
data/README.md CHANGED
@@ -33,18 +33,32 @@ Standard rubygems install should do:
33
33
  $ [sudo] gem install jsduck
34
34
 
35
35
  If you encounter errors during gem installation, you may need to
36
- install the header files for compiling extension modules for ruby 1.8.
37
- For Debian systems you'll need the `ruby1.8-dev` package. For Red Hat
36
+ install the header files for compiling extension modules for Ruby 1.9.
37
+ For Debian systems you'll need the `ruby1.9-dev` package. For Red Hat
38
38
  / CentOS / Fedora use the `ruby-devel` package.
39
39
 
40
40
  For **Windows** users out there, you can download the binary version,
41
41
  which includes Ruby interpreter and all dependencies bundled in a
42
42
  single .exe file. Grab it from the [download page][].
43
43
 
44
- If you are brave enough: [try out JSDuck 4.0 beta.][beta]
44
+ Alternatively you can install through rubygems, but you need to do
45
+ some additional tweaks. First go and [download][libs download]
46
+ therubyracer gem and v8 lib that stereobooster has built for
47
+ windows. You need to install this special rubyracer version instead of
48
+ the one from rubygems:
49
+
50
+ > gem install therubyracer-0.11.0beta1-x86-mingw32.gem
51
+
52
+ To make it actually work you need `v8.dll` somewhere in your
53
+ system. Extract the `lib_v8.3.11.9.zip` take the `v8.dll` inside it
54
+ and place into the `bin` directory of your Ruby installation (other
55
+ dirs that are on your PATH can work too, but I've found this to be the
56
+ most sensible place to put it). Now you're ready to install JSDuck:
57
+
58
+ > gem install jsduck
45
59
 
46
60
  [download page]: https://github.com/senchalabs/jsduck/downloads
47
- [beta]: https://github.com/senchalabs/jsduck/wiki/4.0-beta
61
+ [libs download]: https://github.com/stereobooster/therubyracer/downloads
48
62
 
49
63
  Usage
50
64
  -----
@@ -59,37 +73,40 @@ You can also use `--verbose` option to see what's actually happening.
59
73
 
60
74
  To generate docs for Ext JS 4 add path to the corresponding src/ dir:
61
75
 
62
- $ jsduck ext-4.0.7/src \
76
+ $ jsduck ext-4.1.1/src \
63
77
  --builtin-classes \
64
- --images ext-4.0.7/docs/images \
78
+ --images ext-4.1.1/docs/images \
79
+ --warnings=-no_doc,-dup_member,-link_ambiguous \
80
+ --external XMLHttpRequest \
65
81
  --output your/docs
66
82
 
67
83
  The `--images` option specifies a path for images included with
68
84
  `{@img}` tags inside the source code.
69
85
 
86
+ The `--warnings` option disables some of the warnings which you would
87
+ otherwise be overwhelmed with. That's because Ext JS 4.1.1 was
88
+ released when JSDuck 4 wasn't out yet. Sorry for that, JSDuck just
89
+ wants to be helpful. Similarly the `--external` option defines
90
+ `XMLHttpRequest` as an external class, otherwise a warning would be
91
+ thrown.
92
+
93
+ Another thing that often happens is that JSDuck is unable to determine
94
+ into which class a member belongs and will place all such items into a
95
+ global class - you can disable this using the `--ignore-global`
96
+ switch. For full list of all command line options type
97
+ `jsduck --help`. For help on a specific option use
98
+ `--help=--some-option`.
99
+
70
100
  To generate docs for your own project, simply name additional input
71
101
  directories:
72
102
 
73
- $ jsduck ext-4.0.7/src project1/js project2/js ...
103
+ $ jsduck ext-4.1.1/src project1/js project2/js ...
74
104
 
75
105
  Note that the resulting documentation will only contain the API
76
106
  documentation. Guides, videos and examples will not be present.
77
107
  These can be added using more command line options as explained in the
78
108
  [Advanced Usage][adv] section of wiki.
79
109
 
80
- Running latest JSDuck is expected to generate lots of warnings.
81
- That's because some warning types were added after Ext JS 4.0.7
82
- release. Sorry for that, JSDuck just wants to be helpful. If you are
83
- overwhelmed by the warnings, you can disable them selectively using
84
- something like `--warnings=-link_ambiguous,-no_doc` or you could
85
- disable them all by `--warnings=-all`.
86
-
87
- Another thing that often happens is that JSDuck is unable to determine
88
- into which class a member belongs and will place all such items into a
89
- global class - you can disable this using the `--ignore-global`
90
- switch. For full list of all command line options type
91
- `jsduck --help=full`.
92
-
93
110
  [adv]: https://github.com/senchalabs/jsduck/wiki/Advanced-Usage
94
111
 
95
112
 
@@ -144,6 +161,9 @@ Thanks to [Ondřej Jirman](https://github.com/megous),
144
161
  Katherine Chu,
145
162
  [Rob Dougan](https://github.com/rdougan),
146
163
  [Dave Thompson](https://github.com/limscoder),
164
+ [burnnat](https://github.com/burnnat),
165
+ [vjetteam](https://github.com/vjetteam),
166
+ [Chris Westbrook](https://github.com/cnstaging),
147
167
  and many-many others who reported bugs, submitted patches, and
148
168
  provided a lot of useful input.
149
169
 
data/Rakefile CHANGED
@@ -220,7 +220,6 @@ task :ext4 => :sass do
220
220
  runner = JsDuckRunner.new
221
221
  runner.add_ext4
222
222
  runner.add_debug
223
- runner.add_options("--tests")
224
223
  runner.run
225
224
 
226
225
  system("cp -r #{EXT_BUILD} #{OUT_DIR}/extjs-build")
@@ -233,14 +232,7 @@ task :sdk => :sass do
233
232
  "--output", OUT_DIR,
234
233
  "--config", "#{SDK_DIR}/extjs/docs/config.json",
235
234
  "--examples-base-url", "extjs-build/examples/",
236
- "--import", "Ext JS 1:compare/ext11",
237
- "--import", "Ext JS 2:compare/ext23",
238
- "--import", "Ext JS 3:compare/ext34",
239
- "--import", "Ext JS 4.0.7:compare/ext407",
240
- "--import", "Ext JS 4.1.0:compare/ext410",
241
- "--import", "Ext JS 4.1.1",
242
- "--seo",
243
- "--tests"
235
+ "--seo"
244
236
  )
245
237
  runner.add_debug
246
238
  runner.add_comments('ext-js', '4')
@@ -256,8 +248,7 @@ task :touch2 => :sass do
256
248
  "--output", OUT_DIR,
257
249
  "--config", "#{SDK_DIR}/touch/docs/config.json",
258
250
  "--examples-base-url", "touch-build/examples/production/",
259
- "--seo",
260
- "--tests"
251
+ "--seo"
261
252
  )
262
253
 
263
254
  runner.add_debug
@@ -0,0 +1,3581 @@
1
+ /*
2
+ Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
3
+ Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
4
+ Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
5
+ Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
6
+ Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
7
+ Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
8
+ Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
9
+
10
+ Redistribution and use in source and binary forms, with or without
11
+ modification, are permitted provided that the following conditions are met:
12
+
13
+ * Redistributions of source code must retain the above copyright
14
+ notice, this list of conditions and the following disclaimer.
15
+ * Redistributions in binary form must reproduce the above copyright
16
+ notice, this list of conditions and the following disclaimer in the
17
+ documentation and/or other materials provided with the distribution.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
23
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ /*jslint bitwise:true plusplus:true */
32
+ /*global esprima:true, exports:true,
33
+ throwError: true, createLiteral: true, generateStatement: true,
34
+ parseAssignmentExpression: true, parseBlock: true, parseExpression: true,
35
+ parseFunctionDeclaration: true, parseFunctionExpression: true,
36
+ parseFunctionSourceElements: true, parseVariableIdentifier: true,
37
+ parseLeftHandSideExpression: true,
38
+ parseStatement: true, parseSourceElement: true */
39
+
40
+ (function (exports) {
41
+ 'use strict';
42
+
43
+ var Token,
44
+ TokenName,
45
+ Syntax,
46
+ PropertyKind,
47
+ Messages,
48
+ Regex,
49
+ source,
50
+ strict,
51
+ index,
52
+ lineNumber,
53
+ lineStart,
54
+ length,
55
+ buffer,
56
+ state,
57
+ extra;
58
+
59
+ Token = {
60
+ BooleanLiteral: 1,
61
+ EOF: 2,
62
+ Identifier: 3,
63
+ Keyword: 4,
64
+ NullLiteral: 5,
65
+ NumericLiteral: 6,
66
+ Punctuator: 7,
67
+ StringLiteral: 8
68
+ };
69
+
70
+ TokenName = {};
71
+ TokenName[Token.BooleanLiteral] = 'Boolean';
72
+ TokenName[Token.EOF] = '<end>';
73
+ TokenName[Token.Identifier] = 'Identifier';
74
+ TokenName[Token.Keyword] = 'Keyword';
75
+ TokenName[Token.NullLiteral] = 'Null';
76
+ TokenName[Token.NumericLiteral] = 'Numeric';
77
+ TokenName[Token.Punctuator] = 'Punctuator';
78
+ TokenName[Token.StringLiteral] = 'String';
79
+
80
+ Syntax = {
81
+ AssignmentExpression: 'AssignmentExpression',
82
+ ArrayExpression: 'ArrayExpression',
83
+ BlockStatement: 'BlockStatement',
84
+ BinaryExpression: 'BinaryExpression',
85
+ BreakStatement: 'BreakStatement',
86
+ CallExpression: 'CallExpression',
87
+ CatchClause: 'CatchClause',
88
+ ConditionalExpression: 'ConditionalExpression',
89
+ ContinueStatement: 'ContinueStatement',
90
+ DoWhileStatement: 'DoWhileStatement',
91
+ DebuggerStatement: 'DebuggerStatement',
92
+ EmptyStatement: 'EmptyStatement',
93
+ ExpressionStatement: 'ExpressionStatement',
94
+ ForStatement: 'ForStatement',
95
+ ForInStatement: 'ForInStatement',
96
+ FunctionDeclaration: 'FunctionDeclaration',
97
+ FunctionExpression: 'FunctionExpression',
98
+ Identifier: 'Identifier',
99
+ IfStatement: 'IfStatement',
100
+ Literal: 'Literal',
101
+ LabeledStatement: 'LabeledStatement',
102
+ LogicalExpression: 'LogicalExpression',
103
+ MemberExpression: 'MemberExpression',
104
+ NewExpression: 'NewExpression',
105
+ ObjectExpression: 'ObjectExpression',
106
+ Program: 'Program',
107
+ Property: 'Property',
108
+ ReturnStatement: 'ReturnStatement',
109
+ SequenceExpression: 'SequenceExpression',
110
+ SwitchStatement: 'SwitchStatement',
111
+ SwitchCase: 'SwitchCase',
112
+ ThisExpression: 'ThisExpression',
113
+ ThrowStatement: 'ThrowStatement',
114
+ TryStatement: 'TryStatement',
115
+ UnaryExpression: 'UnaryExpression',
116
+ UpdateExpression: 'UpdateExpression',
117
+ VariableDeclaration: 'VariableDeclaration',
118
+ VariableDeclarator: 'VariableDeclarator',
119
+ WhileStatement: 'WhileStatement',
120
+ WithStatement: 'WithStatement'
121
+ };
122
+
123
+ PropertyKind = {
124
+ Data: 1,
125
+ Get: 2,
126
+ Set: 4
127
+ };
128
+
129
+ // Error messages should be identical to V8.
130
+ Messages = {
131
+ UnexpectedToken: 'Unexpected token %0',
132
+ UnexpectedNumber: 'Unexpected number',
133
+ UnexpectedString: 'Unexpected string',
134
+ UnexpectedIdentifier: 'Unexpected identifier',
135
+ UnexpectedReserved: 'Unexpected reserved word',
136
+ UnexpectedEOS: 'Unexpected end of input',
137
+ NewlineAfterThrow: 'Illegal newline after throw',
138
+ InvalidRegExp: 'Invalid regular expression',
139
+ UnterminatedRegExp: 'Invalid regular expression: missing /',
140
+ InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
141
+ InvalidLHSInForIn: 'Invalid left-hand side in for-in',
142
+ NoCatchOrFinally: 'Missing catch or finally after try',
143
+ UnknownLabel: 'Undefined label \'%0\'',
144
+ Redeclaration: '%0 \'%1\' has already been declared',
145
+ IllegalContinue: 'Illegal continue statement',
146
+ IllegalBreak: 'Illegal break statement',
147
+ IllegalReturn: 'Illegal return statement',
148
+ StrictModeWith: 'Strict mode code may not include a with statement',
149
+ StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
150
+ StrictVarName: 'Variable name may not be eval or arguments in strict mode',
151
+ StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
152
+ StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
153
+ StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
154
+ StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
155
+ StrictDelete: 'Delete of an unqualified identifier in strict mode.',
156
+ StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
157
+ AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
158
+ AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
159
+ StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
160
+ StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
161
+ StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
162
+ StrictReservedWord: 'Use of future reserved word in strict mode'
163
+ };
164
+
165
+ // See also tools/generate-unicode-regex.py.
166
+ Regex = {
167
+ 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]'),
168
+ 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]')
169
+ };
170
+
171
+ // Ensure the condition is true, otherwise throw an error.
172
+ // This is only to have a better contract semantic, i.e. another safety net
173
+ // to catch a logic error. The condition shall be fulfilled in normal case.
174
+ // Do NOT use this to enforce a certain condition on any user input.
175
+
176
+ function assert(condition, message) {
177
+ if (!condition) {
178
+ throw new Error('ASSERT: ' + message);
179
+ }
180
+ }
181
+
182
+ function sliceSource(from, to) {
183
+ return source.slice(from, to);
184
+ }
185
+
186
+ if (typeof 'esprima'[0] === 'undefined') {
187
+ sliceSource = function sliceArraySource(from, to) {
188
+ return source.slice(from, to).join('');
189
+ };
190
+ }
191
+
192
+ function isDecimalDigit(ch) {
193
+ return '0123456789'.indexOf(ch) >= 0;
194
+ }
195
+
196
+ function isHexDigit(ch) {
197
+ return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
198
+ }
199
+
200
+ function isOctalDigit(ch) {
201
+ return '01234567'.indexOf(ch) >= 0;
202
+ }
203
+
204
+
205
+ // 7.2 White Space
206
+
207
+ function isWhiteSpace(ch) {
208
+ return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') ||
209
+ (ch === '\u000C') || (ch === '\u00A0') ||
210
+ (ch.charCodeAt(0) >= 0x1680 &&
211
+ '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0);
212
+ }
213
+
214
+ // 7.3 Line Terminators
215
+
216
+ function isLineTerminator(ch) {
217
+ return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029');
218
+ }
219
+
220
+ // 7.6 Identifier Names and Identifiers
221
+
222
+ function isIdentifierStart(ch) {
223
+ return (ch === '$') || (ch === '_') || (ch === '\\') ||
224
+ (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
225
+ ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch));
226
+ }
227
+
228
+ function isIdentifierPart(ch) {
229
+ return (ch === '$') || (ch === '_') || (ch === '\\') ||
230
+ (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
231
+ ((ch >= '0') && (ch <= '9')) ||
232
+ ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
233
+ }
234
+
235
+ // 7.6.1.2 Future Reserved Words
236
+
237
+ function isFutureReservedWord(id) {
238
+ switch (id) {
239
+
240
+ // Future reserved words.
241
+ case 'class':
242
+ case 'enum':
243
+ case 'export':
244
+ case 'extends':
245
+ case 'import':
246
+ case 'super':
247
+ return true;
248
+ }
249
+
250
+ return false;
251
+ }
252
+
253
+ function isStrictModeReservedWord(id) {
254
+ switch (id) {
255
+
256
+ // Strict Mode reserved words.
257
+ case 'implements':
258
+ case 'interface':
259
+ case 'package':
260
+ case 'private':
261
+ case 'protected':
262
+ case 'public':
263
+ case 'static':
264
+ case 'yield':
265
+ case 'let':
266
+ return true;
267
+ }
268
+
269
+ return false;
270
+ }
271
+
272
+ function isRestrictedWord(id) {
273
+ return id === 'eval' || id === 'arguments';
274
+ }
275
+
276
+ // 7.6.1.1 Keywords
277
+
278
+ function isKeyword(id) {
279
+ var keyword = false;
280
+ switch (id.length) {
281
+ case 2:
282
+ keyword = (id === 'if') || (id === 'in') || (id === 'do');
283
+ break;
284
+ case 3:
285
+ keyword = (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try');
286
+ break;
287
+ case 4:
288
+ keyword = (id === 'this') || (id === 'else') || (id === 'case') || (id === 'void') || (id === 'with');
289
+ break;
290
+ case 5:
291
+ keyword = (id === 'while') || (id === 'break') || (id === 'catch') || (id === 'throw');
292
+ break;
293
+ case 6:
294
+ keyword = (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch');
295
+ break;
296
+ case 7:
297
+ keyword = (id === 'default') || (id === 'finally');
298
+ break;
299
+ case 8:
300
+ keyword = (id === 'function') || (id === 'continue') || (id === 'debugger');
301
+ break;
302
+ case 10:
303
+ keyword = (id === 'instanceof');
304
+ break;
305
+ }
306
+
307
+ if (keyword) {
308
+ return true;
309
+ }
310
+
311
+ switch (id) {
312
+ // Future reserved words.
313
+ // 'const' is specialized as Keyword in V8.
314
+ case 'const':
315
+ return true;
316
+
317
+ // For compatiblity to SpiderMonkey and ES.next
318
+ case 'yield':
319
+ case 'let':
320
+ return true;
321
+ }
322
+
323
+ if (strict && isStrictModeReservedWord(id)) {
324
+ return true;
325
+ }
326
+
327
+ return isFutureReservedWord(id);
328
+ }
329
+
330
+ // Return the next character and move forward.
331
+
332
+ function nextChar() {
333
+ return source[index++];
334
+ }
335
+
336
+ // 7.4 Comments
337
+
338
+ function skipComment() {
339
+ var ch, blockComment, lineComment;
340
+
341
+ blockComment = false;
342
+ lineComment = false;
343
+
344
+ while (index < length) {
345
+ ch = source[index];
346
+
347
+ if (lineComment) {
348
+ ch = nextChar();
349
+ if (isLineTerminator(ch)) {
350
+ lineComment = false;
351
+ if (ch === '\r' && source[index] === '\n') {
352
+ ++index;
353
+ }
354
+ ++lineNumber;
355
+ lineStart = index;
356
+ }
357
+ } else if (blockComment) {
358
+ if (isLineTerminator(ch)) {
359
+ if (ch === '\r' && source[index + 1] === '\n') {
360
+ ++index;
361
+ }
362
+ ++lineNumber;
363
+ ++index;
364
+ lineStart = index;
365
+ if (index >= length) {
366
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
367
+ }
368
+ } else {
369
+ ch = nextChar();
370
+ if (index >= length) {
371
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
372
+ }
373
+ if (ch === '*') {
374
+ ch = source[index];
375
+ if (ch === '/') {
376
+ ++index;
377
+ blockComment = false;
378
+ }
379
+ }
380
+ }
381
+ } else if (ch === '/') {
382
+ ch = source[index + 1];
383
+ if (ch === '/') {
384
+ index += 2;
385
+ lineComment = true;
386
+ } else if (ch === '*') {
387
+ index += 2;
388
+ blockComment = true;
389
+ if (index >= length) {
390
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
391
+ }
392
+ } else {
393
+ break;
394
+ }
395
+ } else if (isWhiteSpace(ch)) {
396
+ ++index;
397
+ } else if (isLineTerminator(ch)) {
398
+ ++index;
399
+ if (ch === '\r' && source[index] === '\n') {
400
+ ++index;
401
+ }
402
+ ++lineNumber;
403
+ lineStart = index;
404
+ } else {
405
+ break;
406
+ }
407
+ }
408
+ }
409
+
410
+ function scanHexEscape(prefix) {
411
+ var i, len, ch, code = 0;
412
+
413
+ len = (prefix === 'u') ? 4 : 2;
414
+ for (i = 0; i < len; ++i) {
415
+ if (index < length && isHexDigit(source[index])) {
416
+ ch = nextChar();
417
+ code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
418
+ } else {
419
+ return '';
420
+ }
421
+ }
422
+ return String.fromCharCode(code);
423
+ }
424
+
425
+ function scanIdentifier() {
426
+ var ch, start, id, restore;
427
+
428
+ ch = source[index];
429
+ if (!isIdentifierStart(ch)) {
430
+ return;
431
+ }
432
+
433
+ start = index;
434
+ if (ch === '\\') {
435
+ ++index;
436
+ if (source[index] !== 'u') {
437
+ return;
438
+ }
439
+ ++index;
440
+ restore = index;
441
+ ch = scanHexEscape('u');
442
+ if (ch) {
443
+ if (ch === '\\' || !isIdentifierStart(ch)) {
444
+ return;
445
+ }
446
+ id = ch;
447
+ } else {
448
+ index = restore;
449
+ id = 'u';
450
+ }
451
+ } else {
452
+ id = nextChar();
453
+ }
454
+
455
+ while (index < length) {
456
+ ch = source[index];
457
+ if (!isIdentifierPart(ch)) {
458
+ break;
459
+ }
460
+ if (ch === '\\') {
461
+ ++index;
462
+ if (source[index] !== 'u') {
463
+ return;
464
+ }
465
+ ++index;
466
+ restore = index;
467
+ ch = scanHexEscape('u');
468
+ if (ch) {
469
+ if (ch === '\\' || !isIdentifierPart(ch)) {
470
+ return;
471
+ }
472
+ id += ch;
473
+ } else {
474
+ index = restore;
475
+ id += 'u';
476
+ }
477
+ } else {
478
+ id += nextChar();
479
+ }
480
+ }
481
+
482
+ // There is no keyword or literal with only one character.
483
+ // Thus, it must be an identifier.
484
+ if (id.length === 1) {
485
+ return {
486
+ type: Token.Identifier,
487
+ value: id,
488
+ lineNumber: lineNumber,
489
+ lineStart: lineStart,
490
+ range: [start, index]
491
+ };
492
+ }
493
+
494
+ if (isKeyword(id)) {
495
+ return {
496
+ type: Token.Keyword,
497
+ value: id,
498
+ lineNumber: lineNumber,
499
+ lineStart: lineStart,
500
+ range: [start, index]
501
+ };
502
+ }
503
+
504
+ // 7.8.1 Null Literals
505
+
506
+ if (id === 'null') {
507
+ return {
508
+ type: Token.NullLiteral,
509
+ value: id,
510
+ lineNumber: lineNumber,
511
+ lineStart: lineStart,
512
+ range: [start, index]
513
+ };
514
+ }
515
+
516
+ // 7.8.2 Boolean Literals
517
+
518
+ if (id === 'true' || id === 'false') {
519
+ return {
520
+ type: Token.BooleanLiteral,
521
+ value: id,
522
+ lineNumber: lineNumber,
523
+ lineStart: lineStart,
524
+ range: [start, index]
525
+ };
526
+ }
527
+
528
+ return {
529
+ type: Token.Identifier,
530
+ value: id,
531
+ lineNumber: lineNumber,
532
+ lineStart: lineStart,
533
+ range: [start, index]
534
+ };
535
+ }
536
+
537
+ // 7.7 Punctuators
538
+
539
+ function scanPunctuator() {
540
+ var start = index,
541
+ ch1 = source[index],
542
+ ch2,
543
+ ch3,
544
+ ch4;
545
+
546
+ // Check for most common single-character punctuators.
547
+
548
+ if (ch1 === ';' || ch1 === '{' || ch1 === '}') {
549
+ ++index;
550
+ return {
551
+ type: Token.Punctuator,
552
+ value: ch1,
553
+ lineNumber: lineNumber,
554
+ lineStart: lineStart,
555
+ range: [start, index]
556
+ };
557
+ }
558
+
559
+ if (ch1 === ',' || ch1 === '(' || ch1 === ')') {
560
+ ++index;
561
+ return {
562
+ type: Token.Punctuator,
563
+ value: ch1,
564
+ lineNumber: lineNumber,
565
+ lineStart: lineStart,
566
+ range: [start, index]
567
+ };
568
+ }
569
+
570
+ // Dot (.) can also start a floating-point number, hence the need
571
+ // to check the next character.
572
+
573
+ ch2 = source[index + 1];
574
+ if (ch1 === '.' && !isDecimalDigit(ch2)) {
575
+ return {
576
+ type: Token.Punctuator,
577
+ value: nextChar(),
578
+ lineNumber: lineNumber,
579
+ lineStart: lineStart,
580
+ range: [start, index]
581
+ };
582
+ }
583
+
584
+ // Peek more characters.
585
+
586
+ ch3 = source[index + 2];
587
+ ch4 = source[index + 3];
588
+
589
+ // 4-character punctuator: >>>=
590
+
591
+ if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
592
+ if (ch4 === '=') {
593
+ index += 4;
594
+ return {
595
+ type: Token.Punctuator,
596
+ value: '>>>=',
597
+ lineNumber: lineNumber,
598
+ lineStart: lineStart,
599
+ range: [start, index]
600
+ };
601
+ }
602
+ }
603
+
604
+ // 3-character punctuators: === !== >>> <<= >>=
605
+
606
+ if (ch1 === '=' && ch2 === '=' && ch3 === '=') {
607
+ index += 3;
608
+ return {
609
+ type: Token.Punctuator,
610
+ value: '===',
611
+ lineNumber: lineNumber,
612
+ lineStart: lineStart,
613
+ range: [start, index]
614
+ };
615
+ }
616
+
617
+ if (ch1 === '!' && ch2 === '=' && ch3 === '=') {
618
+ index += 3;
619
+ return {
620
+ type: Token.Punctuator,
621
+ value: '!==',
622
+ lineNumber: lineNumber,
623
+ lineStart: lineStart,
624
+ range: [start, index]
625
+ };
626
+ }
627
+
628
+ if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
629
+ index += 3;
630
+ return {
631
+ type: Token.Punctuator,
632
+ value: '>>>',
633
+ lineNumber: lineNumber,
634
+ lineStart: lineStart,
635
+ range: [start, index]
636
+ };
637
+ }
638
+
639
+ if (ch1 === '<' && ch2 === '<' && ch3 === '=') {
640
+ index += 3;
641
+ return {
642
+ type: Token.Punctuator,
643
+ value: '<<=',
644
+ lineNumber: lineNumber,
645
+ lineStart: lineStart,
646
+ range: [start, index]
647
+ };
648
+ }
649
+
650
+ if (ch1 === '>' && ch2 === '>' && ch3 === '=') {
651
+ index += 3;
652
+ return {
653
+ type: Token.Punctuator,
654
+ value: '>>=',
655
+ lineNumber: lineNumber,
656
+ lineStart: lineStart,
657
+ range: [start, index]
658
+ };
659
+ }
660
+
661
+ // 2-character punctuators: <= >= == != ++ -- << >> && ||
662
+ // += -= *= %= &= |= ^= /=
663
+
664
+ if (ch2 === '=') {
665
+ if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
666
+ index += 2;
667
+ return {
668
+ type: Token.Punctuator,
669
+ value: ch1 + ch2,
670
+ lineNumber: lineNumber,
671
+ lineStart: lineStart,
672
+ range: [start, index]
673
+ };
674
+ }
675
+ }
676
+
677
+ if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) {
678
+ if ('+-<>&|'.indexOf(ch2) >= 0) {
679
+ index += 2;
680
+ return {
681
+ type: Token.Punctuator,
682
+ value: ch1 + ch2,
683
+ lineNumber: lineNumber,
684
+ lineStart: lineStart,
685
+ range: [start, index]
686
+ };
687
+ }
688
+ }
689
+
690
+ // The remaining 1-character punctuators.
691
+
692
+ if ('[]<>+-*%&|^!~?:=/'.indexOf(ch1) >= 0) {
693
+ return {
694
+ type: Token.Punctuator,
695
+ value: nextChar(),
696
+ lineNumber: lineNumber,
697
+ lineStart: lineStart,
698
+ range: [start, index]
699
+ };
700
+ }
701
+ }
702
+
703
+ // 7.8.3 Numeric Literals
704
+
705
+ function scanNumericLiteral() {
706
+ var number, start, ch;
707
+
708
+ ch = source[index];
709
+ assert(isDecimalDigit(ch) || (ch === '.'),
710
+ 'Numeric literal must start with a decimal digit or a decimal point');
711
+
712
+ start = index;
713
+ number = '';
714
+ if (ch !== '.') {
715
+ number = nextChar();
716
+ ch = source[index];
717
+
718
+ // Hex number starts with '0x'.
719
+ // Octal number starts with '0'.
720
+ if (number === '0') {
721
+ if (ch === 'x' || ch === 'X') {
722
+ number += nextChar();
723
+ while (index < length) {
724
+ ch = source[index];
725
+ if (!isHexDigit(ch)) {
726
+ break;
727
+ }
728
+ number += nextChar();
729
+ }
730
+
731
+ if (number.length <= 2) {
732
+ // only 0x
733
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
734
+ }
735
+
736
+ if (index < length) {
737
+ ch = source[index];
738
+ if (isIdentifierStart(ch)) {
739
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
740
+ }
741
+ }
742
+ return {
743
+ type: Token.NumericLiteral,
744
+ value: parseInt(number, 16),
745
+ lineNumber: lineNumber,
746
+ lineStart: lineStart,
747
+ range: [start, index]
748
+ };
749
+ } else if (isOctalDigit(ch)) {
750
+ number += nextChar();
751
+ while (index < length) {
752
+ ch = source[index];
753
+ if (!isOctalDigit(ch)) {
754
+ break;
755
+ }
756
+ number += nextChar();
757
+ }
758
+
759
+ if (index < length) {
760
+ ch = source[index];
761
+ if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
762
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
763
+ }
764
+ }
765
+ return {
766
+ type: Token.NumericLiteral,
767
+ value: parseInt(number, 8),
768
+ octal: true,
769
+ lineNumber: lineNumber,
770
+ lineStart: lineStart,
771
+ range: [start, index]
772
+ };
773
+ }
774
+
775
+ // decimal number starts with '0' such as '09' is illegal.
776
+ if (isDecimalDigit(ch)) {
777
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
778
+ }
779
+ }
780
+
781
+ while (index < length) {
782
+ ch = source[index];
783
+ if (!isDecimalDigit(ch)) {
784
+ break;
785
+ }
786
+ number += nextChar();
787
+ }
788
+ }
789
+
790
+ if (ch === '.') {
791
+ number += nextChar();
792
+ while (index < length) {
793
+ ch = source[index];
794
+ if (!isDecimalDigit(ch)) {
795
+ break;
796
+ }
797
+ number += nextChar();
798
+ }
799
+ }
800
+
801
+ if (ch === 'e' || ch === 'E') {
802
+ number += nextChar();
803
+
804
+ ch = source[index];
805
+ if (ch === '+' || ch === '-') {
806
+ number += nextChar();
807
+ }
808
+
809
+ ch = source[index];
810
+ if (isDecimalDigit(ch)) {
811
+ number += nextChar();
812
+ while (index < length) {
813
+ ch = source[index];
814
+ if (!isDecimalDigit(ch)) {
815
+ break;
816
+ }
817
+ number += nextChar();
818
+ }
819
+ } else {
820
+ ch = 'character ' + ch;
821
+ if (index >= length) {
822
+ ch = '<end>';
823
+ }
824
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
825
+ }
826
+ }
827
+
828
+ if (index < length) {
829
+ ch = source[index];
830
+ if (isIdentifierStart(ch)) {
831
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
832
+ }
833
+ }
834
+
835
+ return {
836
+ type: Token.NumericLiteral,
837
+ value: parseFloat(number),
838
+ lineNumber: lineNumber,
839
+ lineStart: lineStart,
840
+ range: [start, index]
841
+ };
842
+ }
843
+
844
+ // 7.8.4 String Literals
845
+
846
+ function scanStringLiteral() {
847
+ var str = '', quote, start, ch, code, unescaped, restore, octal = false;
848
+
849
+ quote = source[index];
850
+ assert((quote === '\'' || quote === '"'),
851
+ 'String literal must starts with a quote');
852
+
853
+ start = index;
854
+ ++index;
855
+
856
+ while (index < length) {
857
+ ch = nextChar();
858
+
859
+ if (ch === quote) {
860
+ quote = '';
861
+ break;
862
+ } else if (ch === '\\') {
863
+ ch = nextChar();
864
+ if (!isLineTerminator(ch)) {
865
+ switch (ch) {
866
+ case 'n':
867
+ str += '\n';
868
+ break;
869
+ case 'r':
870
+ str += '\r';
871
+ break;
872
+ case 't':
873
+ str += '\t';
874
+ break;
875
+ case 'u':
876
+ case 'x':
877
+ restore = index;
878
+ unescaped = scanHexEscape(ch);
879
+ if (unescaped) {
880
+ str += unescaped;
881
+ } else {
882
+ index = restore;
883
+ str += ch;
884
+ }
885
+ break;
886
+ case 'b':
887
+ str += '\b';
888
+ break;
889
+ case 'f':
890
+ str += '\f';
891
+ break;
892
+ case 'v':
893
+ str += '\v';
894
+ break;
895
+
896
+ default:
897
+ if (isOctalDigit(ch)) {
898
+ code = '01234567'.indexOf(ch);
899
+
900
+ // \0 is not octal escape sequence
901
+ if (code !== 0) {
902
+ octal = true;
903
+ }
904
+
905
+ if (index < length && isOctalDigit(source[index])) {
906
+ octal = true;
907
+ code = code * 8 + '01234567'.indexOf(nextChar());
908
+
909
+ // 3 digits are only allowed when string starts
910
+ // with 0, 1, 2, 3
911
+ if ('0123'.indexOf(ch) >= 0 &&
912
+ index < length &&
913
+ isOctalDigit(source[index])) {
914
+ code = code * 8 + '01234567'.indexOf(nextChar());
915
+ }
916
+ }
917
+ str += String.fromCharCode(code);
918
+ } else {
919
+ str += ch;
920
+ }
921
+ break;
922
+ }
923
+ } else {
924
+ ++lineNumber;
925
+ if (ch === '\r' && source[index] === '\n') {
926
+ ++index;
927
+ }
928
+ }
929
+ } else if (isLineTerminator(ch)) {
930
+ break;
931
+ } else {
932
+ str += ch;
933
+ }
934
+ }
935
+
936
+ if (quote !== '') {
937
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
938
+ }
939
+
940
+ return {
941
+ type: Token.StringLiteral,
942
+ value: str,
943
+ octal: octal,
944
+ lineNumber: lineNumber,
945
+ lineStart: lineStart,
946
+ range: [start, index]
947
+ };
948
+ }
949
+
950
+ function scanRegExp() {
951
+ var str = '', ch, start, pattern, flags, value, classMarker = false, restore;
952
+
953
+ buffer = null;
954
+ skipComment();
955
+
956
+ start = index;
957
+ ch = source[index];
958
+ assert(ch === '/', 'Regular expression literal must start with a slash');
959
+ str = nextChar();
960
+
961
+ while (index < length) {
962
+ ch = nextChar();
963
+ str += ch;
964
+ if (classMarker) {
965
+ if (ch === ']') {
966
+ classMarker = false;
967
+ }
968
+ } else {
969
+ if (ch === '\\') {
970
+ ch = nextChar();
971
+ // ECMA-262 7.8.5
972
+ if (isLineTerminator(ch)) {
973
+ throwError({}, Messages.UnterminatedRegExp);
974
+ }
975
+ str += ch;
976
+ }
977
+ else if (ch === '/') {
978
+ break;
979
+ }
980
+ else if (ch === '[') {
981
+ classMarker = true;
982
+ }
983
+ else if (isLineTerminator(ch)) {
984
+ throwError({}, Messages.UnterminatedRegExp);
985
+ }
986
+ }
987
+ }
988
+
989
+ if (str.length === 1) {
990
+ throwError({}, Messages.UnterminatedRegExp);
991
+ }
992
+
993
+ // Exclude leading and trailing slash.
994
+ pattern = str.substr(1, str.length - 2);
995
+
996
+ flags = '';
997
+ while (index < length) {
998
+ ch = source[index];
999
+ if (!isIdentifierPart(ch)) {
1000
+ break;
1001
+ }
1002
+
1003
+ ++index;
1004
+ if (ch === '\\' && index < length) {
1005
+ ch = source[index];
1006
+ if (ch === 'u') {
1007
+ ++index;
1008
+ restore = index;
1009
+ ch = scanHexEscape('u');
1010
+ if (ch) {
1011
+ flags += ch;
1012
+ str += '\\u';
1013
+ for (; restore < index; ++restore) {
1014
+ str += source[restore];
1015
+ }
1016
+ } else {
1017
+ index = restore;
1018
+ flags += 'u';
1019
+ str += '\\u';
1020
+ }
1021
+ } else {
1022
+ str += '\\';
1023
+ }
1024
+ } else {
1025
+ flags += ch;
1026
+ str += ch;
1027
+ }
1028
+ }
1029
+
1030
+ try {
1031
+ value = new RegExp(pattern, flags);
1032
+ } catch (e) {
1033
+ throwError({}, Messages.InvalidRegExp);
1034
+ }
1035
+
1036
+ return {
1037
+ literal: str,
1038
+ value: value,
1039
+ range: [start, index]
1040
+ };
1041
+ }
1042
+
1043
+ function isIdentifierName(token) {
1044
+ return token.type === Token.Identifier ||
1045
+ token.type === Token.Keyword ||
1046
+ token.type === Token.BooleanLiteral ||
1047
+ token.type === Token.NullLiteral;
1048
+ }
1049
+
1050
+ function advance() {
1051
+ var ch, token;
1052
+
1053
+ skipComment();
1054
+
1055
+ if (index >= length) {
1056
+ return {
1057
+ type: Token.EOF,
1058
+ lineNumber: lineNumber,
1059
+ lineStart: lineStart,
1060
+ range: [index, index]
1061
+ };
1062
+ }
1063
+
1064
+ token = scanPunctuator();
1065
+ if (typeof token !== 'undefined') {
1066
+ return token;
1067
+ }
1068
+
1069
+ ch = source[index];
1070
+
1071
+ if (ch === '\'' || ch === '"') {
1072
+ return scanStringLiteral();
1073
+ }
1074
+
1075
+ if (ch === '.' || isDecimalDigit(ch)) {
1076
+ return scanNumericLiteral();
1077
+ }
1078
+
1079
+ token = scanIdentifier();
1080
+ if (typeof token !== 'undefined') {
1081
+ return token;
1082
+ }
1083
+
1084
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1085
+ }
1086
+
1087
+ function lex() {
1088
+ var token;
1089
+
1090
+ if (buffer) {
1091
+ index = buffer.range[1];
1092
+ lineNumber = buffer.lineNumber;
1093
+ lineStart = buffer.lineStart;
1094
+ token = buffer;
1095
+ buffer = null;
1096
+ return token;
1097
+ }
1098
+
1099
+ buffer = null;
1100
+ return advance();
1101
+ }
1102
+
1103
+ function lookahead() {
1104
+ var pos, line, start;
1105
+
1106
+ if (buffer !== null) {
1107
+ return buffer;
1108
+ }
1109
+
1110
+ pos = index;
1111
+ line = lineNumber;
1112
+ start = lineStart;
1113
+ buffer = advance();
1114
+ index = pos;
1115
+ lineNumber = line;
1116
+ lineStart = start;
1117
+
1118
+ return buffer;
1119
+ }
1120
+
1121
+ // Return true if there is a line terminator before the next token.
1122
+
1123
+ function peekLineTerminator() {
1124
+ var pos, line, start, found;
1125
+
1126
+ pos = index;
1127
+ line = lineNumber;
1128
+ start = lineStart;
1129
+ skipComment();
1130
+ found = lineNumber !== line;
1131
+ index = pos;
1132
+ lineNumber = line;
1133
+ lineStart = start;
1134
+
1135
+ return found;
1136
+ }
1137
+
1138
+ // Throw an exception
1139
+
1140
+ function throwError(token, messageFormat) {
1141
+ var error,
1142
+ args = Array.prototype.slice.call(arguments, 2),
1143
+ msg = messageFormat.replace(
1144
+ /%(\d)/g,
1145
+ function (whole, index) {
1146
+ return args[index] || '';
1147
+ }
1148
+ );
1149
+
1150
+ if (typeof token.lineNumber === 'number') {
1151
+ error = new Error('Line ' + token.lineNumber + ': ' + msg);
1152
+ error.index = token.range[0];
1153
+ error.lineNumber = token.lineNumber;
1154
+ error.column = token.range[0] - lineStart + 1;
1155
+ } else {
1156
+ error = new Error('Line ' + lineNumber + ': ' + msg);
1157
+ error.index = index;
1158
+ error.lineNumber = lineNumber;
1159
+ error.column = index - lineStart + 1;
1160
+ }
1161
+
1162
+ throw error;
1163
+ }
1164
+
1165
+ function throwErrorTolerant() {
1166
+ var error;
1167
+ try {
1168
+ throwError.apply(null, arguments);
1169
+ } catch (e) {
1170
+ if (extra.errors) {
1171
+ extra.errors.push(e);
1172
+ } else {
1173
+ throw e;
1174
+ }
1175
+ }
1176
+ }
1177
+
1178
+
1179
+ // Throw an exception because of the token.
1180
+
1181
+ function throwUnexpected(token) {
1182
+ var s;
1183
+
1184
+ if (token.type === Token.EOF) {
1185
+ throwError(token, Messages.UnexpectedEOS);
1186
+ }
1187
+
1188
+ if (token.type === Token.NumericLiteral) {
1189
+ throwError(token, Messages.UnexpectedNumber);
1190
+ }
1191
+
1192
+ if (token.type === Token.StringLiteral) {
1193
+ throwError(token, Messages.UnexpectedString);
1194
+ }
1195
+
1196
+ if (token.type === Token.Identifier) {
1197
+ throwError(token, Messages.UnexpectedIdentifier);
1198
+ }
1199
+
1200
+ if (token.type === Token.Keyword) {
1201
+ if (isFutureReservedWord(token.value)) {
1202
+ throwError(token, Messages.UnexpectedReserved);
1203
+ } else if (strict && isStrictModeReservedWord(token.value)) {
1204
+ throwError(token, Messages.StrictReservedWord);
1205
+ }
1206
+ throwError(token, Messages.UnexpectedToken, token.value);
1207
+ }
1208
+
1209
+ // BooleanLiteral, NullLiteral, or Punctuator.
1210
+ throwError(token, Messages.UnexpectedToken, token.value);
1211
+ }
1212
+
1213
+ // Expect the next token to match the specified punctuator.
1214
+ // If not, an exception will be thrown.
1215
+
1216
+ function expect(value) {
1217
+ var token = lex();
1218
+ if (token.type !== Token.Punctuator || token.value !== value) {
1219
+ throwUnexpected(token);
1220
+ }
1221
+ }
1222
+
1223
+ // Expect the next token to match the specified keyword.
1224
+ // If not, an exception will be thrown.
1225
+
1226
+ function expectKeyword(keyword) {
1227
+ var token = lex();
1228
+ if (token.type !== Token.Keyword || token.value !== keyword) {
1229
+ throwUnexpected(token);
1230
+ }
1231
+ }
1232
+
1233
+ // Return true if the next token matches the specified punctuator.
1234
+
1235
+ function match(value) {
1236
+ var token = lookahead();
1237
+ return token.type === Token.Punctuator && token.value === value;
1238
+ }
1239
+
1240
+ // Return true if the next token matches the specified keyword
1241
+
1242
+ function matchKeyword(keyword) {
1243
+ var token = lookahead();
1244
+ return token.type === Token.Keyword && token.value === keyword;
1245
+ }
1246
+
1247
+ // Return true if the next token is an assignment operator
1248
+
1249
+ function matchAssign() {
1250
+ var token = lookahead(),
1251
+ op = token.value;
1252
+
1253
+ if (token.type !== Token.Punctuator) {
1254
+ return false;
1255
+ }
1256
+ return op === '=' ||
1257
+ op === '*=' ||
1258
+ op === '/=' ||
1259
+ op === '%=' ||
1260
+ op === '+=' ||
1261
+ op === '-=' ||
1262
+ op === '<<=' ||
1263
+ op === '>>=' ||
1264
+ op === '>>>=' ||
1265
+ op === '&=' ||
1266
+ op === '^=' ||
1267
+ op === '|=';
1268
+ }
1269
+
1270
+ function consumeSemicolon() {
1271
+ var token, line;
1272
+
1273
+ // Catch the very common case first.
1274
+ if (source[index] === ';') {
1275
+ lex();
1276
+ return;
1277
+ }
1278
+
1279
+ line = lineNumber;
1280
+ skipComment();
1281
+ if (lineNumber !== line) {
1282
+ return;
1283
+ }
1284
+
1285
+ if (match(';')) {
1286
+ lex();
1287
+ return;
1288
+ }
1289
+
1290
+ token = lookahead();
1291
+ if (token.type !== Token.EOF && !match('}')) {
1292
+ throwUnexpected(token);
1293
+ }
1294
+ return;
1295
+ }
1296
+
1297
+ // Return true if provided expression is LeftHandSideExpression
1298
+
1299
+ function isLeftHandSide(expr) {
1300
+ switch (expr.type) {
1301
+ case 'AssignmentExpression':
1302
+ case 'BinaryExpression':
1303
+ case 'ConditionalExpression':
1304
+ case 'LogicalExpression':
1305
+ case 'SequenceExpression':
1306
+ case 'UnaryExpression':
1307
+ case 'UpdateExpression':
1308
+ return false;
1309
+ }
1310
+ return true;
1311
+ }
1312
+
1313
+ // 11.1.4 Array Initialiser
1314
+
1315
+ function parseArrayInitialiser() {
1316
+ var elements = [],
1317
+ undef;
1318
+
1319
+ expect('[');
1320
+
1321
+ while (!match(']')) {
1322
+ if (match(',')) {
1323
+ lex();
1324
+ elements.push(undef);
1325
+ } else {
1326
+ elements.push(parseAssignmentExpression());
1327
+
1328
+ if (!match(']')) {
1329
+ expect(',');
1330
+ }
1331
+ }
1332
+ }
1333
+
1334
+ expect(']');
1335
+
1336
+ return {
1337
+ type: Syntax.ArrayExpression,
1338
+ elements: elements
1339
+ };
1340
+ }
1341
+
1342
+ // 11.1.5 Object Initialiser
1343
+
1344
+ function parsePropertyFunction(param, first) {
1345
+ var previousStrict, body;
1346
+
1347
+ previousStrict = strict;
1348
+ body = parseFunctionSourceElements();
1349
+ if (first && strict && isRestrictedWord(param[0].name)) {
1350
+ throwError(first, Messages.StrictParamName);
1351
+ }
1352
+ strict = previousStrict;
1353
+
1354
+ return {
1355
+ type: Syntax.FunctionExpression,
1356
+ id: null,
1357
+ params: param,
1358
+ body: body
1359
+ };
1360
+ }
1361
+
1362
+ function parseObjectPropertyKey() {
1363
+ var token = lex();
1364
+
1365
+ // Note: This function is called only from parseObjectProperty(), where
1366
+ // EOF and Punctuator tokens are already filtered out.
1367
+
1368
+ if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
1369
+ if (strict && token.octal) {
1370
+ throwError(token, Messages.StrictOctalLiteral);
1371
+ }
1372
+ return createLiteral(token);
1373
+ }
1374
+
1375
+ return {
1376
+ type: Syntax.Identifier,
1377
+ name: token.value
1378
+ };
1379
+ }
1380
+
1381
+ function parseObjectProperty() {
1382
+ var token, key, id, param;
1383
+
1384
+ token = lookahead();
1385
+
1386
+ if (token.type === Token.Identifier) {
1387
+
1388
+ id = parseObjectPropertyKey();
1389
+
1390
+ // Property Assignment: Getter and Setter.
1391
+
1392
+ if (token.value === 'get' && !match(':')) {
1393
+ key = parseObjectPropertyKey();
1394
+ expect('(');
1395
+ expect(')');
1396
+ return {
1397
+ type: Syntax.Property,
1398
+ key: key,
1399
+ value: parsePropertyFunction([]),
1400
+ kind: 'get'
1401
+ };
1402
+ } else if (token.value === 'set' && !match(':')) {
1403
+ key = parseObjectPropertyKey();
1404
+ expect('(');
1405
+ token = lookahead();
1406
+ if (token.type !== Token.Identifier) {
1407
+ throwUnexpected(lex());
1408
+ }
1409
+ param = [ parseVariableIdentifier() ];
1410
+ expect(')');
1411
+ return {
1412
+ type: Syntax.Property,
1413
+ key: key,
1414
+ value: parsePropertyFunction(param, token),
1415
+ kind: 'set'
1416
+ };
1417
+ } else {
1418
+ expect(':');
1419
+ return {
1420
+ type: Syntax.Property,
1421
+ key: id,
1422
+ value: parseAssignmentExpression(),
1423
+ kind: 'init'
1424
+ };
1425
+ }
1426
+ } else if (token.type === Token.EOF || token.type === Token.Punctuator) {
1427
+ throwUnexpected(token);
1428
+ } else {
1429
+ key = parseObjectPropertyKey();
1430
+ expect(':');
1431
+ return {
1432
+ type: Syntax.Property,
1433
+ key: key,
1434
+ value: parseAssignmentExpression(),
1435
+ kind: 'init'
1436
+ };
1437
+ }
1438
+ }
1439
+
1440
+ function parseObjectInitialiser() {
1441
+ var token, properties = [], property, name, kind, map = {}, toString = String;
1442
+
1443
+ expect('{');
1444
+
1445
+ while (!match('}')) {
1446
+ property = parseObjectProperty();
1447
+
1448
+ if (property.key.type === Syntax.Identifier) {
1449
+ name = property.key.name;
1450
+ } else {
1451
+ name = toString(property.key.value);
1452
+ }
1453
+ kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
1454
+ if (Object.prototype.hasOwnProperty.call(map, name)) {
1455
+ if (map[name] === PropertyKind.Data) {
1456
+ if (strict && kind === PropertyKind.Data) {
1457
+ throwErrorTolerant({}, Messages.StrictDuplicateProperty);
1458
+ } else if (kind !== PropertyKind.Data) {
1459
+ throwError({}, Messages.AccessorDataProperty);
1460
+ }
1461
+ } else {
1462
+ if (kind === PropertyKind.Data) {
1463
+ throwError({}, Messages.AccessorDataProperty);
1464
+ } else if (map[name] & kind) {
1465
+ throwError({}, Messages.AccessorGetSet);
1466
+ }
1467
+ }
1468
+ map[name] |= kind;
1469
+ } else {
1470
+ map[name] = kind;
1471
+ }
1472
+
1473
+ properties.push(property);
1474
+
1475
+ if (!match('}')) {
1476
+ expect(',');
1477
+ }
1478
+ }
1479
+
1480
+ expect('}');
1481
+
1482
+ return {
1483
+ type: Syntax.ObjectExpression,
1484
+ properties: properties
1485
+ };
1486
+ }
1487
+
1488
+ // 11.1 Primary Expressions
1489
+
1490
+ function parsePrimaryExpression() {
1491
+ var expr,
1492
+ token = lookahead(),
1493
+ type = token.type;
1494
+
1495
+ if (type === Token.Identifier) {
1496
+ return {
1497
+ type: Syntax.Identifier,
1498
+ name: lex().value
1499
+ };
1500
+ }
1501
+
1502
+ if (type === Token.StringLiteral || type === Token.NumericLiteral) {
1503
+ if (strict && token.octal) {
1504
+ throwErrorTolerant(token, Messages.StrictOctalLiteral);
1505
+ }
1506
+ return createLiteral(lex());
1507
+ }
1508
+
1509
+ if (type === Token.Keyword) {
1510
+ if (matchKeyword('this')) {
1511
+ lex();
1512
+ return {
1513
+ type: Syntax.ThisExpression
1514
+ };
1515
+ }
1516
+
1517
+ if (matchKeyword('function')) {
1518
+ return parseFunctionExpression();
1519
+ }
1520
+ }
1521
+
1522
+ if (type === Token.BooleanLiteral) {
1523
+ lex();
1524
+ token.value = (token.value === 'true');
1525
+ return createLiteral(token);
1526
+ }
1527
+
1528
+ if (type === Token.NullLiteral) {
1529
+ lex();
1530
+ token.value = null;
1531
+ return createLiteral(token);
1532
+ }
1533
+
1534
+ if (match('[')) {
1535
+ return parseArrayInitialiser();
1536
+ }
1537
+
1538
+ if (match('{')) {
1539
+ return parseObjectInitialiser();
1540
+ }
1541
+
1542
+ if (match('(')) {
1543
+ lex();
1544
+ state.lastParenthesized = expr = parseExpression();
1545
+ expect(')');
1546
+ return expr;
1547
+ }
1548
+
1549
+ if (match('/') || match('/=')) {
1550
+ return createLiteral(scanRegExp());
1551
+ }
1552
+
1553
+ return throwUnexpected(lex());
1554
+ }
1555
+
1556
+ // 11.2 Left-Hand-Side Expressions
1557
+
1558
+ function parseArguments() {
1559
+ var args = [];
1560
+
1561
+ expect('(');
1562
+
1563
+ if (!match(')')) {
1564
+ while (index < length) {
1565
+ args.push(parseAssignmentExpression());
1566
+ if (match(')')) {
1567
+ break;
1568
+ }
1569
+ expect(',');
1570
+ }
1571
+ }
1572
+
1573
+ expect(')');
1574
+
1575
+ return args;
1576
+ }
1577
+
1578
+ function parseNonComputedProperty() {
1579
+ var token = lex();
1580
+
1581
+ if (!isIdentifierName(token)) {
1582
+ throwUnexpected(token);
1583
+ }
1584
+
1585
+ return {
1586
+ type: Syntax.Identifier,
1587
+ name: token.value
1588
+ };
1589
+ }
1590
+
1591
+ function parseNonComputedMember(object) {
1592
+ return {
1593
+ type: Syntax.MemberExpression,
1594
+ computed: false,
1595
+ object: object,
1596
+ property: parseNonComputedProperty()
1597
+ };
1598
+ }
1599
+
1600
+ function parseComputedMember(object) {
1601
+ var property, expr;
1602
+
1603
+ expect('[');
1604
+ property = parseExpression();
1605
+ expr = {
1606
+ type: Syntax.MemberExpression,
1607
+ computed: true,
1608
+ object: object,
1609
+ property: property
1610
+ };
1611
+ expect(']');
1612
+ return expr;
1613
+ }
1614
+
1615
+ function parseCallMember(object) {
1616
+ return {
1617
+ type: Syntax.CallExpression,
1618
+ callee: object,
1619
+ 'arguments': parseArguments()
1620
+ };
1621
+ }
1622
+
1623
+ function parseNewExpression() {
1624
+ var expr;
1625
+
1626
+ expectKeyword('new');
1627
+
1628
+ expr = {
1629
+ type: Syntax.NewExpression,
1630
+ callee: parseLeftHandSideExpression(),
1631
+ 'arguments': []
1632
+ };
1633
+
1634
+ if (match('(')) {
1635
+ expr['arguments'] = parseArguments();
1636
+ }
1637
+
1638
+ return expr;
1639
+ }
1640
+
1641
+ function parseLeftHandSideExpressionAllowCall() {
1642
+ var useNew, expr;
1643
+
1644
+ useNew = matchKeyword('new');
1645
+ expr = useNew ? parseNewExpression() : parsePrimaryExpression();
1646
+
1647
+ while (index < length) {
1648
+ if (match('.')) {
1649
+ lex();
1650
+ expr = parseNonComputedMember(expr);
1651
+ } else if (match('[')) {
1652
+ expr = parseComputedMember(expr);
1653
+ } else if (match('(')) {
1654
+ expr = parseCallMember(expr);
1655
+ } else {
1656
+ break;
1657
+ }
1658
+ }
1659
+
1660
+ return expr;
1661
+ }
1662
+
1663
+ function parseLeftHandSideExpression() {
1664
+ var useNew, expr;
1665
+
1666
+ useNew = matchKeyword('new');
1667
+ expr = useNew ? parseNewExpression() : parsePrimaryExpression();
1668
+
1669
+ while (index < length) {
1670
+ if (match('.')) {
1671
+ lex();
1672
+ expr = parseNonComputedMember(expr);
1673
+ } else if (match('[')) {
1674
+ expr = parseComputedMember(expr);
1675
+ } else {
1676
+ break;
1677
+ }
1678
+ }
1679
+
1680
+ return expr;
1681
+ }
1682
+
1683
+ // 11.3 Postfix Expressions
1684
+
1685
+ function parsePostfixExpression() {
1686
+ var expr = parseLeftHandSideExpressionAllowCall();
1687
+
1688
+ if ((match('++') || match('--')) && !peekLineTerminator()) {
1689
+ // 11.3.1, 11.3.2
1690
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
1691
+ throwError({}, Messages.StrictLHSPostfix);
1692
+ }
1693
+ expr = {
1694
+ type: Syntax.UpdateExpression,
1695
+ operator: lex().value,
1696
+ argument: expr,
1697
+ prefix: false
1698
+ };
1699
+ }
1700
+
1701
+ return expr;
1702
+ }
1703
+
1704
+ // 11.4 Unary Operators
1705
+
1706
+ function parseUnaryExpression() {
1707
+ var token, expr;
1708
+
1709
+ if (match('++') || match('--')) {
1710
+ token = lex();
1711
+ expr = parseUnaryExpression();
1712
+ // 11.4.4, 11.4.5
1713
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
1714
+ throwError({}, Messages.StrictLHSPrefix);
1715
+ }
1716
+ expr = {
1717
+ type: Syntax.UpdateExpression,
1718
+ operator: token.value,
1719
+ argument: expr,
1720
+ prefix: true
1721
+ };
1722
+ return expr;
1723
+ }
1724
+
1725
+ if (match('+') || match('-') || match('~') || match('!')) {
1726
+ expr = {
1727
+ type: Syntax.UnaryExpression,
1728
+ operator: lex().value,
1729
+ argument: parseUnaryExpression()
1730
+ };
1731
+ return expr;
1732
+ }
1733
+
1734
+ if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
1735
+ expr = {
1736
+ type: Syntax.UnaryExpression,
1737
+ operator: lex().value,
1738
+ argument: parseUnaryExpression()
1739
+ };
1740
+ if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
1741
+ throwErrorTolerant({}, Messages.StrictDelete);
1742
+ }
1743
+ return expr;
1744
+ }
1745
+
1746
+ return parsePostfixExpression();
1747
+ }
1748
+
1749
+ // 11.5 Multiplicative Operators
1750
+
1751
+ function parseMultiplicativeExpression() {
1752
+ var expr = parseUnaryExpression();
1753
+
1754
+ while (match('*') || match('/') || match('%')) {
1755
+ expr = {
1756
+ type: Syntax.BinaryExpression,
1757
+ operator: lex().value,
1758
+ left: expr,
1759
+ right: parseUnaryExpression()
1760
+ };
1761
+ }
1762
+
1763
+ return expr;
1764
+ }
1765
+
1766
+ // 11.6 Additive Operators
1767
+
1768
+ function parseAdditiveExpression() {
1769
+ var expr = parseMultiplicativeExpression();
1770
+
1771
+ while (match('+') || match('-')) {
1772
+ expr = {
1773
+ type: Syntax.BinaryExpression,
1774
+ operator: lex().value,
1775
+ left: expr,
1776
+ right: parseMultiplicativeExpression()
1777
+ };
1778
+ }
1779
+
1780
+ return expr;
1781
+ }
1782
+
1783
+ // 11.7 Bitwise Shift Operators
1784
+
1785
+ function parseShiftExpression() {
1786
+ var expr = parseAdditiveExpression();
1787
+
1788
+ while (match('<<') || match('>>') || match('>>>')) {
1789
+ expr = {
1790
+ type: Syntax.BinaryExpression,
1791
+ operator: lex().value,
1792
+ left: expr,
1793
+ right: parseAdditiveExpression()
1794
+ };
1795
+ }
1796
+
1797
+ return expr;
1798
+ }
1799
+ // 11.8 Relational Operators
1800
+
1801
+ function parseRelationalExpression() {
1802
+ var expr, previousAllowIn;
1803
+
1804
+ previousAllowIn = state.allowIn;
1805
+ state.allowIn = true;
1806
+ expr = parseShiftExpression();
1807
+ state.allowIn = previousAllowIn;
1808
+
1809
+ if (match('<') || match('>') || match('<=') || match('>=')) {
1810
+ expr = {
1811
+ type: Syntax.BinaryExpression,
1812
+ operator: lex().value,
1813
+ left: expr,
1814
+ right: parseRelationalExpression()
1815
+ };
1816
+ } else if (state.allowIn && matchKeyword('in')) {
1817
+ lex();
1818
+ expr = {
1819
+ type: Syntax.BinaryExpression,
1820
+ operator: 'in',
1821
+ left: expr,
1822
+ right: parseRelationalExpression()
1823
+ };
1824
+ } else if (matchKeyword('instanceof')) {
1825
+ lex();
1826
+ expr = {
1827
+ type: Syntax.BinaryExpression,
1828
+ operator: 'instanceof',
1829
+ left: expr,
1830
+ right: parseRelationalExpression()
1831
+ };
1832
+ }
1833
+
1834
+ return expr;
1835
+ }
1836
+
1837
+ // 11.9 Equality Operators
1838
+
1839
+ function parseEqualityExpression() {
1840
+ var expr = parseRelationalExpression();
1841
+
1842
+ while (match('==') || match('!=') || match('===') || match('!==')) {
1843
+ expr = {
1844
+ type: Syntax.BinaryExpression,
1845
+ operator: lex().value,
1846
+ left: expr,
1847
+ right: parseRelationalExpression()
1848
+ };
1849
+ }
1850
+
1851
+ return expr;
1852
+ }
1853
+
1854
+ // 11.10 Binary Bitwise Operators
1855
+
1856
+ function parseBitwiseANDExpression() {
1857
+ var expr = parseEqualityExpression();
1858
+
1859
+ while (match('&')) {
1860
+ lex();
1861
+ expr = {
1862
+ type: Syntax.BinaryExpression,
1863
+ operator: '&',
1864
+ left: expr,
1865
+ right: parseEqualityExpression()
1866
+ };
1867
+ }
1868
+
1869
+ return expr;
1870
+ }
1871
+
1872
+ function parseBitwiseORExpression() {
1873
+ var expr = parseBitwiseANDExpression();
1874
+
1875
+ while (match('|')) {
1876
+ lex();
1877
+ expr = {
1878
+ type: Syntax.BinaryExpression,
1879
+ operator: '|',
1880
+ left: expr,
1881
+ right: parseBitwiseANDExpression()
1882
+ };
1883
+ }
1884
+
1885
+ return expr;
1886
+ }
1887
+
1888
+ function parseBitwiseXORExpression() {
1889
+ var expr = parseBitwiseORExpression();
1890
+
1891
+ while (match('^')) {
1892
+ lex();
1893
+ expr = {
1894
+ type: Syntax.BinaryExpression,
1895
+ operator: '^',
1896
+ left: expr,
1897
+ right: parseBitwiseORExpression()
1898
+ };
1899
+ }
1900
+
1901
+ return expr;
1902
+ }
1903
+
1904
+ // 11.11 Binary Logical Operators
1905
+
1906
+ function parseLogicalANDExpression() {
1907
+ var expr = parseBitwiseXORExpression();
1908
+
1909
+ while (match('&&')) {
1910
+ lex();
1911
+ expr = {
1912
+ type: Syntax.LogicalExpression,
1913
+ operator: '&&',
1914
+ left: expr,
1915
+ right: parseBitwiseXORExpression()
1916
+ };
1917
+ }
1918
+
1919
+ return expr;
1920
+ }
1921
+
1922
+ function parseLogicalORExpression() {
1923
+ var expr = parseLogicalANDExpression();
1924
+
1925
+ while (match('||')) {
1926
+ lex();
1927
+ expr = {
1928
+ type: Syntax.LogicalExpression,
1929
+ operator: '||',
1930
+ left: expr,
1931
+ right: parseLogicalANDExpression()
1932
+ };
1933
+ }
1934
+
1935
+ return expr;
1936
+ }
1937
+
1938
+ // 11.12 Conditional Operator
1939
+
1940
+ function parseConditionalExpression() {
1941
+ var expr, previousAllowIn, consequent;
1942
+
1943
+ expr = parseLogicalORExpression();
1944
+
1945
+ if (match('?')) {
1946
+ lex();
1947
+ previousAllowIn = state.allowIn;
1948
+ state.allowIn = true;
1949
+ consequent = parseAssignmentExpression();
1950
+ state.allowIn = previousAllowIn;
1951
+ expect(':');
1952
+
1953
+ expr = {
1954
+ type: Syntax.ConditionalExpression,
1955
+ test: expr,
1956
+ consequent: consequent,
1957
+ alternate: parseAssignmentExpression()
1958
+ };
1959
+ }
1960
+
1961
+ return expr;
1962
+ }
1963
+
1964
+ // 11.13 Assignment Operators
1965
+
1966
+ function parseAssignmentExpression() {
1967
+ var expr;
1968
+
1969
+ expr = parseConditionalExpression();
1970
+
1971
+ if (matchAssign()) {
1972
+ // LeftHandSideExpression
1973
+ if (state.lastParenthesized !== expr && !isLeftHandSide(expr)) {
1974
+ throwError({}, Messages.InvalidLHSInAssignment);
1975
+ }
1976
+
1977
+ // 11.13.1
1978
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
1979
+ throwError({}, Messages.StrictLHSAssignment);
1980
+ }
1981
+
1982
+ expr = {
1983
+ type: Syntax.AssignmentExpression,
1984
+ operator: lex().value,
1985
+ left: expr,
1986
+ right: parseAssignmentExpression()
1987
+ };
1988
+ }
1989
+
1990
+ return expr;
1991
+ }
1992
+
1993
+ // 11.14 Comma Operator
1994
+
1995
+ function parseExpression() {
1996
+ var expr = parseAssignmentExpression();
1997
+
1998
+ if (match(',')) {
1999
+ expr = {
2000
+ type: Syntax.SequenceExpression,
2001
+ expressions: [ expr ]
2002
+ };
2003
+
2004
+ while (index < length) {
2005
+ if (!match(',')) {
2006
+ break;
2007
+ }
2008
+ lex();
2009
+ expr.expressions.push(parseAssignmentExpression());
2010
+ }
2011
+
2012
+ }
2013
+ return expr;
2014
+ }
2015
+
2016
+ // 12.1 Block
2017
+
2018
+ function parseStatementList() {
2019
+ var list = [],
2020
+ statement;
2021
+
2022
+ while (index < length) {
2023
+ if (match('}')) {
2024
+ break;
2025
+ }
2026
+ statement = parseSourceElement();
2027
+ if (typeof statement === 'undefined') {
2028
+ break;
2029
+ }
2030
+ list.push(statement);
2031
+ }
2032
+
2033
+ return list;
2034
+ }
2035
+
2036
+ function parseBlock() {
2037
+ var block;
2038
+
2039
+ expect('{');
2040
+
2041
+ block = parseStatementList();
2042
+
2043
+ expect('}');
2044
+
2045
+ return {
2046
+ type: Syntax.BlockStatement,
2047
+ body: block
2048
+ };
2049
+ }
2050
+
2051
+ // 12.2 Variable Statement
2052
+
2053
+ function parseVariableIdentifier() {
2054
+ var token = lex();
2055
+
2056
+ if (token.type !== Token.Identifier) {
2057
+ throwUnexpected(token);
2058
+ }
2059
+
2060
+ return {
2061
+ type: Syntax.Identifier,
2062
+ name: token.value
2063
+ };
2064
+ }
2065
+
2066
+ function parseVariableDeclaration(kind) {
2067
+ var id = parseVariableIdentifier(),
2068
+ init = null;
2069
+
2070
+ // 12.2.1
2071
+ if (strict && isRestrictedWord(id.name)) {
2072
+ throwErrorTolerant({}, Messages.StrictVarName);
2073
+ }
2074
+
2075
+ if (kind === 'const') {
2076
+ expect('=');
2077
+ init = parseAssignmentExpression();
2078
+ } else if (match('=')) {
2079
+ lex();
2080
+ init = parseAssignmentExpression();
2081
+ }
2082
+
2083
+ return {
2084
+ type: Syntax.VariableDeclarator,
2085
+ id: id,
2086
+ init: init
2087
+ };
2088
+ }
2089
+
2090
+ function parseVariableDeclarationList(kind) {
2091
+ var list = [];
2092
+
2093
+ while (index < length) {
2094
+ list.push(parseVariableDeclaration(kind));
2095
+ if (!match(',')) {
2096
+ break;
2097
+ }
2098
+ lex();
2099
+ }
2100
+
2101
+ return list;
2102
+ }
2103
+
2104
+ function parseVariableStatement() {
2105
+ var declarations;
2106
+
2107
+ expectKeyword('var');
2108
+
2109
+ declarations = parseVariableDeclarationList();
2110
+
2111
+ consumeSemicolon();
2112
+
2113
+ return {
2114
+ type: Syntax.VariableDeclaration,
2115
+ declarations: declarations,
2116
+ kind: 'var'
2117
+ };
2118
+ }
2119
+
2120
+ // kind may be `const` or `let`
2121
+ // Both are experimental and not in the specification yet.
2122
+ // see http://wiki.ecmascript.org/doku.php?id=harmony:const
2123
+ // and http://wiki.ecmascript.org/doku.php?id=harmony:let
2124
+ function parseConstLetDeclaration(kind) {
2125
+ var declarations;
2126
+
2127
+ expectKeyword(kind);
2128
+
2129
+ declarations = parseVariableDeclarationList(kind);
2130
+
2131
+ consumeSemicolon();
2132
+
2133
+ return {
2134
+ type: Syntax.VariableDeclaration,
2135
+ declarations: declarations,
2136
+ kind: kind
2137
+ };
2138
+ }
2139
+
2140
+ // 12.3 Empty Statement
2141
+
2142
+ function parseEmptyStatement() {
2143
+ expect(';');
2144
+
2145
+ return {
2146
+ type: Syntax.EmptyStatement
2147
+ };
2148
+ }
2149
+
2150
+ // 12.4 Expression Statement
2151
+
2152
+ function parseExpressionStatement() {
2153
+ var expr = parseExpression();
2154
+
2155
+ consumeSemicolon();
2156
+
2157
+ return {
2158
+ type: Syntax.ExpressionStatement,
2159
+ expression: expr
2160
+ };
2161
+ }
2162
+
2163
+ // 12.5 If statement
2164
+
2165
+ function parseIfStatement() {
2166
+ var test, consequent, alternate;
2167
+
2168
+ expectKeyword('if');
2169
+
2170
+ expect('(');
2171
+
2172
+ test = parseExpression();
2173
+
2174
+ expect(')');
2175
+
2176
+ consequent = parseStatement();
2177
+
2178
+ if (matchKeyword('else')) {
2179
+ lex();
2180
+ alternate = parseStatement();
2181
+ } else {
2182
+ alternate = null;
2183
+ }
2184
+
2185
+ return {
2186
+ type: Syntax.IfStatement,
2187
+ test: test,
2188
+ consequent: consequent,
2189
+ alternate: alternate
2190
+ };
2191
+ }
2192
+
2193
+ // 12.6 Iteration Statements
2194
+
2195
+ function parseDoWhileStatement() {
2196
+ var body, test, oldInIteration;
2197
+
2198
+ expectKeyword('do');
2199
+
2200
+ oldInIteration = state.inIteration;
2201
+ state.inIteration = true;
2202
+
2203
+ body = parseStatement();
2204
+
2205
+ state.inIteration = oldInIteration;
2206
+
2207
+ expectKeyword('while');
2208
+
2209
+ expect('(');
2210
+
2211
+ test = parseExpression();
2212
+
2213
+ expect(')');
2214
+
2215
+ if (match(';')) {
2216
+ lex();
2217
+ }
2218
+
2219
+ return {
2220
+ type: Syntax.DoWhileStatement,
2221
+ body: body,
2222
+ test: test
2223
+ };
2224
+ }
2225
+
2226
+ function parseWhileStatement() {
2227
+ var test, body, oldInIteration;
2228
+
2229
+ expectKeyword('while');
2230
+
2231
+ expect('(');
2232
+
2233
+ test = parseExpression();
2234
+
2235
+ expect(')');
2236
+
2237
+ oldInIteration = state.inIteration;
2238
+ state.inIteration = true;
2239
+
2240
+ body = parseStatement();
2241
+
2242
+ state.inIteration = oldInIteration;
2243
+
2244
+ return {
2245
+ type: Syntax.WhileStatement,
2246
+ test: test,
2247
+ body: body
2248
+ };
2249
+ }
2250
+
2251
+ function parseForVariableDeclaration() {
2252
+ var token = lex();
2253
+
2254
+ return {
2255
+ type: Syntax.VariableDeclaration,
2256
+ declarations: parseVariableDeclarationList(),
2257
+ kind: token.value
2258
+ };
2259
+ }
2260
+
2261
+ function parseForStatement() {
2262
+ var init, test, update, left, right, body, oldInIteration;
2263
+
2264
+ init = test = update = null;
2265
+
2266
+ expectKeyword('for');
2267
+
2268
+ expect('(');
2269
+
2270
+ if (match(';')) {
2271
+ lex();
2272
+ } else {
2273
+ if (matchKeyword('var') || matchKeyword('let')) {
2274
+ state.allowIn = false;
2275
+ init = parseForVariableDeclaration();
2276
+ state.allowIn = true;
2277
+
2278
+ if (init.declarations.length === 1 && matchKeyword('in')) {
2279
+ lex();
2280
+ left = init;
2281
+ right = parseExpression();
2282
+ init = null;
2283
+ }
2284
+ } else {
2285
+ state.allowIn = false;
2286
+ init = parseExpression();
2287
+ state.allowIn = true;
2288
+
2289
+ if (matchKeyword('in')) {
2290
+ // LeftHandSideExpression
2291
+ if (matchKeyword('in') && (state.lastParenthesized !== init && !isLeftHandSide(init))) {
2292
+ throwError({}, Messages.InvalidLHSInForIn);
2293
+ }
2294
+ lex();
2295
+ left = init;
2296
+ right = parseExpression();
2297
+ init = null;
2298
+ }
2299
+ }
2300
+
2301
+ if (typeof left === 'undefined') {
2302
+ expect(';');
2303
+ }
2304
+ }
2305
+
2306
+ if (typeof left === 'undefined') {
2307
+
2308
+ if (!match(';')) {
2309
+ test = parseExpression();
2310
+ }
2311
+ expect(';');
2312
+
2313
+ if (!match(')')) {
2314
+ update = parseExpression();
2315
+ }
2316
+ }
2317
+
2318
+ expect(')');
2319
+
2320
+ oldInIteration = state.inIteration;
2321
+ state.inIteration = true;
2322
+
2323
+ body = parseStatement();
2324
+
2325
+ state.inIteration = oldInIteration;
2326
+
2327
+ if (typeof left === 'undefined') {
2328
+ return {
2329
+ type: Syntax.ForStatement,
2330
+ init: init,
2331
+ test: test,
2332
+ update: update,
2333
+ body: body
2334
+ };
2335
+ }
2336
+
2337
+ return {
2338
+ type: Syntax.ForInStatement,
2339
+ left: left,
2340
+ right: right,
2341
+ body: body,
2342
+ each: false
2343
+ };
2344
+ }
2345
+
2346
+ // 12.7 The continue statement
2347
+
2348
+ function parseContinueStatement() {
2349
+ var token, label = null;
2350
+
2351
+ expectKeyword('continue');
2352
+
2353
+ // Optimize the most common form: 'continue;'.
2354
+ if (source[index] === ';') {
2355
+ lex();
2356
+
2357
+ if (!state.inIteration) {
2358
+ throwError({}, Messages.IllegalContinue);
2359
+ }
2360
+
2361
+ return {
2362
+ type: Syntax.ContinueStatement,
2363
+ label: null
2364
+ };
2365
+ }
2366
+
2367
+ if (peekLineTerminator()) {
2368
+ if (!state.inIteration) {
2369
+ throwError({}, Messages.IllegalContinue);
2370
+ }
2371
+
2372
+ return {
2373
+ type: Syntax.ContinueStatement,
2374
+ label: null
2375
+ };
2376
+ }
2377
+
2378
+ token = lookahead();
2379
+ if (token.type === Token.Identifier) {
2380
+ label = parseVariableIdentifier();
2381
+
2382
+ if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
2383
+ throwError({}, Messages.UnknownLabel, label.name);
2384
+ }
2385
+ }
2386
+
2387
+ consumeSemicolon();
2388
+
2389
+ if (label === null && !state.inIteration) {
2390
+ throwError({}, Messages.IllegalContinue);
2391
+ }
2392
+
2393
+ return {
2394
+ type: Syntax.ContinueStatement,
2395
+ label: label
2396
+ };
2397
+ }
2398
+
2399
+ // 12.8 The break statement
2400
+
2401
+ function parseBreakStatement() {
2402
+ var token, label = null;
2403
+
2404
+ expectKeyword('break');
2405
+
2406
+ // Optimize the most common form: 'break;'.
2407
+ if (source[index] === ';') {
2408
+ lex();
2409
+
2410
+ if (!(state.inIteration || state.inSwitch)) {
2411
+ throwError({}, Messages.IllegalBreak);
2412
+ }
2413
+
2414
+ return {
2415
+ type: Syntax.BreakStatement,
2416
+ label: null
2417
+ };
2418
+ }
2419
+
2420
+ if (peekLineTerminator()) {
2421
+ if (!(state.inIteration || state.inSwitch)) {
2422
+ throwError({}, Messages.IllegalBreak);
2423
+ }
2424
+
2425
+ return {
2426
+ type: Syntax.BreakStatement,
2427
+ label: null
2428
+ };
2429
+ }
2430
+
2431
+ token = lookahead();
2432
+ if (token.type === Token.Identifier) {
2433
+ label = parseVariableIdentifier();
2434
+
2435
+ if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
2436
+ throwError({}, Messages.UnknownLabel, label.name);
2437
+ }
2438
+ }
2439
+
2440
+ consumeSemicolon();
2441
+
2442
+ if (label === null && !(state.inIteration || state.inSwitch)) {
2443
+ throwError({}, Messages.IllegalBreak);
2444
+ }
2445
+
2446
+ return {
2447
+ type: Syntax.BreakStatement,
2448
+ label: label
2449
+ };
2450
+ }
2451
+
2452
+ // 12.9 The return statement
2453
+
2454
+ function parseReturnStatement() {
2455
+ var token, argument = null;
2456
+
2457
+ expectKeyword('return');
2458
+
2459
+ if (!state.inFunctionBody) {
2460
+ throwErrorTolerant({}, Messages.IllegalReturn);
2461
+ }
2462
+
2463
+ // 'return' followed by a space and an identifier is very common.
2464
+ if (source[index] === ' ') {
2465
+ if (isIdentifierStart(source[index + 1])) {
2466
+ argument = parseExpression();
2467
+ consumeSemicolon();
2468
+ return {
2469
+ type: Syntax.ReturnStatement,
2470
+ argument: argument
2471
+ };
2472
+ }
2473
+ }
2474
+
2475
+ if (peekLineTerminator()) {
2476
+ return {
2477
+ type: Syntax.ReturnStatement,
2478
+ argument: null
2479
+ };
2480
+ }
2481
+
2482
+ if (!match(';')) {
2483
+ token = lookahead();
2484
+ if (!match('}') && token.type !== Token.EOF) {
2485
+ argument = parseExpression();
2486
+ }
2487
+ }
2488
+
2489
+ consumeSemicolon();
2490
+
2491
+ return {
2492
+ type: Syntax.ReturnStatement,
2493
+ argument: argument
2494
+ };
2495
+ }
2496
+
2497
+ // 12.10 The with statement
2498
+
2499
+ function parseWithStatement() {
2500
+ var object, body;
2501
+
2502
+ if (strict) {
2503
+ throwErrorTolerant({}, Messages.StrictModeWith);
2504
+ }
2505
+
2506
+ expectKeyword('with');
2507
+
2508
+ expect('(');
2509
+
2510
+ object = parseExpression();
2511
+
2512
+ expect(')');
2513
+
2514
+ body = parseStatement();
2515
+
2516
+ return {
2517
+ type: Syntax.WithStatement,
2518
+ object: object,
2519
+ body: body
2520
+ };
2521
+ }
2522
+
2523
+ // 12.10 The swith statement
2524
+
2525
+ function parseSwitchCase() {
2526
+ var test,
2527
+ consequent = [],
2528
+ statement;
2529
+
2530
+ if (matchKeyword('default')) {
2531
+ lex();
2532
+ test = null;
2533
+ } else {
2534
+ expectKeyword('case');
2535
+ test = parseExpression();
2536
+ }
2537
+ expect(':');
2538
+
2539
+ while (index < length) {
2540
+ if (match('}') || matchKeyword('default') || matchKeyword('case')) {
2541
+ break;
2542
+ }
2543
+ statement = parseStatement();
2544
+ if (typeof statement === 'undefined') {
2545
+ break;
2546
+ }
2547
+ consequent.push(statement);
2548
+ }
2549
+
2550
+ return {
2551
+ type: Syntax.SwitchCase,
2552
+ test: test,
2553
+ consequent: consequent
2554
+ };
2555
+ }
2556
+
2557
+ function parseSwitchStatement() {
2558
+ var discriminant, cases, oldInSwitch;
2559
+
2560
+ expectKeyword('switch');
2561
+
2562
+ expect('(');
2563
+
2564
+ discriminant = parseExpression();
2565
+
2566
+ expect(')');
2567
+
2568
+ expect('{');
2569
+
2570
+ if (match('}')) {
2571
+ lex();
2572
+ return {
2573
+ type: Syntax.SwitchStatement,
2574
+ discriminant: discriminant
2575
+ };
2576
+ }
2577
+
2578
+ cases = [];
2579
+
2580
+ oldInSwitch = state.inSwitch;
2581
+ state.inSwitch = true;
2582
+
2583
+ while (index < length) {
2584
+ if (match('}')) {
2585
+ break;
2586
+ }
2587
+ cases.push(parseSwitchCase());
2588
+ }
2589
+
2590
+ state.inSwitch = oldInSwitch;
2591
+
2592
+ expect('}');
2593
+
2594
+ return {
2595
+ type: Syntax.SwitchStatement,
2596
+ discriminant: discriminant,
2597
+ cases: cases
2598
+ };
2599
+ }
2600
+
2601
+ // 12.13 The throw statement
2602
+
2603
+ function parseThrowStatement() {
2604
+ var argument;
2605
+
2606
+ expectKeyword('throw');
2607
+
2608
+ if (peekLineTerminator()) {
2609
+ throwError({}, Messages.NewlineAfterThrow);
2610
+ }
2611
+
2612
+ argument = parseExpression();
2613
+
2614
+ consumeSemicolon();
2615
+
2616
+ return {
2617
+ type: Syntax.ThrowStatement,
2618
+ argument: argument
2619
+ };
2620
+ }
2621
+
2622
+ // 12.14 The try statement
2623
+
2624
+ function parseCatchClause() {
2625
+ var param;
2626
+
2627
+ expectKeyword('catch');
2628
+
2629
+ expect('(');
2630
+ if (!match(')')) {
2631
+ param = parseExpression();
2632
+ // 12.14.1
2633
+ if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) {
2634
+ throwErrorTolerant({}, Messages.StrictCatchVariable);
2635
+ }
2636
+ }
2637
+ expect(')');
2638
+
2639
+ return {
2640
+ type: Syntax.CatchClause,
2641
+ param: param,
2642
+ guard: null,
2643
+ body: parseBlock()
2644
+ };
2645
+ }
2646
+
2647
+ function parseTryStatement() {
2648
+ var block, handlers = [], finalizer = null;
2649
+
2650
+ expectKeyword('try');
2651
+
2652
+ block = parseBlock();
2653
+
2654
+ if (matchKeyword('catch')) {
2655
+ handlers.push(parseCatchClause());
2656
+ }
2657
+
2658
+ if (matchKeyword('finally')) {
2659
+ lex();
2660
+ finalizer = parseBlock();
2661
+ }
2662
+
2663
+ if (handlers.length === 0 && !finalizer) {
2664
+ throwError({}, Messages.NoCatchOrFinally);
2665
+ }
2666
+
2667
+ return {
2668
+ type: Syntax.TryStatement,
2669
+ block: block,
2670
+ handlers: handlers,
2671
+ finalizer: finalizer
2672
+ };
2673
+ }
2674
+
2675
+ // 12.15 The debugger statement
2676
+
2677
+ function parseDebuggerStatement() {
2678
+ expectKeyword('debugger');
2679
+
2680
+ consumeSemicolon();
2681
+
2682
+ return {
2683
+ type: Syntax.DebuggerStatement
2684
+ };
2685
+ }
2686
+
2687
+ // 12 Statements
2688
+
2689
+ function parseStatement() {
2690
+ var token = lookahead(),
2691
+ expr,
2692
+ labeledBody;
2693
+
2694
+ if (token.type === Token.EOF) {
2695
+ throwUnexpected(token);
2696
+ }
2697
+
2698
+ if (token.type === Token.Punctuator) {
2699
+ switch (token.value) {
2700
+ case ';':
2701
+ return parseEmptyStatement();
2702
+ case '{':
2703
+ return parseBlock();
2704
+ case '(':
2705
+ return parseExpressionStatement();
2706
+ default:
2707
+ break;
2708
+ }
2709
+ }
2710
+
2711
+ if (token.type === Token.Keyword) {
2712
+ switch (token.value) {
2713
+ case 'break':
2714
+ return parseBreakStatement();
2715
+ case 'continue':
2716
+ return parseContinueStatement();
2717
+ case 'debugger':
2718
+ return parseDebuggerStatement();
2719
+ case 'do':
2720
+ return parseDoWhileStatement();
2721
+ case 'for':
2722
+ return parseForStatement();
2723
+ case 'function':
2724
+ return parseFunctionDeclaration();
2725
+ case 'if':
2726
+ return parseIfStatement();
2727
+ case 'return':
2728
+ return parseReturnStatement();
2729
+ case 'switch':
2730
+ return parseSwitchStatement();
2731
+ case 'throw':
2732
+ return parseThrowStatement();
2733
+ case 'try':
2734
+ return parseTryStatement();
2735
+ case 'var':
2736
+ return parseVariableStatement();
2737
+ case 'while':
2738
+ return parseWhileStatement();
2739
+ case 'with':
2740
+ return parseWithStatement();
2741
+ default:
2742
+ break;
2743
+ }
2744
+ }
2745
+
2746
+ expr = parseExpression();
2747
+
2748
+ // 12.12 Labelled Statements
2749
+ if ((expr.type === Syntax.Identifier) && match(':')) {
2750
+ lex();
2751
+
2752
+ if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) {
2753
+ throwError({}, Messages.Redeclaration, 'Label', expr.name);
2754
+ }
2755
+
2756
+ state.labelSet[expr.name] = true;
2757
+ labeledBody = parseStatement();
2758
+ delete state.labelSet[expr.name];
2759
+
2760
+ return {
2761
+ type: Syntax.LabeledStatement,
2762
+ label: expr,
2763
+ body: labeledBody
2764
+ };
2765
+ }
2766
+
2767
+ consumeSemicolon();
2768
+
2769
+ return {
2770
+ type: Syntax.ExpressionStatement,
2771
+ expression: expr
2772
+ };
2773
+ }
2774
+
2775
+ // 13 Function Definition
2776
+
2777
+ function parseFunctionSourceElements() {
2778
+ var sourceElement, sourceElements = [], token, directive, firstRestricted,
2779
+ oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody;
2780
+
2781
+ expect('{');
2782
+
2783
+ while (index < length) {
2784
+ token = lookahead();
2785
+ if (token.type !== Token.StringLiteral) {
2786
+ break;
2787
+ }
2788
+
2789
+ sourceElement = parseSourceElement();
2790
+ sourceElements.push(sourceElement);
2791
+ if (sourceElement.expression.type !== Syntax.Literal) {
2792
+ // this is not directive
2793
+ break;
2794
+ }
2795
+ directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
2796
+ if (directive === 'use strict') {
2797
+ strict = true;
2798
+ if (firstRestricted) {
2799
+ throwError(firstRestricted, Messages.StrictOctalLiteral);
2800
+ }
2801
+ } else {
2802
+ if (!firstRestricted && token.octal) {
2803
+ firstRestricted = token;
2804
+ }
2805
+ }
2806
+ }
2807
+
2808
+ oldLabelSet = state.labelSet;
2809
+ oldInIteration = state.inIteration;
2810
+ oldInSwitch = state.inSwitch;
2811
+ oldInFunctionBody = state.inFunctionBody;
2812
+
2813
+ state.labelSet = {};
2814
+ state.inIteration = false;
2815
+ state.inSwitch = false;
2816
+ state.inFunctionBody = true;
2817
+
2818
+ while (index < length) {
2819
+ if (match('}')) {
2820
+ break;
2821
+ }
2822
+ sourceElement = parseSourceElement();
2823
+ if (typeof sourceElement === 'undefined') {
2824
+ break;
2825
+ }
2826
+ sourceElements.push(sourceElement);
2827
+ }
2828
+
2829
+ expect('}');
2830
+
2831
+ state.labelSet = oldLabelSet;
2832
+ state.inIteration = oldInIteration;
2833
+ state.inSwitch = oldInSwitch;
2834
+ state.inFunctionBody = oldInFunctionBody;
2835
+
2836
+ return {
2837
+ type: Syntax.BlockStatement,
2838
+ body: sourceElements
2839
+ };
2840
+ }
2841
+
2842
+ function parseFunctionDeclaration() {
2843
+ var id, param, params = [], body, token, firstRestricted, message, previousStrict, paramSet;
2844
+
2845
+ expectKeyword('function');
2846
+ token = lookahead();
2847
+ id = parseVariableIdentifier();
2848
+ if (strict) {
2849
+ if (isRestrictedWord(token.value)) {
2850
+ throwError(token, Messages.StrictFunctionName);
2851
+ }
2852
+ } else {
2853
+ if (isRestrictedWord(token.value)) {
2854
+ firstRestricted = token;
2855
+ message = Messages.StrictFunctionName;
2856
+ } else if (isStrictModeReservedWord(token.value)) {
2857
+ firstRestricted = token;
2858
+ message = Messages.StrictReservedWord;
2859
+ }
2860
+ }
2861
+
2862
+ expect('(');
2863
+
2864
+ if (!match(')')) {
2865
+ paramSet = {};
2866
+ while (index < length) {
2867
+ token = lookahead();
2868
+ param = parseVariableIdentifier();
2869
+ if (strict) {
2870
+ if (isRestrictedWord(token.value)) {
2871
+ throwError(token, Messages.StrictParamName);
2872
+ }
2873
+ if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
2874
+ throwError(token, Messages.StrictParamDupe);
2875
+ }
2876
+ } else if (!firstRestricted) {
2877
+ if (isRestrictedWord(token.value)) {
2878
+ firstRestricted = token;
2879
+ message = Messages.StrictParamName;
2880
+ } else if (isStrictModeReservedWord(token.value)) {
2881
+ firstRestricted = token;
2882
+ message = Messages.StrictReservedWord;
2883
+ } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
2884
+ firstRestricted = token;
2885
+ message = Messages.StrictParamDupe;
2886
+ }
2887
+ }
2888
+ params.push(param);
2889
+ paramSet[param.name] = true;
2890
+ if (match(')')) {
2891
+ break;
2892
+ }
2893
+ expect(',');
2894
+ }
2895
+ }
2896
+
2897
+ expect(')');
2898
+
2899
+ previousStrict = strict;
2900
+ body = parseFunctionSourceElements();
2901
+ if (strict && firstRestricted) {
2902
+ throwError(firstRestricted, message);
2903
+ }
2904
+ strict = previousStrict;
2905
+
2906
+ return {
2907
+ type: Syntax.FunctionDeclaration,
2908
+ id: id,
2909
+ params: params,
2910
+ body: body
2911
+ };
2912
+ }
2913
+
2914
+ function parseFunctionExpression() {
2915
+ var token, id = null, firstRestricted, message, param, params = [], body, previousStrict, paramSet;
2916
+
2917
+ expectKeyword('function');
2918
+
2919
+ if (!match('(')) {
2920
+ token = lookahead();
2921
+ id = parseVariableIdentifier();
2922
+ if (strict) {
2923
+ if (isRestrictedWord(token.value)) {
2924
+ throwError(token, Messages.StrictFunctionName);
2925
+ }
2926
+ } else {
2927
+ if (isRestrictedWord(token.value)) {
2928
+ firstRestricted = token;
2929
+ message = Messages.StrictFunctionName;
2930
+ } else if (isStrictModeReservedWord(token.value)) {
2931
+ firstRestricted = token;
2932
+ message = Messages.StrictReservedWord;
2933
+ }
2934
+ }
2935
+ }
2936
+
2937
+ expect('(');
2938
+
2939
+ if (!match(')')) {
2940
+ paramSet = {};
2941
+ while (index < length) {
2942
+ token = lookahead();
2943
+ param = parseVariableIdentifier();
2944
+ if (strict) {
2945
+ if (isRestrictedWord(token.value)) {
2946
+ throwError(token, Messages.StrictParamName);
2947
+ }
2948
+ if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
2949
+ throwError(token, Messages.StrictParamDupe);
2950
+ }
2951
+ } else if (!firstRestricted) {
2952
+ if (isRestrictedWord(token.value)) {
2953
+ firstRestricted = token;
2954
+ message = Messages.StrictParamName;
2955
+ } else if (isStrictModeReservedWord(token.value)) {
2956
+ firstRestricted = token;
2957
+ message = Messages.StrictReservedWord;
2958
+ } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
2959
+ firstRestricted = token;
2960
+ message = Messages.StrictParamDupe;
2961
+ }
2962
+ }
2963
+ params.push(param);
2964
+ paramSet[param.name] = true;
2965
+ if (match(')')) {
2966
+ break;
2967
+ }
2968
+ expect(',');
2969
+ }
2970
+ }
2971
+
2972
+ expect(')');
2973
+
2974
+ previousStrict = strict;
2975
+ body = parseFunctionSourceElements();
2976
+ if (strict && firstRestricted) {
2977
+ throwError(firstRestricted, message);
2978
+ }
2979
+ strict = previousStrict;
2980
+
2981
+ return {
2982
+ type: Syntax.FunctionExpression,
2983
+ id: id,
2984
+ params: params,
2985
+ body: body
2986
+ };
2987
+ }
2988
+
2989
+ // 14 Program
2990
+
2991
+ function parseSourceElement() {
2992
+ var token = lookahead();
2993
+
2994
+ if (token.type === Token.Keyword) {
2995
+ switch (token.value) {
2996
+ case 'const':
2997
+ case 'let':
2998
+ return parseConstLetDeclaration(token.value);
2999
+ case 'function':
3000
+ return parseFunctionDeclaration();
3001
+ default:
3002
+ return parseStatement();
3003
+ }
3004
+ }
3005
+
3006
+ if (token.type !== Token.EOF) {
3007
+ return parseStatement();
3008
+ }
3009
+ }
3010
+
3011
+ function parseSourceElements() {
3012
+ var sourceElement, sourceElements = [], token, directive, firstRestricted;
3013
+
3014
+ while (index < length) {
3015
+ token = lookahead();
3016
+ if (token.type !== Token.StringLiteral) {
3017
+ break;
3018
+ }
3019
+
3020
+ sourceElement = parseSourceElement();
3021
+ sourceElements.push(sourceElement);
3022
+ if (sourceElement.expression.type !== Syntax.Literal) {
3023
+ // this is not directive
3024
+ break;
3025
+ }
3026
+ directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
3027
+ if (directive === 'use strict') {
3028
+ strict = true;
3029
+ if (firstRestricted) {
3030
+ throwError(firstRestricted, Messages.StrictOctalLiteral);
3031
+ }
3032
+ } else {
3033
+ if (!firstRestricted && token.octal) {
3034
+ firstRestricted = token;
3035
+ }
3036
+ }
3037
+ }
3038
+
3039
+ while (index < length) {
3040
+ sourceElement = parseSourceElement();
3041
+ if (typeof sourceElement === 'undefined') {
3042
+ break;
3043
+ }
3044
+ sourceElements.push(sourceElement);
3045
+ }
3046
+ return sourceElements;
3047
+ }
3048
+
3049
+ function parseProgram() {
3050
+ var program;
3051
+ strict = false;
3052
+ program = {
3053
+ type: Syntax.Program,
3054
+ body: parseSourceElements()
3055
+ };
3056
+ return program;
3057
+ }
3058
+
3059
+ // The following functions are needed only when the option to preserve
3060
+ // the comments is active.
3061
+
3062
+ function addComment(start, end, type, value) {
3063
+ assert(typeof start === 'number', 'Comment must have valid position');
3064
+
3065
+ // Because the way the actual token is scanned, often the comments
3066
+ // (if any) are skipped twice during the lexical analysis.
3067
+ // Thus, we need to skip adding a comment if the comment array already
3068
+ // handled it.
3069
+ if (extra.comments.length > 0) {
3070
+ if (extra.comments[extra.comments.length - 1].range[1] > start) {
3071
+ return;
3072
+ }
3073
+ }
3074
+
3075
+ extra.comments.push({
3076
+ range: [start, end],
3077
+ type: type,
3078
+ value: value
3079
+ });
3080
+ }
3081
+
3082
+ function scanComment() {
3083
+ var comment, ch, start, blockComment, lineComment;
3084
+
3085
+ comment = '';
3086
+ blockComment = false;
3087
+ lineComment = false;
3088
+
3089
+ while (index < length) {
3090
+ ch = source[index];
3091
+
3092
+ if (lineComment) {
3093
+ ch = nextChar();
3094
+ if (index >= length) {
3095
+ lineComment = false;
3096
+ comment += ch;
3097
+ addComment(start, index, 'Line', comment);
3098
+ } else if (isLineTerminator(ch)) {
3099
+ lineComment = false;
3100
+ addComment(start, index, 'Line', comment);
3101
+ if (ch === '\r' && source[index] === '\n') {
3102
+ ++index;
3103
+ }
3104
+ ++lineNumber;
3105
+ lineStart = index;
3106
+ comment = '';
3107
+ } else {
3108
+ comment += ch;
3109
+ }
3110
+ } else if (blockComment) {
3111
+ if (isLineTerminator(ch)) {
3112
+ if (ch === '\r' && source[index + 1] === '\n') {
3113
+ ++index;
3114
+ comment += '\r\n';
3115
+ } else {
3116
+ comment += ch;
3117
+ }
3118
+ ++lineNumber;
3119
+ ++index;
3120
+ lineStart = index;
3121
+ if (index >= length) {
3122
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
3123
+ }
3124
+ } else {
3125
+ ch = nextChar();
3126
+ if (index >= length) {
3127
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
3128
+ }
3129
+ comment += ch;
3130
+ if (ch === '*') {
3131
+ ch = source[index];
3132
+ if (ch === '/') {
3133
+ comment = comment.substr(0, comment.length - 1);
3134
+ blockComment = false;
3135
+ ++index;
3136
+ addComment(start, index, 'Block', comment);
3137
+ comment = '';
3138
+ }
3139
+ }
3140
+ }
3141
+ } else if (ch === '/') {
3142
+ ch = source[index + 1];
3143
+ if (ch === '/') {
3144
+ start = index;
3145
+ index += 2;
3146
+ lineComment = true;
3147
+ } else if (ch === '*') {
3148
+ start = index;
3149
+ index += 2;
3150
+ blockComment = true;
3151
+ if (index >= length) {
3152
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
3153
+ }
3154
+ } else {
3155
+ break;
3156
+ }
3157
+ } else if (isWhiteSpace(ch)) {
3158
+ ++index;
3159
+ } else if (isLineTerminator(ch)) {
3160
+ ++index;
3161
+ if (ch === '\r' && source[index] === '\n') {
3162
+ ++index;
3163
+ }
3164
+ ++lineNumber;
3165
+ lineStart = index;
3166
+ } else {
3167
+ break;
3168
+ }
3169
+ }
3170
+ }
3171
+
3172
+ function collectToken() {
3173
+ var token = extra.advance(),
3174
+ range,
3175
+ value;
3176
+
3177
+ if (token.type !== Token.EOF) {
3178
+ range = [token.range[0], token.range[1]];
3179
+ value = sliceSource(token.range[0], token.range[1]);
3180
+ extra.tokens.push({
3181
+ type: TokenName[token.type],
3182
+ value: value,
3183
+ range: range
3184
+ });
3185
+ }
3186
+
3187
+ return token;
3188
+ }
3189
+
3190
+ function collectRegex() {
3191
+ var pos, regex, token;
3192
+
3193
+ skipComment();
3194
+
3195
+ pos = index;
3196
+ regex = extra.scanRegExp();
3197
+
3198
+ // Pop the previous token, which is likely '/' or '/='
3199
+ if (extra.tokens.length > 0) {
3200
+ token = extra.tokens[extra.tokens.length - 1];
3201
+ if (token.range[0] === pos && token.type === 'Punctuator') {
3202
+ if (token.value === '/' || token.value === '/=') {
3203
+ extra.tokens.pop();
3204
+ }
3205
+ }
3206
+ }
3207
+
3208
+ extra.tokens.push({
3209
+ type: 'RegularExpression',
3210
+ value: regex.literal,
3211
+ range: [pos, index]
3212
+ });
3213
+
3214
+ return regex;
3215
+ }
3216
+
3217
+ function createLiteral(token) {
3218
+ return {
3219
+ type: Syntax.Literal,
3220
+ value: token.value
3221
+ };
3222
+ }
3223
+
3224
+ function createRawLiteral(token) {
3225
+ return {
3226
+ type: Syntax.Literal,
3227
+ value: token.value,
3228
+ raw: sliceSource(token.range[0], token.range[1])
3229
+ };
3230
+ }
3231
+
3232
+ function wrapTrackingFunction(range, loc) {
3233
+
3234
+ return function (parseFunction) {
3235
+
3236
+ function isBinary(node) {
3237
+ return node.type === Syntax.LogicalExpression ||
3238
+ node.type === Syntax.BinaryExpression;
3239
+ }
3240
+
3241
+ function visit(node) {
3242
+ if (isBinary(node.left)) {
3243
+ visit(node.left);
3244
+ }
3245
+ if (isBinary(node.right)) {
3246
+ visit(node.right);
3247
+ }
3248
+
3249
+ if (range && typeof node.range === 'undefined') {
3250
+ // HACK: Add line number as last item in range array
3251
+ node.range = [node.left.range[0], node.right.range[1], node.left.range[2]];
3252
+ }
3253
+ if (loc && typeof node.loc === 'undefined') {
3254
+ node.loc = {
3255
+ start: node.left.loc.start,
3256
+ end: node.right.loc.end
3257
+ };
3258
+ }
3259
+ }
3260
+
3261
+ return function () {
3262
+ var node, rangeInfo, locInfo;
3263
+
3264
+ skipComment();
3265
+ // HACK: Add line number as last item in range array
3266
+ rangeInfo = [index, 0, lineNumber];
3267
+ locInfo = {
3268
+ start: {
3269
+ line: lineNumber,
3270
+ column: index - lineStart
3271
+ }
3272
+ };
3273
+
3274
+ node = parseFunction.apply(null, arguments);
3275
+ if (typeof node !== 'undefined') {
3276
+
3277
+ if (range) {
3278
+ rangeInfo[1] = index;
3279
+ node.range = rangeInfo;
3280
+ }
3281
+
3282
+ if (loc) {
3283
+ locInfo.end = {
3284
+ line: lineNumber,
3285
+ column: index - lineStart
3286
+ };
3287
+ node.loc = locInfo;
3288
+ }
3289
+
3290
+ if (isBinary(node)) {
3291
+ visit(node);
3292
+ }
3293
+
3294
+ if (node.type === Syntax.MemberExpression) {
3295
+ if (typeof node.object.range !== 'undefined') {
3296
+ node.range[0] = node.object.range[0];
3297
+ // HACK: Add line number as last item in range array
3298
+ node.range[2] = node.object.range[2];
3299
+ }
3300
+ if (typeof node.object.loc !== 'undefined') {
3301
+ node.loc.start = node.object.loc.start;
3302
+ }
3303
+ }
3304
+ return node;
3305
+ }
3306
+ };
3307
+
3308
+ };
3309
+ }
3310
+
3311
+ function patch() {
3312
+
3313
+ var wrapTracking;
3314
+
3315
+ if (extra.comments) {
3316
+ extra.skipComment = skipComment;
3317
+ skipComment = scanComment;
3318
+ }
3319
+
3320
+ if (extra.raw) {
3321
+ extra.createLiteral = createLiteral;
3322
+ createLiteral = createRawLiteral;
3323
+ }
3324
+
3325
+ if (extra.range || extra.loc) {
3326
+
3327
+ wrapTracking = wrapTrackingFunction(extra.range, extra.loc);
3328
+
3329
+ extra.parseAdditiveExpression = parseAdditiveExpression;
3330
+ extra.parseAssignmentExpression = parseAssignmentExpression;
3331
+ extra.parseBitwiseANDExpression = parseBitwiseANDExpression;
3332
+ extra.parseBitwiseORExpression = parseBitwiseORExpression;
3333
+ extra.parseBitwiseXORExpression = parseBitwiseXORExpression;
3334
+ extra.parseBlock = parseBlock;
3335
+ extra.parseFunctionSourceElements = parseFunctionSourceElements;
3336
+ extra.parseCallMember = parseCallMember;
3337
+ extra.parseCatchClause = parseCatchClause;
3338
+ extra.parseComputedMember = parseComputedMember;
3339
+ extra.parseConditionalExpression = parseConditionalExpression;
3340
+ extra.parseConstLetDeclaration = parseConstLetDeclaration;
3341
+ extra.parseEqualityExpression = parseEqualityExpression;
3342
+ extra.parseExpression = parseExpression;
3343
+ extra.parseForVariableDeclaration = parseForVariableDeclaration;
3344
+ extra.parseFunctionDeclaration = parseFunctionDeclaration;
3345
+ extra.parseFunctionExpression = parseFunctionExpression;
3346
+ extra.parseLogicalANDExpression = parseLogicalANDExpression;
3347
+ extra.parseLogicalORExpression = parseLogicalORExpression;
3348
+ extra.parseMultiplicativeExpression = parseMultiplicativeExpression;
3349
+ extra.parseNewExpression = parseNewExpression;
3350
+ extra.parseNonComputedMember = parseNonComputedMember;
3351
+ extra.parseNonComputedProperty = parseNonComputedProperty;
3352
+ extra.parseObjectProperty = parseObjectProperty;
3353
+ extra.parseObjectPropertyKey = parseObjectPropertyKey;
3354
+ extra.parsePostfixExpression = parsePostfixExpression;
3355
+ extra.parsePrimaryExpression = parsePrimaryExpression;
3356
+ extra.parseProgram = parseProgram;
3357
+ extra.parsePropertyFunction = parsePropertyFunction;
3358
+ extra.parseRelationalExpression = parseRelationalExpression;
3359
+ extra.parseStatement = parseStatement;
3360
+ extra.parseShiftExpression = parseShiftExpression;
3361
+ extra.parseSwitchCase = parseSwitchCase;
3362
+ extra.parseUnaryExpression = parseUnaryExpression;
3363
+ extra.parseVariableDeclaration = parseVariableDeclaration;
3364
+ extra.parseVariableIdentifier = parseVariableIdentifier;
3365
+
3366
+ parseAdditiveExpression = wrapTracking(extra.parseAdditiveExpression);
3367
+ parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression);
3368
+ parseBitwiseANDExpression = wrapTracking(extra.parseBitwiseANDExpression);
3369
+ parseBitwiseORExpression = wrapTracking(extra.parseBitwiseORExpression);
3370
+ parseBitwiseXORExpression = wrapTracking(extra.parseBitwiseXORExpression);
3371
+ parseBlock = wrapTracking(extra.parseBlock);
3372
+ parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements);
3373
+ parseCallMember = wrapTracking(extra.parseCallMember);
3374
+ parseCatchClause = wrapTracking(extra.parseCatchClause);
3375
+ parseComputedMember = wrapTracking(extra.parseComputedMember);
3376
+ parseConditionalExpression = wrapTracking(extra.parseConditionalExpression);
3377
+ parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration);
3378
+ parseEqualityExpression = wrapTracking(extra.parseEqualityExpression);
3379
+ parseExpression = wrapTracking(extra.parseExpression);
3380
+ parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration);
3381
+ parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration);
3382
+ parseFunctionExpression = wrapTracking(extra.parseFunctionExpression);
3383
+ parseLogicalANDExpression = wrapTracking(extra.parseLogicalANDExpression);
3384
+ parseLogicalORExpression = wrapTracking(extra.parseLogicalORExpression);
3385
+ parseMultiplicativeExpression = wrapTracking(extra.parseMultiplicativeExpression);
3386
+ parseNewExpression = wrapTracking(extra.parseNewExpression);
3387
+ parseNonComputedMember = wrapTracking(extra.parseNonComputedMember);
3388
+ parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty);
3389
+ parseObjectProperty = wrapTracking(extra.parseObjectProperty);
3390
+ parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey);
3391
+ parsePostfixExpression = wrapTracking(extra.parsePostfixExpression);
3392
+ parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression);
3393
+ parseProgram = wrapTracking(extra.parseProgram);
3394
+ parsePropertyFunction = wrapTracking(extra.parsePropertyFunction);
3395
+ parseRelationalExpression = wrapTracking(extra.parseRelationalExpression);
3396
+ parseStatement = wrapTracking(extra.parseStatement);
3397
+ parseShiftExpression = wrapTracking(extra.parseShiftExpression);
3398
+ parseSwitchCase = wrapTracking(extra.parseSwitchCase);
3399
+ parseUnaryExpression = wrapTracking(extra.parseUnaryExpression);
3400
+ parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration);
3401
+ parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier);
3402
+ }
3403
+
3404
+ if (typeof extra.tokens !== 'undefined') {
3405
+ extra.advance = advance;
3406
+ extra.scanRegExp = scanRegExp;
3407
+
3408
+ advance = collectToken;
3409
+ scanRegExp = collectRegex;
3410
+ }
3411
+ }
3412
+
3413
+ function unpatch() {
3414
+ if (typeof extra.skipComment === 'function') {
3415
+ skipComment = extra.skipComment;
3416
+ }
3417
+
3418
+ if (extra.raw) {
3419
+ createLiteral = extra.createLiteral;
3420
+ }
3421
+
3422
+ if (extra.range || extra.loc) {
3423
+ parseAdditiveExpression = extra.parseAdditiveExpression;
3424
+ parseAssignmentExpression = extra.parseAssignmentExpression;
3425
+ parseBitwiseANDExpression = extra.parseBitwiseANDExpression;
3426
+ parseBitwiseORExpression = extra.parseBitwiseORExpression;
3427
+ parseBitwiseXORExpression = extra.parseBitwiseXORExpression;
3428
+ parseBlock = extra.parseBlock;
3429
+ parseFunctionSourceElements = extra.parseFunctionSourceElements;
3430
+ parseCallMember = extra.parseCallMember;
3431
+ parseCatchClause = extra.parseCatchClause;
3432
+ parseComputedMember = extra.parseComputedMember;
3433
+ parseConditionalExpression = extra.parseConditionalExpression;
3434
+ parseConstLetDeclaration = extra.parseConstLetDeclaration;
3435
+ parseEqualityExpression = extra.parseEqualityExpression;
3436
+ parseExpression = extra.parseExpression;
3437
+ parseForVariableDeclaration = extra.parseForVariableDeclaration;
3438
+ parseFunctionDeclaration = extra.parseFunctionDeclaration;
3439
+ parseFunctionExpression = extra.parseFunctionExpression;
3440
+ parseLogicalANDExpression = extra.parseLogicalANDExpression;
3441
+ parseLogicalORExpression = extra.parseLogicalORExpression;
3442
+ parseMultiplicativeExpression = extra.parseMultiplicativeExpression;
3443
+ parseNewExpression = extra.parseNewExpression;
3444
+ parseNonComputedMember = extra.parseNonComputedMember;
3445
+ parseNonComputedProperty = extra.parseNonComputedProperty;
3446
+ parseObjectProperty = extra.parseObjectProperty;
3447
+ parseObjectPropertyKey = extra.parseObjectPropertyKey;
3448
+ parsePrimaryExpression = extra.parsePrimaryExpression;
3449
+ parsePostfixExpression = extra.parsePostfixExpression;
3450
+ parseProgram = extra.parseProgram;
3451
+ parsePropertyFunction = extra.parsePropertyFunction;
3452
+ parseRelationalExpression = extra.parseRelationalExpression;
3453
+ parseStatement = extra.parseStatement;
3454
+ parseShiftExpression = extra.parseShiftExpression;
3455
+ parseSwitchCase = extra.parseSwitchCase;
3456
+ parseUnaryExpression = extra.parseUnaryExpression;
3457
+ parseVariableDeclaration = extra.parseVariableDeclaration;
3458
+ parseVariableIdentifier = extra.parseVariableIdentifier;
3459
+ }
3460
+
3461
+ if (typeof extra.scanRegExp === 'function') {
3462
+ advance = extra.advance;
3463
+ scanRegExp = extra.scanRegExp;
3464
+ }
3465
+ }
3466
+
3467
+ function stringToArray(str) {
3468
+ var length = str.length,
3469
+ result = [],
3470
+ i;
3471
+ for (i = 0; i < length; ++i) {
3472
+ result[i] = str.charAt(i);
3473
+ }
3474
+ return result;
3475
+ }
3476
+
3477
+ function parse(code, options) {
3478
+ var program, toString;
3479
+
3480
+ toString = String;
3481
+ if (typeof code !== 'string' && !(code instanceof String)) {
3482
+ code = toString(code);
3483
+ }
3484
+
3485
+ source = code;
3486
+ index = 0;
3487
+ lineNumber = (source.length > 0) ? 1 : 0;
3488
+ lineStart = 0;
3489
+ length = source.length;
3490
+ buffer = null;
3491
+ state = {
3492
+ allowIn: true,
3493
+ labelSet: {},
3494
+ lastParenthesized: null,
3495
+ inFunctionBody: false,
3496
+ inIteration: false,
3497
+ inSwitch: false
3498
+ };
3499
+
3500
+ extra = {};
3501
+ if (typeof options !== 'undefined') {
3502
+ extra.range = (typeof options.range === 'boolean') && options.range;
3503
+ extra.loc = (typeof options.loc === 'boolean') && options.loc;
3504
+ extra.raw = (typeof options.raw === 'boolean') && options.raw;
3505
+ if (typeof options.tokens === 'boolean' && options.tokens) {
3506
+ extra.tokens = [];
3507
+ }
3508
+ if (typeof options.comment === 'boolean' && options.comment) {
3509
+ extra.comments = [];
3510
+ }
3511
+ if (typeof options.tolerant === 'boolean' && options.tolerant) {
3512
+ extra.errors = [];
3513
+ }
3514
+ }
3515
+
3516
+ if (length > 0) {
3517
+ if (typeof source[0] === 'undefined') {
3518
+ // Try first to convert to a string. This is good as fast path
3519
+ // for old IE which understands string indexing for string
3520
+ // literals only and not for string object.
3521
+ if (code instanceof String) {
3522
+ source = code.valueOf();
3523
+ }
3524
+
3525
+ // Force accessing the characters via an array.
3526
+ if (typeof source[0] === 'undefined') {
3527
+ source = stringToArray(code);
3528
+ }
3529
+ }
3530
+ }
3531
+
3532
+ patch();
3533
+ try {
3534
+ program = parseProgram();
3535
+ if (typeof extra.comments !== 'undefined') {
3536
+ program.comments = extra.comments;
3537
+ }
3538
+ if (typeof extra.tokens !== 'undefined') {
3539
+ program.tokens = extra.tokens;
3540
+ }
3541
+ if (typeof extra.errors !== 'undefined') {
3542
+ program.errors = extra.errors;
3543
+ }
3544
+ } catch (e) {
3545
+ throw e;
3546
+ } finally {
3547
+ unpatch();
3548
+ extra = {};
3549
+ }
3550
+
3551
+ return program;
3552
+ }
3553
+
3554
+ // Sync with package.json.
3555
+ exports.version = '1.0.0-dev';
3556
+
3557
+ exports.parse = parse;
3558
+
3559
+ // Deep copy.
3560
+ exports.Syntax = (function () {
3561
+ var name, types = {};
3562
+
3563
+ if (typeof Object.create === 'function') {
3564
+ types = Object.create(null);
3565
+ }
3566
+
3567
+ for (name in Syntax) {
3568
+ if (Syntax.hasOwnProperty(name)) {
3569
+ types[name] = Syntax[name];
3570
+ }
3571
+ }
3572
+
3573
+ if (typeof Object.freeze === 'function') {
3574
+ Object.freeze(types);
3575
+ }
3576
+
3577
+ return types;
3578
+ }());
3579
+
3580
+ }(typeof exports === 'undefined' ? (esprima = {}) : exports));
3581
+ /* vim: set sw=4 ts=4 et tw=80 : */