Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 33e397b

Browse files
committedMar 6, 2023
Merge remote-tracking branch 'origin/dev'
2 parents 8222962 + fad72c6 commit 33e397b

File tree

12 files changed

+329
-119
lines changed

12 files changed

+329
-119
lines changed
 

‎.github/workflows/branch-validations.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
runs-on: ubuntu-latest
1717
steps:
1818
- uses: actions/checkout@v3
19-
- uses: symfonycorp/security-checker-action@v2
19+
- uses: symfonycorp/security-checker-action@v3
2020

2121
composer:
2222
runs-on: ubuntu-latest
@@ -27,16 +27,19 @@ jobs:
2727
with:
2828
php-version: '8.1'
2929
tools: composer:v2
30+
3031
- name: Composer cache
3132
uses: actions/cache@v2
3233
with:
3334
key: composer-${{ hashFiles('**/composer.lock') }}
3435
path: ${{ github.workspace }}/.cache
36+
3537
- name: Vendor cache
3638
uses: actions/cache@v2
3739
with:
3840
key: vendor-${{ hashFiles('**/composer.lock') }}
3941
path: ${{ github.workspace }}/vendor
42+
4043
- name: Tools cache
4144
uses: actions/cache@v2
4245
with:
@@ -68,16 +71,19 @@ jobs:
6871
with:
6972
php-version: '8.1'
7073
tools: composer:v2
74+
7175
- name: Composer cache
7276
uses: actions/cache@v2
7377
with:
7478
key: composer-${{ hashFiles('**/composer.lock') }}
7579
path: ${{ github.workspace }}/.cache
80+
7681
- name: Vendor cache
7782
uses: actions/cache@v2
7883
with:
7984
key: vendor-${{ hashFiles('**/composer.lock') }}
8085
path: ${{ github.workspace }}/vendor
86+
8187
- name: Tools cache
8288
uses: actions/cache@v2
8389
with:

‎composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
],
1313
"require": {
1414
"php": "^8.0",
15-
"ext-mbstring": "*"
15+
"ext-mbstring": "^8.0",
16+
"psr/log": "^2.0 || ^3.0"
1617
},
1718
"require-dev": {
1819
"ergebnis/composer-normalize": "^2.15",

‎composer.lock

Lines changed: 130 additions & 98 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎phpcs.xml.dist

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,10 @@
636636
<severity>5</severity>
637637
</rule>
638638

639+
<rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint">
640+
<exclude-pattern>src/StdoutMessageLogger.php</exclude-pattern>
641+
</rule>
642+
639643
<rule ref="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming.SuperfluousPrefix">
640644
<exclude-pattern>src/Atn/Transitions/AbstractPredicateTransition.php</exclude-pattern>
641645
</rule>

‎phpstan.neon.dist

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,9 @@ parameters:
1616
missingCheckedExceptionInThrows: true
1717
tooWideThrowType: true
1818
ignoreErrors:
19-
-
20-
path: src/Dfa/DFA.php
21-
message: '#^Property Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\:\:\$edges \(SplFixedArray\<Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\>\|null\) does not accept SplFixedArray\<mixed\>.$#'
22-
-
23-
path: src/Atn/ParserATNSimulator.php
24-
message: '#^Property Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\:\:\$edges \(SplFixedArray\<Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\>\|null\) does not accept SplFixedArray\<mixed\>.$#'
2519
-
2620
path: src/Atn/ParserATNSimulator.php
2721
message: '#^Property Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\:\:\$edges \(SplFixedArray\<Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\>\|null\) does not accept non\-empty\-array\<int\<0, max\>, Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\>\|SplFixedArray\<Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\>\.$#'
28-
-
29-
path: src/Atn/LexerATNSimulator.php
30-
message: '#^Property Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\:\:\$edges \(SplFixedArray\<Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\>\|null\) does not accept SplFixedArray\<mixed\>\.$#'
3122
-
3223
path: src/Atn/LexerATNSimulator.php
3324
message: '#^Property Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\:\:\$edges \(SplFixedArray\<Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\>\|null\) does not accept non\-empty\-array\<int\<0, 127\>, Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\>\|SplFixedArray\<Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\>\.$#'

‎src/Atn/ATNConfig.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public function toString(bool $showAlt): string
157157
$buf .= ',[' . $this->context . ']';
158158
}
159159

