summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
authorknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-05-26 03:08:26 +0000
committerknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-05-26 03:08:26 +0000
commit35ec34fa2f20e208e2d1ad5574c7d81a8ae9ecc3 (patch)
tree78ae88f5bb834ab555dd5b8bae4bfe8e30d52c75 /parse.y
parent90ac7da8c85bd1a1f13cf2bee7381ae77a4a928e (diff)
Merge from ruby_1_8, including r16205.
Note that passing a block to a Proc is experimental and partly broken. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@16605 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
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 057785b..1834778 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 */ '|'
{