From b6c791ae8fd9e43572e5c9e7a6f4e64386bc5898 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 10 May 2022 01:25:20 +0300 Subject: [PATCH 1/2] [DNumber] Add 3rd argument raw value to keep original value --- grammar/php5.y | 2 +- grammar/php7.y | 2 +- lib/PhpParser/Node/Scalar/DNumber.php | 13 +++++++---- lib/PhpParser/Parser/Php5.php | 2 +- lib/PhpParser/Parser/Php7.php | 2 +- test/PhpParser/Node/Scalar/DNumberTest.php | 27 ++++++++++++++++++++++ test/PhpParser/NodeAbstractTest.php | 4 +++- 7 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 test/PhpParser/Node/Scalar/DNumberTest.php diff --git a/grammar/php5.y b/grammar/php5.y index f9e7e7dd16..20a7cd5a66 100644 --- a/grammar/php5.y +++ b/grammar/php5.y @@ -793,7 +793,7 @@ ctor_arguments: common_scalar: T_LNUMBER { $$ = $this->parseLNumber($1, attributes(), true); } - | T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; } + | T_DNUMBER { $$ = new Scalar\DNumber(Scalar\DNumber::parse($1), attributes(), $1); } | T_CONSTANT_ENCAPSED_STRING { $attrs = attributes(); $attrs['kind'] = strKind($1); $$ = new Scalar\String_(Scalar\String_::parse($1, false), $attrs); } diff --git a/grammar/php7.y b/grammar/php7.y index eac68d095a..c3112aa8fc 100644 --- a/grammar/php7.y +++ b/grammar/php7.y @@ -1024,7 +1024,7 @@ dereferencable_scalar: scalar: T_LNUMBER { $$ = $this->parseLNumber($1, attributes()); } - | T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; } + | T_DNUMBER { $$ = new Scalar\DNumber(Scalar\DNumber::parse($1), attributes(), $1); } | dereferencable_scalar { $$ = $1; } | constant { $$ = $1; } | class_constant { $$ = $1; } diff --git a/lib/PhpParser/Node/Scalar/DNumber.php b/lib/PhpParser/Node/Scalar/DNumber.php index 29ce0dd401..19b2d17279 100644 --- a/lib/PhpParser/Node/Scalar/DNumber.php +++ b/lib/PhpParser/Node/Scalar/DNumber.php @@ -9,15 +9,20 @@ class DNumber extends Scalar /** @var float Number value */ public $value; + /** @var float|string */ + public $rawValue; + /** * Constructs a float number scalar node. * - * @param float $value Value of the number - * @param array $attributes Additional attributes + * @param float $value Value of the number + * @param array $attributes Additional attributes + * @param string|float|null $rawValue */ - public function __construct(float $value, array $attributes = []) { + public function __construct(float $value, array $attributes = [], $rawValue = null) { $this->attributes = $attributes; $this->value = $value; + $this->rawValue = $rawValue ?? $value; } public function getSubNodeNames() : array { @@ -63,7 +68,7 @@ public static function parse(string $str) : float { // dec return (float) $str; } - + public function getType() : string { return 'Scalar_DNumber'; } diff --git a/lib/PhpParser/Parser/Php5.php b/lib/PhpParser/Parser/Php5.php index c62adfd2ce..4dd145fb37 100644 --- a/lib/PhpParser/Parser/Php5.php +++ b/lib/PhpParser/Parser/Php5.php @@ -2275,7 +2275,7 @@ protected function initReduceCallbacks() { $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, true); }, 434 => function ($stackPos) { - $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos-(1-1)]), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos-(1-1)]), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, $this->semStack[$stackPos-(1-1)]); }, 435 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$stackPos-(1-1)][0] === "'" || ($this->semStack[$stackPos-(1-1)][1] === "'" && ($this->semStack[$stackPos-(1-1)][0] === 'b' || $this->semStack[$stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED); diff --git a/lib/PhpParser/Parser/Php7.php b/lib/PhpParser/Parser/Php7.php index 7a0854b306..739b08d014 100644 --- a/lib/PhpParser/Parser/Php7.php +++ b/lib/PhpParser/Parser/Php7.php @@ -2554,7 +2554,7 @@ protected function initReduceCallbacks() { $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 515 => function ($stackPos) { - $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos-(1-1)]), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos-(1-1)]), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, $this->semStack[$stackPos-(1-1)]); }, 516 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; diff --git a/test/PhpParser/Node/Scalar/DNumberTest.php b/test/PhpParser/Node/Scalar/DNumberTest.php new file mode 100644 index 0000000000..ffb1800993 --- /dev/null +++ b/test/PhpParser/Node/Scalar/DNumberTest.php @@ -0,0 +1,27 @@ +create(ParserFactory::PREFER_PHP7); + $nodes = $parser->parse('assertInstanceOf(Echo_::class, $echo); + + /** @var Echo_ $echo */ + $lLumber = $echo->exprs[0]; + $this->assertInstanceOf(DNumber::class, $lLumber); + + /** @var DNumber $dnumber */ + $this->assertSame(1234.56, $lLumber->value); + $this->assertSame('1_234.56', $lLumber->rawValue); + } +} diff --git a/test/PhpParser/NodeAbstractTest.php b/test/PhpParser/NodeAbstractTest.php index 3553c4c87b..9706e65b25 100644 --- a/test/PhpParser/NodeAbstractTest.php +++ b/test/PhpParser/NodeAbstractTest.php @@ -271,6 +271,7 @@ function functionName(&$a = 0, $b = 1.0) { "default": { "nodeType": "Scalar_DNumber", "value": 1, + "rawValue": "1.0", "attributes": { "startLine": 4, "endLine": 4 @@ -428,7 +429,8 @@ function functionName(&$a = 0, $b = 1.0) { "startLine": 4, "endLine": 4 }, - "value": 1 + "value": 1, + "rawValue": "1.0" }, "flags": 0, "attrGroups": [] From 153fcb011c0b67b2f5c6b6037ff3934b20d0435d Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 12 May 2022 22:49:13 +0200 Subject: [PATCH 2/2] add fromString() method to create DNumber --- grammar/php5.y | 2 +- grammar/php7.y | 2 +- lib/PhpParser/Node/Scalar/DNumber.php | 22 ++++++++++++++-------- lib/PhpParser/Parser/Php5.php | 2 +- lib/PhpParser/Parser/Php7.php | 2 +- test/PhpParser/Node/Scalar/DNumberTest.php | 2 +- test/PhpParser/NodeAbstractTest.php | 10 +++++----- 7 files changed, 24 insertions(+), 18 deletions(-) diff --git a/grammar/php5.y b/grammar/php5.y index 20a7cd5a66..927762b450 100644 --- a/grammar/php5.y +++ b/grammar/php5.y @@ -793,7 +793,7 @@ ctor_arguments: common_scalar: T_LNUMBER { $$ = $this->parseLNumber($1, attributes(), true); } - | T_DNUMBER { $$ = new Scalar\DNumber(Scalar\DNumber::parse($1), attributes(), $1); } + | T_DNUMBER { $$ = Scalar\DNumber::fromString($1, attributes()); } | T_CONSTANT_ENCAPSED_STRING { $attrs = attributes(); $attrs['kind'] = strKind($1); $$ = new Scalar\String_(Scalar\String_::parse($1, false), $attrs); } diff --git a/grammar/php7.y b/grammar/php7.y index c3112aa8fc..379581f6a0 100644 --- a/grammar/php7.y +++ b/grammar/php7.y @@ -1024,7 +1024,7 @@ dereferencable_scalar: scalar: T_LNUMBER { $$ = $this->parseLNumber($1, attributes()); } - | T_DNUMBER { $$ = new Scalar\DNumber(Scalar\DNumber::parse($1), attributes(), $1); } + | T_DNUMBER { $$ = Scalar\DNumber::fromString($1, attributes()); } | dereferencable_scalar { $$ = $1; } | constant { $$ = $1; } | class_constant { $$ = $1; } diff --git a/lib/PhpParser/Node/Scalar/DNumber.php b/lib/PhpParser/Node/Scalar/DNumber.php index 19b2d17279..d4796d65bb 100644 --- a/lib/PhpParser/Node/Scalar/DNumber.php +++ b/lib/PhpParser/Node/Scalar/DNumber.php @@ -9,26 +9,32 @@ class DNumber extends Scalar /** @var float Number value */ public $value; - /** @var float|string */ - public $rawValue; - /** * Constructs a float number scalar node. * - * @param float $value Value of the number - * @param array $attributes Additional attributes - * @param string|float|null $rawValue + * @param float $value Value of the number + * @param array $attributes Additional attributes */ - public function __construct(float $value, array $attributes = [], $rawValue = null) { + public function __construct(float $value, array $attributes = []) { $this->attributes = $attributes; $this->value = $value; - $this->rawValue = $rawValue ?? $value; } public function getSubNodeNames() : array { return ['value']; } + /** + * @param mixed[] $attributes + */ + public static function fromString(string $str, array $attributes = []): DNumber + { + $attributes['rawValue'] = $str; + $float = self::parse($str); + + return new DNumber($float, $attributes); + } + /** * @internal * diff --git a/lib/PhpParser/Parser/Php5.php b/lib/PhpParser/Parser/Php5.php index 4dd145fb37..9ab8d6b9bd 100644 --- a/lib/PhpParser/Parser/Php5.php +++ b/lib/PhpParser/Parser/Php5.php @@ -2275,7 +2275,7 @@ protected function initReduceCallbacks() { $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, true); }, 434 => function ($stackPos) { - $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos-(1-1)]), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, $this->semStack[$stackPos-(1-1)]); + $this->semValue = Scalar\DNumber::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 435 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$stackPos-(1-1)][0] === "'" || ($this->semStack[$stackPos-(1-1)][1] === "'" && ($this->semStack[$stackPos-(1-1)][0] === 'b' || $this->semStack[$stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED); diff --git a/lib/PhpParser/Parser/Php7.php b/lib/PhpParser/Parser/Php7.php index 739b08d014..4eb291ea5f 100644 --- a/lib/PhpParser/Parser/Php7.php +++ b/lib/PhpParser/Parser/Php7.php @@ -2554,7 +2554,7 @@ protected function initReduceCallbacks() { $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 515 => function ($stackPos) { - $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos-(1-1)]), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, $this->semStack[$stackPos-(1-1)]); + $this->semValue = Scalar\DNumber::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 516 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; diff --git a/test/PhpParser/Node/Scalar/DNumberTest.php b/test/PhpParser/Node/Scalar/DNumberTest.php index ffb1800993..b3e7c76a3c 100644 --- a/test/PhpParser/Node/Scalar/DNumberTest.php +++ b/test/PhpParser/Node/Scalar/DNumberTest.php @@ -22,6 +22,6 @@ public function testRawValue() /** @var DNumber $dnumber */ $this->assertSame(1234.56, $lLumber->value); - $this->assertSame('1_234.56', $lLumber->rawValue); + $this->assertSame('1_234.56', $lLumber->getAttribute('rawValue')); } } diff --git a/test/PhpParser/NodeAbstractTest.php b/test/PhpParser/NodeAbstractTest.php index 9706e65b25..2ea13cd3db 100644 --- a/test/PhpParser/NodeAbstractTest.php +++ b/test/PhpParser/NodeAbstractTest.php @@ -271,10 +271,10 @@ function functionName(&$a = 0, $b = 1.0) { "default": { "nodeType": "Scalar_DNumber", "value": 1, - "rawValue": "1.0", "attributes": { "startLine": 4, - "endLine": 4 + "endLine": 4, + "rawValue": "1.0" } }, "flags": 0, @@ -427,10 +427,10 @@ function functionName(&$a = 0, $b = 1.0) { "nodeType": "Scalar_DNumber", "attributes": { "startLine": 4, - "endLine": 4 + "endLine": 4, + "rawValue": "1.0" }, - "value": 1, - "rawValue": "1.0" + "value": 1 }, "flags": 0, "attrGroups": []