Add common KeywordEmulator

The logic for keyword emulation is always going to be the same.
This commit is contained in:
Nikita Popov 2020-08-01 22:02:52 +02:00
parent 7b2ec6703f
commit 3698f4b727
3 changed files with 61 additions and 67 deletions

View File

@ -4,48 +4,20 @@ namespace PhpParser\Lexer\TokenEmulator;
use PhpParser\Lexer\Emulative;
final class FnTokenEmulator implements TokenEmulatorInterface
final class FnTokenEmulator extends KeywordEmulator
{
public function getPhpVersion(): string
{
return Emulative::PHP_7_4;
}
public function isEmulationNeeded(string $code): bool
public function getKeywordString(): string
{
return strpos($code, 'fn') !== false;
return 'fn';
}
public function emulate(string $code, array $tokens): array
public function getKeywordToken(): int
{
foreach ($tokens as $i => $token) {
if ($token[0] === T_STRING && strtolower($token[1]) === 'fn') {
$previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $i);
if ($previousNonSpaceToken !== null && $previousNonSpaceToken[0] === T_OBJECT_OPERATOR) {
continue;
}
$tokens[$i][0] = Emulative::T_FN;
}
}
return $tokens;
return Emulative::T_FN;
}
/**
* @param mixed[] $tokens
* @return mixed[]|null
*/
private function getPreviousNonSpaceToken(array $tokens, int $start)
{
for ($i = $start - 1; $i >= 0; --$i) {
if ($tokens[$i][0] === T_WHITESPACE) {
continue;
}
return $tokens[$i];
}
return null;
}
}
}

View File

@ -0,0 +1,50 @@
<?php declare(strict_types=1);
namespace PhpParser\Lexer\TokenEmulator;
use PhpParser\Lexer\Emulative;
abstract class KeywordEmulator implements TokenEmulatorInterface
{
abstract function getKeywordString(): string;
abstract function getKeywordToken(): int;
public function isEmulationNeeded(string $code): bool
{
return strpos($code, $this->getKeywordString()) !== false;
}
public function emulate(string $code, array $tokens): array
{
$keywordString = $this->getKeywordString();
foreach ($tokens as $i => $token) {
if ($token[0] === T_STRING && strtolower($token[1]) === $keywordString) {
$previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $i);
if ($previousNonSpaceToken !== null && $previousNonSpaceToken[0] === T_OBJECT_OPERATOR) {
continue;
}
$tokens[$i][0] = $this->getKeywordToken();
}
}
return $tokens;
}
/**
* @param mixed[] $tokens
* @return mixed[]|null
*/
private function getPreviousNonSpaceToken(array $tokens, int $start)
{
for ($i = $start - 1; $i >= 0; --$i) {
if ($tokens[$i][0] === T_WHITESPACE) {
continue;
}
return $tokens[$i];
}
return null;
}
}

View File

@ -4,48 +4,20 @@ namespace PhpParser\Lexer\TokenEmulator;
use PhpParser\Lexer\Emulative;
final class MatchTokenEmulator implements TokenEmulatorInterface
final class MatchTokenEmulator extends KeywordEmulator
{
public function getPhpVersion(): string
{
return Emulative::PHP_8_0;
}
public function isEmulationNeeded(string $code): bool
public function getKeywordString(): string
{
return strpos($code, 'match') !== false;
return 'match';
}
public function emulate(string $code, array $tokens): array
public function getKeywordToken(): int
{
foreach ($tokens as $i => $token) {
if ($token[0] === T_STRING && strtolower($token[1]) === 'match') {
$previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $i);
if ($previousNonSpaceToken !== null && $previousNonSpaceToken[0] === T_OBJECT_OPERATOR) {
continue;
}
$tokens[$i][0] = Emulative::T_MATCH;
}
}
return $tokens;
}
/**
* @param mixed[] $tokens
* @return mixed[]|null
*/
private function getPreviousNonSpaceToken(array $tokens, int $start)
{
for ($i = $start - 1; $i >= 0; --$i) {
if ($tokens[$i][0] === T_WHITESPACE) {
continue;
}
return $tokens[$i];
}
return null;
return Emulative::T_MATCH;
}
}