Avoid cyclic reference in parser

Pass $this as an explicit $self argument to the reduce callbacks,
so we can make them static. This avoids a circular reference in
the parser, so that it can be immediately destroyed when it goes
out of scope.

Fixes #980.
This commit is contained in:
Nikita Popov 2024-02-21 21:11:36 +01:00
parent 2218c2252c
commit af14fdb282
5 changed files with 1869 additions and 1868 deletions

View File

@ -1,7 +1,7 @@
<?php declare(strict_types=1);
$meta #
#semval($) $this->semValue
#semval($,%t) $this->semValue
#semval($) $self->semValue
#semval($,%t) $self->semValue
#semval(%n) $stackPos-(%l-%n)
#semval(%n,%t) $stackPos-(%l-%n)
@ -97,7 +97,7 @@ class #(-p) extends \PhpParser\ParserAbstract
protected function initReduceCallbacks(): void {
$this->reduceCallbacks = [
#reduce
%n => function ($stackPos) {
%n => static function ($self, $stackPos) {
%b
},
#noact

View File

@ -23,6 +23,7 @@ function preprocessGrammar($code) {
$code = resolveNodes($code);
$code = resolveMacros($code);
$code = resolveStackAccess($code);
$code = str_replace('$this', '$self', $code);
return $code;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -318,7 +318,7 @@ abstract class ParserAbstract implements Parser {
try {
$callback = $this->reduceCallbacks[$rule];
if ($callback !== null) {
$callback($stackPos);
$callback($this, $stackPos);
} elseif ($ruleLength > 0) {
$this->semValue = $this->semStack[$stackPos - $ruleLength + 1];
}