Да, вы можете запускать флекс-код автономно, и для некоторых целей тот тип конечного автомата, который генерирует флекс, является идеальным инструментом для работы, и больше ничего (например, не зависящий от контекста грамматический парсер) не понадобится.Пример, который я привожу своим ученикам, заключается в том, что для обработки некоторых простых коммуникационных пакетов может потребоваться только конечный автомат, и вместо того, чтобы вручную кодировать его *, просто используйте такой инструмент, как 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;
}
}