1: | <?php declare(strict_types=1); |
2: | |
3: | namespace PhpParser\Lexer\TokenEmulator; |
4: | |
5: | abstract class KeywordEmulator extends TokenEmulator |
6: | { |
7: | abstract function getKeywordString(): string; |
8: | abstract function getKeywordToken(): int; |
9: | |
10: | public function isEmulationNeeded(string $code): bool |
11: | { |
12: | return strpos(strtolower($code), $this->getKeywordString()) !== false; |
13: | } |
14: | |
15: | protected function isKeywordContext(array $tokens, int $pos): bool |
16: | { |
17: | $previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $pos); |
18: | return $previousNonSpaceToken === null || $previousNonSpaceToken[0] !== \T_OBJECT_OPERATOR; |
19: | } |
20: | |
21: | public function emulate(string $code, array $tokens): array |
22: | { |
23: | $keywordString = $this->getKeywordString(); |
24: | foreach ($tokens as $i => $token) { |
25: | if ($token[0] === T_STRING && strtolower($token[1]) === $keywordString |
26: | && $this->isKeywordContext($tokens, $i)) { |
27: | $tokens[$i][0] = $this->getKeywordToken(); |
28: | } |
29: | } |
30: | |
31: | return $tokens; |
32: | } |
33: | |
34: | |
35: | |
36: | |
37: | |
38: | private function getPreviousNonSpaceToken(array $tokens, int $start) |
39: | { |
40: | for ($i = $start - 1; $i >= 0; --$i) { |
41: | if ($tokens[$i][0] === T_WHITESPACE) { |
42: | continue; |
43: | } |
44: | |
45: | return $tokens[$i]; |
46: | } |
47: | |
48: | return null; |
49: | } |
50: | |
51: | public function reverseEmulate(string $code, array $tokens): array |
52: | { |
53: | $keywordToken = $this->getKeywordToken(); |
54: | foreach ($tokens as $i => $token) { |
55: | if ($token[0] === $keywordToken) { |
56: | $tokens[$i][0] = \T_STRING; |
57: | } |
58: | } |
59: | |
60: | return $tokens; |
61: | } |
62: | } |
63: | |