In perl.git, the branch smoke-me/nicholas/S_scan_ident has been updated <http://perl5.git.perl.org/perl.git/commitdiff/5fd6a1f52e77aaae4c3ed9b44061fca8731d857f?hp=657d1e609c0896b75625a0275d2b5c978675cb04>
- Log ----------------------------------------------------------------- commit 5fd6a1f52e77aaae4c3ed9b44061fca8731d857f Author: Nicholas Clark <[email protected]> Date: Mon Apr 8 16:30:18 2013 +0200 Add comments describing the operation of S_scan_ident(). M toke.c commit c24ff615604e2d55bf75299dced6fd9d857cd178 Author: Nicholas Clark <[email protected]> Date: Mon Apr 8 16:27:19 2013 +0200 More tests for the "Ambiguous use of ... resolved ..." warning S_scan_ident(). In particular, test that the special case for reporting $# as @ works. M t/lib/warnings/toke ----------------------------------------------------------------------- Summary of changes: t/lib/warnings/toke | 15 +++++++++++++++ toke.c | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+), 0 deletions(-) diff --git a/t/lib/warnings/toke b/t/lib/warnings/toke index 5ee3ad5..df2a0b4 100644 --- a/t/lib/warnings/toke +++ b/t/lib/warnings/toke @@ -425,10 +425,25 @@ EXPECT # toke.c use warnings 'ambiguous' ; $a = ${time} ; +$a = @{time} ; +$a = $#{time} ; # This one is special cased in toke.c +$a = %{time} ; +$a = *{time} ; +$a = defined &{time} ; # To avoid calling &::time no warnings 'ambiguous' ; $a = ${time} ; +$a = @{time} ; +$a = $#{time} ; # This one is special cased in toke.c +$a = %{time} ; +$a = *{time} ; +$a = defined &{time} ; # To avoid calling &::time EXPECT Ambiguous use of ${time} resolved to $time at - line 3. +Ambiguous use of @{time} resolved to @time at - line 4. +Ambiguous use of @{time} resolved to @time at - line 5. +Ambiguous use of %{time} resolved to %time at - line 6. +Ambiguous use of *{time} resolved to *time at - line 7. +Ambiguous use of &{time} resolved to &time at - line 8. ######## # toke.c use warnings 'ambiguous' ; diff --git a/toke.c b/toke.c index 275c957..911a223 100644 --- a/toke.c +++ b/toke.c @@ -9285,6 +9285,8 @@ S_scan_ident(pTHX_ char *s, const char *send, char *dest, STRLEN destlen, I32 ck *d = '\0'; d = dest; if (*d) { + /* Either a digit variable, or parse_ident() found an identifier + (anything valid as a bareword), so job done and return. */ if (PL_lex_state != LEX_NORMAL) PL_lex_state = LEX_INTERPENDMAYBE; return s; @@ -9296,8 +9298,12 @@ S_scan_ident(pTHX_ char *s, const char *send, char *dest, STRLEN destlen, I32 ck || s[1] == '{' || strnEQ(s+1,"::",2)) ) { + /* Dereferencing a value in a scalar variable. + The alternatives are different syntaxes for a scalar variable. + Using ' as a leading package separator isn't allowed. :: is. */ return s; } + /* Handle the opening { of @{...}, &{...}, *{...}, %{...}, ${...} */ if (*s == '{') { bracket = s; s++; @@ -9324,20 +9330,29 @@ S_scan_ident(pTHX_ char *s, const char *send, char *dest, STRLEN destlen, I32 ck d[1] = '\0'; } } + /* Convert $^F, ${^F} and the ^F of ${^FOO} to control characters */ if (*d == '^' && *s && isCONTROLVAR(*s)) { *d = toCTRL(*s); s++; } + /* Warn about ambiguous code after unary operators if {...} notation isn't + used. There's no difference in ambiguity; it's merely a heuristic + about when not to warn. */ else if (ck_uni && !bracket) check_uni(); if (bracket) { + /* If we were processing {...} notation then... */ if (isIDFIRST_lazy_if(d,is_utf8)) { + /* if it starts as a valid identifier, assume that it is one. + (the later check for } being at the expected point will trap + cases where this doesn't pan out.) */ d += is_utf8 ? UTF8SKIP(d) : 1; parse_ident(&s, &d, e, 1, is_utf8); *d = '\0'; while (s < send && SPACE_OR_TAB(*s)) s++; if ((*s == '[' || (*s == '{' && strNE(dest, "sub")))) { + /* ${foo[0]} and ${foo{bar}} notation. */ if (ckWARN(WARN_AMBIGUOUS) && keyword(dest, d - dest, 0)) { const char * const brack = (const char *) @@ -9370,6 +9385,8 @@ S_scan_ident(pTHX_ char *s, const char *send, char *dest, STRLEN destlen, I32 ck while (s < send && SPACE_OR_TAB(*s)) s++; + /* Expect to find a closing } after consuming any trailing whitespace. + */ if (*s == '}') { s++; if (PL_lex_state == LEX_INTERPNORMAL && !PL_lex_brackets) { @@ -9392,6 +9409,8 @@ S_scan_ident(pTHX_ char *s, const char *send, char *dest, STRLEN destlen, I32 ck } } else { + /* Didn't find the closing } at the point we expected, so restore + state such that the next thing to process is the opening { and */ s = bracket; /* let the parser handle it */ *dest = '\0'; } -- Perl5 Master Repository
