在flex规则中使用外部定义的常量

时间:2012-03-13 23:53:42

标签: c flex-lexer

我在头文件中定义了一些常量,这些常量包含由flex / bison编写的文件解析器解析的某些字符串的最大长度。我想将用于检查字符串长度的代码从c代码移动到我的正则表达式,以使事情更简洁。

现在我的规则看起来像:

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

长度检查在野牛规则中进行。

我想修改它,以便检查不超过MAX_STR_LEN的匹配项,该匹配项在名为constants.h的头文件中定义。如果MAX_STR_LEN等于32,那么我想要的效果如下:

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

无论如何在没有通过预处理的额外步骤运行我的flex文件的情况下执行此操作吗?

修改

以下规则将失败,因为MAX_STR_LEN不是字面数字,它被视为字符串,因此flex认为已为单个规则定义了2个操作。

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

此外,如果试图在flex文件的声明部分中定义一个宏,那么它也会失败。

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

3 个答案:

答案 0 :(得分:2)

你可以在行动规则中处理它:

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

这使得规则与模式

上的{1,MAX_STR_LEN}修饰符实际上相同

答案 1 :(得分:1)

Flex生成C源文件。在这个C源文件的顶部是你自己写的“任意C代码”:

%{
whatever you like goes here
%}

由于这是在生成的代码之前发布的,因此您可以#include "constants.h"访问您的宏。你也可以#include <string.h>并在strdup之前放弃演员,只要你不限制自己严格的POSIX(如果你的库里有strdup,你可能已经在string.h)。

答案 2 :(得分:0)

不,flex生成的扫描仪是固定的,不能在运行时更改。除了对torek的答案(if (strlen (yytext) > MAX_STR_LEN) return TOOLONG_STRING;)的评论中讨论的选项之外,另一个更复杂的可能性是用开始条件和临时缓冲区等自己进行字符串累积,如果超过MAX_STR_LEN找到字符,发出错误信号,但很难想象这是值得努力的场景。

完全不相关,我会考虑是否确实存在限制长度的令人信服的理由。一旦你设计你的程序时假设“字符串永远不会超过MAX_STR_LEN”,就很难改变装备。如果您从“字符串可以是任意长度”的要求开始,那么代码就不那么复杂了,但是您可以获得很大的灵活性。