Должен ли мой Flex-код быть недействительным в одиночку, чтобы быть действительным с Bison? - PullRequest
0 голосов
/ 04 июля 2019

Каждый урок начинается только с Flex lexer. А потом они представляют Бизона. Я могу запустить Flex, запустить Bison и просто скомпилировать - я написал для него скрипт оболочки - но разве я не смогу генерировать и компилировать только из Flex? Или я должен отказаться от этого?

Было множество ошибок при пропуске моего бизона. Некоторые источники включают в себя:

<tab>{FLA}  {yylval.midi = midi(yytext[1],yytext[0],1) ; return FLA;}

С ошибкой "неопределенная ссылка на` yylval '. И:

#include "y.tab.h"

Который не может найти файл .h. Я включил sed regex в мой скрипт компиляции, чтобы сгенерировать файл kinder .l, пропуская эти проблемные вещи, которые затем я могу встроить в C-код и скомпилировать в одиночку, чтобы отслеживать мой лексер, который я разрабатываю рядом с моим парсером. для моей записи.

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

1 Ответ

0 голосов
/ 04 июля 2019

Да, вы можете запускать флекс-код автономно, и для некоторых целей тот тип конечного автомата, который генерирует флекс, является идеальным инструментом для работы, и больше ничего (например, не зависящий от контекста грамматический парсер) не понадобится.Пример, который я привожу своим ученикам, заключается в том, что для обработки некоторых простых коммуникационных пакетов может потребоваться только конечный автомат, и вместо того, чтобы вручную кодировать его *, просто используйте такой инструмент, как flex.

Однакопри совместном использовании flex и bison я считаю хорошей практикой разработки программного обеспечения выполнять модульное тестирование компонента flex отдельно от компонента bison.Это экономит часы отладки, когда вы сначала избавляетесь от лексера.Техника, которой я учу своих учеников, заключается в использовании макросов C и условной компиляции для разделения бизон-зависимого кода.У других могут быть другие механизмы, которые они предпочитают.

Давайте рассмотрим пример.Скажем, у вас есть простой язык с целочисленными константами и идентификаторами, которые передаются обратно в синтаксический анализатор yylval, как показано в вашем вопросе.Я делаю это так:

%{
#ifdef PRINT
#define TOKEN(token) printf("Token: " #token ": %s\n", yytext)
#else
#define TOKEN(token) yylval=SymbolTable(yytext); return(token)
#endif
%}

identifier       [a-zA-Z][0-9a-zA-Z]*
number           [0-9]+

%%

{identifier}     TOKEN(ID);
{number}         TOKEN(NUMBER);

Тогда я могу создать свою автономную версию следующим образом:

flex sample.l
gcc -o lexer.exe lex.yy.c -lfl -DPRINT

* Я полагаю, вы знаете,что конечный автомат - это просто переключатель внутри цикла ...

while (not <<EOF>>) do {
  switch (state) {

   state1:   ... break;

 }
}
...