aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2020-05-14 17:27:48 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2020-05-14 19:58:44 +0900
commitd7d0d01401a8082e514eb2cb3cec5410e7acba7d (patch)
treea40aa20206bb3603d683bec7cbe5d45e0e91e0be
parent634eeb4353ca92a94b4642bd05837868f630eda1 (diff)
downloadruby-d7d0d01401a8082e514eb2cb3cec5410e7acba7d.tar.gz
Endless method definition including `rescue` modifier
-rw-r--r--parse.y36
-rw-r--r--test/ruby/test_syntax.rb6
2 files changed, 40 insertions, 2 deletions
diff --git a/parse.y b/parse.y
index 63d75d8832..6b378b0697 100644
--- a/parse.y
+++ b/parse.y
@@ -920,6 +920,17 @@ set_defun_body(struct parser_params *p, NODE *n, NODE *args, NODE *body, const Y
set_line_body(body, loc->beg_pos.lineno);
return n;
}
+
+static NODE *
+rescued_expr(struct parser_params *p, NODE *arg, NODE *rescue,
+ const YYLTYPE *arg_loc, const YYLTYPE *mod_loc, const YYLTYPE *res_loc)
+{
+ YYLTYPE loc = code_loc_gen(mod_loc, res_loc);
+ rescue = NEW_RESBODY(0, remove_begin(rescue), 0, &loc);
+ loc.beg_pos = arg_loc->beg_pos;
+ return NEW_RESCUE(arg, rescue, 0, &loc);
+}
+
#endif /* RIPPER */
static void
@@ -2455,6 +2466,16 @@ arg : lhs '=' arg_rhs
/*% ripper: def!(get_value($1), $2, $4) %*/
local_pop(p);
}
+ | defn_head f_paren_args '=' arg modifier_rescue arg
+ {
+ restore_defun(p, $<node>1->nd_defn);
+ /*%%%*/
+ $4 = rescued_expr(p, $4, $6, &@4, &@5, &@6);
+ $$ = set_defun_body(p, $1, $2, $4, &@$);
+ /*% %*/
+ /*% ripper: def!(get_value($1), $2, rescue_mod!($4, $6)) %*/
+ local_pop(p);
+ }
| defs_head f_paren_args '=' arg
{
restore_defun(p, $<node>1->nd_defn);
@@ -2466,6 +2487,18 @@ arg : lhs '=' arg_rhs
/*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $4) %*/
local_pop(p);
}
+ | defs_head f_paren_args '=' arg modifier_rescue arg
+ {
+ restore_defun(p, $<node>1->nd_defn);
+ /*%%%*/
+ $4 = rescued_expr(p, $4, $6, &@4, &@5, &@6);
+ $$ = set_defun_body(p, $1, $2, $4, &@$);
+ /*%
+ $1 = get_value($1);
+ %*/
+ /*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, rescue_mod!($4, $6)) %*/
+ local_pop(p);
+ }
| primary
{
$$ = $1;
@@ -2525,9 +2558,8 @@ arg_rhs : arg %prec tOP_ASGN
| arg modifier_rescue arg
{
/*%%%*/
- YYLTYPE loc = code_loc_gen(&@2, &@3);
value_expr($1);
- $$ = NEW_RESCUE($1, NEW_RESBODY(0, remove_begin($3), 0, &loc), 0, &@$);
+ $$ = rescued_expr(p, $1, $3, &@1, &@2, &@3);
/*% %*/
/*% ripper: rescue_mod!($1, $3) %*/
}
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index df6c2e383f..23061e364b 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -1423,6 +1423,12 @@ eom
assert_valid_syntax('private def obj.inc(x) = x + 1')
eval('def self.inc(x) = x + 1 => @x')
assert_equal(:inc, @x)
+ k = Class.new do
+ class_eval('def rescued(x) = raise("to be caught") rescue "instance #{x}"')
+ class_eval('def self.rescued(x) = raise("to be caught") rescue "class #{x}"')
+ end
+ assert_equal("class ok", k.rescued("ok"))
+ assert_equal("instance ok", k.new.rescued("ok"))
end
def test_methoddef_in_cond