Переключить входной поток в lex и yacc

Я настаиваю на использовании lex, а не flex.

Я разрабатываю API в lex, подобный тому, который существует в flex util (yy_switch_buffer, yy_create_buffer...), предлагая возможность переключения между несколькими буферами.

Это главная трудность для меня до сих пор:

  • например, когда я сталкиваюсь с #include маркер я должен переключить буфер на включенный файл. Итак, сначала я должен прервать текущее действие синтаксического анализа (я пытался fclose(yyin) FAILED) Парсер завершил весь текущий yyin. НЕ хорошо, потому что я должен анализировать включенный файл для хранения структур (например), используемых в основном файле.

Вопрос: как я могу немедленно прервать анализатор? Достаточно ли мне определить новый буфер, используя yyin = fopen(somefile, "r");??

4 ответа

Решение

Будет трудно справиться с этим, если это вообще выполнимо. AFAIK, Lex позволяет переключать входные потоки только на EOF (реальные или смоделированные), когда он вызывает yywrap(),

Может быть, вы можете подделать вещи так, что когда вы найдете директиву include, вы подделаете EOF для текущего потока и затем получите yywrap() исправьте ситуацию так, чтобы новый ввод исходил из включенного файла, а затем, когда вы достигнете EOF для включенного файла, вы получите yywrap() восстановить ввод из исходного входного потока в исходное положение. Понятно, что это работает для вложенных включений (если вообще работает), если вы не ограничите произвольно количество уровней включения.

Решение для "включенных входных файлов" является частью гибкой документации, которая предоставляет пример того, как переключаться между гибкими входами ftp://ftp.gnu.org/old-gnu/Manuals/flex-2.5.4/html_mono/flex.html#SEC12 ("Несколько входных буферов")

Переносимого способа сделать это с помощью POSIX lex не существует - разные реализации имеют разные внутренние механизмы того, как они обрабатывают и буферизуют ввод, и во время lexing могут считывать данные перед текущим токеном обработки и буферизовать кучу входных данных. Поэтому вам нужно получить его, чтобы сохранить то, что он в данный момент буферизовал, и переключиться на другой вход, а затем восстановить буферизованный материал (так, чтобы он был прочитан далее) после того, как вы закончите с #include или чем-то еще. Это как раз то, для чего нужны вызовы Flex для управления буфером, но если вы настаиваете на использовании lex, вам нужно (эффективно) портировать эти подпрограммы, чтобы понять внутреннюю часть тех версий lex, которые вам нужно поддерживать.

Вы можете найти гибкий инструмент, перенесенный в систему Windows здесь http://sourceforge.net/projects/winflexbison/

Другие вопросы по тегам