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