1<?php declare(strict_types=1); 2 3namespace PhpParser\Lexer\TokenEmulator; 4 5abstract 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 public function emulate(string $code, array $tokens): array 16 { 17 $keywordString = $this->getKeywordString(); 18 foreach ($tokens as $i => $token) { 19 if ($token[0] === T_STRING && strtolower($token[1]) === $keywordString) { 20 $previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $i); 21 if ($previousNonSpaceToken !== null && $previousNonSpaceToken[0] === \T_OBJECT_OPERATOR) { 22 continue; 23 } 24 25 $tokens[$i][0] = $this->getKeywordToken(); 26 } 27 } 28 29 return $tokens; 30 } 31 32 /** 33 * @param mixed[] $tokens 34 * @return mixed[]|null 35 */ 36 private function getPreviousNonSpaceToken(array $tokens, int $start) 37 { 38 for ($i = $start - 1; $i >= 0; --$i) { 39 if ($tokens[$i][0] === T_WHITESPACE) { 40 continue; 41 } 42 43 return $tokens[$i]; 44 } 45 46 return null; 47 } 48 49 public function reverseEmulate(string $code, array $tokens): array 50 { 51 $keywordToken = $this->getKeywordToken(); 52 foreach ($tokens as $i => $token) { 53 if ($token[0] === $keywordToken) { 54 $tokens[$i][0] = \T_STRING; 55 } 56 } 57 58 return $tokens; 59 } 60} 61