Из моего комментария:
Кто-нибудь видит потенциальную проблему,
если я просто напишу большой переключатель
заявление для преобразования токенов обратно в
их строковые представления (т.е.
T_DO, чтобы 'сделать'), сопоставьте это с
токены, соединяйте пробелы и ищите
какой-то PHP-код довольно-печатный
решение?
После некоторых поисков я нашел в этом вопросе самодельное решение PHP, которое на самом деле использует интерфейс PHP Tokenizer, а также некоторые инструменты форматирования кода PHP, которые являются более настраиваемыми (но требуют решения как описано выше).
Они могут быть использованы для быстрой реализации решения. Я отправлю сюда, когда найду время, чтобы приготовить это.
Решение с PHP_Beautifier
Это быстрое решение, которое я приготовил, я оставлю его здесь как часть вопроса. Обратите внимание, что он требует от вас открыть класс PHP_Beautifier, изменив все (возможно, не все, но это проще), то есть приватный на защищенный , чтобы вы могли фактически использовать внутренняя работа PHP_Beautifier (в противном случае было бы невозможно повторно использовать функциональные возможности PHP_Beautifier без повторной реализации половины их кода).
Пример использования класса:
file: main.php
<?php
// read some PHP code (the file itself will do)
$phpCode = file_get_contents(__FILE__);
// create a new instance of PHP2PHP
$php2php = new PHP2PHP();
// tokenize the code (forwards to token_get_all)
$phpCode = $php2php->php2token($phpCode);
// print the tokens, in some way
echo join(' ', array_map(function($token) {
return (is_array($token))
? ($token[0] === T_WHITESPACE)
? ($token[1] === "\n")
? "\n"
: ''
: token_name($token[0])
: $token;
}, $phpCode));
// transform the tokens back into legible PHP code
$phpCode = $php2php->token2php($phpCode);
?>
Поскольку PHP2PHP расширяет PHP_Beautifier, он допускает ту же тонкую настройку под тем же API, который использует PHP_Beautifier. Сам класс:
file: PHP2PHP.php
class PHP2PHP extends PHP_Beautifier {
function php2token($phpCode) {
return token_get_all($phpCode);
}
function token2php(array $phpToken) {
// prepare properties
$this->resetProperties();
$this->aTokens = $phpToken;
$iTotal = count($this->aTokens);
$iPrevAssoc = false;
// send a signal to the filter, announcing the init of the processing of a file
foreach($this->aFilters as $oFilter)
$oFilter->preProcess();
for ($this->iCount = 0;
$this->iCount < $iTotal;
$this->iCount++) {
$aCurrentToken = $this->aTokens[$this->iCount];
if (is_string($aCurrentToken))
$aCurrentToken = array(
0 => $aCurrentToken,
1 => $aCurrentToken
);
// ArrayNested->off();
$sTextLog = PHP_Beautifier_Common::wsToString($aCurrentToken[1]);
// ArrayNested->on();
$sTokenName = (is_numeric($aCurrentToken[0])) ? token_name($aCurrentToken[0]) : '';
$this->oLog->log("Token:" . $sTokenName . "[" . $sTextLog . "]", PEAR_LOG_DEBUG);
$this->controlToken($aCurrentToken);
$iFirstOut = count($this->aOut); //5
$bError = false;
$this->aCurrentToken = $aCurrentToken;
if ($this->bBeautify) {
foreach($this->aFilters as $oFilter) {
$bError = true;
if ($oFilter->handleToken($this->aCurrentToken) !== FALSE) {
$this->oLog->log('Filter:' . $oFilter->getName() , PEAR_LOG_DEBUG);
$bError = false;
break;
}
}
} else {
$this->add($aCurrentToken[1]);
}
$this->controlTokenPost($aCurrentToken);
$iLastOut = count($this->aOut);
// set the assoc
if (($iLastOut-$iFirstOut) > 0) {
$this->aAssocs[$this->iCount] = array(
'offset' => $iFirstOut
);
if ($iPrevAssoc !== FALSE)
$this->aAssocs[$iPrevAssoc]['length'] = $iFirstOut-$this->aAssocs[$iPrevAssoc]['offset'];
$iPrevAssoc = $this->iCount;
}
if ($bError)
throw new Exception("Can'process token: " . var_dump($aCurrentToken));
} // ~for
// generate the last assoc
if (count($this->aOut) == 0)
throw new Exception("Nothing on output!");
$this->aAssocs[$iPrevAssoc]['length'] = (count($this->aOut) -1) - $this->aAssocs[$iPrevAssoc]['offset'];
// post-processing
foreach($this->aFilters as $oFilter)
$oFilter->postProcess();
return $this->get();
}
}
?>