Skip to content

PHP 8.0+ does no longer accept a comment in the whitespace between ampersand and argument in function signature #10083

Closed

Description

@olleharstedt

Description

The following code:

<?php

function foo(
array
#if __PHP__
&
#endif
$bodies
)
{
}

Resulted in this output:

    Parse error: syntax error, unexpected variable "$bodies" in /in/aq2rT on line 8

    Process exited with code 255.

But I expected this output instead:

<Empty, should compile without syntax error as in PHP 7.4

PHP Version

PHP 8.1 and above, works fine in PHP 7.4

Operating System

No response

Activity

  1. iluuu1994 commented on Dec 11, 2022

    @iluuu1994
    Member

    This is expected and caused by some parser/tokenizer hackery for intersection types that was necessary to avoid ambiguity. See 069a9fa.

  2. olleharstedt commented on Dec 11, 2022

    @olleharstedt
    Author

    Won't fix = impossible to fix?

  3. iluuu1994 commented on Dec 11, 2022

    @iluuu1994
    Member

    Yes 🙂

  4. olleharstedt commented on Dec 11, 2022

    @olleharstedt
    Author

    😢

  5. iluuu1994 commented on Dec 11, 2022

    @iluuu1994
    Member

    I think in theory we could adjust the tokens so that variables are assumed after & /* comment */ instead of intersection types, but one case will always not work.

  6. olleharstedt commented on Dec 11, 2022

    @olleharstedt
    Author

    Are comments part of the token stream? That's the problem? Because whitespace and newline works fine.

  7. iluuu1994 commented on Dec 11, 2022

    @iluuu1994
    Member

    No. The problem is that the grammar is ambiguous. Our LR(1) parser only gets one token of lookahead, but code like function foo(Foo |& Bar $param) { (| denoting the current position) requires multiple tokens of lookahead to understand if this is a param by reference (Foo &$param) or an intersection type. We avoid this ambiguity by creating different tokens for & depending on what follows, but this has limitations in that comments will influence tokenization.

    <ST_IN_SCRIPTING>"&"[ \t\r\n]*("$"|"...") {
    yyless(1);
    RETURN_TOKEN(T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG);
    }
    <ST_IN_SCRIPTING>"&" {
    RETURN_TOKEN(T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG);
    }

  8. olleharstedt commented on Dec 11, 2022

    @olleharstedt
    Author

    Ah ok. But expanding <ST_IN_SCRIPTING>"&"[ \t\r\n]*("$"|"...") { to also eat comments could fix it? If that's possible during lexing. But maybe not good for lexing performance. Or possible only eat the single-line comments # and //.

  9. 5 remaining items

  10. olleharstedt commented on Dec 11, 2022

    @olleharstedt
    Author

    Yep, can do, thanks!

  11. Danack commented on Dec 11, 2022

    @Danack
    Contributor

    To be clear, this appears to have been found during someone doing code-golf. It doesn't appear to affect an in production codebase.

  12. olleharstedt commented on Dec 11, 2022

    @olleharstedt
    Author
    <ST_IN_SCRIPTING>"&"([ \t\r\n]|("#".*"\n")|("//".*"\n")|("/*".*"*/"))*("$"|"...") {
    

    Possibly this. But does not match newlines inside /* */ comments. :/

  13. iluuu1994 commented on Dec 12, 2022

    @iluuu1994
    Member

    Attempted fix #10084 showed this doesn't seem feasible for now.

  14. cmb69 commented on Dec 12, 2022

    @cmb69
    Member

    I agree that we shouldn't try to fix this with more regexps; in the long run, we might consider using a GLP parser. Still, it may make sense to document the current restriction.

  15. iluuu1994 commented on Dec 18, 2022

    @iluuu1994
    Member

    Reopening as it looks like there's a viable solution after all. See GH-10125.

  16. derickr commented on Feb 8, 2023

    @derickr
    Member

    This seems to break installs with re2c 0.15.3, which the date/time parser still uses. The source code also defines the minimum as 0.13.4 which is also broken. It looks like re2c 1.0.3 (which is what my release VM insisted on) does work.

    I can't find in the GIT repo or mailing list history why the date/time parser (which we commit) couldn't deal with a later version. I think we should change the minimum in PHP to 1.0.3 (like the release images do) and I will also start using that for timelib's parser.

    I've made a PR to add that check: #10542

  17. added a commit that references this issue on Jul 8, 2026
    f291d37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions