我应该明确:我不想或不需要一个完整的PHP解析器。只需要知道给定标记是: - PHP代码 - PHP单引号字符串 - PHP双引号字符串 - PHP注释 - 非PHP,而是HTML / JavaScript。
PHP本身内置了tokenizer,它与PHP解释器嵌入在Zend引擎中。使用这些函数,您可以编写自己的PHP源代码分析或修改工具,而无需处理词法级别的语言规范。
您在评论中问是否可以从标记化输出中重新生成代码 - 可以的,所有空格都保留为T_WHITESPACE标记。以下是将标记化输出转换回代码的示例:
$regenerated='';
$tokens = token_get_all($code);
foreach($tokens as $idx=>$t)
{
if (is_array($t))
{
//do something with string and comments here?
switch($t[0])
{
case T_CONSTANT_ENCAPSED_STRING:
break;
case T_COMMENT:
case T_DOC_COMMENT:
break;
}
$regenerated.=$t[1];
}
else
{
$regenerated.=$t;
}
}
为了将PHP与其他内容分离,PHP内置的标记解析器是您最好的选择:请参见token_get_all()
。
对于其他部分,您可能最好使用DOM解析器。以这种方式隔离<script>
部分(以及外部脚本,甚至onXXXX
事件)很容易。
不过,从解析的DOM树中重新构建相同的文档可能会很困难 - 我想这取决于您需要对结果进行什么操作以及原始HTML有多干净。在那部分中,正则表达式(呃!)可能效果更好。
如果你只是想要检查标记,那么像其他人建议的那样,PHP分词器可能是一个不错的选择。
如果你想要以可靠的方式自动更改源代码,我不确定那会对你有所帮助。你将如何重新生成修改后的源文本?
另一种方法是使用程序转换引擎。这样的引擎可以解析源文本为抽象语法树,捕获程序的结构(以及所有标记的有效内容),并允许使用可靠的模式匹配/转换搜索和转换这些AST。要做到这一点,你需要一个能够可靠地解析PHP的引擎,并且能够从更改后的AST中产生可编译的源文本。
我们的DMS软件重构工具包是一个程序转换系统,它拥有一个强大的PHP前端,可以准确地处理PHP5的解析、转换和漂亮地打印回文本。 (正确地获取PHP解析器是很难的,因为该语言文档不完善)。由于前端可以准确地捕捉HTML和PHP代码,您不需要将文本分开;它们将被放置在独特的树节点中,以清晰可辨的方式。
要将所有回显字符串从小写转换为大写,您可以使用DMS解析PHP,然后应用以下转换规则:
rule uppercase_echoed_string(s: STRING): statement -> statement
= "echo \s;" -> "echo \uppercase\(\s\);".
这条规则是用DMS的规则规范语言(RSL)编写的,显然不是PHP。引号内的东西是PHP代码;这些是包裹在被操作的程序语言文本周围的元引号。\字符是一个元转义符:\s表示必须匹配字符串文字的元变量,\uppercase是一个外部于RSL语言的DMS函数名称,( )是元括号,用于将大写应用于已匹配的字符串\s的元函数调用。由于该规则操作AST,因此不会产生混淆;它不会更改/* echo 'def' */的文本,因为那不是语句。
您可能需要几条规则来处理各种语法组合:在这种情况下,STRING仅指单引号的文字字符串;双引号字符串不是整体实体,而是由一系列与双引号字符串内的PHP表达式对应的QUOTED_STRING_FRAGMENTS组成的文本。
在转换过程结束时,更改后的AST将以原始缩进和注释的形式发出,除了应用变换的地方。
对于DMS来说,还有一个完全准确的JavaScript解析器,如果您想要准确地处理SCRIPT标签的内容,那么您就需要它。
如果您想要对源代码进行可靠的更改,我认为这是唯一好的方法。您可以尝试字符串操作和正则表达式,但解析PHP需要一个上下文无关的解析器,而REs不会做到这一点,因此您得到的任何结果都不可信。