Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

why does 'print ("hey)")' give a warning?

by lanzz (Acolyte)
on Jul 09, 2001 at 10:50 UTC ( [id://94916]=perlquestion: print w/replies, xml ) Need Help??

lanzz has asked for the wisdom of the Perl Monks concerning the following question:

this code gives a warning:
use warnings; print ("hey)");
while this one does NOT:
use warnings; print ("hey");
since when a closing parenthesis is a special symbol inside a string?

Replies are listed 'Best First'.
Re: why does 'print ("hey)")' give a warning?
by chipmunk (Parson) on Jul 09, 2001 at 18:58 UTC
    This a bug in toke.c, in the following code:
    STATIC void S_checkcomma(pTHX_ register char *s, char *name, char *what) { char *w; if (*s == ' ' && s[1] == '(') { /* XXX gotta be a better way * +/ if (ckWARN(WARN_SYNTAX)) { int level = 1; for (w = s+2; *w && level; w++) { if (*w == '(') ++level; else if (*w == ')') --level; } if (*w) for (; *w && isSPACE(*w); w++) ; if (!*w || !strchr(";|})]oaiuw!=", *w)) /* an advisory + hack only... */ Perl_warner(aTHX_ WARN_SYNTAX, "%s (...) interpreted as function",name); } } # [the S_checkcomma function continues from here with an unrelated + syntax check]

     

    Here's the code again, this time with comments interspersed:
    STATIC void S_checkcomma(pTHX_ register char *s, char *name, char *what) { char *w; if (*s == ' ' && s[1] == '(') { /* XXX gotta be a better way * +/
    When this function is called, the tokenizer has just grabbed the name of a function. If the current character is a space, and the next character is an open paren, then we'll do the following...         if (ckWARN(WARN_SYNTAX)) { (...but only if syntax warnings are turned on...)
    int level = 1; for (w = s+2; *w && level; w++) { if (*w == '(') ++level; else if (*w == ')') --level; }
    That for loop should be familiar to many programmers. It's simply counting open and close parens. The conditional, *w && level, will cause the loop to exit either at the end of the line (when *w is null) or when the matching close paren for the first open paren is found (level is 0). However, note that the loop ignores anything that isn't a paren.
    if (*w) for (; *w && isSPACE(*w); w++) ;
    This extra loop just skips any whitespace after that last closing paren.             if (!*w || !strchr(";|})]oaiuw!=", *w))     /* an advisory hack only... */ Now, if we're at the end of the line (*w is null) or the current character is not one of ;|})]oaiuw!=, then the warning in question is produced:
    Perl_warner(aTHX_ WARN_SYNTAX, "%s (...) interpreted as function",name); } }
    Remember the part about the counting of parens ignoring anything that isn't a paren? So, in print ("hey)");, this bit of toke.c thinks that the first close paren is the matching paren, even though that paren is inside a string. The character after that paren is a double quote, which is not in that set of acceptable characters, and so the warning is produced.

    This suggests some other interesting snippets:

    print (/\)/); # warning print (/./); # no warning print ("hey))"); # no warning print ("hey")&&1; # warning print ("hey")||1; # no warning

    As the comment says, there's "gotta be a better way". :)

    To avoid this warning, you could remove the space before the open paren, add a plus before the open paren, or remove the parens entirely if they're unneeded.

    By the way, you're probably wondering why the set of characters ;|})]oaiuw!= is special. Frankly, I just don't know!

      By the way, you're probably wondering why the set of characters ;|})]oaiuw!= is special. Frankly, I just don't know!

      They are most of the characters that can end an expression:

      or and if unless while
      And, as you spotted, & is valid but missing.

      -- iakobski

        And so is f for for.

        -- Abigail

Re: why does 'print ("hey)")' give a warning?
by CharlesClarkson (Curate) on Jul 09, 2001 at 12:20 UTC
    Because there is a space between print and ("hey)").
    Try these:
    print("hey)"); print "hey)"; print 'hey)';

    HTH,
    Charles K. Clarkson
Re: why does 'print ("hey)")' give a warning?
by PetaMem (Priest) on Jul 09, 2001 at 14:01 UTC
    BTW:

    is "use warning" the same like #!/usr/bin/perl -w

    ???

    Ciao

      use warnings; is only available on Perl 5.6.0 on up. -w works on all platforms (unix/win/mac/etc) with a Perl that supports warnings because the /perl executable looks for shebang line options regardless of whether the that platform actually uses the shebang line per se to target the perl exe. So to make your code backwards compatible with the still extremely common perl 5.5 use -w. You will find more discussion of this here use warnings vs. perl -w

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Take a look at perllexwarn (Perl Lexical Warnings) for way too much detail on the differences between use warnings;, -w, and $^W.

      HTH,
      Charles K. Clarkson
      Same idea, but better. You can enable or disable specific warnings, define your own in your modules, and scope the settings. It doesn't set the same variable that -w does, BTW, if you code is looking at that.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://94916]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (7)
As of 2024-03-29 09:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found