jsduck 5.0.0.beta3 → 5.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 : */