aboutsummaryrefslogtreecommitdiffstats
path: root/parse.y
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2019-10-19 03:05:03 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2019-10-22 02:35:43 +0900
commit62d43828770211470bcacb9e943876f981b5a1b4 (patch)
tree97c1cdebd90cff8bf28320d5ad053b80cc53df53 /parse.y
parent35f90bf1b9b06f93e919af3c4095b7aff903d799 (diff)
downloadruby-62d43828770211470bcacb9e943876f981b5a1b4.tar.gz
Arguments forwarding [Feature #16253]
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y47
1 files changed, 44 insertions, 3 deletions
diff --git a/parse.y b/parse.y
index 4cd6b2195e..657e521982 100644
--- a/parse.y
+++ b/parse.y
@@ -597,6 +597,10 @@ static void numparam_pop(struct parser_params *p, NODE *prev_inner);
# define METHOD_NOT '!'
#endif
+#define idFWD_REST '*'
+#define idFWD_KWREST idPow /* Use simple "**", as tDSTAR is "**arg" */
+#define idFWD_BLOCK '&'
+
#define RE_OPTION_ONCE (1<<16)
#define RE_OPTION_ENCODING_SHIFT 8
#define RE_OPTION_ENCODING(e) (((e)&0xff)<<RE_OPTION_ENCODING_SHIFT)
@@ -1063,7 +1067,7 @@ static void token_info_warn(struct parser_params *p, const char *token, token_in
%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg
%type <id> f_kwrest f_label f_arg_asgn call_op call_op2 reswords relop dot_or_colon
%type <id> p_kwrest p_kwnorest
-%type <id> f_no_kwarg
+%type <id> f_no_kwarg args_forward
%token END_OF_INPUT 0 "end-of-input"
%token <id> '.'
/* escaped chars, should be ignored otherwise */
@@ -2406,6 +2410,23 @@ paren_args : '(' opt_call_args rparen
/*% %*/
/*% ripper: arg_paren!(escape_Qundef($2)) %*/
}
+ | '(' args_forward rparen
+ {
+ if (!local_id(p, idFWD_REST) || !local_id(p, idFWD_KWREST) || !local_id(p, idFWD_BLOCK)) {
+ compile_error(p, "unexpected ...");
+ $$ = Qnone;
+ }
+ else {
+ /*%%%*/
+ NODE *splat = NEW_SPLAT(NEW_LVAR(idFWD_REST, &@2), &@2);
+ NODE *kwrest = list_append(p, NEW_LIST(0, &@2), NEW_LVAR(idFWD_KWREST, &@2));
+ NODE *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@2), &@2);
+ $$ = arg_append(p, splat, new_hash(p, kwrest, &@2), &@2);
+ $$ = arg_blk_pass($$, block);
+ /*% %*/
+ /*% ripper: arg_paren!($2) %*/
+ }
+ }
;
opt_paren_args : none
@@ -3396,7 +3417,7 @@ block_param_def : '|' opt_bv_decl '|'
/*%%%*/
$$ = 0;
/*% %*/
- /*% ripper: block_var!(params_new(Qnil,Qnil,Qnil,Qnil,Qnil,Qnil,Qnil), escape_Qundef($2)) %*/
+ /*% ripper: block_var!(params!(Qnil,Qnil,Qnil,Qnil,Qnil,Qnil,Qnil), escape_Qundef($2)) %*/
}
| tOROP
{
@@ -3404,7 +3425,7 @@ block_param_def : '|' opt_bv_decl '|'
/*%%%*/
$$ = 0;
/*% %*/
- /*% ripper: block_var!(params_new(Qnil,Qnil,Qnil,Qnil,Qnil,Qnil,Qnil), Qnil) %*/
+ /*% ripper: block_var!(params!(Qnil,Qnil,Qnil,Qnil,Qnil,Qnil,Qnil), Qnil) %*/
}
| '|' block_param opt_bv_decl '|'
{
@@ -4862,6 +4883,17 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail
{
$$ = new_args(p, Qnone, Qnone, Qnone, Qnone, $1, &@$);
}
+ | args_forward
+ {
+ arg_var(p, idFWD_REST);
+ arg_var(p, idFWD_KWREST);
+ arg_var(p, idFWD_BLOCK);
+ /*%%%*/
+ $$ = new_args_tail(p, Qnone, idFWD_KWREST, idFWD_BLOCK, &@1);
+ $$ = new_args(p, Qnone, Qnone, idFWD_REST, Qnone, $$, &@$);
+ /*% %*/
+ /*% ripper: params_new(Qnone, Qnone, $1, Qnone, Qnone, Qnone, Qnone) %*/
+ }
| /* none */
{
$$ = new_args_tail(p, Qnone, Qnone, Qnone, &@0);
@@ -4869,6 +4901,15 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail
}
;
+args_forward : tBDOT3
+ {
+ /*%%%*/
+ $$ = idDot3;
+ /*% %*/
+ /*% ripper: args_forward! %*/
+ }
+ ;
+
f_bad_arg : tCONSTANT
{
/*%%%*/