[perl #114222] Make ‘use’ parse arguments in term context
authorFather Chrysostomos <sprout@cpan.org>
Sat, 4 Aug 2012 01:35:26 +0000 (18:35 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 4 Aug 2012 02:40:30 +0000 (19:40 -0700)
(lexing context, that is)

use constant { () }

was a syntax error, because the lexer was guessing when { should be
a statement or hash.

It should not be doing that where a term is expected.

It was actually getting itself confused, and trying to parse the
argument list as a statement.

Setting PL_expect after force_next is ineffectual, as force_next
records the current value of PL_expect, arranging to have it
restored.

OPERATOR(USE) was setting PL_expect, but too late.  So no we set
PL_expect explicitly in S_tokenize_use, before any forced tokens,
and use TOKEN(USE), which does not set PL_expect (as setting it
there has no effect).

t/comp/use.t
toke.c

index 25e2a96..12409cf 100644 (file)
@@ -6,7 +6,7 @@ BEGIN {
     $INC{"feature.pm"} = 1; # so we don't attempt to load feature.pm
 }
 
-print "1..83\n";
+print "1..84\n";
 
 # Can't require test.pl, as we're testing the use/require mechanism here.
 
@@ -167,6 +167,9 @@ ok $@, 'no strict vars allows ver decl to enable subs';
 
 { use test_use }       # check that subparse saves pending tokens
 
+use test_use { () };
+is ref $test_use::got[0], 'HASH', 'use parses arguments in term lexing cx';
+
 local $test_use::VERSION = 1.0;
 
 eval "use test_use 0.9";
diff --git a/toke.c b/toke.c
index c65aecf..9deac94 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -4318,6 +4318,7 @@ S_tokenize_use(pTHX_ int is_use, char *s) {
     if (PL_expect != XSTATE)
        yyerror(Perl_form(aTHX_ "\"%s\" not allowed in expression",
                    is_use ? "use" : "no"));
+    PL_expect = XTERM;
     s = SKIPSPACE1(s);
     if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) {
        s = force_version(s, TRUE);
@@ -7751,7 +7752,7 @@ Perl_yylex(pTHX)
 
        case KEY_no:
            s = tokenize_use(0, s);
-           OPERATOR(USE);
+           TERM(USE);
 
        case KEY_not:
            if (*s == '(' || (s = SKIPSPACE1(s), *s == '('))