From 0ef61b49bb787b4da846eb18cda44936e5484ce9 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 3 Jan 2019 08:59:45 +0100 Subject: [PATCH] add float/double/real KIND support to Cast\Double node --- CHANGELOG.md | 5 +++++ grammar/php5.y | 5 ++++- grammar/php7.y | 5 ++++- lib/PhpParser/Node/Expr/Cast/Double.php | 5 +++++ lib/PhpParser/Parser/Php5.php | 4 +++- lib/PhpParser/Parser/Php7.php | 4 +++- lib/PhpParser/ParserAbstract.php | 15 +++++++++++++++ lib/PhpParser/PrettyPrinter/Standard.php | 10 +++++++++- test/PhpParser/ParserTest.php | 4 ++++ test/code/prettyPrinter/expr/operators.test | 8 +++++++- 10 files changed, 59 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 961360f2..751aa567 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Version 4.1.2-dev ----------------- +### Added + +* Added `kind` attribute to `Cast\Double_`, which allows to distinguish between `(float)`, + `(double)` and `(real)`. The form of the cast will be preserved by the pretty printer. (#565) + ### Fixed * Remove assertion when pretty printing anonymous class with a name (#554). diff --git a/grammar/php5.y b/grammar/php5.y index abc5cedf..b81df691 100644 --- a/grammar/php5.y +++ b/grammar/php5.y @@ -628,7 +628,10 @@ expr: | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } - | T_DOUBLE_CAST expr { $$ = Expr\Cast\Double [$2]; } + | T_DOUBLE_CAST expr + { $attrs = attributes(); + $attrs['kind'] = $this->getFloatCastKind($1); + $$ = new Expr\Cast\Double($2, $attrs); } | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } diff --git a/grammar/php7.y b/grammar/php7.y index 681fda0a..0db9ba5f 100644 --- a/grammar/php7.y +++ b/grammar/php7.y @@ -706,7 +706,10 @@ expr: | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } - | T_DOUBLE_CAST expr { $$ = Expr\Cast\Double [$2]; } + | T_DOUBLE_CAST expr + { $attrs = attributes(); + $attrs['kind'] = $this->getFloatCastKind($1); + $$ = new Expr\Cast\Double($2, $attrs); } | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } diff --git a/lib/PhpParser/Node/Expr/Cast/Double.php b/lib/PhpParser/Node/Expr/Cast/Double.php index 0cee5543..891ba5f8 100644 --- a/lib/PhpParser/Node/Expr/Cast/Double.php +++ b/lib/PhpParser/Node/Expr/Cast/Double.php @@ -6,6 +6,11 @@ use PhpParser\Node\Expr\Cast; class Double extends Cast { + // For use in "kind" attribute + const KIND_DOUBLE = 1; // "double" syntax + const KIND_FLOAT = 2; // "float" syntax + const KIND_REAL = 3; // "real" syntax + public function getType() : string { return 'Expr_Cast_Double'; } diff --git a/lib/PhpParser/Parser/Php5.php b/lib/PhpParser/Parser/Php5.php index 4da2dc97..8c94dfc9 100644 --- a/lib/PhpParser/Parser/Php5.php +++ b/lib/PhpParser/Parser/Php5.php @@ -2032,7 +2032,9 @@ class Php5 extends \PhpParser\ParserAbstract $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 361 => function ($stackPos) { - $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]); + $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs); }, 362 => function ($stackPos) { $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); diff --git a/lib/PhpParser/Parser/Php7.php b/lib/PhpParser/Parser/Php7.php index b34ee824..15dfed0d 100644 --- a/lib/PhpParser/Parser/Php7.php +++ b/lib/PhpParser/Parser/Php7.php @@ -2003,7 +2003,9 @@ class Php7 extends \PhpParser\ParserAbstract $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 381 => function ($stackPos) { - $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]); + $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs); }, 382 => function ($stackPos) { $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); diff --git a/lib/PhpParser/ParserAbstract.php b/lib/PhpParser/ParserAbstract.php index 8b7bba83..4d95a6f6 100644 --- a/lib/PhpParser/ParserAbstract.php +++ b/lib/PhpParser/ParserAbstract.php @@ -7,6 +7,7 @@ namespace PhpParser; * turn is based on work by Masato Bito. */ use PhpParser\Node\Expr; +use PhpParser\Node\Expr\Cast\Double; use PhpParser\Node\Name; use PhpParser\Node\Param; use PhpParser\Node\Scalar\Encapsed; @@ -680,6 +681,20 @@ abstract class ParserAbstract implements Parser return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos]; } + protected function getFloatCastKind(string $cast): int + { + $cast = strtolower($cast); + if (strpos($cast, 'float') !== false) { + return Double::KIND_FLOAT; + } + + if (strpos($cast, 'real') !== false) { + return Double::KIND_REAL; + } + + return Double::KIND_DOUBLE; + } + protected function parseLNumber($str, $attributes, $allowInvalidOctal = false) { try { return LNumber::fromString($str, $attributes, $allowInvalidOctal); diff --git a/lib/PhpParser/PrettyPrinter/Standard.php b/lib/PhpParser/PrettyPrinter/Standard.php index 96963307..5e821467 100644 --- a/lib/PhpParser/PrettyPrinter/Standard.php +++ b/lib/PhpParser/PrettyPrinter/Standard.php @@ -435,7 +435,15 @@ class Standard extends PrettyPrinterAbstract } protected function pExpr_Cast_Double(Cast\Double $node) { - return $this->pPrefixOp(Cast\Double::class, '(double) ', $node->expr); + $kind = $node->getAttribute('kind', Cast\Double::KIND_DOUBLE); + if ($kind === Cast\Double::KIND_DOUBLE) { + $cast = '(double)'; + } elseif ($kind === Cast\Double::KIND_FLOAT) { + $cast = '(float)'; + } elseif ($kind === Cast\Double::KIND_REAL) { + $cast = '(real)'; + } + return $this->pPrefixOp(Cast\Double::class, $cast . ' ', $node->expr); } protected function pExpr_Cast_String(Cast\String_ $node) { diff --git a/test/PhpParser/ParserTest.php b/test/PhpParser/ParserTest.php index d31ac6ef..5bbee190 100644 --- a/test/PhpParser/ParserTest.php +++ b/test/PhpParser/ParserTest.php @@ -167,6 +167,10 @@ EOC; ["namespace Foo;", ['kind' => Stmt\Namespace_::KIND_SEMICOLON]], ["namespace Foo {}", ['kind' => Stmt\Namespace_::KIND_BRACED]], ["namespace {}", ['kind' => Stmt\Namespace_::KIND_BRACED]], + ["(float) 5.0", ['kind' => Expr\Cast\Double::KIND_FLOAT]], + ["(double) 5.0", ['kind' => Expr\Cast\Double::KIND_DOUBLE]], + ["(real) 5.0", ['kind' => Expr\Cast\Double::KIND_REAL]], + [" ( REAL ) 5.0", ['kind' => Expr\Cast\Double::KIND_REAL]], ]; } } diff --git a/test/code/prettyPrinter/expr/operators.test b/test/code/prettyPrinter/expr/operators.test index 72b68418..69817690 100644 --- a/test/code/prettyPrinter/expr/operators.test +++ b/test/code/prettyPrinter/expr/operators.test @@ -19,6 +19,9 @@ $a--; (float) $a; (double) $a; (real) $a; +( float) $a; +(double ) $a; +( REAL ) $a; (string) $a; (binary) $a; (array) $a; @@ -87,9 +90,12 @@ $a--; +$a; (int) $a; (int) $a; +(float) $a; (double) $a; +(real) $a; +(float) $a; (double) $a; -(double) $a; +(real) $a; (string) $a; (string) $a; (array) $a;