160-
if ($this->semanticContext->equals(SemanticContext::none())) {
160+
if (!$this->semanticContext->equals(SemanticContext::none())) {
161161
$buf .= ',' . $this->semanticContext;
162162
}
163163

@@ -177,9 +177,9 @@ public function __toString(): string
177177
$this->state,
178178
$this->alt,
179179
$this->context !== null ? ',[' . $this->context . ']' : '',
180-
$this->semanticContext->equals(SemanticContext::none()) ?
181-
',' . $this->semanticContext :
182-
'',
180+
$this->semanticContext->equals(SemanticContext::none())
181+
? ''
182+
: ',' . $this->semanticContext,
183183
$this->reachesIntoOuterContext > 0 ? ',up=' . $this->reachesIntoOuterContext : '',
184184
);
185185
}

‎src/Atn/ParserATNSimulator.php

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Antlr\Antlr4\Runtime\Error\Exceptions\RecognitionException;
2525
use Antlr\Antlr4\Runtime\IntervalSet;
2626
use Antlr\Antlr4\Runtime\IntStream;
27+
use Antlr\Antlr4\Runtime\LoggerProvider;
2728
use Antlr\Antlr4\Runtime\Parser;
2829
use Antlr\Antlr4\Runtime\ParserRuleContext;
2930
use Antlr\Antlr4\Runtime\PredictionContexts\PredictionContext;
@@ -35,6 +36,7 @@
3536
use Antlr\Antlr4\Runtime\Utils\BitSet;
3637
use Antlr\Antlr4\Runtime\Utils\DoubleKeyMap;
3738
use Antlr\Antlr4\Runtime\Utils\Set;
39+
use Psr\Log\LoggerInterface as Logger;
3840

