Как мне реализовать двухпроходный сканер с помощью Flex?

StackOverflow https://stackoverflow.com/questions/104967

Вопрос

В качестве домашнего проекта я хотел бы попытаться реализовать базовый язык моего собственного дизайна, который можно использовать в качестве языка веб-сценариев.Запустить программу на C ++ как Apache CGI тривиально, поэтому реальная работа заключается в том, как проанализировать входной файл, содержащий некод (разметку HTML / CSS) и код на стороне сервера.

На моем курсе компиляции для старшекурсников мы использовали Гибкий и Бизон сгенерировать сканер и синтаксический анализатор для простого языка.Нам дали копию грамматики, и мы написали синтаксический анализатор, который перевел простой язык в простую сборку для виртуальной машины.Сканер flex маркирует входные данные и передает маркеры анализатору Bison.

Разница между этим и тем, что я хотел бы сделать, заключается в том, что, как и PHP, этот язык может иметь простую HTML-разметку и язык сценариев, чередующийся следующим образом:

<p>Hello,
<? echo "World ?>
</p>

Ошибаюсь ли я, предполагая, что было бы эффективно проанализировать входной файл следующим образом:

  1. Сканируйте входные данные до тех пор, пока не будет найден начальный тег скрипта ('
  2. Второй сканер маркирует раздел сценария на стороне сервера входного файла (из тега open:") и передает токен анализатору, которому нет необходимости знать о разметке в файле.
  3. Управление возвращается первому сканеру, который продолжает эту общую схему.

По сути, первый сканер различает только разметку (которая возвращается непосредственно в браузер без изменений) и код, который передается второму сканеру, который, в свою очередь, маркирует код и передает токены анализатору.

Если это нет надежный шаблон проектирования, как такие языки, как PHP, эффективно обрабатывают входные данные сканирования и синтаксический анализ кода?

Это было полезно?

Решение

Вы хотите посмотреть на начальные условия.Например:

"<?"            { BEGIN (PHP); }
<PHP>[a-zA-Z]*  { return PHP_TOKEN; }
<PHP>">?"       { BEGIN (0); }
[a-zA-Z]*       { return HTML_TOKEN; }

Вы начинаете работу в состоянии 0, используйте макрос BEGIN для изменения состояний.Чтобы сопоставлять RE только находясь в определенном состоянии, добавляйте к RE название состояния, заключенное в угловые скобки.

В приведенном выше примере "PHP" - это состояние."PHP_TOKEN" и "HTML_TOKEN" - это _%token_, определенные вашим файлом yacc.

Другие советы

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

Если вас интересует, как работает сам PHP, загрузите исходный код (попробуйте исходный код PHP4, его намного проще понять).То, на что вы хотите посмотреть, находится в каталоге Zend, zend_language_scanner.l.

Написав что-то подобное сам, я бы действительно рекомендовал переосмыслить использование маршрута Flex и Bison и выбрать что-нибудь современное, например Antlr.Это намного проще и понятнее (макросы, используемые в грамматике lex, становятся очень запутанными и их трудно читать), и у него есть встроенный отладчик (АнтлрВоркс) таким образом, вам не придется тратить часы на просмотр файлов отладки размером 3 мегабайта.Он также поддерживает множество языков (Java, c #, Си, Python, Actionscript) и содержит отличную книгу и очень хороший веб-сайт, который должен помочь вам начать работу в кратчайшие сроки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top