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 057785bc17..1834778e92 100644
--- a/parse.y
+++ b/parse.y
@@ -195,6 +195,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. */
@@ -278,7 +280,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_rest_arg f_block_arg opt_f_block_arg
%type <node> assoc_list assocs assoc undef_list backref string_dvar
-%type <node> block_var opt_block_var brace_block cmd_brace_block do_block lhs none fitem
+%type <node> for_var block_var opt_block_var block_par
+%type <node> brace_block cmd_brace_block do_block lhs none fitem
%type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
%type <id> fsym variable sym symbol operation operation2 operation3
%type <id> cname fname op
@@ -1610,7 +1613,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
{
@@ -1757,10 +1760,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 */ '|'
{