Автоматический разбор PHP для отделения кода PHP от HTML - PullRequest
5 голосов
/ 07 ноября 2010

Я работаю над большой базой PHP-кода; Я хотел бы отделить код PHP от HTML и JavaScript. (Мне нужно сделать несколько автоматических поисков и замен в коде PHP, и разные в HTML, и разные в JS). Есть хороший движок парсера, который мог бы выделить PHP для меня? Я мог бы сделать это с помощью регулярных выражений, но они не идеальны. Я мог бы построить что-нибудь в ANTLR, возможно, но лучше уже существующее хорошее решение.

Я должен прояснить: я не хочу или не нуждаюсь в полном парсере PHP. Просто нужно знать, является ли данный токен: - код PHP - строка одинарной кавычки PHP - строка двойных кавычек PHP - PHP Комментарий - не PHP, а HTML / JavaScript

Ответы [ 3 ]

4 голосов
/ 07 ноября 2010

Как насчет токенизатора , встроенного прямо в сам PHP?

Функции токенизатора предоставляют интерфейс для PHP-токенизатора, встроенного в Zend Engine.Используя эти функции, вы можете написать свой собственный инструмент для анализа или модификации исходного кода 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;
    }
}
3 голосов
/ 07 ноября 2010

Чтобы отделить PHP от остальных, встроенный токенизатор PHP - ваш лучший выбор: см. token_get_all()

В остальном вам лучше всего использовать DOMпарсер .Таким образом легко изолировать части <script> (и внешние сценарии и даже события onXXXX).

Может быть, трудно пересоздать идентичный документ из разобранного дерева DOM, хотя - я полагаю, это зависит от того, что вам нужно делать с результатами и насколько чист исходный HTML.Регулярное выражение (гадость!) Может работать лучше для этой части.

0 голосов
/ 07 ноября 2010

Если все, что вы хотите сделать, это проверить токены, то токенайзер PHP, как предлагали другие, может быть хорошим выбором.

Если вы хотите сделать этодля автоматического изменения исходного кода надежным способом, я не уверен, что это поможет вам.Как вы будете регенерировать измененный исходный текст?

Еще один способ сделать это - использовать программа преобразования движок.Такой механизм может анализировать исходный текст в абстрактных синтаксических деревьях, фиксируя структуру программы (а также эффективное содержимое всех токенов), и позволяет осуществлять поиск и преобразование этих AST с использованием надежных сопоставлений / преобразований шаблонов.Для этого вам понадобится механизм, который надежно анализирует PHP и сможет воспроизводить скомпилированный исходный текст из измененного AST.

Наш DMS Software Reengineering Toolkit является такой системой преобразования программ, ион имеет надежный PHP Front End , который может точно обрабатывать PHP5 с точки зрения синтаксического анализа, преобразования и печати результатов обратно в текст.(Правильный синтаксический анализатор PHP сложен , потому что язык плохо документирован).Поскольку интерфейс может точно подобрать HTML и PHP-код, вам не нужно для разделения текста;они будут припаркованы в четко различимых местах в уникальных узлах дерева.

Чтобы изменить все отображаемые строки с строчных на прописные, вы должны использовать DMS для анализа PHP, а затем применить следующее правило преобразования:

 rule uppercase_echoed_string(s: STRING): statement -> statement
 =   "echo \s;" ->  "echo \uppercase\(\s\);".

Это правило написано на языке спецификации правил (RSL) DMS, который явно не является PHP.Материал внутри кавычек - это PHP-код;это мета кавычки, обернутые вокруг текста языка программирования, которым манипулируют.\ Chararacter является мета-escape: \ s указывает метавариабельную переменную, которая должна совпадать со строковым литералом, \ uppercase - это имя функции DMS, внешней по отношению к языку RSL, а () - это круглые скобки мета вокруг вызова мета-функции в верхнем регистре, применяется к соответствующей строке \ s.Поскольку правило действует на AST, его нельзя спутать;это не изменит текст / * echo 'def' * /, потому что это не утверждение.

Скорее всего, вам понадобится несколько правил для обработки разнообразных синтаксических комбинаций: STRING в данном случае относится к буквальным строкам в одинарных кавычках;Строки с двойными кавычками не являются монолитными объектами, а состоят из серии QUOTED_STRING_FRAGMENTS, которые соответствуют тексту в строке с двойными кавычками между выражениями PHP внутри этой строки с двойными кавычками.

В конце процесса преобразования измененный AST отправляется в комплекте с исходным отступом и комментариями, за исключением случаев, когда были применены преобразования.

Существует также полностью синтаксический анализатор JavaScript для DMS, который вам понадобится, если вы хотите точно обрабатывать содержимое тегов SCRIPT.

Если вы хотите внести надежные изменения вИсходный код, это ИМХО является единственным хорошим способом сделать это.Вы можете попробовать взлом строк и регулярные выражения, но для синтаксического анализа PHP требуется синтаксический анализатор, а RE этого не делают, поэтому любой полученный вами результат не будет заслуживающим доверия.

...