parser 2.6.0.0 → 3.1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/parser/all.rb +3 -0
- data/lib/parser/ast/processor.rb +48 -1
- data/lib/parser/base.rb +30 -6
- data/lib/parser/builders/default.rb +670 -38
- data/lib/parser/context.rb +24 -26
- data/lib/parser/current.rb +36 -9
- data/lib/parser/current_arg_stack.rb +46 -0
- data/lib/parser/diagnostic/engine.rb +1 -2
- data/lib/parser/diagnostic.rb +1 -1
- data/lib/parser/lexer/dedenter.rb +58 -49
- data/lib/parser/lexer/explanation.rb +1 -1
- data/lib/parser/lexer.rb +13837 -11893
- data/lib/parser/macruby.rb +2544 -2489
- data/lib/parser/max_numparam_stack.rb +56 -0
- data/lib/parser/messages.rb +78 -44
- data/lib/parser/meta.rb +13 -3
- data/lib/parser/ruby18.rb +2313 -2259
- data/lib/parser/ruby19.rb +2537 -2488
- data/lib/parser/ruby20.rb +2724 -2673
- data/lib/parser/ruby21.rb +2766 -2727
- data/lib/parser/ruby22.rb +2683 -2628
- data/lib/parser/ruby23.rb +2796 -2755
- data/lib/parser/ruby24.rb +2812 -2771
- data/lib/parser/ruby25.rb +2703 -2670
- data/lib/parser/ruby26.rb +2794 -2747
- data/lib/parser/ruby27.rb +7914 -0
- data/lib/parser/ruby28.rb +8047 -0
- data/lib/parser/ruby30.rb +8096 -0
- data/lib/parser/ruby31.rb +8354 -0
- data/lib/parser/rubymotion.rb +2527 -2485
- data/lib/parser/runner/ruby_parse.rb +2 -2
- data/lib/parser/runner/ruby_rewrite.rb +2 -2
- data/lib/parser/runner.rb +36 -2
- data/lib/parser/source/buffer.rb +53 -28
- data/lib/parser/source/comment/associator.rb +31 -8
- data/lib/parser/source/comment.rb +14 -1
- data/lib/parser/source/map/method_definition.rb +25 -0
- data/lib/parser/source/range.rb +19 -3
- data/lib/parser/source/tree_rewriter/action.rb +137 -28
- data/lib/parser/source/tree_rewriter.rb +144 -14
- data/lib/parser/static_environment.rb +23 -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/lib/parser.rb +4 -0
- data/parser.gemspec +12 -19
- metadata +34 -99
- data/.gitignore +0 -32
- data/.travis.yml +0 -45
- data/.yardopts +0 -21
- data/CHANGELOG.md +0 -943
- data/CONTRIBUTING.md +0 -17
- data/Gemfile +0 -10
- data/README.md +0 -301
- data/Rakefile +0 -165
- data/ci/run_rubocop_specs +0 -14
- data/doc/AST_FORMAT.md +0 -1735
- 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 -2383
- 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 -2408
- data/lib/parser/ruby25.y +0 -2405
- data/lib/parser/ruby26.y +0 -2413
- 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 -3543
- data/test/test_lexer_stack_state.rb +0 -78
- data/test/test_parse_helper.rb +0 -80
- data/test/test_parser.rb +0 -7087
- 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/context.rb
CHANGED
@@ -5,47 +5,45 @@ module Parser
|
|
5
5
|
#
|
6
6
|
# Supported states:
|
7
7
|
# + :class - in the class body (class A; end)
|
8
|
+
# + :module - in the module body (module M; end)
|
8
9
|
# + :sclass - in the singleton class body (class << obj; end)
|
9
10
|
# + :def - in the method body (def m; end)
|
10
11
|
# + :defs - in the singleton method body (def self.m; end)
|
12
|
+
# + :def_open_args - in the arglist of the method definition
|
13
|
+
# keep in mind that it's set **only** after reducing the first argument,
|
14
|
+
# if you need to handle the first argument check `lex_state == expr_fname`
|
11
15
|
# + :block - in the block body (tap {})
|
12
16
|
# + :lambda - in the lambda body (-> {})
|
13
17
|
#
|
14
18
|
class Context
|
15
|
-
|
19
|
+
FLAGS = %i[
|
20
|
+
in_defined
|
21
|
+
in_kwarg
|
22
|
+
in_argdef
|
23
|
+
in_def
|
24
|
+
in_class
|
25
|
+
in_block
|
26
|
+
in_lambda
|
27
|
+
]
|
16
28
|
|
17
29
|
def initialize
|
18
|
-
|
19
|
-
freeze
|
20
|
-
end
|
21
|
-
|
22
|
-
def push(state)
|
23
|
-
@stack << state
|
24
|
-
end
|
25
|
-
|
26
|
-
def pop
|
27
|
-
@stack.pop
|
30
|
+
reset
|
28
31
|
end
|
29
32
|
|
30
33
|
def reset
|
31
|
-
@
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
@
|
36
|
-
|
37
|
-
|
38
|
-
def indirectly_in_def?
|
39
|
-
@stack.include?(:def) || @stack.include?(:defs)
|
34
|
+
@in_defined = false
|
35
|
+
@in_kwarg = false
|
36
|
+
@in_argdef = false
|
37
|
+
@in_def = false
|
38
|
+
@in_class = false
|
39
|
+
@in_block = false
|
40
|
+
@in_lambda = false
|
40
41
|
end
|
41
42
|
|
42
|
-
|
43
|
-
def_index = stack.rindex { |item| [:def, :defs].include?(item) }
|
44
|
-
sclass_index = stack.rindex(:sclass)
|
43
|
+
attr_accessor(*FLAGS)
|
45
44
|
|
46
|
-
|
45
|
+
def in_dynamic_block?
|
46
|
+
in_block || in_lambda
|
47
47
|
end
|
48
|
-
alias module_definition_allowed? class_definition_allowed?
|
49
|
-
alias dynamic_const_definition_allowed? class_definition_allowed?
|
50
48
|
end
|
51
49
|
end
|
data/lib/parser/current.rb
CHANGED
@@ -3,9 +3,9 @@
|
|
3
3
|
module Parser
|
4
4
|
class << self
|
5
5
|
def warn_syntax_deviation(feature, version)
|
6
|
-
warn "warning: parser/current is loading #{feature}, which recognizes"
|
7
|
-
|
8
|
-
|
6
|
+
warn "warning: parser/current is loading #{feature}, which recognizes" \
|
7
|
+
"#{version}-compliant syntax, but you are running #{RUBY_VERSION}.\n" \
|
8
|
+
"Please see https://github.com/whitequark/parser#compatibility-with-ruby-mri."
|
9
9
|
end
|
10
10
|
private :warn_syntax_deviation
|
11
11
|
end
|
@@ -48,7 +48,7 @@ module Parser
|
|
48
48
|
CurrentRuby = Ruby23
|
49
49
|
|
50
50
|
when /^2\.4\./
|
51
|
-
current_version = '2.4.
|
51
|
+
current_version = '2.4.10'
|
52
52
|
if RUBY_VERSION != current_version
|
53
53
|
warn_syntax_deviation 'parser/ruby24', current_version
|
54
54
|
end
|
@@ -57,7 +57,7 @@ module Parser
|
|
57
57
|
CurrentRuby = Ruby24
|
58
58
|
|
59
59
|
when /^2\.5\./
|
60
|
-
current_version = '2.5.
|
60
|
+
current_version = '2.5.9'
|
61
61
|
if RUBY_VERSION != current_version
|
62
62
|
warn_syntax_deviation 'parser/ruby25', current_version
|
63
63
|
end
|
@@ -66,7 +66,7 @@ module Parser
|
|
66
66
|
CurrentRuby = Ruby25
|
67
67
|
|
68
68
|
when /^2\.6\./
|
69
|
-
current_version = '2.6.
|
69
|
+
current_version = '2.6.9'
|
70
70
|
if RUBY_VERSION != current_version
|
71
71
|
warn_syntax_deviation 'parser/ruby26', current_version
|
72
72
|
end
|
@@ -74,10 +74,37 @@ module Parser
|
|
74
74
|
require 'parser/ruby26'
|
75
75
|
CurrentRuby = Ruby26
|
76
76
|
|
77
|
+
when /^2\.7\./
|
78
|
+
current_version = '2.7.5'
|
79
|
+
if RUBY_VERSION != current_version
|
80
|
+
warn_syntax_deviation 'parser/ruby27', current_version
|
81
|
+
end
|
82
|
+
|
83
|
+
require 'parser/ruby27'
|
84
|
+
CurrentRuby = Ruby27
|
85
|
+
|
86
|
+
when /^3\.0\./
|
87
|
+
current_version = '3.0.3'
|
88
|
+
if RUBY_VERSION != current_version
|
89
|
+
warn_syntax_deviation 'parser/ruby30', current_version
|
90
|
+
end
|
91
|
+
|
92
|
+
require 'parser/ruby30'
|
93
|
+
CurrentRuby = Ruby30
|
94
|
+
|
95
|
+
when /^3\.1\./
|
96
|
+
current_version = '3.1.0'
|
97
|
+
if RUBY_VERSION != current_version
|
98
|
+
warn_syntax_deviation 'parser/ruby31', current_version
|
99
|
+
end
|
100
|
+
|
101
|
+
require 'parser/ruby31'
|
102
|
+
CurrentRuby = Ruby31
|
103
|
+
|
77
104
|
else # :nocov:
|
78
105
|
# Keep this in sync with released Ruby.
|
79
|
-
warn_syntax_deviation 'parser/
|
80
|
-
require 'parser/
|
81
|
-
CurrentRuby =
|
106
|
+
warn_syntax_deviation 'parser/ruby31', '3.1.x'
|
107
|
+
require 'parser/ruby31'
|
108
|
+
CurrentRuby = Ruby31
|
82
109
|
end
|
83
110
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Parser
|
4
|
+
# Stack that holds names of current arguments,
|
5
|
+
# i.e. while parsing
|
6
|
+
# def m1(a = (def m2(b = def m3(c = 1); end); end)); end
|
7
|
+
# ^
|
8
|
+
# stack is [:a, :b, :c]
|
9
|
+
#
|
10
|
+
# Emulates `p->cur_arg` in MRI's parse.y
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
#
|
14
|
+
class CurrentArgStack
|
15
|
+
attr_reader :stack
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@stack = []
|
19
|
+
freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
def empty?
|
23
|
+
@stack.size == 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def push(value)
|
27
|
+
@stack << value
|
28
|
+
end
|
29
|
+
|
30
|
+
def set(value)
|
31
|
+
@stack[@stack.length - 1] = value
|
32
|
+
end
|
33
|
+
|
34
|
+
def pop
|
35
|
+
@stack.pop
|
36
|
+
end
|
37
|
+
|
38
|
+
def reset
|
39
|
+
@stack.clear
|
40
|
+
end
|
41
|
+
|
42
|
+
def top
|
43
|
+
@stack.last
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -7,8 +7,7 @@ module Parser
|
|
7
7
|
# diagnostics by delegating them to registered consumers.
|
8
8
|
#
|
9
9
|
# @example
|
10
|
-
# buffer = Parser::Source::Buffer.new(__FILE__)
|
11
|
-
# buffer.code = 'foobar'
|
10
|
+
# buffer = Parser::Source::Buffer.new(__FILE__, source: 'foobar')
|
12
11
|
#
|
13
12
|
# consumer = lambda do |diagnostic|
|
14
13
|
# puts diagnostic.message
|
data/lib/parser/diagnostic.rb
CHANGED
@@ -3,72 +3,81 @@
|
|
3
3
|
module Parser
|
4
4
|
|
5
5
|
class Lexer::Dedenter
|
6
|
+
# Tab (\t) counts as 8 spaces
|
7
|
+
TAB_WIDTH = 8
|
8
|
+
|
6
9
|
def initialize(dedent_level)
|
7
10
|
@dedent_level = dedent_level
|
8
11
|
@at_line_begin = true
|
9
12
|
@indent_level = 0
|
10
13
|
end
|
11
14
|
|
15
|
+
# For a heredoc like
|
16
|
+
# <<-HERE
|
17
|
+
# a
|
18
|
+
# b
|
19
|
+
# HERE
|
20
|
+
# this method gets called with " a\n" and " b\n"
|
21
|
+
#
|
22
|
+
# However, the following heredoc:
|
23
|
+
#
|
24
|
+
# <<-HERE
|
25
|
+
# a\
|
26
|
+
# b
|
27
|
+
# HERE
|
28
|
+
# calls this method only once with a string " a\\\n b\n"
|
29
|
+
#
|
30
|
+
# This is important because technically it's a single line,
|
31
|
+
# but it has to be concatenated __after__ dedenting.
|
32
|
+
#
|
33
|
+
# It has no effect for non-squiggly heredocs, i.e. it simply removes "\\\n"
|
34
|
+
# Of course, lexer could do it but once again: it's all because of dedenting.
|
35
|
+
#
|
12
36
|
def dedent(string)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
37
|
+
original_encoding = string.encoding
|
38
|
+
# Prevent the following error when processing binary encoded source.
|
39
|
+
# "\xC0".split # => ArgumentError (invalid byte sequence in UTF-8)
|
40
|
+
lines = string.force_encoding(Encoding::BINARY).split("\\\n")
|
41
|
+
if lines.length == 1
|
42
|
+
# If the line continuation sequence was found but there is no second
|
43
|
+
# line, it was not really a line continuation and must be ignored.
|
44
|
+
lines = [string.force_encoding(original_encoding)]
|
45
|
+
else
|
46
|
+
lines.map! {|s| s.force_encoding(original_encoding) }
|
47
|
+
end
|
17
48
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
if char == ?\n
|
28
|
-
# trimming \n, starting a new line
|
29
|
-
string.slice!(index - offset)
|
30
|
-
offset += 1
|
31
|
-
@at_line_begin = true
|
32
|
-
space_begin = space_end = index - offset
|
33
|
-
@indent_level = 0
|
34
|
-
elsif char == ?n
|
35
|
-
# replacing \\n to \n
|
36
|
-
string.slice!(index - offset)
|
37
|
-
string.insert(index - offset, ?\n)
|
38
|
-
else
|
39
|
-
# exiting escape mode as it's not an escape sequence
|
40
|
-
@at_line_begin = _at_line_begin
|
41
|
-
escape = false
|
42
|
-
redo
|
43
|
-
end
|
44
|
-
escape = false
|
45
|
-
elsif @at_line_begin
|
46
|
-
if char == ?\n || @indent_level >= @dedent_level
|
47
|
-
string.slice!(space_begin...space_end)
|
48
|
-
offset += space_end - space_begin
|
49
|
-
@at_line_begin = false
|
50
|
-
end
|
49
|
+
if @at_line_begin
|
50
|
+
lines_to_dedent = lines
|
51
|
+
else
|
52
|
+
_first, *lines_to_dedent = lines
|
53
|
+
end
|
54
|
+
|
55
|
+
lines_to_dedent.each do |line|
|
56
|
+
left_to_remove = @dedent_level
|
57
|
+
remove = 0
|
51
58
|
|
59
|
+
line.each_char do |char|
|
60
|
+
break if left_to_remove <= 0
|
52
61
|
case char
|
53
62
|
when ?\s
|
54
|
-
|
55
|
-
|
63
|
+
remove += 1
|
64
|
+
left_to_remove -= 1
|
56
65
|
when ?\t
|
57
|
-
|
58
|
-
|
66
|
+
break if TAB_WIDTH * (remove / TAB_WIDTH + 1) > @dedent_level
|
67
|
+
remove += 1
|
68
|
+
left_to_remove -= TAB_WIDTH
|
69
|
+
else
|
70
|
+
# no more spaces or tabs
|
71
|
+
break
|
59
72
|
end
|
60
|
-
elsif char == ?\n && index == last_index
|
61
|
-
@at_line_begin = true
|
62
|
-
@indent_level = 0
|
63
|
-
space_begin = space_end = index - offset + 1
|
64
73
|
end
|
65
|
-
end
|
66
74
|
|
67
|
-
|
68
|
-
string.slice!(space_begin..space_end)
|
75
|
+
line.slice!(0, remove)
|
69
76
|
end
|
70
77
|
|
71
|
-
|
78
|
+
string.replace(lines.join)
|
79
|
+
|
80
|
+
@at_line_begin = string.end_with?("\n")
|
72
81
|
end
|
73
82
|
|
74
83
|
def interrupt
|