3941
/**
4042
* The embodiment of the adaptive LL(*), ALL(*), parsing strategy.
@@ -231,6 +233,8 @@
231233
*/
232234
final class ParserATNSimulator extends ATNSimulator
233235
{
236+
public static bool $traceAtnSimulation = false;
237+
234238
protected Parser $parser;
235239

236240
/** @var array<DFA> */
@@ -260,6 +264,8 @@ final class ParserATNSimulator extends ATNSimulator
260264

261265
protected ?DFA $dfa = null;
262266

267+
private Logger $logger;
268+
263269
/**
264270
* @param array<DFA> $decisionToDFA
265271
*/
@@ -273,6 +279,7 @@ public function __construct(
273279

274280
$this->parser = $parser;
275281
$this->decisionToDFA = $decisionToDFA;
282+
$this->logger = LoggerProvider::getLogger();
276283
}
277284

278285
public function reset(): void
@@ -296,6 +303,18 @@ public function clearDFA(): void
296303
*/
297304
public function adaptivePredict(TokenStream $input, int $decision, ParserRuleContext $outerContext): int
298305
{
306+
if (self::$traceAtnSimulation) {
307+
$this->logger->debug(
308+
'adaptivePredict decision {decision} exec LA(1)=={token} line {line}:{pos}',
309+
[
310+
'decision' => $decision,
311+
'token' => $this->getTokenName($input->LA(1)),
312+
'line' => $input->LT(1)?->getLine(),
313+
'pos' => $input->LT(1)?->getCharPositionInLine(),
314+
],
315+
);
316+
}
317+
299318
$this->input = $input;
300319
$this->startIndex = $input->getIndex();
301320
$this->outerContext = $outerContext;
@@ -404,6 +423,19 @@ public function execATN(
404423
int $startIndex,
405424
ParserRuleContext $outerContext,
406425
): ?int {
426+
if (self::$traceAtnSimulation) {
427+
$this->logger->debug(
428+
'execATN decision {decision}, DFA state {state}, LA(1)=={token} line {line}:{pos}',
429+
[
430+
'decision' => $dfa->decision,
431+
'state' => $s0->__toString(),
432+
'token' => $this->getTokenName($input->LA(1)),
433+
'line' => $input->LT(1)?->getLine(),
434+
'pos' => $input->LT(1)?->getCharPositionInLine(),
435+
],
436+
);
437+
}
438+
407439
$previousD = $s0;
408440

409441
$t = $input->LA(1);
@@ -655,6 +687,12 @@ protected function execATNWithFullContext(
655687
int $startIndex,
656688
ParserRuleContext $outerContext,
657689
): int {
690+
if (self::$traceAtnSimulation) {
691+
$this->logger->debug('execATNWithFullContext {state}', [
692+
'state' => $s0->__toString(),
693+
]);
694+
}
695+
658696
$fullCtx = true;
659697
$foundExactAmbig = false;
660698
$reach = null;
@@ -890,15 +928,18 @@ protected function computeReachSet(ATNConfigSet $closure, int $t, bool $fullCtx)
890928
* multiple alternatives are viable.*/
891929

892930
if ($skippedStopStates !== null && (!$fullCtx || !PredictionMode::hasConfigInRuleStopState($reach))) {
893-
if (\count($skippedStopStates) === 0) {
894-
throw new \LogicException('Skipped stop states cannot be empty.');
895-
}
896-
897931
foreach ($skippedStopStates as $lValue) {
898932
$reach->add($lValue, $this->mergeCache);
899933
}
900934
}
901935

936+
if (self::$traceAtnSimulation) {
937+
$this->logger->debug('computeReachSet {closure} -> {reach}', [
938+
'closure' => $closure->__toString(),
939+
'reach' => $reach->__toString(),
940+
]);
941+
}
942+
902943
if ($reach->isEmpty()) {
903944
return null;
904945
}
@@ -964,6 +1005,13 @@ protected function computeStartState(ATNState $p, RuleContext $ctx, bool $fullCt
9641005
$initialContext = PredictionContext::fromRuleContext($this->atn, $ctx);
9651006
$configs = new ATNConfigSet($fullCtx);
9661007

1008+
if (self::$traceAtnSimulation) {
1009+
$this->logger->debug('computeStartState from ATN state {state} initialContext={initialContext}', [
1010+
'state' => $p->__toString(),
1011+
'initialContext' => $initialContext->__toString(),
1012+
]);
1013+
}
1014+
9671015
foreach ($p->getTransitions() as $i => $t) {
9681016
$c = new ATNConfig(null, $t->target, $initialContext, null, $i + 1);
9691017
$closureBusy = new Set();
@@ -1464,6 +1512,12 @@ protected function closureCheckingStopState(
14641512
int $depth,
14651513
bool $treatEofAsEpsilon,
14661514
): void {
1515+
if (self::$traceAtnSimulation) {
1516+
$this->logger->debug('closure({config})', [
1517+
'config' => $config->toString(true),
1518+
]);
1519+
}
1520+
14671521
if ($config->state instanceof RuleStopState) {
14681522
// We hit rule end. If we have context info, use it run thru all possible stack tops in ctx
14691523
$context = $config->context;
@@ -2150,6 +2204,12 @@ protected function addDFAState(DFA $dfa, DFAState $D): DFAState
21502204
$existing = $dfa->states->get($D);
21512205

21522206
if ($existing instanceof DFAState) {
2207+
if (self::$traceAtnSimulation) {
2208+
$this->logger->debug('addDFAState {state} exists', [
2209+
'state' => $D->__toString(),
2210+
]);
2211+
}
2212+
21532213
return $existing;
21542214
}
21552215

@@ -2160,6 +2220,12 @@ protected function addDFAState(DFA $dfa, DFAState $D): DFAState
21602220
$D->configs->setReadonly(true);
21612221
}
21622222

2223+
if (self::$traceAtnSimulation) {
2224+
$this->logger->debug('addDFAState new {state}', [
2225+
'state' => $D->__toString(),
2226+
]);
2227+
}
2228+
21632229
$dfa->states->add($D);
21642230

21652231
return $D;

‎src/LoggerProvider.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Antlr\Antlr4\Runtime;
6+
7+
use Psr\Log\LoggerInterface as PsrLogger;
8+
9+
final class LoggerProvider
10+
{
11+
private static ?PsrLogger $logger = null;
12+
13+
public static function setLogger(PsrLogger $logger): void
14+
{
15+
self::$logger = $logger;
16+
}
17+
18+
public static function getLogger(): PsrLogger
19+
{
20+
if (self::$logger === null) {
21+
self::$logger = new StdoutMessageLogger();
22+
}
23+
24+
return self::$logger;
25+
}
26+
}

‎src/PredictionContexts/PredictionContext.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
namespace Antlr\Antlr4\Runtime\PredictionContexts;
66

77
use Antlr\Antlr4\Runtime\Atn\ATN;
8+
use Antlr\Antlr4\Runtime\Atn\ParserATNSimulator;
89
use Antlr\Antlr4\Runtime\Atn\Transitions\RuleTransition;
910
use Antlr\Antlr4\Runtime\Comparison\Hashable;
11+
use Antlr\Antlr4\Runtime\LoggerProvider;
1012
use Antlr\Antlr4\Runtime\RuleContext;
1113
use Antlr\Antlr4\Runtime\Utils\DoubleKeyMap;
1214

@@ -392,12 +394,28 @@ public static function mergeArrays(
392394
$previous = $mergeCache->getByTwoKeys($a, $b);
393395

394396
if ($previous !== null) {
397+
if (ParserATNSimulator::$traceAtnSimulation) {
398+
LoggerProvider::getLogger()
399+
->debug('mergeArrays a={a},b={b} -> previous', [
400+
'a' => $a->__toString(),
401+
'b' => $b->__toString(),
402+
]);
403+
}
404+
395405
return $previous;
396406
}
397407

398408
$previous = $mergeCache->getByTwoKeys($b, $a);
399409

400410
if ($previous !== null) {
411+
if (ParserATNSimulator::$traceAtnSimulation) {
412+
LoggerProvider::getLogger()
413+
->debug('mergeArrays a={a},b={b} -> previous', [
414+
'a' => $a->__toString(),
415+
'b' => $b->__toString(),
416+
]);
417+
}
418+
401419
return $previous;
402420
}
403421
}
@@ -500,6 +518,14 @@ public static function mergeArrays(
500518
$mergeCache->set($a, $b, $a);
501519
}
502520

521+
if (ParserATNSimulator::$traceAtnSimulation) {
522+
LoggerProvider::getLogger()
523+
->debug('mergeArrays a={a},b={b} -> a', [
524+
'a' => $a->__toString(),
525+
'b' => $b->__toString(),
526+
]);
527+
}
528+
503529
return $a;
504530
}
505531

@@ -508,13 +534,30 @@ public static function mergeArrays(
508534
$mergeCache->set($a, $b, $b);
509535
}
510536

537+
if (ParserATNSimulator::$traceAtnSimulation) {
538+
LoggerProvider::getLogger()
539+
->debug('mergeArrays a={a},b={b} -> b', [
540+
'a' => $a->__toString(),
541+
'b' => $b->__toString(),
542+
]);
543+
}
544+
511545
return $b;
512546
}
513547

514548
if ($mergeCache !== null) {
515549
$mergeCache->set($a, $b, $M);
516550
}
517551

552+
if (ParserATNSimulator::$traceAtnSimulation) {
553+
LoggerProvider::getLogger()
554+
->debug('mergeArrays a={a},b={b} -> M', [
555+
'a' => $a->__toString(),
556+
'b' => $b->__toString(),
557+
'M' => $M->__toString(),
558+
]);
559+
}
560+
518561
return $M;
519562
}
520563

‎src/RuntimeMetaData.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ final class RuntimeMetaData
5151
* - suffix is an optional string. When `suffix` is omitted, the `-`
5252
* (hyphen-minus) appearing before it is also omitted.
5353
*/
54-
public const VERSION = '4.11.1';
54+
public const VERSION = '4.12.0';
5555

5656
/**
5757
* Gets the currently executing version of the ANTLR 4 runtime library.

‎src/StdoutMessageLogger.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Antlr\Antlr4\Runtime;
6+
7+
use Psr\Log\AbstractLogger;
8+
use Psr\Log\LoggerInterface as Logger;
9+
10+
final class StdoutMessageLogger extends AbstractLogger implements Logger
11+
{
12+
/**
13+
* @param mixed $level
14+
* @param array<mixed> $context
15+
*/
16+
public function log($level, \Stringable|string $message, array $context = []): void
17+
{
18+
\fwrite(\STDOUT, self::formatMessage($message, $context) . \PHP_EOL);
19+
}
20+
21+
/**
22+
* @param array<string, mixed> $context
23+
*/
24+
private static function formatMessage(\Stringable|string $message, array $context): string
25+
{
26+
$replace = [];
27+
foreach ($context as $key => $val) {
28+
$replace['{' . $key . '}'] = $val;
29+
}
30+
31+
return \strtr((string) $message, $replace);
32+
}
33+
}

‎src/Utils/Pair.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ public function hashCode(): int
3838

3939
public function __toString(): string
4040
{
41-
return \sprintf('%s, %s', (string) $this->a, (string) $this->b);
41+
return \sprintf(
42+
'%s, %s',
43+
$this->a === null
44+
? 'null'
45+
: ($this->a instanceof \Stringable ? (string) $this->a : $this->a::class),
46+
$this->b === null
47+
? 'null'
48+
: ($this->b instanceof \Stringable ? (string) $this->b : $this->b::class),
49+
);
4250
}
4351
}

0 commit comments

Comments
 (0)
Please sign in to comment.