in reply to why does 'print ("hey)")' give a warning?
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:
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...)STATIC void S_checkcomma(pTHX_ register char *s, char *name, char *what) { char *w; if (*s == ' ' && s[1] == '(') { /* XXX gotta be a better way * +/
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.int level = 1; for (w = s+2; *w && level; w++) { if (*w == '(') ++level; else if (*w == ')') --level; }
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:if (*w) for (; *w && isSPACE(*w); w++) ;
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.Perl_warner(aTHX_ WARN_SYNTAX, "%s (...) interpreted as function",name); } }
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!
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Re: why does 'print ("hey)")' give a warning?
by iakobski (Pilgrim) on Jul 09, 2001 at 19:13 UTC | |
by Abigail (Deacon) on Jul 10, 2001 at 02:57 UTC |