summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y75
1 files changed, 72 insertions, 3 deletions
diff --git a/parse.y b/parse.y
index d934774eb4..ff8cc62e55 100644
--- a/parse.y
+++ b/parse.y
@@ -179,6 +179,8 @@ static void top_local_setup();
#define nd_paren(node) (char)((node)->u2.id >> CHAR_BIT*2)
#define nd_nest u3.id
+#define NEW_BLOCK_VAR(b, v) NEW_NODE(NODE_BLOCK_PASS, 0, b, v)
+
/* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
for instance). This is too low for Ruby to parse some files, such as
date/format.rb, therefore bump the value up to at least Bison's default. */
@@ -262,7 +264,8 @@ static void top_local_setup();
%type <node> mrhs superclass block_call block_command
%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
%type <node> assoc_list assocs assoc kwargs undef_list backref string_dvar
-%type <node> block_var opt_block_var brace_block cmd_brace_block do_block lhs none
+%type <node> for_var block_var opt_block_var block_par
+%type <node> brace_block cmd_brace_block do_block lhs none
%type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
%type <id> fitem variable sym symbol operation operation2 operation3
%type <id> cname fname op f_rest_arg
@@ -1589,7 +1592,7 @@ primary : literal
{
$$ = $4;
}
- | kFOR block_var kIN {COND_PUSH(1);} expr_value do {COND_POP();}
+ | kFOR for_var kIN {COND_PUSH(1);} expr_value do {COND_POP();}
compstmt
kEND
{
@@ -1739,10 +1742,76 @@ opt_else : none
}
;
-block_var : lhs
+for_var : lhs
| mlhs
;
+block_par : mlhs_item
+ {
+ $$ = NEW_LIST($1);
+ }
+ | block_par ',' mlhs_item
+ {
+ $$ = list_append($1, $3);
+ }
+ ;
+
+block_var : block_par
+ {
+ if ($1->nd_alen == 1) {
+ $$ = $1->nd_head;
+ rb_gc_force_recycle((VALUE)$1);
+ }
+ else {
+ $$ = NEW_MASGN($1, 0);
+ }
+ }
+ | block_par ','
+ {
+ $$ = NEW_MASGN($1, 0);
+ }
+ | block_par ',' tAMPER lhs
+ {
+ $$ = NEW_BLOCK_VAR($4, NEW_MASGN($1, 0));
+ }
+ | block_par ',' tSTAR lhs ',' tAMPER lhs
+ {
+ $$ = NEW_BLOCK_VAR($7, NEW_MASGN($1, $4));
+ }
+ | block_par ',' tSTAR ',' tAMPER lhs
+ {
+ $$ = NEW_BLOCK_VAR($6, NEW_MASGN($1, -1));
+ }
+ | block_par ',' tSTAR lhs
+ {
+ $$ = NEW_MASGN($1, $4);
+ }
+ | block_par ',' tSTAR
+ {
+ $$ = NEW_MASGN($1, -1);
+ }
+ | tSTAR lhs ',' tAMPER lhs
+ {
+ $$ = NEW_BLOCK_VAR($5, NEW_MASGN(0, $2));
+ }
+ | tSTAR ',' tAMPER lhs
+ {
+ $$ = NEW_BLOCK_VAR($4, NEW_MASGN(0, -1));
+ }
+ | tSTAR lhs
+ {
+ $$ = NEW_MASGN(0, $2);
+ }
+ | tSTAR
+ {
+ $$ = NEW_MASGN(0, -1);
+ }
+ | tAMPER lhs
+ {
+ $$ = NEW_BLOCK_VAR($2, (NODE*)1);
+ }
+ ;
+
opt_block_var : none
| '|' /* none */ '|'
{