выполнить php-скрипт без циклов или операторов ветвления в нем

Синтаксический анализатор PHP, который может вырезать все операторы цикла и операторы ветвления и выполнять другие

Коды PHP, например: -

ввод

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

вывод

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

person Aayush    schedule 19.12.2016    source источник
comment
и какой именно у вас вопрос?   -  person Franz Gleichmann    schedule 19.12.2016
comment
Ему нужен алгоритм или инструмент, который удалит циклы из исходного файла PHP.   -  person Ira Baxter    schedule 21.12.2016


Ответы (1)


Это чрезвычайно сложно сделать без полноценного синтаксического анализатора языка.

Это можно сделать с помощью системы преобразования программ (PTS). Это инструменты, которые могут анализировать исходный код в структуры данных компилятора (часто абстрактные синтаксические деревья [AST]), могут вносить изменения в AST, а затем могут восстанавливать действительный исходный текст из измененных структур данных компилятора.

Слабый PTS позволит вам обходить дерево / проверять / изменять его только процедурно, классическим способом, которым это делает компилятор. При таком подходе вы должны быть хорошо знакомы со структурами данных (например, вы должны знать точную структуру дерева), а для реального языка необходимо знать и правильно понимать множество деталей. Это работает, если у вас много энтузиазма.

Хороший PTS позволит вам предоставить ему преобразования от источника к источнику, которые он будет использовать для поиска / изменения дерева. Такие перезаписи выглядят так:

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

где thispattern и thatpattern - это шаблоны, записанные на преобразуемом исходном языке. PTS позаботится о преобразовании их в соответствующие структуры данных компилятора, чтобы вы могли обойтись гораздо меньшими затратами.

В случае OP ему нужен PTS, который может анализировать и преобразовывать PHP.

Единственный известный мне "хороший" PTS, который может делать это в готовом виде, - это наш DMS Software Reengineering Toolkit с его интерфейсом PHP.

Вам нужно написать короткую метапрограмму 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

Основная часть работы выполняется правилами перезаписи DMS в файле "my_rewrite_rules.rsl":

 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 записываются внутри метаквот "...", которые позволяют отличать текст шаблона исходной программы от синтаксиса сам язык правил перезаписи. С помощью метаквотов можно найти текст на исходном языке, смешанный с переменными шаблона \ x, синтаксическая категория которых объявлена ​​как x: category в объявлениях переменных шаблона. Вы должны знать основные синтаксические категории языка (например, «оператор» против «операторов» против «выражения», но вы не знаете всей внутренней структуры цикла while.

Набор правил группирует набор интересных именованных правил в удобный набор, который можно применять в пакете; вы можете увидеть, как этот набор правил упоминается в метапрограмме DMS.

Уловка, используемая при написании этого набора правил, заключается в том, чтобы каждое правило разделяло элементы контролируемого содержимого в блок {...}, потому что блоки приемлемы как операторы. Затем правило очистки strip_useless_blocks избавляет от любых созданных вопиющих блоков.

Вы можете узнать больше о написании правил перезаписи DMS здесь.

Эти правила перезаписи будут постепенно преобразовывать программу OP через ряд следующих этапов (вы можете распечатать полные AST после каждого преобразования, чтобы увидеть это):

Начинать:

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

после strip_if_then:

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

после полосы_время:

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

после 1-го применения strip_useless_block:

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

после 2-го применения strip_useless_block:

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

и у нас есть желаемый результат OP. Это намного более эффектно на большом файле.

Итак, задачу OP довольно легко выполнить с хорошим PTS.

Признаюсь, я понятия не имею, почему кто-то захочет вырезать такой поток управления. Но суть PTS в том, что вы можете настроить выполнение произвольных задач по изменению кода, которые сложно выполнить вручную.

person Ira Baxter    schedule 21.12.2016
comment
Спасибо, lra это ты направил мои исследования в правильном направлении - person Aayush; 22.12.2016
comment
Я хочу продвинуться вперед с помощью следующего URL-адреса stackoverflow.com/questions/6153634/ - person Aayush; 22.12.2016