This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Stop trying to disambiguate {} after $
authorFather Chrysostomos <sprout@cpan.org>
Mon, 25 Aug 2014 21:54:30 +0000 (14:54 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 26 Aug 2014 05:17:02 +0000 (22:17 -0700)
$ ./perl -Ilib -e '${function_with_side_effects,42}'
$ ./perl -Ilib -e '${Function_with_side_effects,42}'
syntax error at -e line 1, near "${"
Execution of -e aborted due to compilation errors.

Why is the second one a syntax error?

Because the lexer is trying to disambiguate between a block and a hash
when it sees ‘{’ after ‘$’.  But an anonymous hash constructor cannot
come after a funny character, so any time it chooses the hash inter-
pretation over the blocky one, a syntax error ensues.

t/base/lex.t
toke.c

index d75fa57..7604ee1 100644 (file)
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..92\n";
+print "1..93\n";
 
 $x = 'x';
 
@@ -438,3 +438,9 @@ print "ok $test - => quotes keywords across lines\n"; $test++;
 # [perl #80368]
 print "not " unless eval '"a\U="' eq "a=";
 print "ok $test - [perl #80368] qq <a\\U=>\n"; $test++;
+
+sub Function_with_side_effects { $_ = "sidekick function called" }
+print "not " unless
+    (eval '${Function_with_side_effects,\$_}' || $@)
+      eq "sidekick function called";
+print "ok $test - \${...} where {...} looks like hash\n"; $test++;
diff --git a/toke.c b/toke.c
index fc13ecb..ccf471e 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -5484,6 +5484,11 @@ Perl_yylex(pTHX)
                    }
                    OPERATOR(HASHBRACK);
                }
+               if (PL_expect == XREF && PL_oldoldbufptr != PL_last_lop) {
+                   /* ${...} or @{...} etc., but not print {...} */
+                   PL_expect = XTERM;
+                   break;
+               }
                /* This hack serves to disambiguate a pair of curlies
                 * as being a block or an anon hash.  Normally, expectation
                 * determines that, but in cases where we're not in a