是否有任何可用的解决方案(重新)从Parser Tokens返回的token_get_all
生成PHP代码?其他用于生成PHP代码的解决方案也是受欢迎的,最好使用相关的词法分析器/解析器(如果有的话)。
答案 0 :(得分:2)
来自我的评论:
有没有人看到潜在的问题, 如果我只是写一个大开关 将令牌转换回来的声明 他们的字符串表示(即 T_DO到'do'),映射到 代币,加入空格,寻找 某种PHP代码漂亮的打印 溶液
经过一番研究,我在this问题中找到了一个PHP自制解决方案,它实际上使用了PHP Tokenizer接口,以及一些更易配置的PHP代码格式化工具(但需要如上所述的解决方案) )。
这些可用于快速实现解决方案。当我找到一些时间来烹饪时,我会回到这里。
这是我制作的快速解决方案,我将把它留在这里作为问题的一部分。请注意,它要求您打破PHP_Beautifier类,通过更改私有到 protected 的所有内容(可能不是所有内容,但这更容易),以允许您实际使用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,它允许在PHP_Beautifier使用的相同API下进行相同的微调。课程本身是:
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();
}
}
?>
答案 1 :(得分:2)
在“其他解决方案”类别中,您可以尝试PHP Parser。
解析器将PHP源代码转换为抽象语法树....此外,您可以将语法树转换回PHP代码。
答案 2 :(得分:1)
如果我没有弄错http://pear.php.net/package/PHP_Beautifier使用token_get_all()然后重写流。它使用大量方法(如t_else
和t_close_brace
)输出每个标记。也许你可以为了简单而劫持这个。
答案 3 :(得分:-2)
请参阅我们的PHP Front End。它是一个完整的PHP解析器,自动构建AST,以及一个匹配的prettyprinter,它可以使用原始通信重新生成可编译的PHP代码。 (编辑12/2011: 请参阅此SO答案,了解有关从ASTs中进行漂亮打印所需的更多详细信息,这只是令牌的有组织版本:https://stackoverflow.com/a/5834775/120163)
前端建立在我们的DMS Software Reengineering Toolkit之上,可以分析和转换PHP AST(然后通过prettyprinter代码)。