Skip to content

Commit 1d3e75e

Browse files
committed
S_parse_ident: Apply flag only to first loop iteration
Fixes #23861 This special case of an all numeric identifier doesn't apply to a multi-component package variable. In "Swish::3::", the 3 is not the first component, and so should not be special cased. Therefore turn off the special handling before looping for a subsequent component. In d2a0fb8, I moved some code into a called function, adding a flag for the function to specially treat this case as the caller had done. It was my intent that there be no change in behavior. The called function differs from the original, in that it can loop, gathering each component of a package variable. I overlooked that case, and our test suite lacked a test for this situation. The called function is not an exact fit with what the caller did; hence the new flag. But it had enough overlap that it avoided some duplication of code; and allowed for the caller to be simplified. And there is another case in the caller that repeated nearly duplicate code so that a later commit changed to use this function, further simplifying things.
1 parent 6c69639 commit 1d3e75e

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

t/comp/parser.t

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ BEGIN {
88
chdir 't' if -d 't';
99
}
1010

11-
print "1..191\n";
11+
print "1..192\n";
1212

1313
sub failed {
1414
my ($got, $expected, $name) = @_;
@@ -668,6 +668,11 @@ is $@, "", 'substr keys assignment';
668668
'RT #130815: null pointer deref';
669669
}
670670
671+
{ # GH #23861
672+
eval 'my @foo = keys %SWISH::3::;';
673+
is ($@, "", "Handles all numeric package component after ::");
674+
}
675+
671676
# Add new tests HERE (above this line)
672677
673678
# bug #74022: Loop on characters in \p{OtherIDContinue}

toke.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10557,7 +10557,7 @@ S_parse_ident(pTHX_ const char *s, const char * const s_end,
1055710557
* of ASCII \w characters. As a special case of this, it can
1055810558
* optionally stop parsing at the first non-digit, returning just the
1055910559
* initial digits. */
10560-
const bool stop_at_first_non_digit = flags & STOP_AT_FIRST_NON_DIGIT;
10560+
bool stop_at_first_non_digit = flags & STOP_AT_FIRST_NON_DIGIT;
1056110561

1056210562
/* This type of identifier can be completely prohibited, so that
1056310563
* anything that doesn't match type 1) is not considered to be an
@@ -10657,6 +10657,9 @@ S_parse_ident(pTHX_ const char *s, const char * const s_end,
1065710657
croak(ident_var_zero_multi_digit);
1065810658
}
1065910659

10660+
/* This option only applies to the first component in a
10661+
* multi-component package variable name. So quit the loop before
10662+
* trying to find a package separator */
1066010663
break;
1066110664
}
1066210665
else if (! idfirst_only && isWORDCHAR_A(*s) ) {
@@ -10690,6 +10693,13 @@ S_parse_ident(pTHX_ const char *s, const char * const s_end,
1069010693
*(*d)++ = ':';
1069110694
*(*d)++ = ':';
1069210695
s += (*s == ':') ? 2 : 1;
10696+
10697+
/* This option only applies to the first component in a
10698+
* multi-component package variable name. For example, in
10699+
* "SWISH::3::", the '3' is not the first component, and so the
10700+
* option needs to be turned off before the next loop iteration
10701+
* parses it. */
10702+
stop_at_first_non_digit = false;
1069310703
}
1069410704
else /* None of the above means have come to the end of any
1069510705
identifier*/

0 commit comments

Comments
 (0)