@@ -74,6 +74,8 @@ typedef unsigned int stack_type;
7474#define NUM_SUFFIX_R (1 <<0 )
7575#define NUM_SUFFIX_I (1 <<1 )
7676
77+ #define NUMPARAM_MAX 31
78+
7779static inline mrb_sym
7880intern_cstr_gen (parser_state *p, const char *s)
7981{
@@ -315,6 +317,24 @@ locals_node(parser_state *p)
315317 return p->locals ? p->locals ->car : NULL ;
316318}
317319
320+ static void
321+ nvars_nest (parser_state *p)
322+ {
323+ p->nvars = cons (p->nvars , nint (0 ));
324+ }
325+
326+ static void
327+ nvars_block (parser_state *p)
328+ {
329+ p->nvars = cons (p->nvars , nint (-1 ));
330+ }
331+
332+ static void
333+ nvars_unnest (parser_state *p)
334+ {
335+ p->nvars = p->nvars ->car ;
336+ }
337+
318338/* (:scope (vars..) (prog...)) */
319339static node*
320340new_scope (parser_state *p, node *body)
@@ -649,6 +669,19 @@ new_cvar(parser_state *p, mrb_sym sym)
649669 return cons ((node*)NODE_CVAR, nsym (sym));
650670}
651671
672+ /* (:nvar . a) */
673+ static node*
674+ new_nvar (parser_state *p, int num)
675+ {
676+ if (!p->nvars || intn (p->nvars ->cdr ) < 0 ) {
677+ yyerror (p, " numbered parameter outside block" );
678+ } else {
679+ int nvars = intn (p->nvars ->cdr );
680+ p->nvars ->cdr = nint (nvars > num ? nvars : num);
681+ }
682+ return cons ((node*)NODE_NVAR, nint (num));
683+ }
684+
652685/* (:const . a) */
653686static node*
654687new_const (parser_state *p, mrb_sym sym)
@@ -806,17 +839,44 @@ new_block_arg(parser_state *p, node *a)
806839 return cons ((node*)NODE_BLOCK_ARG, a);
807840}
808841
842+ static node*
843+ setup_args (parser_state *p, node *a)
844+ {
845+ int nvars = intn (p->nvars ->cdr );
846+ if (nvars > 0 ) {
847+ int i;
848+ char buf[5 ];
849+ mrb_sym sym;
850+ // m || opt || rest || tail
851+ if (a && (a->car || (a->cdr && a->cdr ->car ) || (a->cdr ->cdr && a->cdr ->cdr ->car ) || (a->cdr ->cdr ->cdr ->cdr && a->cdr ->cdr ->cdr ->cdr ->car ))) {
852+ yyerror (p, " ordinary parameter is defined" );
853+ } else {
854+ node* args = 0 ;
855+ for (i = nvars; i > 0 ; i--) {
856+ sprintf (buf, " @%d" , i);
857+ sym = intern_cstr (buf);
858+ args = cons (new_arg (p, sym), args);
859+ p->locals ->car = cons (nsym (sym), p->locals ->car );
860+ }
861+ a = new_args (p, args, 0 , 0 , 0 , 0 );
862+ }
863+ }
864+ return a;
865+ }
866+
809867/* (:block arg body) */
810868static node*
811869new_block (parser_state *p, node *a, node *b)
812870{
871+ a = setup_args (p, a);
813872 return list4 ((node*)NODE_BLOCK, locals_node (p), a, b);
814873}
815874
816875/* (:lambda arg body) */
817876static node*
818877new_lambda (parser_state *p, node *a, node *b)
819878{
879+ a = setup_args (p, a);
820880 return list4 ((node*)NODE_LAMBDA, locals_node (p), a, b);
821881}
822882
@@ -1334,6 +1394,7 @@ heredoc_end(parser_state *p)
13341394%token <nd> tSTRING tSTRING_PART tSTRING_MID
13351395%token <nd> tNTH_REF tBACK_REF
13361396%token <num> tREGEXP_END
1397+ %token <num> tNUMPARAM
13371398
13381399%type <nd> singleton string string_fragment string_rep string_interp xstring regexp
13391400%type <nd> literal numeric cpath symbol
@@ -1466,11 +1527,13 @@ top_stmt : stmt
14661527 | keyword_BEGIN
14671528 {
14681529 $<nd>$ = local_switch(p);
1530+ nvars_block (p);
14691531 }
14701532 ' {' top_compstmt ' }'
14711533 {
14721534 yyerror (p, " BEGIN not supported" );
14731535 local_resume (p, $<nd>2 );
1536+ nvars_unnest (p);
14741537 $$ = 0 ;
14751538 }
14761539 ;
@@ -1668,13 +1731,15 @@ block_command : block_call
16681731cmd_brace_block : tLBRACE_ARG
16691732 {
16701733 local_nest (p);
1734+ nvars_nest (p);
16711735 }
16721736 opt_block_param
16731737 compstmt
16741738 ' }'
16751739 {
16761740 $$ = new_block(p, $3 , $4 );
16771741 local_unnest (p);
1742+ nvars_unnest (p);
16781743 }
16791744 ;
16801745
@@ -2410,6 +2475,7 @@ primary : literal
24102475 | tLAMBDA
24112476 {
24122477 local_nest (p);
2478+ nvars_nest (p);
24132479 $<num>$ = p->lpar_beg;
24142480 p->lpar_beg = ++p->paren_nest;
24152481 }
@@ -2423,6 +2489,7 @@ primary : literal
24232489 p->lpar_beg = $<num>2 ;
24242490 $$ = new_lambda(p, $3 , $5 );
24252491 local_unnest (p);
2492+ nvars_unnest (p);
24262493 p->cmdarg_stack = $<stack>4 ;
24272494 CMDARG_LEXPOP ();
24282495 }
@@ -2482,13 +2549,15 @@ primary : literal
24822549 if (p->in_def || p->in_single)
24832550 yyerror (p, " class definition in method body" );
24842551 $<nd>$ = local_switch(p);
2552+ nvars_block (p);
24852553 }
24862554 bodystmt
24872555 keyword_end
24882556 {
24892557 $$ = new_class(p, $2 , $3 , $5 );
24902558 SET_LINENO ($$, $1 );
24912559 local_resume (p, $<nd>4 );
2560+ nvars_unnest (p);
24922561 }
24932562 | keyword_class
24942563 tLSHFT expr
@@ -2499,6 +2568,7 @@ primary : literal
24992568 term
25002569 {
25012570 $<nd>$ = cons(local_switch(p), nint(p->in_single));
2571+ nvars_block (p);
25022572 p->in_single = 0 ;
25032573 }
25042574 bodystmt
@@ -2507,6 +2577,7 @@ primary : literal
25072577 $$ = new_sclass(p, $3 , $7 );
25082578 SET_LINENO ($$, $1 );
25092579 local_resume (p, $<nd>6 ->car);
2580+ nvars_unnest (p);
25102581 p->in_def = $<num>4 ;
25112582 p->in_single = intn($<nd>6 ->cdr);
25122583 }
@@ -2516,13 +2587,15 @@ primary : literal
25162587 if (p->in_def || p->in_single)
25172588 yyerror (p, " module definition in method body" );
25182589 $<nd>$ = local_switch(p);
2590+ nvars_block (p);
25192591 }
25202592 bodystmt
25212593 keyword_end
25222594 {
25232595 $$ = new_module(p, $2 , $4 );
25242596 SET_LINENO ($$, $1 );
25252597 local_resume (p, $<nd>3 );
2598+ nvars_unnest (p);
25262599 }
25272600 | keyword_def fname
25282601 {
@@ -2532,6 +2605,7 @@ primary : literal
25322605 {
25332606 p->in_def++;
25342607 $<nd>$ = local_switch(p);
2608+ nvars_block (p);
25352609 }
25362610 f_arglist
25372611 bodystmt
@@ -2540,6 +2614,7 @@ primary : literal
25402614 $$ = new_def(p, $2 , $5 , $6 );
25412615 SET_LINENO ($$, $1 );
25422616 local_resume (p, $<nd>4 );
2617+ nvars_unnest (p);
25432618 p->in_def--;
25442619 p->cmdarg_stack = $<stack>3 ;
25452620 }
@@ -2554,6 +2629,7 @@ primary : literal
25542629 p->in_single++;
25552630 p->lstate = EXPR_ENDFN; /* force for args */
25562631 $<nd>$ = local_switch(p);
2632+ nvars_block (p);
25572633 }
25582634 f_arglist
25592635 bodystmt
@@ -2562,6 +2638,7 @@ primary : literal
25622638 $$ = new_sdef(p, $2 , $5 , $7 , $8 );
25632639 SET_LINENO ($$, $1 );
25642640 local_resume (p, $<nd>6 );
2641+ nvars_unnest (p);
25652642 p->in_single--;
25662643 p->cmdarg_stack = $<stack>4 ;
25672644 }
@@ -2829,13 +2906,15 @@ lambda_body : tLAMBEG compstmt '}'
28292906do_block : keyword_do_block
28302907 {
28312908 local_nest (p);
2909+ nvars_nest (p);
28322910 }
28332911 opt_block_param
28342912 bodystmt
28352913 keyword_end
28362914 {
28372915 $$ = new_block(p,$3 ,$4 );
28382916 local_unnest (p);
2917+ nvars_unnest (p);
28392918 }
28402919 ;
28412920
@@ -2906,6 +2985,7 @@ method_call : operation paren_args
29062985brace_block : ' {'
29072986 {
29082987 local_nest (p);
2988+ nvars_nest (p);
29092989 $<num>$ = p->lineno;
29102990 }
29112991 opt_block_param
@@ -2914,10 +2994,12 @@ brace_block : '{'
29142994 $$ = new_block(p,$3 ,$4 );
29152995 SET_LINENO ($$, $<num>2 );
29162996 local_unnest (p);
2997+ nvars_unnest (p);
29172998 }
29182999 | keyword_do
29193000 {
29203001 local_nest (p);
3002+ nvars_nest (p);
29213003 $<num>$ = p->lineno;
29223004 }
29233005 opt_block_param
@@ -2926,6 +3008,7 @@ brace_block : '{'
29263008 $$ = new_block(p,$3 ,$4 );
29273009 SET_LINENO ($$, $<num>2 );
29283010 local_unnest (p);
3011+ nvars_unnest (p);
29293012 }
29303013 ;
29313014
@@ -3182,6 +3265,10 @@ variable : tIDENTIFIER
31823265 {
31833266 $$ = new_cvar(p, $1 );
31843267 }
3268+ | tNUMPARAM
3269+ {
3270+ $$ = new_nvar(p, $1 );
3271+ }
31853272 | tCONSTANT
31863273 {
31873274 $$ = new_const(p, $1 );
@@ -5788,14 +5875,36 @@ parser_yylex(parser_state *p)
57885875 }
57895876 else if (ISDIGIT (c)) {
57905877 if (p->tidx == 1 ) {
5791- yyerror_c (p, " wrong instance variable name: @" , c);
5878+ if (last_state == EXPR_FNAME) {
5879+ yyerror_c (p, " wrong instance variable name: @" , c);
5880+ return 0 ;
5881+ }
5882+ if (c == ' 0' ) {
5883+ yyerror (p, " leading zero is not allowed as a numbered parameter" );
5884+ return 0 ;
5885+ }
5886+ do {
5887+ tokadd (p, c);
5888+ c = nextc (p);
5889+ } while (c >= 0 && ISDIGIT (c));
5890+ pushback (p, c);
5891+ tokfix (p);
5892+ {
5893+ unsigned long n = strtoul (tok (p) + 1 , NULL , 10 );
5894+ if (n > NUMPARAM_MAX || n < 0 ) {
5895+ yyerror (p, " too large numbered parameter" );
5896+ return 0 ;
5897+ }
5898+ pylval.num = n;
5899+ }
5900+ p->lstate = EXPR_END;
5901+ return tNUMPARAM;
57925902 }
57935903 else {
57945904 yyerror_c (p, " wrong class variable name: @@" , c);
5905+ return 0 ;
57955906 }
5796- return 0 ;
5797- }
5798- if (!identchar (c)) {
5907+ } else if (!identchar (c)) {
57995908 pushback (p, c);
58005909 return ' @' ;
58015910 }
@@ -6843,6 +6952,10 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
68436952 printf (" NODE_CVAR %s\n " , mrb_sym_name (mrb, sym (tree)));
68446953 break ;
68456954
6955+ case NODE_NVAR:
6956+ printf (" NODE_NVAR %d\n " , intn (tree));
6957+ break ;
6958+
68466959 case NODE_CONST:
68476960 printf (" NODE_CONST %s\n " , mrb_sym_name (mrb, sym (tree)));
68486961 break ;
0 commit comments