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

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

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

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

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

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

  1. Scan input until a script start tag is found ('
  2. Second scanner tokenizes the server-side script section of the input file (from the open tag: '') and passes the token to the parser, which has no need to know about the markup in the file.
  3. Управление возвращается первому сканеру, который продолжает эту общую схему.

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

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


person dmercer    schedule 19.09.2008    source источник


Ответы (2)


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

"<?"            { 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» - это _% токенов, определенных вашим файлом yacc.

person eduffy    schedule 21.09.2008

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

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

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

person Kris Erickson    schedule 19.09.2008