Hi,

At Fri, 13 Apr 2007 15:50:11 +0900,
Robert Klemme wrote in [ruby-talk:247769]:
> I think it's worth the effort only if a) it really accepts "unlimited" 
> cases and b) it doesn't cost performance.  (Haven't checked either)

In this case, yes for a, and almost yes for b, I guess.

Since there was a typo in [ruby-talk:247527], merged patch of
[ruby-talk:247527] and [ruby-talk:247595].


Index: parse.y =================================================================== --- parse.y (revision 12203) +++ parse.y (working copy) @@ -273,5 +273,5 @@ static void top_local_setup(); %type <node> bodystmt compstmt stmts stmt expr arg primary command command_call method_call %type <node> expr_value arg_value primary_value -%type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure +%type <node> if_then opt_else case_body cases opt_rescue rescue exc_list exc_var opt_ensure %type <node> args when_args call_args call_args2 open_args paren_args opt_paren_args %type <node> command_args aref_args opt_block_arg block_arg var_ref var_lhs @@ -376,5 +376,7 @@ bodystmt : compstmt $$ = $1; if ($2) { - $$ = NEW_RESCUE($1, $2, $3); + $$ = $2; + $$->nd_head = $1; + $$->nd_else = $3; } else if ($3) { @@ -1553,11 +1555,9 @@ primary : literal fixpos($$, $1); } - | kIF expr_value then - compstmt - if_tail - kEND + | if_then opt_else kEND { - $$ = NEW_IF(cond($2), $4, $5); - fixpos($$, $2); + $1->nd_else->nd_else = $2; + $$ = $1->nd_body; + rb_gc_force_recycle((VALUE)$1); if (cond_negative(&$$->nd_cond)) { NODE *tmp = $$->nd_body; @@ -1599,14 +1599,16 @@ primary : literal } } - | kCASE expr_value opt_terms - case_body - kEND + | kCASE expr_value opt_terms cases opt_else kEND { - $$ = NEW_CASE($2, $4); + $4->nd_head->nd_next = $5; + $4->nd_head = $2; + $$ = $4; fixpos($$, $2); } - | kCASE opt_terms case_body kEND + | kCASE opt_terms cases opt_else kEND { - $$ = $3; + $3->nd_head->nd_next = $4; + $$ = $3->nd_body; + rb_gc_force_recycle((VALUE)$3); } | kCASE opt_terms kELSE compstmt kEND @@ -1744,18 +1746,26 @@ do : term ; -if_tail : opt_else - | kELSIF expr_value then - compstmt - if_tail +opt_else : none + | kELSE compstmt { - $$ = NEW_IF(cond($2), $4, $5); - fixpos($$, $2); + $$ = $2; } ; -opt_else : none - | kELSE compstmt +if_then : kIF expr_value then + compstmt { - $$ = $2; + $$ = NEW_IF(cond($2), $4, 0); + fixpos($$, $2); + $$ = NEW_IF(0, $$, $$); + } + | if_then kELSIF expr_value then + compstmt + { + NODE *elsif = NEW_IF(cond($3), $5, 0); + fixpos(elsif, $3); + $$ = $1; + $$->nd_else->nd_else = elsif; + $$->nd_else = elsif; } ; @@ -1871,7 +1881,6 @@ brace_block : '{' case_body : kWHEN when_args then compstmt - cases { - $$ = NEW_WHEN($2, $4, $5); + $$ = NEW_WHEN($2, $4, 0); } ; @@ -1887,11 +1896,34 @@ when_args : args ; -cases : opt_else - | case_body +cases : case_body + { + $$ = NEW_CASE($1, $1); + } + | cases + case_body + { + $$ = $1; + $$->nd_head->nd_next = $2; + $$->nd_head = $2; + } ; -opt_rescue : kRESCUE exc_list exc_var then +opt_rescue : none + | opt_rescue + rescue + { + if ($1) { + $1->nd_head->nd_head = $2; + $1->nd_head = $2; + $$ = $1; + } + else { + $$ = NEW_RESCUE($2, $2, 0); + } + } + ; + +rescue : kRESCUE exc_list exc_var then compstmt - opt_rescue { if ($3) { @@ -1899,8 +1931,7 @@ opt_rescue : kRESCUE exc_list exc_var th $5 = block_append($3, $5); } - $$ = NEW_RESBODY($2, $5, $6); + $$ = NEW_RESBODY($2, $5, 0); fixpos($$, $2?$2:$5); } - | none ; @@ -6109,4 +6140,5 @@ rb_id2name(id) { char *name; + st_data_t data; if (id < tLAST_TOKEN) { @@ -6119,6 +6151,6 @@ rb_id2name(id) } - if (st_lookup(sym_rev_tbl, id, (st_data_t *)&name)) - return name; + if (st_lookup(sym_rev_tbl, id, &data)) + return (char *)data; if (is_attrset_id(id)) { @@ -6333,5 +6365,5 @@ rb_parser_free(ptr) NODE **prev = &parser_heap, *n; - while (n = *prev) { + while ((n = *prev) != 0) { if (n->u1.node == ptr) { *prev = n->u2.node;
-- Nobu Nakada