Использование внешне определенных констант в правилах flex - PullRequest
1 голос
/ 14 марта 2012

У меня есть некоторые константы, определенные в заголовочном файле, которые содержат максимальную длину определенных строк, которые должны быть проанализированы анализатором файлов, написанным на flex / bison.Я хочу переместить код для проверки длины строк из кода c в мои регулярные выражения, чтобы сделать вещи немного более краткими.

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

[[:alnum:]]+ { yylval.sval = (char*) strdup(yytext); return STRING; }

Где проверка длины происходит в правилах бизонов.

Я хочу изменить это так, чтобы он проверялдля совпадения не более MAX_STR_LEN, которое определено в заголовке constants.h.Если значение MAX_STR_LEN равно 32, я бы хотел получить такой же эффект, как:

[[:alnum:]]{1,32}

Можно ли как-то это сделать, не выполняя мой flex-файл через дополнительный этап предварительной обработки?

EDIT:

Следующее правило не будет выполнено, поскольку MAX_STR_LEN не является литеральным числом, оно рассматривается как строка, поэтому flex считает, что для одного правила определено 2 действия.

[[:alnum:]]{1,MAX_STR_LEN} { do_something(); }

Кроме того, если кто-то пытается определить макрос в части объявлений гибкого файла, он также не работает как таковой.

max_len 32 /* Also fails if 32 is replaces with MAX_STR_LEN */
%%
[[:alnum:]]{1,max_len} { do_something(); }

Ответы [ 3 ]

2 голосов
/ 14 марта 2012

С этим можно справиться в правиле действия:

[[:alnum:]]+    { if (yyleng > MAX_STR_LEN) yyless(MAX_STRING_LEN);
                  yylval.sval = (char*) strdup(yytext); return STRING; }

Это делает правило фактически таким же, как ваш модификатор {1,MAX_STR_LEN} в шаблоне

1 голос
/ 14 марта 2012

Flex создает исходный файл на языке C. В верхней части этого исходного файла C находится «произвольный код C», который вы пишете сами:

%{
whatever you like goes here
%}

Так как это происходит до сгенерированного кода, вы можете #include "constants.h" и получить доступ к своим макросам. Вы также можете #include <string.h> и отказаться от приведения до strdup, если вы не ограничиваете себя строгим POSIX (если у вас вообще есть strdup в вашей библиотеке, вы, вероятно, имеете его в string.h).

0 голосов
/ 14 марта 2012

Нет, сканер, сгенерированный с помощью flex, установлен в камне и не может быть изменен во время выполнения. Помимо опции, обсуждаемой в комментариях к ответу Торека (if (strlen (yytext) > MAX_STR_LEN) return TOOLONG_STRING;), есть еще одна, более сложная возможность - самостоятельно собирать строки с начальными условиями и временным буфером и т. Д., И если найдено более MAX_STR_LEN символов, сигнализировать об ошибке, но трудно представить сценарий, в котором это стоит усилий.

Совершенно не связанный, я бы подумал о том, есть ли действительно веская причина для ограничения длины. Как только вы создадите свою программу, исходя из предположения, что «строки никогда не будут длиннее MAX_STR_LEN», переключить передачу будет очень сложно. Если вместо этого вы начнете с требования «строки могут быть любой длины», код будет не намного сложнее, но вы получите большую гибкость.

...