1: | <?php declare(strict_types=1); |
2: | |
3: | namespace PhpParser\Lexer\TokenEmulator; |
4: | |
5: | use PhpParser\Lexer\Emulative; |
6: | |
7: | class ExplicitOctalEmulator extends TokenEmulator { |
8: | public function getPhpVersion(): string { |
9: | return Emulative::PHP_8_1; |
10: | } |
11: | |
12: | public function isEmulationNeeded(string $code): bool { |
13: | return strpos($code, '0o') !== false || strpos($code, '0O') !== false; |
14: | } |
15: | |
16: | public function emulate(string $code, array $tokens): array { |
17: | for ($i = 0, $c = count($tokens); $i < $c; ++$i) { |
18: | if ($tokens[$i][0] == \T_LNUMBER && $tokens[$i][1] === '0' && |
19: | isset($tokens[$i + 1]) && $tokens[$i + 1][0] == \T_STRING && |
20: | preg_match('/[oO][0-7]+(?:_[0-7]+)*/', $tokens[$i + 1][1]) |
21: | ) { |
22: | $tokenKind = $this->resolveIntegerOrFloatToken($tokens[$i + 1][1]); |
23: | array_splice($tokens, $i, 2, [ |
24: | [$tokenKind, '0' . $tokens[$i + 1][1], $tokens[$i][2]], |
25: | ]); |
26: | $c--; |
27: | } |
28: | } |
29: | return $tokens; |
30: | } |
31: | |
32: | private function resolveIntegerOrFloatToken(string $str): int |
33: | { |
34: | $str = substr($str, 1); |
35: | $str = str_replace('_', '', $str); |
36: | $num = octdec($str); |
37: | return is_float($num) ? \T_DNUMBER : \T_LNUMBER; |
38: | } |
39: | |
40: | public function reverseEmulate(string $code, array $tokens): array { |
41: | |
42: | return $tokens; |
43: | } |
44: | } |