This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
`for my($k, $v) (%hash)` should not be a syntax error
authorNicholas Clark <nick@ccl4.org>
Fri, 15 Oct 2021 19:59:34 +0000 (19:59 +0000)
committerNicholas Clark <nick@ccl4.org>
Tue, 19 Oct 2021 06:09:02 +0000 (06:09 +0000)
commitbd09be5b1b65f68dd41433db47acee101aa69f7b
treeaebeb3770c02120cf13091e7d02e15e6713550e8
parent65b7cc064468ea58fd900e8293dfb0fdd1de8092
`for my($k, $v) (%hash)` should not be a syntax error

No-one had thought to test for this explicitly. After all, both
`for my $foo ...` and `for my$foo ...` are valid syntax, so tweaking the
C lexer code to add an optional '(' should work, surely?

The problem was that, *as was*, the lexer code didn't "accept" those two
syntax variants the way the comments would suggest.

`for my $foo ...` was treated as

1) we saw 'my '
2) we saw the dollar sign
3) success!

but `for my$foo ...` was treated as

0) we didn't see 'my ' or 'our '
1) we saw the literal string 'my' which is valid as a package name
2) we saw the dollar sign
3) success!

ie some sort of mangled variant of `for my Dog $spot ...` without 'my'

*but* as the lexer was happy with what it saw, it returned that the input
stream was valid for a "for" token, and control continues to the grammar.
The grammar, of course, didn't make these mistakes, so parsed everything
properly and built the correct optree.

(And, if presented with `for Dog $spot (...)` the grammar wouldn't match,
so all invalid code was correctly rejected)

However, all this came unstuck with `for my($k` because that didn't
mis-tokenise as some crazy package name 'my(', so it reported a syntax error.

Hence rewrite yyl_foreach() to actually tokenise everything correctly.

"Correctly", to be clear, is bug-for-bug compatible with the current emergent
behaviour for various corner cases for "parses and runs" vs "syntax error".

We don't always report identical error messages for certain syntax errors,
where the precise message reported was itself emergent behaviour from the
bugs in the previous implementation.
t/comp/parser.t
t/comp/parser_run.t
t/op/for-many.t
toke.c