parser 2.5.1.0 → 3.0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/parser.rb +4 -0
- data/lib/parser/all.rb +3 -0
- data/lib/parser/ast/processor.rb +49 -1
- data/lib/parser/base.rb +30 -6
- data/lib/parser/builders/default.rb +586 -29
- data/lib/parser/context.rb +17 -0
- data/lib/parser/current.rb +34 -7
- data/lib/parser/current_arg_stack.rb +46 -0
- data/lib/parser/diagnostic.rb +1 -1
- data/lib/parser/diagnostic/engine.rb +1 -2
- data/lib/parser/lexer.rb +23780 -0
- data/lib/parser/lexer/dedenter.rb +52 -49
- data/lib/parser/lexer/literal.rb +4 -0
- data/lib/parser/lexer/stack_state.rb +4 -0
- data/lib/parser/macruby.rb +6149 -0
- data/lib/parser/max_numparam_stack.rb +56 -0
- data/lib/parser/messages.rb +74 -44
- data/lib/parser/meta.rb +13 -3
- data/lib/parser/ruby18.rb +5667 -0
- data/lib/parser/ruby19.rb +6092 -0
- data/lib/parser/ruby20.rb +6527 -0
- data/lib/parser/ruby21.rb +6578 -0
- data/lib/parser/ruby22.rb +6613 -0
- data/lib/parser/ruby23.rb +6624 -0
- data/lib/parser/ruby24.rb +6694 -0
- data/lib/parser/ruby25.rb +6662 -0
- data/lib/parser/ruby26.rb +6676 -0
- data/lib/parser/ruby27.rb +7862 -0
- data/lib/parser/ruby28.rb +8047 -0
- data/lib/parser/ruby30.rb +8060 -0
- data/lib/parser/ruby31.rb +8075 -0
- data/lib/parser/rubymotion.rb +6086 -0
- data/lib/parser/runner.rb +36 -2
- data/lib/parser/runner/ruby_parse.rb +2 -2
- data/lib/parser/runner/ruby_rewrite.rb +2 -2
- data/lib/parser/source/buffer.rb +54 -29
- data/lib/parser/source/comment.rb +18 -5
- data/lib/parser/source/comment/associator.rb +34 -11
- data/lib/parser/source/map.rb +1 -1
- data/lib/parser/source/map/method_definition.rb +25 -0
- data/lib/parser/source/range.rb +20 -4
- data/lib/parser/source/tree_rewriter.rb +146 -16
- data/lib/parser/source/tree_rewriter/action.rb +137 -28
- data/lib/parser/static_environment.rb +14 -0
- data/lib/parser/tree_rewriter.rb +3 -3
- data/lib/parser/variables_stack.rb +36 -0
- data/lib/parser/version.rb +1 -1
- data/parser.gemspec +13 -21
- metadata +34 -98
- data/.gitignore +0 -32
- data/.travis.yml +0 -21
- data/.yardopts +0 -21
- data/CHANGELOG.md +0 -909
- data/CONTRIBUTING.md +0 -17
- data/Gemfile +0 -10
- data/README.md +0 -301
- data/Rakefile +0 -165
- data/doc/AST_FORMAT.md +0 -1718
- data/doc/CUSTOMIZATION.md +0 -37
- data/doc/INTERNALS.md +0 -21
- data/doc/css/.gitkeep +0 -0
- data/doc/css/common.css +0 -68
- data/lib/parser/lexer.rl +0 -2376
- data/lib/parser/macruby.y +0 -2198
- data/lib/parser/ruby18.y +0 -1934
- data/lib/parser/ruby19.y +0 -2175
- data/lib/parser/ruby20.y +0 -2353
- data/lib/parser/ruby21.y +0 -2357
- data/lib/parser/ruby22.y +0 -2364
- data/lib/parser/ruby23.y +0 -2370
- data/lib/parser/ruby24.y +0 -2395
- data/lib/parser/ruby25.y +0 -2392
- data/lib/parser/ruby26.y +0 -2392
- data/lib/parser/rubymotion.y +0 -2182
- data/test/bug_163/fixtures/input.rb +0 -5
- data/test/bug_163/fixtures/output.rb +0 -5
- data/test/bug_163/rewriter.rb +0 -20
- data/test/helper.rb +0 -52
- data/test/parse_helper.rb +0 -315
- data/test/racc_coverage_helper.rb +0 -133
- data/test/test_base.rb +0 -31
- data/test/test_current.rb +0 -27
- data/test/test_diagnostic.rb +0 -96
- data/test/test_diagnostic_engine.rb +0 -62
- data/test/test_encoding.rb +0 -99
- data/test/test_lexer.rb +0 -3537
- data/test/test_lexer_stack_state.rb +0 -78
- data/test/test_parse_helper.rb +0 -80
- data/test/test_parser.rb +0 -6968
- data/test/test_runner_rewrite.rb +0 -47
- data/test/test_source_buffer.rb +0 -162
- data/test/test_source_comment.rb +0 -36
- data/test/test_source_comment_associator.rb +0 -367
- data/test/test_source_map.rb +0 -15
- data/test/test_source_range.rb +0 -172
- data/test/test_source_rewriter.rb +0 -541
- data/test/test_source_rewriter_action.rb +0 -46
- data/test/test_source_tree_rewriter.rb +0 -173
- data/test/test_static_environment.rb +0 -45
- data/test/using_tree_rewriter/fixtures/input.rb +0 -3
- data/test/using_tree_rewriter/fixtures/output.rb +0 -3
- data/test/using_tree_rewriter/using_tree_rewriter.rb +0 -9
data/lib/parser/runner.rb
CHANGED
@@ -14,9 +14,8 @@ module Parser
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def initialize
|
17
|
-
Parser::Builders::Default.modernize
|
18
|
-
|
19
17
|
@option_parser = OptionParser.new { |opts| setup_option_parsing(opts) }
|
18
|
+
@legacy = {}
|
20
19
|
@parser_class = nil
|
21
20
|
@parser = nil
|
22
21
|
@files = []
|
@@ -30,6 +29,7 @@ module Parser
|
|
30
29
|
|
31
30
|
def execute(options)
|
32
31
|
parse_options(options)
|
32
|
+
setup_builder_default
|
33
33
|
prepare_parser
|
34
34
|
|
35
35
|
process_all_input
|
@@ -37,6 +37,8 @@ module Parser
|
|
37
37
|
|
38
38
|
private
|
39
39
|
|
40
|
+
LEGACY_MODES = %i[lambda procarg0 encoding index arg_inside_procarg0 forward_arg kwargs match_pattern].freeze
|
41
|
+
|
40
42
|
def runner_name
|
41
43
|
raise NotImplementedError, "implement #{self.class}##{__callee__}"
|
42
44
|
end
|
@@ -106,6 +108,21 @@ module Parser
|
|
106
108
|
@parser_class = Parser::Ruby26
|
107
109
|
end
|
108
110
|
|
111
|
+
opts.on '--27', 'Parse as Ruby 2.7 would' do
|
112
|
+
require 'parser/ruby27'
|
113
|
+
@parser_class = Parser::Ruby27
|
114
|
+
end
|
115
|
+
|
116
|
+
opts.on '--30', 'Parse as Ruby 3.0 would' do
|
117
|
+
require 'parser/ruby30'
|
118
|
+
@parser_class = Parser::Ruby30
|
119
|
+
end
|
120
|
+
|
121
|
+
opts.on '--31', 'Parse as Ruby 3.1 would' do
|
122
|
+
require 'parser/ruby31'
|
123
|
+
@parser_class = Parser::Ruby31
|
124
|
+
end
|
125
|
+
|
109
126
|
opts.on '--mac', 'Parse as MacRuby 0.12 would' do
|
110
127
|
require 'parser/macruby'
|
111
128
|
@parser_class = Parser::MacRuby
|
@@ -116,6 +133,17 @@ module Parser
|
|
116
133
|
@parser_class = Parser::RubyMotion
|
117
134
|
end
|
118
135
|
|
136
|
+
opts.on '--legacy', "Parse with all legacy modes" do
|
137
|
+
@legacy = Hash.new(true)
|
138
|
+
end
|
139
|
+
|
140
|
+
LEGACY_MODES.each do |mode|
|
141
|
+
opt_name = "--legacy-#{mode.to_s.gsub('_', '-')}"
|
142
|
+
opts.on opt_name, "Parse with legacy mode for emit_#{mode}" do
|
143
|
+
@legacy[mode] = true
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
119
147
|
opts.on '-w', '--warnings', 'Enable warnings' do |w|
|
120
148
|
@warnings = w
|
121
149
|
end
|
@@ -154,6 +182,12 @@ module Parser
|
|
154
182
|
end
|
155
183
|
end
|
156
184
|
|
185
|
+
def setup_builder_default
|
186
|
+
LEGACY_MODES.each do |mode|
|
187
|
+
Parser::Builders::Default.send(:"emit_#{mode}=", !@legacy[mode])
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
157
191
|
def prepare_parser
|
158
192
|
@parser = @parser_class.new
|
159
193
|
|
@@ -123,7 +123,7 @@ module Parser
|
|
123
123
|
opts.on '--emit-ruby', 'Emit S-expressions as valid Ruby code' do
|
124
124
|
@emit_ruby = true
|
125
125
|
end
|
126
|
-
|
126
|
+
|
127
127
|
opts.on '--emit-json', 'Emit S-expressions as valid JSON' do
|
128
128
|
@emit_json = true
|
129
129
|
end
|
@@ -146,7 +146,7 @@ module Parser
|
|
146
146
|
if @emit_ruby
|
147
147
|
puts ast.inspect
|
148
148
|
elsif @emit_json
|
149
|
-
puts JSON.generate(ast.to_sexp_array)
|
149
|
+
puts(ast ? JSON.generate(ast.to_sexp_array) : nil)
|
150
150
|
else
|
151
151
|
puts ast.to_s
|
152
152
|
end
|
@@ -55,8 +55,8 @@ module Parser
|
|
55
55
|
new_source = rewriter.rewrite(buffer, ast)
|
56
56
|
|
57
57
|
new_buffer = Source::Buffer.new(initial_buffer.name +
|
58
|
-
'|after ' + rewriter_class.name
|
59
|
-
|
58
|
+
'|after ' + rewriter_class.name,
|
59
|
+
source: new_source)
|
60
60
|
|
61
61
|
@parser.reset
|
62
62
|
new_ast = @parser.parse(new_buffer)
|
data/lib/parser/source/buffer.rb
CHANGED
@@ -46,7 +46,7 @@ module Parser
|
|
46
46
|
# magic encoding comment or UTF-8 BOM. `string` can be in any encoding.
|
47
47
|
#
|
48
48
|
# @param [String] string
|
49
|
-
# @return [String
|
49
|
+
# @return [String, nil] encoding name, if recognized
|
50
50
|
#
|
51
51
|
def self.recognize_encoding(string)
|
52
52
|
return if string.empty?
|
@@ -102,7 +102,7 @@ module Parser
|
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
|
-
def initialize(name, first_line = 1)
|
105
|
+
def initialize(name, first_line = 1, source: nil)
|
106
106
|
@name = name.to_s
|
107
107
|
@source = nil
|
108
108
|
@first_line = first_line
|
@@ -114,8 +114,9 @@ module Parser
|
|
114
114
|
@slice_source = nil
|
115
115
|
|
116
116
|
# Cache for fast lookup
|
117
|
-
@
|
118
|
-
|
117
|
+
@line_index_for_position = {}
|
118
|
+
|
119
|
+
self.source = source if source
|
119
120
|
end
|
120
121
|
|
121
122
|
##
|
@@ -205,9 +206,10 @@ module Parser
|
|
205
206
|
# @return [[Integer, Integer]] `[line, column]`
|
206
207
|
#
|
207
208
|
def decompose_position(position)
|
208
|
-
|
209
|
+
line_index = line_index_for_position(position)
|
210
|
+
line_begin = line_begins[line_index]
|
209
211
|
|
210
|
-
[ @first_line +
|
212
|
+
[ @first_line + line_index , position - line_begin ]
|
211
213
|
end
|
212
214
|
|
213
215
|
##
|
@@ -218,10 +220,7 @@ module Parser
|
|
218
220
|
# @api private
|
219
221
|
#
|
220
222
|
def line_for_position(position)
|
221
|
-
|
222
|
-
line_no, _ = line_for(position)
|
223
|
-
@first_line + line_no
|
224
|
-
end
|
223
|
+
line_index_for_position(position) + @first_line
|
225
224
|
end
|
226
225
|
|
227
226
|
##
|
@@ -232,10 +231,8 @@ module Parser
|
|
232
231
|
# @api private
|
233
232
|
#
|
234
233
|
def column_for_position(position)
|
235
|
-
|
236
|
-
|
237
|
-
position - line_begin
|
238
|
-
end
|
234
|
+
line_index = line_index_for_position(position)
|
235
|
+
position - line_begins[line_index]
|
239
236
|
end
|
240
237
|
|
241
238
|
##
|
@@ -276,15 +273,13 @@ module Parser
|
|
276
273
|
# @raise [IndexError] if `lineno` is out of bounds
|
277
274
|
#
|
278
275
|
def line_range(lineno)
|
279
|
-
index = lineno - @first_line
|
280
|
-
if index
|
276
|
+
index = lineno - @first_line
|
277
|
+
if index < 0 || index + 1 >= line_begins.size
|
281
278
|
raise IndexError, 'Parser::Source::Buffer: range for line ' \
|
282
279
|
"#{lineno} requested, valid line numbers are #{@first_line}.." \
|
283
|
-
"#{@first_line + line_begins.size -
|
284
|
-
elsif index == line_begins.size
|
285
|
-
Range.new(self, line_begins[-index][1], @source.size)
|
280
|
+
"#{@first_line + line_begins.size - 2}"
|
286
281
|
else
|
287
|
-
Range.new(self, line_begins[
|
282
|
+
Range.new(self, line_begins[index], line_begins[index + 1] - 1)
|
288
283
|
end
|
289
284
|
end
|
290
285
|
|
@@ -301,27 +296,57 @@ module Parser
|
|
301
296
|
# @return [Integer]
|
302
297
|
#
|
303
298
|
def last_line
|
304
|
-
line_begins.size + @first_line -
|
299
|
+
line_begins.size + @first_line - 2
|
300
|
+
end
|
301
|
+
|
302
|
+
# :nodoc:
|
303
|
+
def freeze
|
304
|
+
source_lines; line_begins; source_range # build cache
|
305
|
+
super
|
306
|
+
end
|
307
|
+
|
308
|
+
# :nodoc:
|
309
|
+
def inspect
|
310
|
+
"#<#{self.class} #{name}>"
|
305
311
|
end
|
306
312
|
|
307
313
|
private
|
308
314
|
|
315
|
+
# @returns [0, line_begin_of_line_1, ..., source.size + 1]
|
309
316
|
def line_begins
|
310
|
-
|
311
|
-
|
312
|
-
|
317
|
+
@line_begins ||= begin
|
318
|
+
begins = [0]
|
319
|
+
index = 0
|
313
320
|
while index = @source.index("\n".freeze, index)
|
314
321
|
index += 1
|
315
|
-
|
322
|
+
begins << index
|
316
323
|
end
|
324
|
+
begins << @source.size + 1
|
325
|
+
begins
|
317
326
|
end
|
327
|
+
end
|
318
328
|
|
319
|
-
|
329
|
+
# @returns 0-based line index of position
|
330
|
+
def line_index_for_position(position)
|
331
|
+
@line_index_for_position[position] || begin
|
332
|
+
index = bsearch(line_begins, position) - 1
|
333
|
+
@line_index_for_position[position] = index unless @line_index_for_position.frozen?
|
334
|
+
index
|
335
|
+
end
|
320
336
|
end
|
321
337
|
|
322
|
-
|
323
|
-
line_begins
|
324
|
-
|
338
|
+
if Array.method_defined?(:bsearch_index) # RUBY_VERSION >= 2.3
|
339
|
+
def bsearch(line_begins, position)
|
340
|
+
line_begins.bsearch_index do |line_begin|
|
341
|
+
position < line_begin
|
342
|
+
end || line_begins.size - 1 # || only for out of bound values
|
343
|
+
end
|
344
|
+
else
|
345
|
+
def bsearch(line_begins, position)
|
346
|
+
@line_range ||= 0...line_begins.size
|
347
|
+
@line_range.bsearch do |i|
|
348
|
+
position < line_begins[i]
|
349
|
+
end || line_begins.size - 1 # || only for out of bound values
|
325
350
|
end
|
326
351
|
end
|
327
352
|
end
|
@@ -10,7 +10,7 @@ module Parser
|
|
10
10
|
# @return [String]
|
11
11
|
#
|
12
12
|
# @!attribute [r] location
|
13
|
-
# @return [Parser::Source::
|
13
|
+
# @return [Parser::Source::Range]
|
14
14
|
#
|
15
15
|
# @api public
|
16
16
|
#
|
@@ -24,8 +24,8 @@ module Parser
|
|
24
24
|
# Associate `comments` with `ast` nodes by their corresponding node.
|
25
25
|
#
|
26
26
|
# @param [Parser::AST::Node] ast
|
27
|
-
# @param [Array
|
28
|
-
# @return [Hash
|
27
|
+
# @param [Array<Comment>] comments
|
28
|
+
# @return [Hash<Parser::AST::Node, Array<Comment>>]
|
29
29
|
# @see Parser::Source::Comment::Associator#associate
|
30
30
|
# @deprecated Use {associate_locations}.
|
31
31
|
#
|
@@ -39,8 +39,8 @@ module Parser
|
|
39
39
|
# source.
|
40
40
|
#
|
41
41
|
# @param [Parser::AST::Node] ast
|
42
|
-
# @param [Array
|
43
|
-
# @return [Hash
|
42
|
+
# @param [Array<Comment>] comments
|
43
|
+
# @return [Hash<Parser::Source::Map, Array<Comment>>]
|
44
44
|
# @see Parser::Source::Comment::Associator#associate_locations
|
45
45
|
#
|
46
46
|
def self.associate_locations(ast, comments)
|
@@ -48,6 +48,19 @@ module Parser
|
|
48
48
|
associator.associate_locations
|
49
49
|
end
|
50
50
|
|
51
|
+
##
|
52
|
+
# Associate `comments` with `ast` nodes using identity.
|
53
|
+
#
|
54
|
+
# @param [Parser::AST::Node] ast
|
55
|
+
# @param [Array<Comment>] comments
|
56
|
+
# @return [Hash<Parser::Source::Node, Array<Comment>>]
|
57
|
+
# @see Parser::Source::Comment::Associator#associate_by_identity
|
58
|
+
#
|
59
|
+
def self.associate_by_identity(ast, comments)
|
60
|
+
associator = Associator.new(ast, comments)
|
61
|
+
associator.associate_by_identity
|
62
|
+
end
|
63
|
+
|
51
64
|
##
|
52
65
|
# @param [Parser::Source::Range] range
|
53
66
|
#
|
@@ -47,7 +47,7 @@ module Parser
|
|
47
47
|
|
48
48
|
##
|
49
49
|
# @param [Parser::AST::Node] ast
|
50
|
-
# @param [Array
|
50
|
+
# @param [Array<Parser::Source::Comment>] comments
|
51
51
|
def initialize(ast, comments)
|
52
52
|
@ast = ast
|
53
53
|
@comments = comments
|
@@ -84,12 +84,24 @@ module Parser
|
|
84
84
|
#
|
85
85
|
# Note that {associate} produces unexpected result for nodes which are
|
86
86
|
# equal but have distinct locations; comments for these nodes are merged.
|
87
|
+
# You may prefer using {associate_by_identity} or {associate_locations}.
|
87
88
|
#
|
88
|
-
# @return [Hash
|
89
|
+
# @return [Hash<Parser::AST::Node, Array<Parser::Source::Comment>>]
|
89
90
|
# @deprecated Use {associate_locations}.
|
90
91
|
#
|
91
92
|
def associate
|
92
|
-
@
|
93
|
+
@map_using = :eql
|
94
|
+
do_associate
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Same as {associate}, but compares by identity, thus producing an unambiguous
|
99
|
+
# result even in presence of equal nodes.
|
100
|
+
#
|
101
|
+
# @return [Hash<Parser::Source::Node, Array<Parser::Source::Comment>>]
|
102
|
+
#
|
103
|
+
def associate_locations
|
104
|
+
@map_using = :location
|
93
105
|
do_associate
|
94
106
|
end
|
95
107
|
|
@@ -98,17 +110,31 @@ module Parser
|
|
98
110
|
# the hash key, thus producing an unambiguous result even in presence
|
99
111
|
# of equal nodes.
|
100
112
|
#
|
101
|
-
# @return [Hash
|
113
|
+
# @return [Hash<Parser::Source::Map, Array<Parser::Source::Comment>>]
|
102
114
|
#
|
103
|
-
def
|
104
|
-
@
|
115
|
+
def associate_by_identity
|
116
|
+
@map_using = :identity
|
105
117
|
do_associate
|
106
118
|
end
|
107
119
|
|
108
120
|
private
|
109
121
|
|
122
|
+
POSTFIX_TYPES = Set[:if, :while, :while_post, :until, :until_post, :masgn].freeze
|
123
|
+
def children_in_source_order(node)
|
124
|
+
if POSTFIX_TYPES.include?(node.type)
|
125
|
+
# All these types have either nodes with expressions, or `nil`
|
126
|
+
# so a compact will do, but they need to be sorted.
|
127
|
+
node.children.compact.sort_by { |child| child.loc.expression.begin_pos }
|
128
|
+
else
|
129
|
+
node.children.select do |child|
|
130
|
+
child.is_a?(AST::Node) && child.loc && child.loc.expression
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
110
135
|
def do_associate
|
111
136
|
@mapping = Hash.new { |h, k| h[k] = [] }
|
137
|
+
@mapping.compare_by_identity if @map_using == :identity
|
112
138
|
@comment_num = -1
|
113
139
|
advance_comment
|
114
140
|
|
@@ -131,10 +157,7 @@ module Parser
|
|
131
157
|
node_loc = node.location
|
132
158
|
if @current_comment.location.line <= node_loc.last_line ||
|
133
159
|
node_loc.is_a?(Map::Heredoc)
|
134
|
-
node.
|
135
|
-
next unless child.is_a?(AST::Node) && child.loc && child.loc.expression
|
136
|
-
visit(child)
|
137
|
-
end
|
160
|
+
children_in_source_order(node).each { |child| visit(child) }
|
138
161
|
|
139
162
|
process_trailing_comments(node)
|
140
163
|
end
|
@@ -181,7 +204,7 @@ module Parser
|
|
181
204
|
end
|
182
205
|
|
183
206
|
def associate_and_advance_comment(node)
|
184
|
-
key = @
|
207
|
+
key = @map_using == :location ? node.location : node
|
185
208
|
@mapping[key] << @current_comment
|
186
209
|
advance_comment
|
187
210
|
end
|
data/lib/parser/source/map.rb
CHANGED
@@ -161,7 +161,7 @@ module Parser
|
|
161
161
|
# # :expression => #<Source::Range (string) 0...6>
|
162
162
|
# # }
|
163
163
|
#
|
164
|
-
# @return [Hash
|
164
|
+
# @return [Hash<Symbol, Parser::Source::Range>]
|
165
165
|
#
|
166
166
|
def to_hash
|
167
167
|
instance_variables.inject({}) do |hash, ivar|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Parser
|
4
|
+
module Source
|
5
|
+
|
6
|
+
class Map::MethodDefinition < Map
|
7
|
+
attr_reader :keyword
|
8
|
+
attr_reader :operator
|
9
|
+
attr_reader :name
|
10
|
+
attr_reader :end
|
11
|
+
attr_reader :assignment
|
12
|
+
|
13
|
+
def initialize(keyword_l, operator_l, name_l, end_l, assignment_l, body_l)
|
14
|
+
@keyword = keyword_l
|
15
|
+
@operator = operator_l
|
16
|
+
@name = name_l
|
17
|
+
@end = end_l
|
18
|
+
@assignment = assignment_l
|
19
|
+
|
20
|
+
super(@keyword.join(end_l || body_l))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/parser/source/range.rb
CHANGED
@@ -13,7 +13,7 @@ module Parser
|
|
13
13
|
# ^^
|
14
14
|
#
|
15
15
|
# @!attribute [r] source_buffer
|
16
|
-
# @return [Parser::
|
16
|
+
# @return [Parser::Source::Buffer]
|
17
17
|
#
|
18
18
|
# @!attribute [r] begin_pos
|
19
19
|
# @return [Integer] index of the first character in the range
|
@@ -112,11 +112,11 @@ module Parser
|
|
112
112
|
# @raise RangeError
|
113
113
|
#
|
114
114
|
def column_range
|
115
|
-
if
|
115
|
+
if line != last_line
|
116
116
|
raise RangeError, "#{self.inspect} spans more than one line"
|
117
117
|
end
|
118
118
|
|
119
|
-
|
119
|
+
column...last_column
|
120
120
|
end
|
121
121
|
|
122
122
|
##
|
@@ -143,12 +143,19 @@ module Parser
|
|
143
143
|
end
|
144
144
|
|
145
145
|
##
|
146
|
-
# @return [Array
|
146
|
+
# @return [Array<Integer>] a set of character indexes contained in this range.
|
147
147
|
#
|
148
148
|
def to_a
|
149
149
|
(@begin_pos...@end_pos).to_a
|
150
150
|
end
|
151
151
|
|
152
|
+
##
|
153
|
+
# @return [Range] a Ruby range with the same `begin_pos` and `end_pos`
|
154
|
+
#
|
155
|
+
def to_range
|
156
|
+
self.begin_pos...self.end_pos
|
157
|
+
end
|
158
|
+
|
152
159
|
##
|
153
160
|
# Composes a GNU/Clang-style string representation of the beginning of this
|
154
161
|
# range.
|
@@ -298,6 +305,15 @@ module Parser
|
|
298
305
|
(@end_pos <=> other.end_pos)
|
299
306
|
end
|
300
307
|
|
308
|
+
alias_method :eql?, :==
|
309
|
+
|
310
|
+
##
|
311
|
+
# Support for Ranges be used in as Hash indices and in Sets.
|
312
|
+
#
|
313
|
+
def hash
|
314
|
+
[@source_buffer, @begin_pos, @end_pos].hash
|
315
|
+
end
|
316
|
+
|
301
317
|
##
|
302
318
|
# @return [String] a human-readable representation of this range.
|
303
319
|
#
|