diff --git a/.github/workflows/branch-validations.yaml b/.github/workflows/branch-validations.yaml
index 5d67b20..0406cbb 100644
--- a/.github/workflows/branch-validations.yaml
+++ b/.github/workflows/branch-validations.yaml
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- - uses: symfonycorp/security-checker-action@v2
+ - uses: symfonycorp/security-checker-action@v3
composer:
runs-on: ubuntu-latest
@@ -27,16 +27,19 @@ jobs:
with:
php-version: '8.1'
tools: composer:v2
+
- name: Composer cache
uses: actions/cache@v2
with:
key: composer-${{ hashFiles('**/composer.lock') }}
path: ${{ github.workspace }}/.cache
+
- name: Vendor cache
uses: actions/cache@v2
with:
key: vendor-${{ hashFiles('**/composer.lock') }}
path: ${{ github.workspace }}/vendor
+
- name: Tools cache
uses: actions/cache@v2
with:
@@ -68,16 +71,19 @@ jobs:
with:
php-version: '8.1'
tools: composer:v2
+
- name: Composer cache
uses: actions/cache@v2
with:
key: composer-${{ hashFiles('**/composer.lock') }}
path: ${{ github.workspace }}/.cache
+
- name: Vendor cache
uses: actions/cache@v2
with:
key: vendor-${{ hashFiles('**/composer.lock') }}
path: ${{ github.workspace }}/vendor
+
- name: Tools cache
uses: actions/cache@v2
with:
diff --git a/composer.json b/composer.json
index 66160e1..5160d18 100644
--- a/composer.json
+++ b/composer.json
@@ -12,7 +12,8 @@
],
"require": {
"php": "^8.0",
- "ext-mbstring": "*"
+ "ext-mbstring": "^8.0",
+ "psr/log": "^2.0 || ^3.0"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.15",
diff --git a/composer.lock b/composer.lock
index 43b0285..ec737fb 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,59 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "c9bd0e80e7e22f425eb286b5c42b5f54",
- "packages": [],
+ "content-hash": "6d73951acc3119aabd404dbbe0967053",
+ "packages": [
+ {
+ "name": "psr/log",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.0"
+ },
+ "time": "2021-07-14T16:46:02+00:00"
+ }
+ ],
"packages-dev": [
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
@@ -84,35 +135,35 @@
},
{
"name": "ergebnis/composer-normalize",
- "version": "2.24.0",
+ "version": "2.28.3",
"source": {
"type": "git",
"url": "https://github.com/ergebnis/composer-normalize.git",
- "reference": "0492b8de602ac601f5d53a5ef9c9558701a18f31"
+ "reference": "ec75a2bf751f6fec165e9ea0262655b8ca397e5c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/0492b8de602ac601f5d53a5ef9c9558701a18f31",
- "reference": "0492b8de602ac601f5d53a5ef9c9558701a18f31",
+ "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/ec75a2bf751f6fec165e9ea0262655b8ca397e5c",
+ "reference": "ec75a2bf751f6fec165e9ea0262655b8ca397e5c",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.0.0",
"ergebnis/json-normalizer": "~2.1.0",
"ergebnis/json-printer": "^3.2.0",
- "justinrainbow/json-schema": "^5.2.11",
+ "justinrainbow/json-schema": "^5.2.12",
"localheinz/diff": "^1.1.1",
"php": "^7.4 || ^8.0"
},
"require-dev": {
- "composer/composer": "^2.2.5",
+ "composer/composer": "^2.3.9",
"ergebnis/license": "^1.2.0",
- "ergebnis/php-cs-fixer-config": "^3.4.0",
+ "ergebnis/php-cs-fixer-config": "^4.4.0",
"fakerphp/faker": "^1.19.0",
- "phpunit/phpunit": "^9.5.17",
- "psalm/plugin-phpunit": "~0.16.1",
- "symfony/filesystem": "^5.4.6",
- "vimeo/psalm": "^4.22.0"
+ "phpunit/phpunit": "^9.5.21",
+ "psalm/plugin-phpunit": "~0.17.0",
+ "symfony/filesystem": "^5.4.9",
+ "vimeo/psalm": "^4.24.0"
},
"type": "composer-plugin",
"extra": {
@@ -149,13 +200,7 @@
"issues": "https://github.com/ergebnis/composer-normalize/issues",
"source": "https://github.com/ergebnis/composer-normalize"
},
- "funding": [
- {
- "url": "https://github.com/localheinz",
- "type": "github"
- }
- ],
- "time": "2022-03-09T08:15:05+00:00"
+ "time": "2022-07-05T16:09:10+00:00"
},
{
"name": "ergebnis/json-normalizer",
@@ -358,16 +403,16 @@
},
{
"name": "justinrainbow/json-schema",
- "version": "5.2.11",
+ "version": "5.2.12",
"source": {
"type": "git",
"url": "https://github.com/justinrainbow/json-schema.git",
- "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa"
+ "reference": "ad87d5a5ca981228e0e205c2bc7dfb8e24559b60"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2ab6744b7296ded80f8cc4f9509abbff393399aa",
- "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa",
+ "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/ad87d5a5ca981228e0e205c2bc7dfb8e24559b60",
+ "reference": "ad87d5a5ca981228e0e205c2bc7dfb8e24559b60",
"shasum": ""
},
"require": {
@@ -422,9 +467,9 @@
],
"support": {
"issues": "https://github.com/justinrainbow/json-schema/issues",
- "source": "https://github.com/justinrainbow/json-schema/tree/5.2.11"
+ "source": "https://github.com/justinrainbow/json-schema/tree/5.2.12"
},
- "time": "2021-07-22T09:24:00+00:00"
+ "time": "2022-04-13T08:02:27+00:00"
},
{
"name": "localheinz/diff",
@@ -488,28 +533,27 @@
},
{
"name": "phpstan/extension-installer",
- "version": "1.1.0",
+ "version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/extension-installer.git",
- "reference": "66c7adc9dfa38b6b5838a9fb728b68a7d8348051"
+ "reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/66c7adc9dfa38b6b5838a9fb728b68a7d8348051",
- "reference": "66c7adc9dfa38b6b5838a9fb728b68a7d8348051",
+ "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
+ "reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
"shasum": ""
},
"require": {
- "composer-plugin-api": "^1.1 || ^2.0",
- "php": "^7.1 || ^8.0",
- "phpstan/phpstan": ">=0.11.6"
+ "composer-plugin-api": "^2.0",
+ "php": "^7.2 || ^8.0",
+ "phpstan/phpstan": "^1.8.0"
},
"require-dev": {
- "composer/composer": "^1.8",
- "phing/phing": "^2.16.3",
+ "composer/composer": "^2.0",
"php-parallel-lint/php-parallel-lint": "^1.2.0",
- "phpstan/phpstan-strict-rules": "^0.11 || ^0.12"
+ "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0"
},
"type": "composer-plugin",
"extra": {
@@ -527,41 +571,37 @@
"description": "Composer plugin for automatic installation of PHPStan extensions",
"support": {
"issues": "https://github.com/phpstan/extension-installer/issues",
- "source": "https://github.com/phpstan/extension-installer/tree/1.1.0"
+ "source": "https://github.com/phpstan/extension-installer/tree/1.2.0"
},
- "time": "2020-12-13T13:06:13+00:00"
+ "time": "2022-10-17T12:59:16+00:00"
},
{
"name": "phpstan/phpdoc-parser",
- "version": "1.2.0",
+ "version": "1.13.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
- "reference": "dbc093d7af60eff5cd575d2ed761b15ed40bd08e"
+ "reference": "aac44118344d197e6d5f7c6cee91885f0a89acdd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/dbc093d7af60eff5cd575d2ed761b15ed40bd08e",
- "reference": "dbc093d7af60eff5cd575d2ed761b15ed40bd08e",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/aac44118344d197e6d5f7c6cee91885f0a89acdd",
+ "reference": "aac44118344d197e6d5f7c6cee91885f0a89acdd",
"shasum": ""
},
"require": {
- "php": "^7.1 || ^8.0"
+ "php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "^1.0",
+ "phpstan/phpstan": "^1.5",
+ "phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0-dev"
- }
- },
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
@@ -576,26 +616,26 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
- "source": "https://github.com/phpstan/phpdoc-parser/tree/1.2.0"
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/1.13.1"
},
- "time": "2021-09-16T20:46:02+00:00"
+ "time": "2022-11-20T08:52:26+00:00"
},
{
"name": "phpstan/phpstan",
- "version": "1.4.9",
+ "version": "1.9.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "1a45f44d319cf000a8c960af6b7435741e944771"
+ "reference": "d6fdf01c53978b6429f1393ba4afeca39cc68afa"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/1a45f44d319cf000a8c960af6b7435741e944771",
- "reference": "1a45f44d319cf000a8c960af6b7435741e944771",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/d6fdf01c53978b6429f1393ba4afeca39cc68afa",
+ "reference": "d6fdf01c53978b6429f1393ba4afeca39cc68afa",
"shasum": ""
},
"require": {
- "php": "^7.1|^8.0"
+ "php": "^7.2|^8.0"
},
"conflict": {
"phpstan/phpstan-shim": "*"
@@ -605,11 +645,6 @@
"phpstan.phar"
],
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.4-dev"
- }
- },
"autoload": {
"files": [
"bootstrap.php"
@@ -620,9 +655,13 @@
"MIT"
],
"description": "PHPStan - PHP Static Analysis Tool",
+ "keywords": [
+ "dev",
+ "static analysis"
+ ],
"support": {
"issues": "https://github.com/phpstan/phpstan/issues",
- "source": "https://github.com/phpstan/phpstan/tree/1.4.9"
+ "source": "https://github.com/phpstan/phpstan/tree/1.9.2"
},
"funding": [
{
@@ -633,16 +672,12 @@
"url": "https://github.com/phpstan",
"type": "github"
},
- {
- "url": "https://www.patreon.com/phpstan",
- "type": "patreon"
- },
{
"url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
"type": "tidelift"
}
],
- "time": "2022-03-10T08:52:08+00:00"
+ "time": "2022-11-10T09:56:11+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
@@ -696,21 +731,21 @@
},
{
"name": "phpstan/phpstan-strict-rules",
- "version": "1.1.0",
+ "version": "1.4.4",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
- "reference": "e12d55f74a8cca18c6e684c6450767e055ba7717"
+ "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/e12d55f74a8cca18c6e684c6450767e055ba7717",
- "reference": "e12d55f74a8cca18c6e684c6450767e055ba7717",
+ "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6",
+ "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6",
"shasum": ""
},
"require": {
- "php": "^7.1 || ^8.0",
- "phpstan/phpstan": "^1.2.0"
+ "php": "^7.2 || ^8.0",
+ "phpstan/phpstan": "^1.8.6"
},
"require-dev": {
"nikic/php-parser": "^4.13.0",
@@ -720,9 +755,6 @@
},
"type": "phpstan-extension",
"extra": {
- "branch-alias": {
- "dev-master": "1.0-dev"
- },
"phpstan": {
"includes": [
"rules.neon"
@@ -741,38 +773,38 @@
"description": "Extra strict and opinionated rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
- "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.1.0"
+ "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.4"
},
- "time": "2021-11-18T09:30:29+00:00"
+ "time": "2022-09-21T11:38:17+00:00"
},
{
"name": "slevomat/coding-standard",
- "version": "7.0.19",
+ "version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
- "reference": "bef66a43815bbf9b5f49775e9ded3f7c6ba0cc37"
+ "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/bef66a43815bbf9b5f49775e9ded3f7c6ba0cc37",
- "reference": "bef66a43815bbf9b5f49775e9ded3f7c6ba0cc37",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
+ "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
- "php": "^7.1 || ^8.0",
- "phpstan/phpdoc-parser": "^1.0.0",
+ "php": "^7.2 || ^8.0",
+ "phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
- "phing/phing": "2.17.2",
+ "phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
- "phpstan/phpstan": "1.4.6",
+ "phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
- "phpstan/phpstan-phpunit": "1.0.0",
- "phpstan/phpstan-strict-rules": "1.1.0",
- "phpunit/phpunit": "7.5.20|8.5.21|9.5.16"
+ "phpstan/phpstan-phpunit": "1.0.0|1.1.1",
+ "phpstan/phpstan-strict-rules": "1.2.3",
+ "phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
@@ -792,7 +824,7 @@
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
- "source": "https://github.com/slevomat/coding-standard/tree/7.0.19"
+ "source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
@@ -804,20 +836,20 @@
"type": "tidelift"
}
],
- "time": "2022-03-01T18:01:41+00:00"
+ "time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.6.2",
+ "version": "3.7.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
+ "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
- "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
+ "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
"shasum": ""
},
"require": {
@@ -860,7 +892,7 @@
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
- "time": "2021-12-12T21:44:58+00:00"
+ "time": "2022-06-18T07:21:10+00:00"
}
],
"aliases": [],
@@ -870,8 +902,8 @@
"prefer-lowest": false,
"platform": {
"php": "^8.0",
- "ext-mbstring": "*"
+ "ext-mbstring": "^8.0"
},
"platform-dev": [],
- "plugin-api-version": "2.2.0"
+ "plugin-api-version": "2.3.0"
}
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index bf40ce2..fe0b85e 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -636,6 +636,10 @@
5
+
+ src/StdoutMessageLogger.php
+
+
src/Atn/Transitions/AbstractPredicateTransition.php
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index e4ce2f4..0c0bb88 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -16,18 +16,9 @@ parameters:
missingCheckedExceptionInThrows: true
tooWideThrowType: true
ignoreErrors:
- -
- path: src/Dfa/DFA.php
- message: '#^Property Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\:\:\$edges \(SplFixedArray\\|null\) does not accept SplFixedArray\.$#'
- -
- path: src/Atn/ParserATNSimulator.php
- message: '#^Property Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\:\:\$edges \(SplFixedArray\\|null\) does not accept SplFixedArray\.$#'
-
path: src/Atn/ParserATNSimulator.php
message: '#^Property Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\:\:\$edges \(SplFixedArray\\|null\) does not accept non\-empty\-array\, Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\>\|SplFixedArray\\.$#'
- -
- path: src/Atn/LexerATNSimulator.php
- message: '#^Property Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\:\:\$edges \(SplFixedArray\\|null\) does not accept SplFixedArray\\.$#'
-
path: src/Atn/LexerATNSimulator.php
message: '#^Property Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\:\:\$edges \(SplFixedArray\\|null\) does not accept non\-empty\-array\, Antlr\\Antlr4\\Runtime\\Dfa\\DFAState\>\|SplFixedArray\\.$#'
\ No newline at end of file
diff --git a/src/Atn/ATNConfig.php b/src/Atn/ATNConfig.php
index 425b9b0..7e9c9b9 100644
--- a/src/Atn/ATNConfig.php
+++ b/src/Atn/ATNConfig.php
@@ -157,7 +157,7 @@ public function toString(bool $showAlt): string
$buf .= ',[' . $this->context . ']';
}
- if ($this->semanticContext->equals(SemanticContext::none())) {
+ if (!$this->semanticContext->equals(SemanticContext::none())) {
$buf .= ',' . $this->semanticContext;
}
@@ -177,9 +177,9 @@ public function __toString(): string
$this->state,
$this->alt,
$this->context !== null ? ',[' . $this->context . ']' : '',
- $this->semanticContext->equals(SemanticContext::none()) ?
- ',' . $this->semanticContext :
- '',
+ $this->semanticContext->equals(SemanticContext::none())
+ ? ''
+ : ',' . $this->semanticContext,
$this->reachesIntoOuterContext > 0 ? ',up=' . $this->reachesIntoOuterContext : '',
);
}
diff --git a/src/Atn/ParserATNSimulator.php b/src/Atn/ParserATNSimulator.php
index 36c31a4..57fb55a 100644
--- a/src/Atn/ParserATNSimulator.php
+++ b/src/Atn/ParserATNSimulator.php
@@ -24,6 +24,7 @@
use Antlr\Antlr4\Runtime\Error\Exceptions\RecognitionException;
use Antlr\Antlr4\Runtime\IntervalSet;
use Antlr\Antlr4\Runtime\IntStream;
+use Antlr\Antlr4\Runtime\LoggerProvider;
use Antlr\Antlr4\Runtime\Parser;
use Antlr\Antlr4\Runtime\ParserRuleContext;
use Antlr\Antlr4\Runtime\PredictionContexts\PredictionContext;
@@ -35,6 +36,7 @@
use Antlr\Antlr4\Runtime\Utils\BitSet;
use Antlr\Antlr4\Runtime\Utils\DoubleKeyMap;
use Antlr\Antlr4\Runtime\Utils\Set;
+use Psr\Log\LoggerInterface as Logger;
/**
* The embodiment of the adaptive LL(*), ALL(*), parsing strategy.
@@ -231,6 +233,8 @@
*/
final class ParserATNSimulator extends ATNSimulator
{
+ public static bool $traceAtnSimulation = false;
+
protected Parser $parser;
/** @var array */
@@ -260,6 +264,8 @@ final class ParserATNSimulator extends ATNSimulator
protected ?DFA $dfa = null;
+ private Logger $logger;
+
/**
* @param array $decisionToDFA
*/
@@ -273,6 +279,7 @@ public function __construct(
$this->parser = $parser;
$this->decisionToDFA = $decisionToDFA;
+ $this->logger = LoggerProvider::getLogger();
}
public function reset(): void
@@ -296,6 +303,18 @@ public function clearDFA(): void
*/
public function adaptivePredict(TokenStream $input, int $decision, ParserRuleContext $outerContext): int
{
+ if (self::$traceAtnSimulation) {
+ $this->logger->debug(
+ 'adaptivePredict decision {decision} exec LA(1)=={token} line {line}:{pos}',
+ [
+ 'decision' => $decision,
+ 'token' => $this->getTokenName($input->LA(1)),
+ 'line' => $input->LT(1)?->getLine(),
+ 'pos' => $input->LT(1)?->getCharPositionInLine(),
+ ],
+ );
+ }
+
$this->input = $input;
$this->startIndex = $input->getIndex();
$this->outerContext = $outerContext;
@@ -404,6 +423,19 @@ public function execATN(
int $startIndex,
ParserRuleContext $outerContext,
): ?int {
+ if (self::$traceAtnSimulation) {
+ $this->logger->debug(
+ 'execATN decision {decision}, DFA state {state}, LA(1)=={token} line {line}:{pos}',
+ [
+ 'decision' => $dfa->decision,
+ 'state' => $s0->__toString(),
+ 'token' => $this->getTokenName($input->LA(1)),
+ 'line' => $input->LT(1)?->getLine(),
+ 'pos' => $input->LT(1)?->getCharPositionInLine(),
+ ],
+ );
+ }
+
$previousD = $s0;
$t = $input->LA(1);
@@ -655,6 +687,12 @@ protected function execATNWithFullContext(
int $startIndex,
ParserRuleContext $outerContext,
): int {
+ if (self::$traceAtnSimulation) {
+ $this->logger->debug('execATNWithFullContext {state}', [
+ 'state' => $s0->__toString(),
+ ]);
+ }
+
$fullCtx = true;
$foundExactAmbig = false;
$reach = null;
@@ -890,15 +928,18 @@ protected function computeReachSet(ATNConfigSet $closure, int $t, bool $fullCtx)
* multiple alternatives are viable.*/
if ($skippedStopStates !== null && (!$fullCtx || !PredictionMode::hasConfigInRuleStopState($reach))) {
- if (\count($skippedStopStates) === 0) {
- throw new \LogicException('Skipped stop states cannot be empty.');
- }
-
foreach ($skippedStopStates as $lValue) {
$reach->add($lValue, $this->mergeCache);
}
}
+ if (self::$traceAtnSimulation) {
+ $this->logger->debug('computeReachSet {closure} -> {reach}', [
+ 'closure' => $closure->__toString(),
+ 'reach' => $reach->__toString(),
+ ]);
+ }
+
if ($reach->isEmpty()) {
return null;
}
@@ -964,6 +1005,13 @@ protected function computeStartState(ATNState $p, RuleContext $ctx, bool $fullCt
$initialContext = PredictionContext::fromRuleContext($this->atn, $ctx);
$configs = new ATNConfigSet($fullCtx);
+ if (self::$traceAtnSimulation) {
+ $this->logger->debug('computeStartState from ATN state {state} initialContext={initialContext}', [
+ 'state' => $p->__toString(),
+ 'initialContext' => $initialContext->__toString(),
+ ]);
+ }
+
foreach ($p->getTransitions() as $i => $t) {
$c = new ATNConfig(null, $t->target, $initialContext, null, $i + 1);
$closureBusy = new Set();
@@ -1464,6 +1512,12 @@ protected function closureCheckingStopState(
int $depth,
bool $treatEofAsEpsilon,
): void {
+ if (self::$traceAtnSimulation) {
+ $this->logger->debug('closure({config})', [
+ 'config' => $config->toString(true),
+ ]);
+ }
+
if ($config->state instanceof RuleStopState) {
// We hit rule end. If we have context info, use it run thru all possible stack tops in ctx
$context = $config->context;
@@ -2150,6 +2204,12 @@ protected function addDFAState(DFA $dfa, DFAState $D): DFAState
$existing = $dfa->states->get($D);
if ($existing instanceof DFAState) {
+ if (self::$traceAtnSimulation) {
+ $this->logger->debug('addDFAState {state} exists', [
+ 'state' => $D->__toString(),
+ ]);
+ }
+
return $existing;
}
@@ -2160,6 +2220,12 @@ protected function addDFAState(DFA $dfa, DFAState $D): DFAState
$D->configs->setReadonly(true);
}
+ if (self::$traceAtnSimulation) {
+ $this->logger->debug('addDFAState new {state}', [
+ 'state' => $D->__toString(),
+ ]);
+ }
+
$dfa->states->add($D);
return $D;
diff --git a/src/LoggerProvider.php b/src/LoggerProvider.php
new file mode 100644
index 0000000..5bb5cd1
--- /dev/null
+++ b/src/LoggerProvider.php
@@ -0,0 +1,26 @@
+getByTwoKeys($a, $b);
if ($previous !== null) {
+ if (ParserATNSimulator::$traceAtnSimulation) {
+ LoggerProvider::getLogger()
+ ->debug('mergeArrays a={a},b={b} -> previous', [
+ 'a' => $a->__toString(),
+ 'b' => $b->__toString(),
+ ]);
+ }
+
return $previous;
}
$previous = $mergeCache->getByTwoKeys($b, $a);
if ($previous !== null) {
+ if (ParserATNSimulator::$traceAtnSimulation) {
+ LoggerProvider::getLogger()
+ ->debug('mergeArrays a={a},b={b} -> previous', [
+ 'a' => $a->__toString(),
+ 'b' => $b->__toString(),
+ ]);
+ }
+
return $previous;
}
}
@@ -500,6 +518,14 @@ public static function mergeArrays(
$mergeCache->set($a, $b, $a);
}
+ if (ParserATNSimulator::$traceAtnSimulation) {
+ LoggerProvider::getLogger()
+ ->debug('mergeArrays a={a},b={b} -> a', [
+ 'a' => $a->__toString(),
+ 'b' => $b->__toString(),
+ ]);
+ }
+
return $a;
}
@@ -508,6 +534,14 @@ public static function mergeArrays(
$mergeCache->set($a, $b, $b);
}
+ if (ParserATNSimulator::$traceAtnSimulation) {
+ LoggerProvider::getLogger()
+ ->debug('mergeArrays a={a},b={b} -> b', [
+ 'a' => $a->__toString(),
+ 'b' => $b->__toString(),
+ ]);
+ }
+
return $b;
}
@@ -515,6 +549,15 @@ public static function mergeArrays(
$mergeCache->set($a, $b, $M);
}
+ if (ParserATNSimulator::$traceAtnSimulation) {
+ LoggerProvider::getLogger()
+ ->debug('mergeArrays a={a},b={b} -> M', [
+ 'a' => $a->__toString(),
+ 'b' => $b->__toString(),
+ 'M' => $M->__toString(),
+ ]);
+ }
+
return $M;
}
diff --git a/src/RuntimeMetaData.php b/src/RuntimeMetaData.php
index 58db9a1..cad69b6 100644
--- a/src/RuntimeMetaData.php
+++ b/src/RuntimeMetaData.php
@@ -51,7 +51,7 @@ final class RuntimeMetaData
* - suffix is an optional string. When `suffix` is omitted, the `-`
* (hyphen-minus) appearing before it is also omitted.
*/
- public const VERSION = '4.11.1';
+ public const VERSION = '4.12.0';
/**
* Gets the currently executing version of the ANTLR 4 runtime library.
diff --git a/src/StdoutMessageLogger.php b/src/StdoutMessageLogger.php
new file mode 100644
index 0000000..58d2af4
--- /dev/null
+++ b/src/StdoutMessageLogger.php
@@ -0,0 +1,33 @@
+ $context
+ */
+ public function log($level, \Stringable|string $message, array $context = []): void
+ {
+ \fwrite(\STDOUT, self::formatMessage($message, $context) . \PHP_EOL);
+ }
+
+ /**
+ * @param array $context
+ */
+ private static function formatMessage(\Stringable|string $message, array $context): string
+ {
+ $replace = [];
+ foreach ($context as $key => $val) {
+ $replace['{' . $key . '}'] = $val;
+ }
+
+ return \strtr((string) $message, $replace);
+ }
+}
diff --git a/src/Utils/Pair.php b/src/Utils/Pair.php
index fc80417..3a3c5a3 100644
--- a/src/Utils/Pair.php
+++ b/src/Utils/Pair.php
@@ -38,6 +38,14 @@ public function hashCode(): int
public function __toString(): string
{
- return \sprintf('%s, %s', (string) $this->a, (string) $this->b);
+ return \sprintf(
+ '%s, %s',
+ $this->a === null
+ ? 'null'
+ : ($this->a instanceof \Stringable ? (string) $this->a : $this->a::class),
+ $this->b === null
+ ? 'null'
+ : ($this->b instanceof \Stringable ? (string) $this->b : $this->b::class),
+ );
}
}