Support new numbered parameter syntax `_1` instead of `@1`.

parent 72d57ad0
...@@ -74,7 +74,7 @@ typedef unsigned int stack_type; ...@@ -74,7 +74,7 @@ typedef unsigned int stack_type;
#define NUM_SUFFIX_R (1<<0) #define NUM_SUFFIX_R (1<<0)
#define NUM_SUFFIX_I (1<<1) #define NUM_SUFFIX_I (1<<1)
#define NUMPARAM_MAX 31 #define NUMPARAM_MAX 9
static inline mrb_sym static inline mrb_sym
intern_cstr_gen(parser_state *p, const char *s) intern_cstr_gen(parser_state *p, const char *s)
...@@ -845,7 +845,6 @@ setup_args(parser_state *p, node *a) ...@@ -845,7 +845,6 @@ setup_args(parser_state *p, node *a)
int nvars = intn(p->nvars->cdr); int nvars = intn(p->nvars->cdr);
if (nvars > 0) { if (nvars > 0) {
int i; int i;
char buf[5];
mrb_sym sym; mrb_sym sym;
// m || opt || rest || tail // m || opt || rest || tail
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))) { 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))) {
...@@ -853,7 +852,11 @@ setup_args(parser_state *p, node *a) ...@@ -853,7 +852,11 @@ setup_args(parser_state *p, node *a)
} else { } else {
node* args = 0; node* args = 0;
for (i = nvars; i > 0; i--) { for (i = nvars; i > 0; i--) {
sprintf(buf, "@%d", i); char buf[3];
buf[0] = '_';
buf[1] = i+'0';
buf[3] = '\0';
sym = intern_cstr(buf); sym = intern_cstr(buf);
args = cons(new_arg(p, sym), args); args = cons(new_arg(p, sym), args);
p->locals->car = cons(nsym(sym), p->locals->car); p->locals->car = cons(nsym(sym), p->locals->car);
...@@ -2395,6 +2398,10 @@ primary : literal ...@@ -2395,6 +2398,10 @@ primary : literal
| heredoc | heredoc
| var_ref | var_ref
| backref | backref
| tNUMPARAM
{
$$ = new_nvar(p, $1);
}
| tFID | tFID
{ {
$$ = new_fcall(p, $1, 0); $$ = new_fcall(p, $1, 0);
...@@ -3265,10 +3272,6 @@ variable : tIDENTIFIER ...@@ -3265,10 +3272,6 @@ variable : tIDENTIFIER
{ {
$$ = new_cvar(p, $1); $$ = new_cvar(p, $1);
} }
| tNUMPARAM
{
$$ = new_nvar(p, $1);
}
| tCONSTANT | tCONSTANT
{ {
$$ = new_const(p, $1); $$ = new_const(p, $1);
...@@ -5875,36 +5878,14 @@ parser_yylex(parser_state *p) ...@@ -5875,36 +5878,14 @@ parser_yylex(parser_state *p)
} }
else if (ISDIGIT(c)) { else if (ISDIGIT(c)) {
if (p->tidx == 1) { if (p->tidx == 1) {
if (last_state == EXPR_FNAME) { yyerror_c(p, "wrong instance variable name: @", c);
yyerror_c(p, "wrong instance variable name: @", c);
return 0;
}
if (c == '0') {
yyerror(p, "leading zero is not allowed as a numbered parameter");
return 0;
}
do {
tokadd(p, c);
c = nextc(p);
} while (c >= 0 && ISDIGIT(c));
pushback(p, c);
tokfix(p);
{
unsigned long n = strtoul(tok(p) + 1, NULL, 10);
if (n > NUMPARAM_MAX || n < 0) {
yyerror(p, "too large numbered parameter");
return 0;
}
pylval.num = n;
}
p->lstate = EXPR_END;
return tNUMPARAM;
} }
else { else {
yyerror_c(p, "wrong class variable name: @@", c); yyerror_c(p, "wrong class variable name: @@", c);
return 0;
} }
} else if (!identchar(c)) { return 0;
}
if (!identchar(c)) {
pushback(p, c); pushback(p, c);
return '@'; return '@';
} }
...@@ -5912,6 +5893,30 @@ parser_yylex(parser_state *p) ...@@ -5912,6 +5893,30 @@ parser_yylex(parser_state *p)
case '_': case '_':
token_column = newtok(p); token_column = newtok(p);
tokadd(p, c);
c = nextc(p);
if (ISDIGIT(c)) {
int n = 0;
while (c >= 0 && ISDIGIT(c)) {
n *= 10;
n += c - '0';
tokadd(p, c);
c = nextc(p);
}
pushback(p, c);
if (n == 0) {
yyerror(p, "_0 is not available");
return 0;
}
if (n > NUMPARAM_MAX || n < 0) {
yyerror(p, "too large numbered parameter");
return 0;
}
pylval.num = n;
p->lstate = EXPR_END;
return tNUMPARAM;
}
break; break;
default: default:
......
...@@ -674,9 +674,9 @@ end ...@@ -674,9 +674,9 @@ end
assert('numbered parameters') do assert('numbered parameters') do
assert_equal(15, [1,2,3,4,5].reduce {@1+@2}) assert_equal(15, [1,2,3,4,5].reduce {_1+_2})
assert_equal(3, ->{@1+@2}.call(1,2)) assert_equal(3, ->{_1+_2}.call(1,2))
assert_equal(4, ->(a=->{@1}){a}.call.call(4)) assert_equal(4, ->(a=->{_1}){a}.call.call(4))
assert_equal(5, -> a: ->{@1} {a}.call.call(5)) assert_equal(5, -> a: ->{_1} {a}.call.call(5))
assert_equal(55, Proc.new do @1 + @2 + @3 + @4 + @5 + @6 + @7 + @8 + @9 + @10 end.call(*[1, 2, 3, 4, 5, 6, 7, 8, 9, 10])) assert_equal(45, Proc.new do _1 + _2 + _3 + _4 + _5 + _6 + _7 + _8 + _9 end.call(*[1, 2, 3, 4, 5, 6, 7, 8, 9]))
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment