From 9be555fe652a63803455b32f6178f0d7f1594a8d Mon Sep 17 00:00:00 2001 From: Ilya Bylich Date: Wed, 8 Dec 2021 15:23:45 +0300 Subject: [PATCH 1/3] Update changelog. --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a477a233..cb52470e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ Changelog ========= -Not released (2021-12-08) -------------------------- +v3.0.3.2 (2021-12-08) +--------------------- Bugs fixed: * dedenter.rb: fix an encoding/squiggly heredoc regression (#836) (hmdne) From 09d681e534885f1aa22f0099089841ae9d86f847 Mon Sep 17 00:00:00 2001 From: Ilya Bylich Date: Mon, 3 Jan 2022 02:49:07 +0300 Subject: [PATCH 2/3] + ruby31.y: accept forward arg without parentheses. (#839) This commit tracks upstream commit ruby/ruby@aa7c4c3. Also there's a change to Context API that caused a massive rewrite in all grammars. However, it doesn't affect any logic before 3.1, it's mostly a refactoring. --- lib/parser/builders/default.rb | 2 +- lib/parser/context.rb | 64 ++---- lib/parser/lexer.rl | 21 +- lib/parser/lexer/explanation.rb | 2 +- lib/parser/macruby.y | 142 +++++++------ lib/parser/max_numparam_stack.rb | 10 +- lib/parser/ruby18.y | 111 ++++++---- lib/parser/ruby19.y | 142 +++++++------ lib/parser/ruby20.y | 144 +++++++------ lib/parser/ruby21.y | 141 ++++++++----- lib/parser/ruby22.y | 141 ++++++++----- lib/parser/ruby23.y | 141 ++++++++----- lib/parser/ruby24.y | 140 ++++++++----- lib/parser/ruby25.y | 151 ++++++++------ lib/parser/ruby26.y | 158 ++++++++------ lib/parser/ruby27.y | 207 ++++++++++-------- lib/parser/ruby30.y | 253 +++++++++++----------- lib/parser/ruby31.y | 348 +++++++++++++++++-------------- lib/parser/rubymotion.y | 144 +++++++------ test/helper.rb | 2 +- test/parse_helper.rb | 7 +- test/test_parser.rb | 238 ++++++++++----------- 22 files changed, 1507 insertions(+), 1202 deletions(-) diff --git a/lib/parser/builders/default.rb b/lib/parser/builders/default.rb index fe563e9eb..523b51b59 100644 --- a/lib/parser/builders/default.rb +++ b/lib/parser/builders/default.rb @@ -714,7 +714,7 @@ def assignable(node) node.updated(:gvasgn) when :const - unless @parser.context.dynamic_const_definition_allowed? + if @parser.context.in_def diagnostic :error, :dynamic_const, nil, node.loc.expression end diff --git a/lib/parser/context.rb b/lib/parser/context.rb index ef741135f..ff5f24dcf 100644 --- a/lib/parser/context.rb +++ b/lib/parser/context.rb @@ -16,60 +16,34 @@ module Parser # + :lambda - in the lambda body (-> {}) # class Context - attr_reader :stack + FLAGS = %i[ + in_defined + in_kwarg + in_argdef + in_def + in_class + in_block + in_lambda + ] def initialize - @stack = [] - freeze - end - - def push(state) - @stack << state - end - - def pop - @stack.pop + reset end def reset - @stack.clear - end - - def empty? - @stack.empty? - end - - def in_class? - @stack.last == :class - end - - def indirectly_in_def? - @stack.include?(:def) || @stack.include?(:defs) + @in_defined = false + @in_kwarg = false + @in_argdef = false + @in_def = false + @in_class = false + @in_block = false + @in_lambda = false end - def class_definition_allowed? - def_index = stack.rindex { |item| [:def, :defs].include?(item) } - sclass_index = stack.rindex(:sclass) - - def_index.nil? || (!sclass_index.nil? && sclass_index > def_index) - end - alias module_definition_allowed? class_definition_allowed? - alias dynamic_const_definition_allowed? class_definition_allowed? - - def in_block? - @stack.last == :block - end - - def in_lambda? - @stack.last == :lambda - end + attr_accessor(*FLAGS) def in_dynamic_block? - in_block? || in_lambda? - end - - def in_def_open_args? - @stack.last == :def_open_args + in_block || in_lambda end end end diff --git a/lib/parser/lexer.rl b/lib/parser/lexer.rl index 69c2403c7..56b2e5ab2 100644 --- a/lib/parser/lexer.rl +++ b/lib/parser/lexer.rl @@ -95,7 +95,7 @@ class Parser::Lexer attr_accessor :static_env attr_accessor :force_utf32 - attr_accessor :cond, :cmdarg, :in_kwarg, :context, :command_start + attr_accessor :cond, :cmdarg, :context, :command_start attr_accessor :tokens, :comments @@ -173,9 +173,6 @@ class Parser::Lexer # instead of expr_arg at certain points. @command_start = true - # True at the end of "def foo a:" - @in_kwarg = false - # State before =begin / =end block comment @cs_before_block_comment = self.class.lex_en_line_begin end @@ -1442,15 +1439,15 @@ class Parser::Lexer => { emit(:tLABEL, tok(@ts, @te - 2), @ts, @te - 1) fhold; fnext expr_labelarg; fbreak; }; - '...' c_nl + '...' => { - if @version >= 31 - emit(:tBDOT3, '...'.freeze, @ts, @te - 1) - emit(:tNL, "\n".freeze, @te - 1, @te) + if @version >= 31 && @context.in_argdef + emit(:tBDOT3, '...'.freeze) + # emit(:tNL, "\n".freeze, @te - 1, @te) fnext expr_end; fbreak; else - p -= 4; - fhold; fgoto expr_end; + p -= 3; + fgoto expr_end; end }; @@ -2076,7 +2073,7 @@ class Parser::Lexer else emit(:tBDOT3, '...'.freeze, @ts, dots_te) - if @version >= 31 && followed_by_nl && @context.in_def_open_args? + if @version >= 31 && followed_by_nl && @context.in_argdef emit(:tNL, @te - 1, @te) nl_emitted = true end @@ -2161,7 +2158,7 @@ class Parser::Lexer w_newline => { - if @in_kwarg + if @context.in_kwarg fhold; fgoto expr_end; else fgoto line_begin; diff --git a/lib/parser/lexer/explanation.rb b/lib/parser/lexer/explanation.rb index 5066ea46e..2ca384c57 100644 --- a/lib/parser/lexer/explanation.rb +++ b/lib/parser/lexer/explanation.rb @@ -18,7 +18,7 @@ def self.included(klass) def advance type, (val, range) = advance_before_explanation - more = "(in-kwarg)" if @in_kwarg + more = "(in-kwarg)" if @context.in_kwarg puts decorate(range, Color.green("#{type} #{val.inspect}"), diff --git a/lib/parser/macruby.y b/lib/parser/macruby.y index 8b912255d..0bfb42136 100644 --- a/lib/parser/macruby.y +++ b/lib/parser/macruby.y @@ -274,14 +274,15 @@ rule cmd_brace_block: tLBRACE_ARG { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } command: operation command_args =tLOWEST @@ -1044,7 +1045,8 @@ rule } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -1053,6 +1055,8 @@ rule args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } | kIF expr_value then compstmt if_tail kEND { @@ -1124,75 +1128,73 @@ rule val[2], val[4], val[5], val[7], val[8]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | kDEF fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:def) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def } | kDEF singleton dot_or_colon { @@ -1200,18 +1202,17 @@ rule } fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def } | kBREAK { @@ -1232,6 +1233,16 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + then: term | kTHEN | term kTHEN @@ -1459,13 +1470,9 @@ rule lambda: { @static_env.extend_dynamic } - f_larglist - { - @context.pop - } - lambda_body + f_larglist lambda_body { - result = [ val[1], val[3] ] + result = [ val[1], val[2] ] @static_env.unextend } @@ -1481,34 +1488,37 @@ rule lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1582,26 +1592,28 @@ rule brace_block: tLCURLY { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } | kDO { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } case_body: kWHEN args then compstmt cases @@ -2206,3 +2218,15 @@ require 'parser' def default_encoding Encoding::BINARY end + + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + end diff --git a/lib/parser/max_numparam_stack.rb b/lib/parser/max_numparam_stack.rb index 484ae65cf..9a741c72a 100644 --- a/lib/parser/max_numparam_stack.rb +++ b/lib/parser/max_numparam_stack.rb @@ -35,21 +35,21 @@ def register(numparam) end def top - @stack.last + @stack.last[:value] end - def push - @stack.push(0) + def push(static:) + @stack.push(value: 0, static: static) end def pop - @stack.pop + @stack.pop[:value] end private def set(value) - @stack[@stack.length - 1] = value + @stack.last[:value] = value end end diff --git a/lib/parser/ruby18.y b/lib/parser/ruby18.y index d02a9ade5..1e16ed8e1 100644 --- a/lib/parser/ruby18.y +++ b/lib/parser/ruby18.y @@ -142,7 +142,7 @@ rule } | klBEGIN tLCURLY compstmt tRCURLY { - if @context.indirectly_in_def? + if @context.in_def diagnostic :error, :begin_in_method, nil, val[0] end @@ -268,14 +268,15 @@ rule cmd_brace_block: tLBRACE_ARG { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_var compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } command: operation command_args =tLOWEST @@ -1124,67 +1125,73 @@ rule val[2], val[4], val[5], val[7], val[8]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | kDEF fname { - @static_env.extend_static - @context.push(:def) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def } | kDEF singleton dot_or_colon { @@ -1192,16 +1199,17 @@ rule } fname { - @static_env.extend_static - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def } | kBREAK { @@ -1222,6 +1230,16 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + then: term | tCOLON | kTHEN @@ -1336,14 +1354,15 @@ rule do_block: kDO_BLOCK { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_var compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1401,26 +1420,28 @@ rule brace_block: tLCURLY { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_var compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } | kDO { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_var compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } case_body: kWHEN when_args then compstmt cases @@ -1937,3 +1958,15 @@ require 'parser' def default_encoding Encoding::BINARY end + + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + end diff --git a/lib/parser/ruby19.y b/lib/parser/ruby19.y index 76a734dd2..954a4c12a 100644 --- a/lib/parser/ruby19.y +++ b/lib/parser/ruby19.y @@ -280,14 +280,15 @@ rule cmd_brace_block: tLBRACE_ARG { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } command: operation command_args =tLOWEST @@ -1011,7 +1012,8 @@ rule } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -1020,6 +1022,8 @@ rule args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } | kIF expr_value then compstmt if_tail kEND { @@ -1091,75 +1095,73 @@ rule val[2], val[4], val[5], val[7], val[8]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | kDEF fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:def) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def } | kDEF singleton dot_or_colon { @@ -1167,18 +1169,17 @@ rule } fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def } | kBREAK { @@ -1199,6 +1200,16 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + then: term | kTHEN | term kTHEN @@ -1439,13 +1450,9 @@ rule lambda: { @static_env.extend_dynamic } - f_larglist - { - @context.pop - } - lambda_body + f_larglist lambda_body { - result = [ val[1], val[3] ] + result = [ val[1], val[2] ] @static_env.unextend } @@ -1461,34 +1468,37 @@ rule lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1562,26 +1572,28 @@ rule brace_block: tLCURLY { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } | kDO { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } case_body: kWHEN args then compstmt cases @@ -2183,3 +2195,15 @@ require 'parser' def default_encoding Encoding::BINARY end + + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + end diff --git a/lib/parser/ruby20.y b/lib/parser/ruby20.y index 22deff1a5..4f07fa96f 100644 --- a/lib/parser/ruby20.y +++ b/lib/parser/ruby20.y @@ -116,7 +116,7 @@ rule stmt_or_begin: stmt | klBEGIN tLCURLY top_compstmt tRCURLY { - if @context.indirectly_in_def? + if @context.in_def diagnostic :error, :begin_in_method, nil, val[0] end @@ -287,14 +287,15 @@ rule cmd_brace_block: tLBRACE_ARG { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } fcall: operation @@ -1041,7 +1042,8 @@ rule } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -1050,6 +1052,8 @@ rule args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } | kIF expr_value then compstmt if_tail kEND { @@ -1121,75 +1125,73 @@ rule val[2], val[4], val[5], val[7], val[8]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | kDEF fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:def) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def } | kDEF singleton dot_or_colon { @@ -1197,18 +1199,17 @@ rule } fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def } | kBREAK { @@ -1229,6 +1230,16 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + then: term | kTHEN | term kTHEN @@ -1493,13 +1504,9 @@ opt_block_args_tail: lambda: { @static_env.extend_dynamic } - f_larglist - { - @context.pop - } - lambda_body + f_larglist lambda_body { - result = [ val[1], val[3] ] + result = [ val[1], val[2] ] @static_env.unextend } @@ -1515,34 +1522,37 @@ opt_block_args_tail: lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1629,26 +1639,28 @@ opt_block_args_tail: brace_block: tLCURLY { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } | kDO { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } case_body: kWHEN args then compstmt cases @@ -2361,3 +2373,15 @@ require 'parser' def default_encoding Encoding::UTF_8 end + + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + end diff --git a/lib/parser/ruby21.y b/lib/parser/ruby21.y index 05b2603c6..894ff7f5c 100644 --- a/lib/parser/ruby21.y +++ b/lib/parser/ruby21.y @@ -279,14 +279,15 @@ rule cmd_brace_block: tLBRACE_ARG { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } fcall: operation @@ -1031,7 +1032,8 @@ rule } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -1040,6 +1042,8 @@ rule args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } | kIF expr_value then compstmt if_tail kEND { @@ -1111,75 +1115,73 @@ rule val[2], val[4], val[5], val[7], val[8]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | kDEF fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:def) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def } | kDEF singleton dot_or_colon { @@ -1187,18 +1189,17 @@ rule } fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def } | kBREAK { @@ -1219,6 +1220,16 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + then: term | kTHEN | term kTHEN @@ -1477,7 +1488,6 @@ opt_block_args_tail: { result = @lexer.cmdarg.dup @lexer.cmdarg.clear - @context.pop } lambda_body { @@ -1500,34 +1510,37 @@ opt_block_args_tail: lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1614,26 +1627,28 @@ opt_block_args_tail: brace_block: tLCURLY { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } | kDO { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } case_body: kWHEN args then compstmt cases @@ -1998,12 +2013,12 @@ keyword_variable: kNIL @lexer.state = :expr_value } | { - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } f_args term { - @lexer.in_kwarg = val[0] + @context.in_kwarg = val[0] result = @builder.args(nil, val[1], nil) } @@ -2362,3 +2377,15 @@ require 'parser' def default_encoding Encoding::UTF_8 end + + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + end diff --git a/lib/parser/ruby22.y b/lib/parser/ruby22.y index eeb942b43..8a8e27c44 100644 --- a/lib/parser/ruby22.y +++ b/lib/parser/ruby22.y @@ -279,14 +279,15 @@ rule cmd_brace_block: tLBRACE_ARG { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } fcall: operation @@ -1030,7 +1031,8 @@ rule } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -1039,6 +1041,8 @@ rule args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } | kIF expr_value then compstmt if_tail kEND { @@ -1110,75 +1114,73 @@ rule val[2], val[4], val[5], val[7], val[8]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | kDEF fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:def) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def } | kDEF singleton dot_or_colon { @@ -1186,18 +1188,17 @@ rule } fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def } | kBREAK { @@ -1218,6 +1219,16 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + then: term | kTHEN | term kTHEN @@ -1476,7 +1487,6 @@ opt_block_args_tail: { result = @lexer.cmdarg.dup @lexer.cmdarg.clear - @context.pop } lambda_body { @@ -1499,34 +1509,37 @@ opt_block_args_tail: lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1613,26 +1626,28 @@ opt_block_args_tail: brace_block: tLCURLY { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } | kDO { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } case_body: kWHEN args then compstmt cases @@ -1997,12 +2012,12 @@ keyword_variable: kNIL @lexer.state = :expr_value } | { - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } f_args term { - @lexer.in_kwarg = val[0] + @context.in_kwarg = val[0] result = @builder.args(nil, val[1], nil) } @@ -2369,3 +2384,15 @@ require 'parser' def default_encoding Encoding::UTF_8 end + + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + end diff --git a/lib/parser/ruby23.y b/lib/parser/ruby23.y index 924b7d6a6..7b50781a8 100644 --- a/lib/parser/ruby23.y +++ b/lib/parser/ruby23.y @@ -279,14 +279,15 @@ rule cmd_brace_block: tLBRACE_ARG { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } fcall: operation @@ -1030,7 +1031,8 @@ rule } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -1039,6 +1041,8 @@ rule args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } | kIF expr_value then compstmt if_tail kEND { @@ -1110,75 +1114,73 @@ rule val[2], val[4], val[5], val[7], val[8]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | kDEF fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:def) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def } | kDEF singleton dot_or_colon { @@ -1186,18 +1188,17 @@ rule } fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def } | kBREAK { @@ -1218,6 +1219,16 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + then: term | kTHEN | term kTHEN @@ -1476,7 +1487,6 @@ opt_block_args_tail: { result = @lexer.cmdarg.dup @lexer.cmdarg.clear - @context.pop } lambda_body { @@ -1499,34 +1509,37 @@ opt_block_args_tail: lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1613,26 +1626,28 @@ opt_block_args_tail: brace_block: tLCURLY { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } | kDO { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } case_body: kWHEN args then compstmt cases @@ -1995,12 +2010,12 @@ keyword_variable: kNIL @lexer.state = :expr_value } | { - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } f_args term { - @lexer.in_kwarg = val[0] + @context.in_kwarg = val[0] result = @builder.args(nil, val[1], nil) } @@ -2375,3 +2390,15 @@ require 'parser' def default_encoding Encoding::UTF_8 end + + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + end diff --git a/lib/parser/ruby24.y b/lib/parser/ruby24.y index b3a78e38b..ddfb140c0 100644 --- a/lib/parser/ruby24.y +++ b/lib/parser/ruby24.y @@ -285,12 +285,13 @@ rule cmd_brace_block: tLBRACE_ARG { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } fcall: operation @@ -1049,7 +1050,8 @@ rule } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -1058,6 +1060,8 @@ rule args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } | kIF expr_value then compstmt if_tail kEND { @@ -1129,75 +1133,73 @@ rule val[2], val[4], val[5], val[7], val[8]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.cmdarg.push(false) - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.cmdarg.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.cmdarg.push(false) - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.cmdarg.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.cmdarg.push(false) - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.cmdarg.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | kDEF fname { - @static_env.extend_static - @lexer.cmdarg.push(false) - @context.push(:def) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @lexer.cmdarg.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def } | kDEF singleton dot_or_colon { @@ -1205,18 +1207,17 @@ rule } fname { - @static_env.extend_static - @lexer.cmdarg.push(false) - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @lexer.cmdarg.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def } | kBREAK { @@ -1237,6 +1238,15 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + then: term | kTHEN | term kTHEN @@ -1493,7 +1503,6 @@ opt_block_args_tail: } f_larglist { - @context.pop @lexer.cmdarg.push(false) } lambda_body @@ -1516,31 +1525,34 @@ opt_block_args_tail: lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1626,21 +1638,23 @@ opt_block_args_tail: brace_block: tLCURLY { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } | kDO { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } brace_body: { @@ -2033,12 +2047,12 @@ keyword_variable: kNIL @lexer.state = :expr_value } | { - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } f_args term { - @lexer.in_kwarg = val[0] + @context.in_kwarg = val[0] result = @builder.args(nil, val[1], nil) } @@ -2413,3 +2427,15 @@ require 'parser' def default_encoding Encoding::UTF_8 end + + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + end diff --git a/lib/parser/ruby25.y b/lib/parser/ruby25.y index 9229fe2d1..d56ea874a 100644 --- a/lib/parser/ruby25.y +++ b/lib/parser/ruby25.y @@ -299,12 +299,13 @@ rule cmd_brace_block: tLBRACE_ARG { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } fcall: operation @@ -1059,7 +1060,8 @@ rule } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -1068,6 +1070,8 @@ rule args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } | kIF expr_value then compstmt if_tail kEND { @@ -1111,81 +1115,73 @@ rule { result = @builder.for(val[0], val[1], val[2], *val[3], val[4], val[5]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.cmdarg.push(false) - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.cmdarg.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | kDEF fname { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:def) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def } | kDEF singleton dot_or_colon { @@ -1193,20 +1189,17 @@ rule } fname { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def } | kBREAK { @@ -1227,9 +1220,19 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + k_return: kRETURN { - if @context.in_class? + if @context.in_class && !@context.in_def && !(context.in_block || context.in_lambda) diagnostic :error, :invalid_return, nil, val[0] end } @@ -1490,7 +1493,6 @@ opt_block_args_tail: } f_larglist { - @context.pop @lexer.cmdarg.push(false) } lambda_body @@ -1513,31 +1515,34 @@ opt_block_args_tail: lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1623,21 +1628,23 @@ opt_block_args_tail: brace_block: tLCURLY { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } | kDO { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } brace_body: { @@ -2030,12 +2037,12 @@ keyword_variable: kNIL @lexer.state = :expr_value } | { - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } f_args term { - @lexer.in_kwarg = val[0] + @context.in_kwarg = val[0] result = @builder.args(nil, val[1], nil) } @@ -2410,3 +2417,15 @@ require 'parser' def default_encoding Encoding::UTF_8 end + + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + end diff --git a/lib/parser/ruby26.y b/lib/parser/ruby26.y index bbf0dd29c..cf061f1e7 100644 --- a/lib/parser/ruby26.y +++ b/lib/parser/ruby26.y @@ -299,12 +299,13 @@ rule cmd_brace_block: tLBRACE_ARG { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } fcall: operation @@ -1067,7 +1068,8 @@ rule } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -1076,6 +1078,8 @@ rule args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } | kIF expr_value then compstmt if_tail kEND { @@ -1119,102 +1123,91 @@ rule { result = @builder.for(val[0], val[1], val[2], *val[3], val[4], val[5]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.cmdarg.push(false) - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.cmdarg.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kDEF fname + | k_def fname { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:def) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def } - | kDEF singleton dot_or_colon + | k_def singleton dot_or_colon { @lexer.state = :expr_fname } fname { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def } | kBREAK { @@ -1235,9 +1228,22 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + k_def: kDEF + { + result = val[0] + } + k_return: kRETURN { - if @context.in_class? + if @context.in_class && !@context.in_def && !(context.in_block || context.in_lambda) diagnostic :error, :invalid_return, nil, val[0] end } @@ -1498,7 +1504,6 @@ opt_block_args_tail: } f_larglist { - @context.pop @lexer.cmdarg.push(false) } lambda_body @@ -1521,31 +1526,34 @@ opt_block_args_tail: lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } bodystmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1631,21 +1639,23 @@ opt_block_args_tail: brace_block: tLCURLY { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } | kDO { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } brace_body: { @@ -2038,12 +2048,12 @@ keyword_variable: kNIL @lexer.state = :expr_value } | { - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } f_args term { - @lexer.in_kwarg = val[0] + @context.in_kwarg = val[0] result = @builder.args(nil, val[1], nil) } @@ -2418,3 +2428,15 @@ require 'parser' def default_encoding Encoding::UTF_8 end + + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + end diff --git a/lib/parser/ruby27.y b/lib/parser/ruby27.y index 5da29d1c6..3be053042 100644 --- a/lib/parser/ruby27.y +++ b/lib/parser/ruby27.y @@ -48,7 +48,7 @@ rule program: { @current_arg_stack.push(nil) - @max_numparam_stack.push + @max_numparam_stack.push(static: false) } top_compstmt { @@ -299,13 +299,13 @@ rule @lexer.command_start = false @pattern_variables.push - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } p_expr { @pattern_variables.pop - @lexer.in_kwarg = val[2] + @context.in_kwarg = val[2] if @builder.class.emit_match_pattern result = @builder.match_pattern(val[0], val[1], val[3]) else @@ -337,12 +337,13 @@ rule cmd_brace_block: tLBRACE_ARG { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } fcall: operation @@ -1134,7 +1135,8 @@ rule } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -1143,6 +1145,8 @@ rule args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } | kIF expr_value then compstmt if_tail kEND { @@ -1194,71 +1198,65 @@ rule { result = @builder.for(val[0], val[1], val[2], *val[3], val[4], val[5]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.cmdarg.push(false) - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.cmdarg.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kDEF fname + | k_def fname { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:def) + local_push + result = context.dup + @context.in_def = true @current_arg_stack.push(nil) } f_arglist bodystmt kEND @@ -1266,22 +1264,19 @@ rule result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def @current_arg_stack.pop } - | kDEF singleton dot_or_colon + | k_def singleton dot_or_colon { @lexer.state = :expr_fname } fname { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true @current_arg_stack.push(nil) } f_arglist bodystmt kEND @@ -1289,10 +1284,8 @@ rule result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def @current_arg_stack.pop } | kBREAK @@ -1314,9 +1307,22 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + k_def: kDEF + { + result = val[0] + } + k_return: kRETURN { - if @context.in_class? + if @context.in_class && !@context.in_def && !(context.in_block || context.in_lambda) diagnostic :error, :invalid_return, nil, val[0] end } @@ -1566,11 +1572,10 @@ opt_block_args_tail: lambda: { @static_env.extend_dynamic - @max_numparam_stack.push + @max_numparam_stack.push(static: false) } f_larglist { - @context.pop @lexer.cmdarg.push(false) } lambda_body @@ -1598,31 +1603,34 @@ opt_block_args_tail: lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } bodystmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1708,26 +1716,28 @@ opt_block_args_tail: brace_block: tLCURLY { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } | kDO { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } brace_body: { @static_env.extend_dynamic - @max_numparam_stack.push + @max_numparam_stack.push(static: false) } opt_block_param compstmt { @@ -1740,7 +1750,7 @@ opt_block_args_tail: do_body: { @static_env.extend_dynamic - @max_numparam_stack.push + @max_numparam_stack.push(static: false) } { @lexer.cmdarg.push(false) @@ -1774,14 +1784,14 @@ opt_block_args_tail: @pattern_variables.push @pattern_hash_keys.push - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } p_top_expr then { @pattern_hash_keys.pop @pattern_variables.pop - @lexer.in_kwarg = val[1] + @context.in_kwarg = val[1] } compstmt p_cases { @@ -1907,13 +1917,13 @@ opt_block_args_tail: | tLBRACE { @pattern_hash_keys.push - result = @lexer.in_kwarg - @lexer.in_kwarg = false + result = @context.in_kwarg + @context.in_kwarg = false } p_kwargs rbrace { @pattern_hash_keys.pop - @lexer.in_kwarg = val[1] + @context.in_kwarg = val[1] result = @builder.hash_pattern(val[0], val[2], val[3]) } | tLBRACE rbrace @@ -2120,7 +2130,8 @@ opt_block_args_tail: } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -2129,6 +2140,8 @@ opt_block_args_tail: args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } p_variable: tIDENTIFIER @@ -2528,12 +2541,12 @@ keyword_variable: kNIL @lexer.state = :expr_value } | { - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } f_args term { - @lexer.in_kwarg = val[0] + @context.in_kwarg = val[0] result = @builder.args(nil, val[1], nil) } @@ -2939,6 +2952,20 @@ require 'parser' Encoding::UTF_8 end + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + @max_numparam_stack.push(static: true) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + @max_numparam_stack.pop + end + def try_declare_numparam(node) name = node.children[0] @@ -2950,16 +2977,18 @@ require 'parser' diagnostic :error, :ordinary_param_defined, nil, [nil, location] end - raw_context = context.stack.dup raw_max_numparam_stack = max_numparam_stack.stack.dup # ignore current block scope - raw_context.pop raw_max_numparam_stack.pop - raw_context.reverse_each do |outer_scope| - if outer_scope == :block || outer_scope == :lambda - outer_scope_has_numparams = raw_max_numparam_stack.pop > 0 + raw_max_numparam_stack.reverse_each do |outer_scope| + if outer_scope[:static] + # found an outer scope that can't have numparams + # like def/class/etc + break + else + outer_scope_has_numparams = outer_scope[:value] > 0 if outer_scope_has_numparams diagnostic :error, :numparam_used_in_outer_scope, nil, [nil, location] @@ -2967,10 +2996,6 @@ require 'parser' # for now it's ok, but an outer scope can also be a block # with numparams, so we need to continue end - else - # found an outer scope that can't have numparams - # like def/class/etc - break end end diff --git a/lib/parser/ruby30.y b/lib/parser/ruby30.y index c96a2bbc7..f5c43bfd3 100644 --- a/lib/parser/ruby30.y +++ b/lib/parser/ruby30.y @@ -48,7 +48,7 @@ rule program: { @current_arg_stack.push(nil) - @max_numparam_stack.push + @max_numparam_stack.push(static: true) } top_compstmt { @@ -300,13 +300,13 @@ rule @lexer.command_start = false @pattern_variables.push - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } p_expr { @pattern_variables.pop - @lexer.in_kwarg = val[2] + @context.in_kwarg = val[2] result = @builder.match_pattern(val[0], val[1], val[3]) } | arg kIN @@ -315,13 +315,13 @@ rule @lexer.command_start = false @pattern_variables.push - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } p_expr { @pattern_variables.pop - @lexer.in_kwarg = val[2] + @context.in_kwarg = val[2] result = @builder.match_pattern_p(val[0], val[1], val[3]) } | arg =tLBRACE_ARG @@ -339,29 +339,24 @@ rule def_name: fname { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) + local_push @current_arg_stack.push(nil) - result = val[0] + result = [ val[0], @context.dup ] + @context.in_def = true } - defn_head: kDEF def_name + defn_head: k_def def_name { - @context.push(:def) - result = [ val[0], val[1] ] } - defs_head: kDEF singleton dot_or_colon + defs_head: k_def singleton dot_or_colon { @lexer.state = :expr_fname } def_name { - @context.push(:defs) - result = [ val[0], val[1], val[2], val[4] ] } @@ -378,12 +373,13 @@ rule cmd_brace_block: tLBRACE_ARG { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } fcall: operation @@ -875,21 +871,19 @@ rule } | defn_head f_opt_paren_args tEQL arg { - _def_t, name_t = val[0] + def_t, (name_t, ctx) = val[0] endless_method_name(name_t) - result = @builder.def_endless_method(*val[0], + result = @builder.def_endless_method(def_t, name_t, val[1], val[2], val[3]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def @current_arg_stack.pop } | defn_head f_opt_paren_args tEQL arg kRESCUE_MOD arg { - _def_t, name_t = val[0] + def_t, (name_t, ctx) = val[0] endless_method_name(name_t) rescue_body = @builder.rescue_body(val[4], @@ -898,32 +892,28 @@ rule method_body = @builder.begin_body(val[3], [ rescue_body ]) - result = @builder.def_endless_method(*val[0], + result = @builder.def_endless_method(def_t, name_t, val[1], val[2], method_body) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def @current_arg_stack.pop } | defs_head f_opt_paren_args tEQL arg { - _def_t, _recv, _dot_t, name_t = val[0] + def_t, recv, dot_t, (name_t, ctx) = val[0] endless_method_name(name_t) - result = @builder.def_endless_singleton(*val[0], + result = @builder.def_endless_singleton(def_t, recv, dot_t, name_t, val[1], val[2], val[3]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def @current_arg_stack.pop } | defs_head f_opt_paren_args tEQL arg kRESCUE_MOD arg { - _def_t, _recv, _dot_t, name_t = val[0] + def_t, recv, dot_t, (name_t, ctx) = val[0] endless_method_name(name_t) rescue_body = @builder.rescue_body(val[4], @@ -932,13 +922,11 @@ rule method_body = @builder.begin_body(val[3], [ rescue_body ]) - result = @builder.def_endless_singleton(*val[0], + result = @builder.def_endless_singleton(def_t, recv, dot_t, name_t, val[1], val[2], method_body) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def @current_arg_stack.pop } | primary @@ -1292,85 +1280,78 @@ rule { result = @builder.for(val[0], val[1], val[2], *val[3], val[4], val[5]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:class) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.cmdarg.push(false) - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.cmdarg.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | defn_head f_arglist bodystmt kEND { - result = @builder.def_method(*val[0], val[1], + def_t, (name_t, ctx) = val[0] + result = @builder.def_method(def_t, name_t, val[1], val[2], val[3]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def @current_arg_stack.pop } | defs_head f_arglist bodystmt kEND { - result = @builder.def_singleton(*val[0], val[1], + def_t, recv, dot_t, (name_t, ctx) = val[0] + result = @builder.def_singleton(def_t, recv, dot_t, name_t, val[1], val[2], val[3]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def @current_arg_stack.pop } | kBREAK @@ -1392,9 +1373,22 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + k_def: kDEF + { + result = val[0] + } + k_return: kRETURN { - if @context.in_class? + if @context.in_class && !@context.in_def && !(context.in_block || context.in_lambda) diagnostic :error, :invalid_return, nil, val[0] end } @@ -1646,12 +1640,12 @@ opt_block_args_tail: lambda: tLAMBDA { @static_env.extend_dynamic - @max_numparam_stack.push - @context.push(:lambda) + @max_numparam_stack.push(static: false) + result = @context.dup + @context.in_lambda = true } f_larglist { - @context.pop @lexer.cmdarg.push(false) } lambda_body @@ -1663,6 +1657,7 @@ opt_block_args_tail: @max_numparam_stack.pop @static_env.unextend @lexer.cmdarg.pop + @context.in_lambda = val[1].in_lambda result = @builder.block(lambda_call, begin_t, args, body, end_t) @@ -1683,31 +1678,34 @@ opt_block_args_tail: lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } bodystmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1793,26 +1791,28 @@ opt_block_args_tail: brace_block: tLCURLY { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } | kDO { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { result = [ val[0], *val[2], val[3] ] - @context.pop + @context.in_block = val[1].in_block } brace_body: { @static_env.extend_dynamic - @max_numparam_stack.push + @max_numparam_stack.push(static: false) } opt_block_param compstmt { @@ -1825,7 +1825,7 @@ opt_block_args_tail: do_body: { @static_env.extend_dynamic - @max_numparam_stack.push + @max_numparam_stack.push(static: false) } { @lexer.cmdarg.push(false) @@ -1859,14 +1859,14 @@ opt_block_args_tail: @pattern_variables.push @pattern_hash_keys.push - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } p_top_expr then { @pattern_variables.pop @pattern_hash_keys.pop - @lexer.in_kwarg = val[1] + @context.in_kwarg = val[1] } compstmt p_cases { @@ -2007,13 +2007,13 @@ opt_block_args_tail: | tLBRACE { @pattern_hash_keys.push - result = @lexer.in_kwarg - @lexer.in_kwarg = false + result = @context.in_kwarg + @context.in_kwarg = false } p_kwargs rbrace { @pattern_hash_keys.pop - @lexer.in_kwarg = val[1] + @context.in_kwarg = val[1] result = @builder.hash_pattern(val[0], val[2], val[3]) } | tLBRACE rbrace @@ -2623,12 +2623,12 @@ f_opt_paren_args: f_paren_args f_arglist: f_paren_args | { - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } f_args term { - @lexer.in_kwarg = val[0] + @context.in_kwarg = val[0] result = @builder.args(nil, val[1], nil) } @@ -3036,10 +3036,24 @@ require 'parser' end end + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + @max_numparam_stack.push(static: true) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + @max_numparam_stack.pop + end + def try_declare_numparam(node) name = node.children[0] - if name =~ /\A_[1-9]\z/ && !static_env.declared?(name) && context.in_dynamic_block? + if name =~ /\A_[1-9]\z/ && !static_env.declared?(name) && @context.in_dynamic_block? # definitely an implicit param location = node.loc.expression @@ -3047,27 +3061,26 @@ require 'parser' diagnostic :error, :ordinary_param_defined, nil, [nil, location] end - raw_context = context.stack.dup raw_max_numparam_stack = max_numparam_stack.stack.dup # ignore current block scope - raw_context.pop raw_max_numparam_stack.pop - raw_context.reverse_each do |outer_scope| - if outer_scope == :block || outer_scope == :lambda - outer_scope_has_numparams = raw_max_numparam_stack.pop > 0 + raw_max_numparam_stack.reverse_each do |outer_scope| + if outer_scope[:static] + # found an outer scope that can't have numparams + # like def/class/etc + break + else + outer_scope_has_numparams = outer_scope[:value] > 0 if outer_scope_has_numparams diagnostic :error, :numparam_used_in_outer_scope, nil, [nil, location] else # for now it's ok, but an outer scope can also be a block + # like proc { _1; proc { proc { proc { _2 }} }} # with numparams, so we need to continue end - else - # found an outer scope that can't have numparams - # like def/class/etc - break end end diff --git a/lib/parser/ruby31.y b/lib/parser/ruby31.y index 8daa9d48f..03d526a26 100644 --- a/lib/parser/ruby31.y +++ b/lib/parser/ruby31.y @@ -48,7 +48,7 @@ rule program: { @current_arg_stack.push(nil) - @max_numparam_stack.push + @max_numparam_stack.push(static: true) } top_compstmt { @@ -263,21 +263,19 @@ rule } | defn_head f_opt_paren_args tEQL command { - _def_t, name_t = val[0] + def_t, (name_t, ctx) = val[0] endless_method_name(name_t) - result = @builder.def_endless_method(*val[0], + result = @builder.def_endless_method(def_t, name_t, val[1], val[2], val[3]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop @current_arg_stack.pop + @context.in_def = ctx.in_def } | defn_head f_opt_paren_args tEQL command kRESCUE_MOD arg { - _def_t, name_t = val[0] + def_t, (name_t, ctx) = val[0] endless_method_name(name_t) rescue_body = @builder.rescue_body(val[4], @@ -286,32 +284,28 @@ rule method_body = @builder.begin_body(val[3], [ rescue_body ]) - result = @builder.def_endless_method(*val[0], + result = @builder.def_endless_method(def_t, name_t, val[1], val[2], method_body) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop @current_arg_stack.pop + @context.in_def = ctx.in_def } | defs_head f_opt_paren_args tEQL command { - _def_t, _recv, _dot_t, name_t = val[0] + def_t, recv, dot_t, (name_t, ctx) = val[0] endless_method_name(name_t) - result = @builder.def_endless_singleton(*val[0], + result = @builder.def_endless_singleton(def_t, recv, dot_t, name_t, val[1], val[2], val[3]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop @current_arg_stack.pop + @context.in_def = ctx.in_def } | defs_head f_opt_paren_args tEQL command kRESCUE_MOD arg { - _def_t, _recv, _dot_t, name_t = val[0] + def_t, recv, dot_t, (name_t, ctx) = val[0] endless_method_name(name_t) rescue_body = @builder.rescue_body(val[4], @@ -320,14 +314,12 @@ rule method_body = @builder.begin_body(val[3], [ rescue_body ]) - result = @builder.def_endless_singleton(*val[0], + result = @builder.def_endless_singleton(def_t, recv, dot_t, name_t, val[1], val[2], method_body) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop @current_arg_stack.pop + @context.in_def = ctx.in_def } | backref tOP_ASGN command_rhs { @@ -368,13 +360,13 @@ rule @lexer.command_start = false @pattern_variables.push - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } p_top_expr_body { @pattern_variables.pop - @lexer.in_kwarg = val[2] + @context.in_kwarg = val[2] result = @builder.match_pattern(val[0], val[1], val[3]) } | arg kIN @@ -383,13 +375,13 @@ rule @lexer.command_start = false @pattern_variables.push - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } p_top_expr_body { @pattern_variables.pop - @lexer.in_kwarg = val[2] + @context.in_kwarg = val[2] result = @builder.match_pattern_p(val[0], val[1], val[3]) } | arg =tLBRACE_ARG @@ -407,29 +399,25 @@ rule def_name: fname { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) + local_push @current_arg_stack.push(nil) - result = val[0] + result = [ val[0], @context.dup ] + @context.in_def = true } - defn_head: kDEF def_name + defn_head: k_def def_name { - @context.push(:def) - result = [ val[0], val[1] ] } - defs_head: kDEF singleton dot_or_colon + defs_head: k_def singleton dot_or_colon { @lexer.state = :expr_fname + @context.in_argdef = true } def_name { - @context.push(:defs) - result = [ val[0], val[1], val[2], val[4] ] } @@ -446,12 +434,13 @@ rule cmd_brace_block: tLBRACE_ARG { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { + @context.in_block = val[1].in_block result = [ val[0], *val[2], val[3] ] - @context.pop } fcall: operation @@ -932,9 +921,14 @@ rule { result = @builder.logical_op(:or, val[0], val[1], val[2]) } - | kDEFINED opt_nl arg + | kDEFINED opt_nl + { + @context.in_defined = true + } + arg { - result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil) + @context.in_defined = false + result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[3] ], nil) } | arg tEH arg opt_nl tCOLON arg { @@ -943,21 +937,19 @@ rule } | defn_head f_opt_paren_args tEQL arg { - _def_t, name_t = val[0] + def_t, (name_t, ctx) = val[0] endless_method_name(name_t) - result = @builder.def_endless_method(*val[0], + result = @builder.def_endless_method(def_t, name_t, val[1], val[2], val[3]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop @current_arg_stack.pop + @context.in_def = ctx.in_def } | defn_head f_opt_paren_args tEQL arg kRESCUE_MOD arg { - _def_t, name_t = val[0] + def_t, (name_t, ctx) = val[0] endless_method_name(name_t) rescue_body = @builder.rescue_body(val[4], @@ -966,32 +958,28 @@ rule method_body = @builder.begin_body(val[3], [ rescue_body ]) - result = @builder.def_endless_method(*val[0], + result = @builder.def_endless_method(def_t, name_t, val[1], val[2], method_body) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop @current_arg_stack.pop + @context.in_def = ctx.in_def } | defs_head f_opt_paren_args tEQL arg { - _def_t, _recv, _dot_t, name_t = val[0] + def_t, recv, dot_t, (name_t, ctx) = val[0] endless_method_name(name_t) - result = @builder.def_endless_singleton(*val[0], + result = @builder.def_endless_singleton(def_t, recv, dot_t, name_t, val[1], val[2], val[3]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop @current_arg_stack.pop + @context.in_def = ctx.in_def } | defs_head f_opt_paren_args tEQL arg kRESCUE_MOD arg { - _def_t, _recv, _dot_t, name_t = val[0] + def_t, recv, dot_t, (name_t, ctx) = val[0] endless_method_name(name_t) rescue_body = @builder.rescue_body(val[4], @@ -1000,14 +988,12 @@ rule method_body = @builder.begin_body(val[3], [ rescue_body ]) - result = @builder.def_endless_singleton(*val[0], + result = @builder.def_endless_singleton(def_t, recv, dot_t, name_t, val[1], val[2], method_body) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop @current_arg_stack.pop + @context.in_def = ctx.in_def } | primary @@ -1289,10 +1275,15 @@ rule { result = @builder.keyword_cmd(:yield, val[0]) } - | kDEFINED opt_nl tLPAREN2 expr rparen + | kDEFINED opt_nl tLPAREN2 { + @context.in_defined = true + } + expr rparen + { + @context.in_defined = false result = @builder.keyword_cmd(:defined?, val[0], - val[2], [ val[3] ], val[4]) + val[2], [ val[4] ], val[5]) } | kNOT tLPAREN2 expr rparen { @@ -1368,86 +1359,77 @@ rule { result = @builder.for(val[0], val[1], val[2], *val[3], val[4], val[5]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:class) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end - lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.cmdarg.push(false) - @lexer.cond.push(false) - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.cmdarg.push(false) - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.cmdarg.pop - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | defn_head f_arglist bodystmt kEND { - result = @builder.def_method(*val[0], val[1], + def_t, (name_t, ctx) = val[0] + result = @builder.def_method(def_t, name_t, val[1], val[2], val[3]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop @current_arg_stack.pop + @context.in_def = ctx.in_def } | defs_head f_arglist bodystmt kEND { - result = @builder.def_singleton(*val[0], val[1], + def_t, recv, dot_t, (name_t, ctx) = val[0] + result = @builder.def_singleton(def_t, recv, dot_t, name_t, val[1], val[2], val[3]) - @lexer.cmdarg.pop - @lexer.cond.pop - @static_env.unextend - @context.pop + local_pop @current_arg_stack.pop + @context.in_def = ctx.in_def } | kBREAK { @@ -1468,9 +1450,25 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + + k_def: kDEF + { + result = val[0] + @context.in_argdef = true + } + k_return: kRETURN { - if @context.in_class? + if @context.in_class && !@context.in_def && !(context.in_block || context.in_lambda) diagnostic :error, :invalid_return, nil, val[0] end } @@ -1556,6 +1554,15 @@ rule f_any_kwrest: f_kwrest | f_no_kwarg + + f_eq: { + @context.in_argdef = false + } + tEQL + { + result = val[1] + } + block_args_tail: f_block_kwarg tCOMMA f_kwrest opt_f_block_arg { result = val[0].concat(val[2]).concat(val[3]) @@ -1685,12 +1692,14 @@ opt_block_args_tail: { @max_numparam_stack.has_ordinary_params! @current_arg_stack.set(nil) + @context.in_argdef = false result = @builder.args(val[0], val[1], val[2]) } | tPIPE block_param opt_bv_decl tPIPE { @max_numparam_stack.has_ordinary_params! @current_arg_stack.set(nil) + @context.in_argdef = false result = @builder.args(val[0], val[1].concat(val[2]), val[3]) } @@ -1722,12 +1731,12 @@ opt_block_args_tail: lambda: tLAMBDA { @static_env.extend_dynamic - @max_numparam_stack.push - @context.push(:lambda) + @max_numparam_stack.push(static: false) + result = @context.dup + @context.in_lambda = true } f_larglist { - @context.pop @lexer.cmdarg.push(false) } lambda_body @@ -1739,6 +1748,7 @@ opt_block_args_tail: @max_numparam_stack.pop @static_env.unextend @lexer.cmdarg.pop + @context.in_lambda = val[1].in_lambda result = @builder.block(lambda_call, begin_t, args, body, end_t) @@ -1746,11 +1756,13 @@ opt_block_args_tail: f_larglist: tLPAREN2 f_args opt_bv_decl tRPAREN { + @context.in_argdef = false @max_numparam_stack.has_ordinary_params! result = @builder.args(val[0], val[1].concat(val[2]), val[3]) } | f_args { + @context.in_argdef = false if val[0].any? @max_numparam_stack.has_ordinary_params! end @@ -1759,31 +1771,34 @@ opt_block_args_tail: lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { + @context.in_lambda = val[1].in_lambda result = [ val[0], val[2], val[3] ] - @context.pop } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } bodystmt kEND { + @context.in_lambda = val[1].in_lambda result = [ val[0], val[2], val[3] ] - @context.pop } do_block: kDO_BLOCK { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { + @context.in_block = val[1].in_block result = [ val[0], *val[2], val[3] ] - @context.pop } block_call: command do_block @@ -1869,26 +1884,28 @@ opt_block_args_tail: brace_block: tLCURLY { - @context.push(:block) + result = @context.dup + @context.in_block = true } brace_body tRCURLY { + @context.in_block = val[1].in_block result = [ val[0], *val[2], val[3] ] - @context.pop } | kDO { - @context.push(:block) + result = @context.dup + @context.in_block = true } do_body kEND { + @context.in_block = val[1].in_block result = [ val[0], *val[2], val[3] ] - @context.pop } brace_body: { @static_env.extend_dynamic - @max_numparam_stack.push + @max_numparam_stack.push(static: false) } opt_block_param compstmt { @@ -1901,7 +1918,7 @@ opt_block_args_tail: do_body: { @static_env.extend_dynamic - @max_numparam_stack.push + @max_numparam_stack.push(static: false) } { @lexer.cmdarg.push(false) @@ -1935,14 +1952,14 @@ opt_block_args_tail: @pattern_variables.push @pattern_hash_keys.push - result = @lexer.in_kwarg - @lexer.in_kwarg = true + result = @context.in_kwarg + @context.in_kwarg = true } p_top_expr then { @pattern_variables.pop @pattern_hash_keys.pop - @lexer.in_kwarg = val[1] + @context.in_kwarg = val[1] } compstmt p_cases { @@ -2084,13 +2101,13 @@ opt_block_args_tail: | tLBRACE { @pattern_hash_keys.push - result = @lexer.in_kwarg - @lexer.in_kwarg = false + result = @context.in_kwarg + @context.in_kwarg = false } p_kwargs rbrace { @pattern_hash_keys.pop - @lexer.in_kwarg = val[1] + @context.in_kwarg = val[1] result = @builder.hash_pattern(val[0], val[2], val[3]) } | tLBRACE rbrace @@ -2699,6 +2716,7 @@ keyword_variable: kNIL f_opt_paren_args: f_paren_args | none { + @context.in_argdef = false result = @builder.args(nil, [], nil) } @@ -2707,18 +2725,19 @@ f_opt_paren_args: f_paren_args result = @builder.args(val[0], val[1], val[2]) @lexer.state = :expr_value + @context.in_argdef = false } f_arglist: f_paren_args | { - result = @lexer.in_kwarg - @lexer.in_kwarg = true - @context.push(:def_open_args) + result = @context.dup + @context.in_kwarg = true + @context.in_argdef = true } f_args term { - @context.pop - @lexer.in_kwarg = val[0] + @context.in_kwarg = val[0].in_kwarg + @context.in_argdef = false result = @builder.args(nil, val[1], nil) } @@ -2909,6 +2928,7 @@ f_opt_paren_args: f_paren_args @max_numparam_stack.has_ordinary_params! @current_arg_stack.set(val[0][0]) + @context.in_argdef = false result = val[0] } @@ -2916,20 +2936,24 @@ f_opt_paren_args: f_paren_args f_kw: f_label arg_value { @current_arg_stack.set(nil) + @context.in_argdef = true result = @builder.kwoptarg(val[0], val[1]) } | f_label { @current_arg_stack.set(nil) + @context.in_argdef = true result = @builder.kwarg(val[0]) } f_block_kw: f_label primary_value { + @context.in_argdef = true result = @builder.kwoptarg(val[0], val[1]) } | f_label { + @context.in_argdef = true result = @builder.kwarg(val[0]) } @@ -2969,15 +2993,17 @@ f_opt_paren_args: f_paren_args result = [ @builder.kwrestarg(val[0]) ] } - f_opt: f_arg_asgn tEQL arg_value + f_opt: f_arg_asgn f_eq arg_value { @current_arg_stack.set(0) + @context.in_argdef = true result = @builder.optarg(val[0], val[1], val[2]) } - f_block_opt: f_arg_asgn tEQL primary_value + f_block_opt: f_arg_asgn f_eq primary_value { @current_arg_stack.set(0) + @context.in_argdef = true result = @builder.optarg(val[0], val[1], val[2]) } @@ -3141,10 +3167,24 @@ require 'parser' end end + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + @max_numparam_stack.push(static: true) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + @max_numparam_stack.pop + end + def try_declare_numparam(node) name = node.children[0] - if name =~ /\A_[1-9]\z/ && !static_env.declared?(name) && context.in_dynamic_block? + if name =~ /\A_[1-9]\z/ && !static_env.declared?(name) && @context.in_dynamic_block? # definitely an implicit param location = node.loc.expression @@ -3152,27 +3192,25 @@ require 'parser' diagnostic :error, :ordinary_param_defined, nil, [nil, location] end - raw_context = context.stack.dup raw_max_numparam_stack = max_numparam_stack.stack.dup - # ignore current block scope - raw_context.pop raw_max_numparam_stack.pop - raw_context.reverse_each do |outer_scope| - if outer_scope == :block || outer_scope == :lambda - outer_scope_has_numparams = raw_max_numparam_stack.pop > 0 + raw_max_numparam_stack.reverse_each do |outer_scope| + if outer_scope[:static] + # found an outer scope that can't have numparams + # like def/class/etc + break + else + outer_scope_has_numparams = outer_scope[:value] > 0 if outer_scope_has_numparams diagnostic :error, :numparam_used_in_outer_scope, nil, [nil, location] else # for now it's ok, but an outer scope can also be a block + # like proc { _1; proc { proc { proc { _2 }} }} # with numparams, so we need to continue end - else - # found an outer scope that can't have numparams - # like def/class/etc - break end end diff --git a/lib/parser/rubymotion.y b/lib/parser/rubymotion.y index 3b214e7be..41bd116e2 100644 --- a/lib/parser/rubymotion.y +++ b/lib/parser/rubymotion.y @@ -141,7 +141,7 @@ rule } | klBEGIN tLCURLY compstmt tRCURLY { - if @context.indirectly_in_def? + if @context.in_def diagnostic :error, :begin_in_method, nil, val[0] end @@ -265,14 +265,15 @@ rule cmd_brace_block: tLBRACE_ARG { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } command: operation command_args =tLOWEST @@ -1020,7 +1021,8 @@ rule } | tLAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } lambda { @@ -1029,6 +1031,8 @@ rule args, (begin_t, body, end_t) = val[2] result = @builder.block(lambda_call, begin_t, args, body, end_t) + + @context.in_lambda = val[1].in_lambda } | kIF expr_value then compstmt if_tail kEND { @@ -1100,75 +1104,73 @@ rule val[2], val[4], val[5], val[7], val[8]) } - | kCLASS cpath superclass + | k_class cpath superclass { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:class) + local_push + @context.in_class = true } bodystmt kEND { - unless @context.class_definition_allowed? - diagnostic :error, :class_in_def, nil, val[0] + k_class, ctx = val[0] + if @context.in_def + diagnostic :error, :class_in_def, nil, k_class end lt_t, superclass = val[2] - result = @builder.def_class(val[0], val[1], + result = @builder.def_class(k_class, val[1], lt_t, superclass, val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } - | kCLASS tLSHFT expr term + | k_class tLSHFT expr term { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:sclass) + @context.in_def = false + @context.in_class = false + local_push } bodystmt kEND { - result = @builder.def_sclass(val[0], val[1], val[2], + k_class, ctx = val[0] + result = @builder.def_sclass(k_class, val[1], val[2], val[5], val[6]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = ctx.in_def + @context.in_class = ctx.in_class } - | kMODULE cpath + | k_module cpath { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:module) + @context.in_class = true + local_push } bodystmt kEND { - unless @context.module_definition_allowed? - diagnostic :error, :module_in_def, nil, val[0] + k_mod, ctx = val[0] + if @context.in_def + diagnostic :error, :module_in_def, nil, k_mod end - result = @builder.def_module(val[0], val[1], + result = @builder.def_module(k_mod, val[1], val[3], val[4]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_class = ctx.in_class } | kDEF fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:def) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_method(val[0], val[1], val[3], val[4], val[5]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[2].in_def } | kDEF singleton dot_or_colon { @@ -1176,18 +1178,17 @@ rule } fname { - @static_env.extend_static - @lexer.push_cmdarg - @context.push(:defs) + local_push + result = context.dup + @context.in_def = true } f_arglist bodystmt kEND { result = @builder.def_singleton(val[0], val[1], val[2], val[4], val[6], val[7], val[8]) - @lexer.pop_cmdarg - @static_env.unextend - @context.pop + local_pop + @context.in_def = val[5].in_def } | kBREAK { @@ -1208,6 +1209,16 @@ rule primary_value: primary + k_class: kCLASS + { + result = [ val[0], @context.dup ] + } + + k_module: kMODULE + { + result = [ val[0], @context.dup ] + } + then: term | kTHEN | term kTHEN @@ -1435,13 +1446,9 @@ rule lambda: { @static_env.extend_dynamic } - f_larglist - { - @context.pop - } - lambda_body + f_larglist lambda_body { - result = [ val[1], val[3] ] + result = [ val[1], val[2] ] @static_env.unextend } @@ -1457,34 +1464,37 @@ rule lambda_body: tLAMBEG { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt tRCURLY { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } | kDO_LAMBDA { - @context.push(:lambda) + result = @context.dup + @context.in_lambda = true } compstmt kEND { result = [ val[0], val[2], val[3] ] - @context.pop + @context.in_lambda = val[1].in_lambda } do_block: kDO_BLOCK { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } block_call: command do_block @@ -1558,26 +1568,28 @@ rule brace_block: tLCURLY { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt tRCURLY { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } | kDO { @static_env.extend_dynamic - @context.push(:block) + result = @context.dup + @context.in_block = true } opt_block_param compstmt kEND { result = [ val[0], val[2], val[3], val[4] ] @static_env.unextend - @context.pop + @context.in_block = val[1].in_block } case_body: kWHEN args then compstmt cases @@ -2190,3 +2202,15 @@ require 'parser' def default_encoding Encoding::BINARY end + + def local_push + @static_env.extend_static + @lexer.cmdarg.push(false) + @lexer.cond.push(false) + end + + def local_pop + @static_env.unextend + @lexer.cmdarg.pop + @lexer.cond.pop + end diff --git a/test/helper.rb b/test/helper.rb index d783daf00..2c92d896f 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -96,7 +96,7 @@ def assign_properties(properties) module BuilderExt def n(type, children, source_map) - super.updated(nil, nil, context: @parser.context.stack.dup) + super.updated(nil, nil, context: @parser.context.dup) end end Parser::Builders::Default.prepend(BuilderExt) diff --git a/test/parse_helper.rb b/test/parse_helper.rb index 82837fa02..e27d86a1e 100644 --- a/test/parse_helper.rb +++ b/test/parse_helper.rb @@ -264,7 +264,8 @@ def assert_context(context, code, versions=ALL_VERSIONS) assert_equal 1, nodes.count, "there must exactly 1 `get_context()` call" node = nodes.first - assert_equal context, node.context, "(#{version}) expect parsing context to match" + actual_context = Parser::Context::FLAGS.each_with_object([]) { |flag, acc| acc << flag if node.context.public_send(flag) } + assert_equal context.sort, actual_context.sort, "(#{version}) expect parsing context to match" end end @@ -354,7 +355,9 @@ def assert_state_is_final(parser, version) assert lexer.lambda_stack.empty?, "(#{version}) expected lambda_stack to be empty after parsing" assert parser.static_env.empty?, "(#{version}) expected static_env to be empty after parsing" - assert parser.context.empty?, "(#{version}) expected context to be empty after parsing" + Parser::Context::FLAGS.each do |ctx_flag| + refute parser.context.public_send(ctx_flag), "(#{version}) expected context.#{ctx_flag} to be `false` after parsing" + end assert parser.max_numparam_stack.empty?, "(#{version}) expected max_numparam_stack to be empty after parsing" assert parser.current_arg_stack.empty?, "(#{version}) expected current_arg_stack to be empty after parsing" assert parser.pattern_variables.empty?, "(#{version}) expected pattern_variables to be empty after parsing" diff --git a/test/test_parser.rb b/test/test_parser.rb index 9603848db..d735bd66c 100644 --- a/test/test_parser.rb +++ b/test/test_parser.rb @@ -6699,66 +6699,37 @@ def test_context_class %q{class A; get_context; end}, %q{class A < B; get_context; end} ].each do |code| - assert_context([:class], code, ALL_VERSIONS) + assert_context([:in_class], code, ALL_VERSIONS) end end def test_context_module assert_context( - [:module], + [:in_class], %q{module M; get_context; end}, ALL_VERSIONS) end - def test_context_sclass - assert_context( - [:sclass], - %q{class << foo; get_context; end}, - ALL_VERSIONS) - end - def test_context_def - [ + assert_context( + [:in_def], %q{def m; get_context; end}, - %q{def m(a = get_context); end} - ].each do |code| - assert_context([:def], code, ALL_VERSIONS) - end + ALL_VERSIONS) - [ + assert_context( + [:in_def], %q{def m() = get_context}, - %q{def m(a = get_context) = 42} - ].each do |code| - assert_context([:def], code, SINCE_3_0) - end - end - - def test_context_defs - [ - %q{def foo.m; get_context; end}, - %q{def foo.m(a = get_context); end} - ].each do |code| - assert_context([:defs], code, ALL_VERSIONS) - end - - [ - %q{def foo.m() = get_context}, - %q{def foo.m(a = get_context) = 42} - ].each do |code| - assert_context([:defs], code, SINCE_3_0) - end - end + SINCE_3_0) - def test_context_def_open_args assert_context( - [:def, :def_open_args], - %q{def foo a = get_context; end}, - SINCE_3_1) + [:in_def], + %q{def self.m; get_context; end}, + ALL_VERSIONS) assert_context( - [:defs, :def_open_args], - %q{def self.foo a = get_context; end}, - SINCE_3_1) + [:in_def], + %q{def self.m() = get_context}, + SINCE_3_0) end def test_context_cmd_brace_block @@ -6767,7 +6738,7 @@ def test_context_cmd_brace_block 'foo.tap foo { get_context }', 'foo::tap foo { get_context }' ].each do |code| - assert_context([:block], code, ALL_VERSIONS) + assert_context([:in_block], code, ALL_VERSIONS) end end @@ -6780,7 +6751,7 @@ def test_context_brace_block 'foo.tap do get_context end', 'foo::tap do get_context end' ].each do |code| - assert_context([:block], code, ALL_VERSIONS) + assert_context([:in_block], code, ALL_VERSIONS) end end @@ -6790,7 +6761,7 @@ def test_context_do_block %q{foo.tap do get_context end}, %q{foo::tap do get_context end} ].each do |code| - assert_context([:block], code, ALL_VERSIONS) + assert_context([:in_block], code, ALL_VERSIONS) end end @@ -6803,92 +6774,10 @@ def test_context_lambda '->(a = get_context) {}', '->(a = get_context) do end' ].each do |code| - assert_context([:lambda], code, SINCE_1_9) + assert_context([:in_lambda], code, SINCE_1_9) end end - def test_context_nested - assert_context( - [:class, :module, :sclass, :defs, :def, :block], - %q{ - class A - module M - class << foo - def bar.m - def m - tap do - get_context - end - end - end - end - end - end - }, - ALL_VERSIONS) - - assert_context( - [:class, :module, :sclass, :defs, :def, :lambda, :block], - %q{ - class A - module M - class << foo - def bar.m - def m - -> do - tap do - get_context - end - end - end - end - end - end - end - }, - SINCE_1_9) - - assert_context( - [], - %q{ - class A - module M - class << foo - def bar.m - def m - tap do - end - end - end - end - end - end - get_context - }, - ALL_VERSIONS) - - assert_context( - [], - %q{ - class A - module M - class << foo - def bar.m - def m - -> do - tap do - end - end - end - end - end - end - end - get_context - }, - SINCE_1_9) - end - def test_return_in_class assert_parses( s(:class, @@ -8125,7 +8014,7 @@ def test_forward_args_invalid [:error, :unexpected_token, { :token => 'tDOT3' }], %q{def foo ...; end}, %q{ ^^^ location}, - SINCE_2_7) + SINCE_3_1 - SINCE_2_7) end def test_trailing_forward_arg @@ -10832,6 +10721,95 @@ def test_forward_arg_with_open_args %q{ ~~~ location | ~~~~~ highlights (0)}, SINCE_3_1) + + assert_parses( + s(:def, :foo, + s(:args, + s(:arg, :a), + s(:forward_arg)), + s(:send, nil, :bar, + s(:forwarded_args))), + "def foo(a, ...) bar(...) end", + %q{}, + SINCE_3_1) + + assert_parses( + s(:def, :foo, + s(:args, + s(:arg, :a), + s(:forward_arg)), + s(:send, nil, :bar, + s(:forwarded_args))), + "def foo a, ...\n bar(...)\nend", + %q{}, + SINCE_3_1) + + assert_parses( + s(:def, :foo, + s(:args, + s(:optarg, :b, + s(:int, 1)), + s(:forward_arg)), + s(:send, nil, :bar, + s(:forwarded_args))), + "def foo b = 1, ...\n bar(...)\nend", + %q{}, + SINCE_3_1) + + assert_parses( + s(:def, :foo, + s(:args, + s(:forward_arg)), + s(:send, nil, :bar, + s(:forwarded_args))), + "def foo ...; bar(...); end", + %q{}, + SINCE_3_1) + + assert_parses( + s(:def, :foo, + s(:args, + s(:arg, :a), + s(:forward_arg)), + s(:send, nil, :bar, + s(:forwarded_args))), + "def foo a, ...; bar(...); end", + %q{}, + SINCE_3_1) + + assert_parses( + s(:def, :foo, + s(:args, + s(:optarg, :b, + s(:int, 1)), + s(:forward_arg)), + s(:send, nil, :bar, + s(:forwarded_args))), + "def foo b = 1, ...; bar(...); end", + %q{}, + SINCE_3_1) + + assert_parses( + s(:begin, + s(:def, :foo, + s(:args, + s(:forward_arg)), + s(:send, nil, :bar, + s(:forwarded_args)))), + "(def foo ...\n bar(...)\nend)", + %q{}, + SINCE_3_1) + + assert_parses( + s(:begin, + s(:def, :foo, + s(:args, + s(:forward_arg)), + s(:send, nil, :bar, + s(:forwarded_args)))), + "(def foo ...; bar(...); end)", + %q{}, + SINCE_3_1) end def test_anonymous_blockarg From ebe3f64f0d799ac76ad98b865f20e7af0c563895 Mon Sep 17 00:00:00 2001 From: Ilya Bylich Date: Mon, 3 Jan 2022 03:02:31 +0300 Subject: [PATCH 3/3] * parser/current: update for 3.1.0 release. (#840) --- .github/workflows/test.yml | 4 ++-- lib/parser/current.rb | 8 ++++---- lib/parser/version.rb | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 304d0c0e3..32b282af6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,14 +17,14 @@ jobs: strategy: fail-fast: false matrix: - ruby: ["2.4.10", "2.5.9", "2.6.9", "2.7.5", "3.0.3", "jruby-9.2"] + ruby: ["2.6.9", "2.7.5", "3.0.3", "3.1.0", "jruby-9.2"] test_command: ["bundle exec rake test"] include: - ruby: "head" test_command: "bundle exec rake test || true" - ruby: "truffleruby" test_command: "bundle exec rake test || true" - - ruby: "3.0.3" + - ruby: "3.1.0" test_command: "./ci/run_rubocop_specs || true" steps: - uses: actions/checkout@v2 diff --git a/lib/parser/current.rb b/lib/parser/current.rb index f2876de22..cb2405daf 100644 --- a/lib/parser/current.rb +++ b/lib/parser/current.rb @@ -93,7 +93,7 @@ def warn_syntax_deviation(feature, version) CurrentRuby = Ruby30 when /^3\.1\./ - current_version = '3.1.0-dev' + current_version = '3.1.0' if RUBY_VERSION != current_version warn_syntax_deviation 'parser/ruby31', current_version end @@ -103,8 +103,8 @@ def warn_syntax_deviation(feature, version) else # :nocov: # Keep this in sync with released Ruby. - warn_syntax_deviation 'parser/ruby30', '3.0.x' - require 'parser/ruby30' - CurrentRuby = Ruby30 + warn_syntax_deviation 'parser/ruby31', '3.1.x' + require 'parser/ruby31' + CurrentRuby = Ruby31 end end diff --git a/lib/parser/version.rb b/lib/parser/version.rb index 56651925d..fbaf5e585 100644 --- a/lib/parser/version.rb +++ b/lib/parser/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Parser - VERSION = '3.0.3.2' + VERSION = '3.1.0.0' end