Что такое хороший генератор парсера для php?
Мне нужно разобрать небольшой "мини язык", который пользователи могут вводить на моем сайте. Мне было интересно, что аналоги lex и jacc или antlr для мира php.
4 ответа
Я использовал генератор LIME Parser для PHP пару лет назад, и он был уже зрелым и стабильным.
Сам генератор парсера написан на PHP, что на самом деле не имеет никакого значения в техническом смысле - поскольку нам требуется только, чтобы сгенерированный парсер был на PHP - но тем не менее мне нравится эта деталь. Это заставляет меня чувствовать себя менее извиняющимся из-за написания программного обеспечения на PHP;-)
РЕДАКТИРОВАТЬ:
Я должен добавить:
Там, где я писал "использовал", было бы точнее сказать, что я "играл с". Я еще не написал никакого производственного кода, использующего Lime. Но я не вижу причин не делать этого.
"Пример калькулятора", предоставленный lime, использует метод tokenize(), который очень далек от реальной замены мощности lex. Но если вам нужен настоящий токенизатор, то можно использовать lex на "переднем конце", чтобы подавать токены в известь на "заднем конце".
Я перенес Jison, клон Bison в javascript, на php. Результатом является убийственный синтаксический анализатор, способный обрабатывать очень простые и очень сложные лексические операции / синтаксический анализ. Теперь это часть Jison, но в моей ветке есть несколько обновлений - https://github.com/robertleeplummerjr/jison. Файлы находятся здесь - https://github.com/robertleeplummerjr/jison/tree/master/ports/php
Посмотрите readme на этой странице, вы одновременно создаете javascript и php-парсер, которые могут выполнять одинаковые или разные действия. ПРОХЛАДНО!
Я советую вам написать свой собственный парсер, так как сегодня это довольно просто.
По моему мнению, самый простой способ сделать это - создать один класс для каждого возможного типа синтаксиса (выражение, тест, цикл и т. Д.).
Затем в каждом классе закодируйте следующие методы:
- один метод для определения из строки, если строка имеет заданный тип (
a+b
имеет тип 'выражение',if(b)
не является) - один метод "запустить" этот тип (
a+b
вернусьa->run() + b->run()
, а такжеa->run()
вернет значение)