首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不使用循环或分支语句执行php脚本

问不使用循环或分支语句执行php脚本
EN

Stack Overflow用户
提问于 2016-12-19 06:39:19
回答 1查看 64关注 0票数 0

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

PHP代码例如:-

输入

代码语言:javascript
复制
<?php
if(1){
echo "hello";
}
while(1){
echo "world";
}

输出

代码语言:javascript
复制
<?php
echo "hello";
echo "world";
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-21 11:14:52

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

您可以使用程序转换系统(PTS)来完成这一任务。这些工具可以将源代码解析为编译器数据结构(通常是抽象语法树AST),可以对AST进行更改,然后从修改后的编译器数据结构中重新生成有效的源文本。

弱PTS只允许您按程序遍历树/检查/更改树,这是编译器的典型做法。使用这种方法,您必须非常熟悉数据结构(例如,您必须知道树的精确结构),对于一种真实的语言,有很多细节需要了解和纠正。如果你有很大的热情,这是可行的。

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

代码语言:javascript
复制
  when you see *thispattern*, replace it by *thatpattern*, if *condition*

其中,该模式和该模式是在被转换的源语言中编写的模式。PTS负责将它们转换成相应的编译器数据结构,这样你就可以用更少的小楔形来度过难关了。

在OP的例子中,他需要一个能够解析和转换PHP的PTS。

我知道唯一能做到这一点的“好的”PTS是我们的DMS软件重组工具包和PHP前端。

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

代码语言:javascript
复制
 (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

大部分工作由DMS重写文件“my_rewrite_rules.rsl”中的规则完成:

代码语言:javascript
复制
 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重写规则的形式如下:

代码语言:javascript
复制
   rule rulename ( pattern_variable_declarations):
       syntaxcategory -> syntaxcategory
   "thispattern" -> "thatpattern".

此模式和该模式是在metaquotes “.”中编写的,它将源程序模式文本与重写规则语言本身的语法区分开来。使用元引用时,可以发现源语言文本与模式变量\x混在一起,其语法类别在模式变量声明中声明为x:。您确实必须了解语言的主要语法类别(例如,“语句”与“语句”与“表达式”,但您并不了解while循环的所有内部结构。

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

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

你可以请参阅有关DMS重写规则的更多信息。

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

开始:

代码语言:javascript
复制
<?php
if(1){
echo "hello";
}
while(1){
echo "world";
}

在strip_if_then之后:

代码语言:javascript
复制
<?php
{
echo "hello";
}
while(1){
echo "world";
}

在strip_while之后:

代码语言:javascript
复制
<?php
{
echo "hello";
}
{
echo "world";
}

第一次申请strip_useless_block后:

代码语言:javascript
复制
<?php
echo "hello";
{
echo "world";
}

在第二次申请strip_useless_block后:

代码语言:javascript
复制
<?php
echo "hello";
echo "world";

我们得到了OP的预期结果。这在一个大文件上要壮观得多。

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

我得承认,我不知道为什么有人会想要这样去除控制流。但是PTS的重点是您可以配置来执行难以手工执行的任意代码更改任务。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41217007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档