diff --git a/src/Node/DelimitedList/DeclareDirectiveList.php b/src/Node/DelimitedList/DeclareDirectiveList.php new file mode 100644 index 00000000..a88b7331 --- /dev/null +++ b/src/Node/DelimitedList/DeclareDirectiveList.php @@ -0,0 +1,12 @@ +parent = $parentNode; $declareStatement->declareKeyword = $this->eat1(TokenKind::DeclareKeyword); $declareStatement->openParen = $this->eat1(TokenKind::OpenParenToken); - $declareStatement->declareDirective = $this->parseDeclareDirective($declareStatement); + $this->parseAndSetDeclareDirectiveList($declareStatement); $declareStatement->closeParen = $this->eat1(TokenKind::CloseParenToken); if ($this->checkToken(TokenKind::SemicolonToken)) { @@ -2325,26 +2325,76 @@ private function parseDeclareStatement($parentNode) { return $declareStatement; } - private function parseDeclareDirective($parentNode) { - $declareDirective = new DeclareDirective(); + /** + * @param DeclareStatement $parentNode + */ + private function parseAndSetDeclareDirectiveList($parentNode) { + $declareDirectiveList = $this->parseDeclareDirectiveList($parentNode); + + if (!$declareDirectiveList) { + $declareDirective = new DeclareDirective(); + $declareDirective->parent = $parentNode; + + $declareDirective->name = new MissingToken(TokenKind::Name, $this->token->fullStart); + $declareDirective->equals = new MissingToken(TokenKind::EqualsToken, $this->token->fullStart); + // TODO: This is matching the first token in $this::parseDeclareDirectiveFn. + // Probably best to emit a more general "literal error". + $declareDirective->literal = new MissingToken(TokenKind::FloatingLiteralToken, $this->token->fullStart); + + $parentNode->declareDirective = $declareDirective; + return; + } + + $declareDirective = array_shift($declareDirectiveList->children); + $parentNode->declareDirective = $declareDirective; $declareDirective->parent = $parentNode; - $declareDirective->name = $this->eat1(TokenKind::Name); - $declareDirective->equals = $this->eat1(TokenKind::EqualsToken); - $declareDirective->literal = - $this->eat( - TokenKind::FloatingLiteralToken, - TokenKind::IntegerLiteralToken, - TokenKind::DecimalLiteralToken, - TokenKind::OctalLiteralToken, - TokenKind::HexadecimalLiteralToken, - TokenKind::BinaryLiteralToken, - TokenKind::InvalidOctalLiteralToken, - TokenKind::InvalidHexadecimalLiteral, - TokenKind::InvalidBinaryLiteral, - TokenKind::StringLiteralToken - ); // TODO simplify - - return $declareDirective; + + if ($declareDirectiveList->children) { + $parentNode->otherDeclareDirectives = $declareDirectiveList; + } + } + + /** + * @param DeclareStatement $parentNode + * @return DelimitedList\DeclareDirectiveList|null + */ + private function parseDeclareDirectiveList($parentNode) { + $declareDirectiveList = $this->parseDelimitedList( + DelimitedList\DeclareDirectiveList::class, + TokenKind::CommaToken, + function ($token) { + return $token->kind === TokenKind::Name; + }, + $this->parseDeclareDirectiveFn(), + $parentNode, + false + ); + + return $declareDirectiveList; + } + + private function parseDeclareDirectiveFn() { + return function ($parentNode) { + $declareDirective = new DeclareDirective(); + $declareDirective->parent = $parentNode; + $declareDirective->name = $this->eat1(TokenKind::Name); + $declareDirective->equals = $this->eat1(TokenKind::EqualsToken); + $declareDirective->literal = + $this->eat( + TokenKind::FloatingLiteralToken, + TokenKind::IntegerLiteralToken, + TokenKind::DecimalLiteralToken, + TokenKind::OctalLiteralToken, + TokenKind::HexadecimalLiteralToken, + TokenKind::BinaryLiteralToken, + TokenKind::InvalidOctalLiteralToken, + TokenKind::InvalidHexadecimalLiteral, + TokenKind::InvalidBinaryLiteral, + TokenKind::StringLiteralToken + ); // TODO simplify + + return $declareDirective; + }; } private function parseSimpleVariable($parentNode) { diff --git a/tests/ParserGrammarTest.php b/tests/ParserGrammarTest.php index 6fff0c25..32fa8cf3 100644 --- a/tests/ParserGrammarTest.php +++ b/tests/ParserGrammarTest.php @@ -4,7 +4,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -use Microsoft\PhpParser\Token; use Microsoft\PhpParser\DiagnosticsProvider; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestCase; @@ -123,7 +122,7 @@ public function testSpecOutputTreeClassificationAndLength($testCaseFile, $expect } public function outTreeProvider() { - $testCases = glob(__dir__ . "/cases/php-langspec/**/*.php"); + $testCases = glob(__DIR__ . "/cases/php-langspec/**/*.php"); $skipped = json_decode(file_get_contents(__DIR__ . "/skipped.json")); $testProviderArray = array(); diff --git a/tests/cases/parser/declareStatement1.php.tree b/tests/cases/parser/declareStatement1.php.tree index 866cb590..f991f2f1 100644 --- a/tests/cases/parser/declareStatement1.php.tree +++ b/tests/cases/parser/declareStatement1.php.tree @@ -37,6 +37,7 @@ } } }, + "otherDeclareDirectives": null, "closeParen": { "kind": "CloseParenToken", "textLength": 1 diff --git a/tests/cases/parser/declareStatement10.php.tree b/tests/cases/parser/declareStatement10.php.tree index d5efa715..2bece8e3 100644 --- a/tests/cases/parser/declareStatement10.php.tree +++ b/tests/cases/parser/declareStatement10.php.tree @@ -37,6 +37,7 @@ } } }, + "otherDeclareDirectives": null, "closeParen": { "kind": "CloseParenToken", "textLength": 1 diff --git a/tests/cases/parser/declareStatement11.php.tree b/tests/cases/parser/declareStatement11.php.tree index 4ed0df10..8cbbd70f 100644 --- a/tests/cases/parser/declareStatement11.php.tree +++ b/tests/cases/parser/declareStatement11.php.tree @@ -37,6 +37,7 @@ } } }, + "otherDeclareDirectives": null, "closeParen": { "kind": "CloseParenToken", "textLength": 1 diff --git a/tests/cases/parser/declareStatement12.php.tree b/tests/cases/parser/declareStatement12.php.tree index c03f2936..b958b359 100644 --- a/tests/cases/parser/declareStatement12.php.tree +++ b/tests/cases/parser/declareStatement12.php.tree @@ -40,6 +40,7 @@ } } }, + "otherDeclareDirectives": null, "closeParen": { "kind": "CloseParenToken", "textLength": 1 diff --git a/tests/cases/parser/declareStatement13.php.tree b/tests/cases/parser/declareStatement13.php.tree index 9eefc85b..70b508d7 100644 --- a/tests/cases/parser/declareStatement13.php.tree +++ b/tests/cases/parser/declareStatement13.php.tree @@ -37,6 +37,7 @@ } } }, + "otherDeclareDirectives": null, "closeParen": { "kind": "CloseParenToken", "textLength": 1 diff --git a/tests/cases/parser/declareStatement14.php b/tests/cases/parser/declareStatement14.php new file mode 100644 index 00000000..f1c5bf99 --- /dev/null +++ b/tests/cases/parser/declareStatement14.php @@ -0,0 +1,3 @@ +