执行php脚本,不带循环或分支语句

时间:2016-12-19 06:39:20

标签: php parsing lex

一个PHP解析器,它可以删除所有循环语句和分支语句并执行其他

PHP代码例如: -

输入

<?php
if(1){
echo "hello";
}
while(1){
echo "world";
}

输出

<?php
echo "hello";
echo "world";

1 个答案:

答案 0 :(得分:1)

如果没有完整的语言解析器,这将非常困难。

您可以使用program transformation system (PTS)执行此操作。这些工具可以将源代码解析为编译器数据结构(通常是抽象语法树[AST]),可以对AST进行更改,然后可以从修改后的编译器数据结构中重新生成有效的源文本。

弱PTS只会让你按照编译器执行的经典方式在树上/检查/更改它。使用这种方法,您必须非常熟悉数据结构(例如,您必须知道树的精确结构),对于真正的语言,需要了解并获得正确的许多细节。如果你有很多热情,那就行了。

一个好的PTS将允许您提供它将用于搜索/更改树的源到源转换。这样的重写看起来像:

  when you see *thispattern*, replace it by *thatpattern*, if *condition*

其中 thispattern thatpattern 是在被转换的源语言中编写的模式。 PTS负责将它们转换为相应的编译器数据结构,因此您可以使用更少的知识。

在OP的情况下,他需要一个可以解析和转换PHP的PTS。

唯一&#34;好&#34; PTS我知道可以现成的是DMS Software Reengineering Toolkit及其PHP front end

您必须编写一个简短的DMS元程序来打开并读取文件,获取变换并应用它们,然后将结果打印出来(为了清晰起见,过于简化了一点):

 (define main
    (action (procedure void)
        (= AST  (Registry:Parse PHPDomain `my_file.php'))
        (Registry:ApplyTransforms AST (. `my_rewrite_rules.rsl') (. `strip_control_flow'))
        (local (= [os OutputStream:Stream] (OutputSteam:Open `updated_my_file.php'))=
               (Registry:PrettyPrint os PHPDomain AST))
               (= os (OutputStream:Close os))
        )local
    )action
  )define

大部分工作是通过文件&#34; my_rewrite_rules.rsl&#34;中的DMS重写规则完成的:

 domain PHP~PHP5.

 rule strip if_then(c: expression, s: statement):
     statement -> statement =
 " if (\c) \s" ->  "\s".

 rule strip if_then_else(c: expression, s1: statement, s2: statement):
     statement -> statement =
 " if (\c) \s1 else \s2" -> " { \s1 \s2 } ".

 rule strip while(c: expression, s: statement):
     statement -> statement =
 " while (\c) \s" ->  "\s".

 rule strip catch( b1: statements, l: catch_clauses, t: type, e: expression, b2: statements):
     statement -> statement =
 " try { \b1 } \l catch ( \t \e ) { \b2 } "
 -> " { try { \b1 } \l ; \b2 } ".

 rule strip_trivial_try( b1: statements):
     statement -> statement =
 " try { \b1 } " -> "{ \b1 }".

 rule strip_useless_block( b:statements, s: statements):
    statements -> statements =
 "  { \b } \s " ->  " \b \s ".

 ruleset strip_control_flow = {
     strip_if_then,
     strip_if_then_else,
     strip_while,
     strip_catch,
     strip_trivial_try,
     strip_useless_block }

等。我没有涵盖所有案件,但应该明白如何继续。

解释上述内容:DMS重写规则采用

形式
   rule rulename ( pattern_variable_declarations):
       syntaxcategory -> syntaxcategory
   "thispattern" -> "thatpattern".

thispattern thatpattern 写在 metaquotes &#34; ...&#34; 中将源程序模式文本与重写规则语言本身的语法区分开来。人们发现,使用元指数 源语言文本与模式变量 \ x 混合,其语法类别在模式变量声明中声明为 x:category 。 您必须知道该语言的主要语法类别(例如,&#34;语句&#34;与#34;语句&#34; vs&#34;表达&#34;但您不具备了解while循环的所有内部结构。

规则集将一组有趣的命名规则分组到一个方便的包中,该包可以批量应用;您可以在DMS元程序中看到如何提到此规则集。

编写此规则集时使用的技巧是让每个规则将其受控内容元素剥离到块{...}中,因为块可以作为语句使用。然后,清理规则strip_useless_blocks将删除任何创建的异常块。

你可以see more about how DMS rewrite rules are written here.

这些重写规则将逐步转换OP程序,通过以下一系列阶段(您可以在每次转换后完整打印完整的AST以查看此内容):

开始:

<?php
if(1){
echo "hello";
}
while(1){
echo "world";
}

在strip_if_then之后:

<?php
{
echo "hello";
}
while(1){
echo "world";
}
在strip_while之后

<?php
{
echo "hello";
}
{
echo "world";
}
第一次应用strip_useless_block后

<?php
echo "hello";
{
echo "world";
}
第二次应用strip_useless_block后

<?php
echo "hello";
echo "world";

我们有OP的理想结果。这在一个大文件上更加壮观。

因此,OP的任务很容易用一个好的PTS。

我承认我不知道为什么有人想要像这样剥离控制流程。但是,PTS的重点是你可以配置执行难以手工完成的任意代码更改任务。