This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #46947] Parse method-BLOCK arguments as a term
authorFather Chrysostomos <sprout@cpan.org>
Mon, 11 Aug 2014 16:51:34 +0000 (09:51 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Wed, 13 Aug 2014 01:00:51 +0000 (18:00 -0700)
(C.f. bug #114222 and commit 52d0e95b, which did the same thing
for ‘use’.)

When parsing the arguments following a method name and a block (for
‘method { $obj } LIST‘ syntax), the lexer was using heuristics to
determine whether an opening brace was a hash constructor or a block,
as it does at the beginning of a statement.  In every case in which it
determined it was a block, the parser would them throw a syntax error.

In this case, the lexer should not be trying to guess, since we *know*
it can only be a hash here.

This was the result:

$ perl -e 'method {$obj} {$foo=>undef}'
syntax error at -e line 1, near "} {"
Execution of -e aborted due to compilation errors.

Now we get this:

$ ./miniperl -e 'method {$obj} {$foo=>undef}'
Can't call method "method" on an undefined value at -e line 1.

as expected.

perl.h
t/comp/parser.t
toke.c

diff --git a/perl.h b/perl.h
index 0ad3eea..d03c0e8 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -4797,6 +4797,7 @@ typedef enum {
     XATTRBLOCK,
     XATTRTERM,
     XTERMBLOCK,
+    XBLOCKTERM,
     XPOSTDEREF,
     XTERMORDORDOR /* evil hack */
     /* update exp_name[] in toke.c if adding to this enum */
index 7caa116..c5cff29 100644 (file)
@@ -8,7 +8,7 @@ BEGIN {
     chdir 't';
 }
 
-print "1..169\n";
+print "1..170\n";
 
 sub failed {
     my ($got, $expected, $name) = @_;
@@ -499,6 +499,10 @@ eval 'for my a1b $i (1) {}';
 # ng: 'Missing $ on loop variable'
 like $@, "^No such class a1b at ", 'TYPE of my of for statement';
 
+eval 'method {} {$_,undef}';
+like $@, qq/^Can't call method "method" on unblessed reference at /,
+     'method BLOCK {...} does not try to disambiguate';
+
 # Add new tests HERE (above this line)
 
 # bug #74022: Loop on characters in \p{OtherIDContinue}
diff --git a/toke.c b/toke.c
index b0997ef..ea16f9b 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -5449,6 +5449,11 @@ Perl_yylex(pTHX)
            PL_lex_allbrackets++;
            PL_expect = XSTATE;
            break;
+       case XBLOCKTERM:
+           PL_lex_brackstack[PL_lex_brackets++] = XTERM;
+           PL_lex_allbrackets++;
+           PL_expect = XSTATE;
+           break;
        default: {
                const char *t;
                if (PL_oldoldbufptr == PL_last_lop)
@@ -6634,7 +6639,9 @@ Perl_yylex(pTHX)
                    if (!PL_lex_allbrackets &&
                            PL_lex_fakeeof > LEX_FAKEEOF_LOWLOGIC)
                        PL_lex_fakeeof = LEX_FAKEEOF_LOWLOGIC;
-                   PREBLOCK(METHOD);
+                   PL_expect = XBLOCKTERM;
+                   PL_bufptr = s;
+                   return REPORT(METHOD);
                }
 
                /* If followed by a bareword, see if it looks like indir obj. */