jsduck 5.0.0.beta3 → 5.0.0.beta4

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