1: <?php declare(strict_types=1);
2:
3: namespace PhpParser\Node\Scalar;
4:
5: use PhpParser\Node\Scalar;
6:
7: class Float_ extends Scalar {
8: /** @var float Number value */
9: public float $value;
10:
11: /**
12: * Constructs a float number scalar node.
13: *
14: * @param float $value Value of the number
15: * @param array<string, mixed> $attributes Additional attributes
16: */
17: public function __construct(float $value, array $attributes = []) {
18: $this->attributes = $attributes;
19: $this->value = $value;
20: }
21:
22: public function getSubNodeNames(): array {
23: return ['value'];
24: }
25:
26: /**
27: * @param mixed[] $attributes
28: */
29: public static function fromString(string $str, array $attributes = []): Float_ {
30: $attributes['rawValue'] = $str;
31: $float = self::parse($str);
32:
33: return new Float_($float, $attributes);
34: }
35:
36: /**
37: * @internal
38: *
39: * Parses a DNUMBER token like PHP would.
40: *
41: * @param string $str A string number
42: *
43: * @return float The parsed number
44: */
45: public static function parse(string $str): float {
46: $str = str_replace('_', '', $str);
47:
48: // Check whether this is one of the special integer notations.
49: if ('0' === $str[0]) {
50: // hex
51: if ('x' === $str[1] || 'X' === $str[1]) {
52: return hexdec($str);
53: }
54:
55: // bin
56: if ('b' === $str[1] || 'B' === $str[1]) {
57: return bindec($str);
58: }
59:
60: // oct, but only if the string does not contain any of '.eE'.
61: if (false === strpbrk($str, '.eE')) {
62: // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit
63: // (8 or 9) so that only the digits before that are used.
64: return octdec(substr($str, 0, strcspn($str, '89')));
65: }
66: }
67:
68: // dec
69: return (float) $str;
70: }
71:
72: public function getType(): string {
73: return 'Scalar_Float';
74: }
75: }
76:
77: // @deprecated compatibility alias
78: class_alias(Float_::class, DNumber::class);
79: