Skip to content

Replace Hoa with a regex parser generated by phplrt - #6851

Merged
ondrejmirtes merged 11 commits into
2.3.xfrom
phplrt-regex-parser
Oct 26, 2026
Merged

ondrejmirtes merged 11 commits into
2.3.xfrom
phplrt-regex-parser

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

Removes all hoa/* packages (and the 16 patches for them) that PHPStan used to parse regexes, and replaces them with a parser generated by phplrt.

How it works

  • The grammar is ported to phplrt's format in build/regex-parser/RegexGrammar.pp3 (keeping Hoa's license header). Its reducers build the same tree shape Hoa produced, so RegexGroupParser changes are minimal.
  • make regex-parser installs the phplrt compiler into build/regex-parser/vendor (needs PHP 8.4+) and generates src/Type/Regex/Parser/RegexParser.php. The generated parser is committed and must not be edited by hand.
  • At runtime only ondrejmirtes/phplrt-runtime is needed: a PHP 7.4 compatible fork of the phplrt runtime packages (manual downgrade commit + Rector DOWN_TO_PHP_74), so it works after the PHAR is downgraded.
  • Hoa references are removed from the scoper config, bin/phpstan (autoload files hack) and AutoloadFilesTest. CLAUDE.md documents the regex parser setup.

Verification

Every pattern from the php-src test suite (PHP-8.6 branch) and the PCRE2 test suite was run through real preg_match()/preg_match_all() and compared with the inferred array shape:

  • php-src: 451 patterns, 0 wrong results
  • PCRE2: 6,904 patterns, wrong results went from 66 to 7 (remaining are \E and x-mode comment edge cases)

The follow-up commits fix the shape inference bugs this found. Each comes with regression tests taken from those suites that fail without the fix. Parse trees were also checked to be identical between PHP 8.4 (upstream runtime) and PHP 7.4 (fork + downgraded parser), and identical to Hoa's for all patterns Hoa could parse.

Benchmarks

PHP 8.4, the 3,510 corpus patterns both parsers accept, 5 rounds:

Hoa phplrt
Parse time per pattern 1,218 µs 45 µs (~27× faster)
Peak memory 100 MB 18 MB
PHP 7.4 (fork) – 46 µs

phplrt also parses 191 more of the corpus patterns than Hoa.

The grammar is ported to phplrt's PP3 format in build/regex-parser/RegexGrammar.pp3
and compiled with `make regex-parser` into src/Type/Regex/Parser/RegexParser.php.
The compiler runs on PHP 8.4+ and is not a dependency of PHPStan. The generated
parser only needs the phplrt runtime, provided by ondrejmirtes/phplrt-runtime,
a fork downgraded to PHP 7.4.

The parser builds the same trees Hoa did, so RegexGroupParser and
IgnoredRegexValidator walk them without changes in behaviour.

Amp-Thread-ID: https://ampcode.com/threads/T-01a177b5-960f-71d2-a3e2-fa7649f39d2c
@ondrejmirtes
ondrejmirtes merged commit 035c883 into 2.3.x Oct 26, 2026
1026 of 1029 checks passed
@ondrejmirtes
ondrejmirtes deleted the phplrt-regex-parser branch October 26, 2026 12:53
Comment thread bin/phpstan
Comment on lines -55 to -61
// fix missing key for vendor/hoa/protocol/Wrapper.php
$existingComposerAutoloadFiles = $GLOBALS['__composer_autoload_files'] ?? [];
$GLOBALS['__composer_autoload_files'] = array_merge(
$existingComposerAutoloadFiles,
array_fill_keys(['3e76f7f02b41af8cea96018933f6b7e3'], true),
);

@acrobat acrobat Oct 26, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ondrejmirtes can this actually be removed? As this was added because of autoload error in projects using hoa/protocol phpstan/phpstan#13369

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Entire Hoa library was removed from PHPStan, so yes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants