diff options
author | yui-knk <spiketeika@gmail.com> | 2024-01-12 10:46:17 +0900 |
---|---|---|
committer | Yuichiro Kaneko <spiketeika@gmail.com> | 2024-02-20 17:33:58 +0900 |
commit | 89cfc1520717257073012ec07105c551e4b8af7c (patch) | |
tree | 5029b849fffb66c561144615965523cf81278568 /ext/ripper/tools | |
parent | f75b9dbf7dd86f8fa6777a9c9c960c310c940261 (diff) |
[Feature #20257] Rearchitect Ripper
Introduce another semantic value stack for Ripper so that
Ripper can manage both Node and Ruby Object separately.
This rearchitectutre of Ripper solves these issues.
Therefore adding test cases for them.
* [Bug 10436] https://bugs.ruby-lang.org/issues/10436
* [Bug 18988] https://bugs.ruby-lang.org/issues/18988
* [Bug 20055] https://bugs.ruby-lang.org/issues/20055
Checked the differences of `Ripper.sexp` for files under `/test/ruby`
are only on test_pattern_matching.rb.
The differences comes from the differences between
`new_hash_pattern_tail` functions between parser and Ripper.
Ripper `new_hash_pattern_tail` didn’t call `assignable` then
`kw_rest_arg` wasn’t marked as local variable.
This is also fixed by this commit.
```
--- a/./tmp/before/test_pattern_matching.rb
+++ b/./tmp/after/test_pattern_matching.rb
@@ -3607,7 +3607,7 @@
[:in,
[:hshptn, nil, [], [:var_field, [:@ident, “a”, [984, 13]]]],
[[:binary,
- [:vcall, [:@ident, “a”, [985, 10]]],
+ [:var_ref, [:@ident, “a”, [985, 10]]],
:==,
[:hash, nil]]],
nil]]],
@@ -3662,7 +3662,7 @@
[:in,
[:hshptn, nil, [], [:var_field, [:@ident, “a”, [993, 13]]]],
[[:binary,
- [:vcall, [:@ident, “a”, [994, 10]]],
+ [:var_ref, [:@ident, “a”, [994, 10]]],
:==,
[:hash,
[:assoclist_from_args,
@@ -3813,7 +3813,7 @@
[:command,
[:@ident, “raise”, [1022, 10]],
[:args_add_block,
- [[:vcall, [:@ident, “b”, [1022, 16]]]],
+ [[:var_ref, [:@ident, “b”, [1022, 16]]]],
false]]],
[:else, [[:var_ref, [:@kw, “true”, [1024, 10]]]]]]]],
nil,
@@ -3876,7 +3876,7 @@
[:@int, “0”, [1033, 15]]],
:“&&“,
[:binary,
- [:vcall, [:@ident, “b”, [1033, 20]]],
+ [:var_ref, [:@ident, “b”, [1033, 20]]],
:==,
[:hash, nil]]]],
nil]]],
@@ -3946,7 +3946,7 @@
[:@int, “0”, [1042, 15]]],
:“&&“,
[:binary,
- [:vcall, [:@ident, “b”, [1042, 20]]],
+ [:var_ref, [:@ident, “b”, [1042, 20]]],
:==,
[:hash,
[:assoclist_from_args,
@@ -5206,7 +5206,7 @@
[[:assoc_new,
[:@label, “c:“, [1352, 22]],
[:@int, “0”, [1352, 25]]]]]],
- [:vcall, [:@ident, “r”, [1352, 29]]]],
+ [:var_ref, [:@ident, “r”, [1352, 29]]]],
false]]],
[:binary,
[:call,
@@ -5299,7 +5299,7 @@
[:assoc_new,
[:@label, “c:“, [1367, 34]],
[:@int, “0”, [1367, 37]]]]]],
- [:vcall, [:@ident, “r”, [1367, 41]]]],
+ [:var_ref, [:@ident, “r”, [1367, 41]]]],
false]]],
[:binary,
[:call,
@@ -5931,7 +5931,7 @@
[:in,
[:hshptn, nil, [], [:var_field, [:@ident, “r”, [1533, 11]]]],
[[:binary,
- [:vcall, [:@ident, “r”, [1534, 8]]],
+ [:var_ref, [:@ident, “r”, [1534, 8]]],
:==,
[:hash,
[:assoclist_from_args,
```
Diffstat (limited to 'ext/ripper/tools')
-rw-r--r-- | ext/ripper/tools/dsl.rb | 19 | ||||
-rw-r--r-- | ext/ripper/tools/generate.rb | 4 | ||||
-rw-r--r-- | ext/ripper/tools/preproc.rb | 2 |
3 files changed, 16 insertions, 9 deletions
diff --git a/ext/ripper/tools/dsl.rb b/ext/ripper/tools/dsl.rb index f89e07d65e..8f03233574 100644 --- a/ext/ripper/tools/dsl.rb +++ b/ext/ripper/tools/dsl.rb @@ -18,14 +18,15 @@ class DSL NAME_PATTERN = /(?>\$|\d+|[a-zA-Z_][a-zA-Z0-9_]*|\[[a-zA-Z_.][-a-zA-Z0-9_.]*\])(?>(?:\.|->)[a-zA-Z_][a-zA-Z0-9_]*)*/.source NOT_REF_PATTERN = /(?>\#.*|[^\"$@]*|"(?>\\.|[^\"])*")/.source - def initialize(code, options) + def initialize(code, options, lineno = nil) + @lineno = lineno @events = {} @error = options.include?("error") @brace = options.include?("brace") if options.include?("final") @final = "p->result" else - @final = (options.grep(/\A\$#{NAME_PATTERN}\z/o)[0] || "$$") + @final = (options.grep(/\A\$#{NAME_PATTERN}\z/o)[0] || "p->s_lvalue") end @vars = 0 @@ -33,8 +34,11 @@ class DSL p = p = "p" @code = "" - code = code.gsub(%r[\G#{NOT_REF_PATTERN}\K[$@]#{TAG_PATTERN}?#{NAME_PATTERN}]o, '"\&"') + code = code.gsub(%r[\G#{NOT_REF_PATTERN}\K(\$|\$:|@)#{TAG_PATTERN}?#{NAME_PATTERN}]o, '"\&"') @last_value = eval(code) + rescue SyntaxError + $stderr.puts "error on line #{@lineno}" if @lineno + raise end attr_reader :events @@ -65,11 +69,15 @@ class DSL vars = [] args.each do |arg| vars << v = new_var - @code << "#{ v }=#{ arg };" + if arg =~ /\A\$:#{NAME_PATTERN}\z/ + @code << "#{ v }=get_value(#{arg});" + else + @code << "#{ v }=#{ arg };" + end end v = new_var d = "dispatch#{ args.size }(#{ [event, *vars].join(",") })" - d = "#{ vars.last }==Qundef ? #{ vars.first } : #{ d }" if qundef_check + d = "#{ vars.last }==rb_ripper_none ? #{ vars.first } : #{ d }" if qundef_check @code << "#{ v }=#{ d };" v end @@ -88,4 +96,3 @@ class DSL name end end - diff --git a/ext/ripper/tools/generate.rb b/ext/ripper/tools/generate.rb index c44b4ba325..27aa53bce0 100644 --- a/ext/ripper/tools/generate.rb +++ b/ext/ripper/tools/generate.rb @@ -167,14 +167,14 @@ require_relative "dsl" def read_ids1_with_locations(path) h = {} File.open(path) {|f| - f.each do |line| + f.each.with_index(1) do |line, i| next if /\A\#\s*define\s+dispatch/ =~ line next if /ripper_dispatch/ =~ line line.scan(/\bdispatch(\d)\((\w+)/) do |arity, event| (h[event] ||= []).push [f.lineno, arity.to_i] end if line =~ %r</\*% *ripper(?:\[(.*?)\])?: *(.*?) *%\*/> - gen = DSL.new($2, ($1 || "").split(",")) + gen = DSL.new($2, ($1 || "").split(","), i) gen.generate gen.events.each do |event, arity| (h[event] ||= []).push [f.lineno, arity.to_i] diff --git a/ext/ripper/tools/preproc.rb b/ext/ripper/tools/preproc.rb index a0d5e79d7d..981237a585 100644 --- a/ext/ripper/tools/preproc.rb +++ b/ext/ripper/tools/preproc.rb @@ -61,7 +61,7 @@ def prelude(f, out) return when /\A%token/, /\A%type/, /\A} <node(?>_\w+)?>/ # types in %union which have corresponding set_yylval_* macro. - out << line.sub(/<(?:node(?>_\w+)?|num|id)>/, '<val>') + out << line when /^enum lex_state_(?:bits|e) \{/ lex_state_def = true out << line |