【问题标题】:Writing re-entrant lexer with Flex使用 Flex 编写可重入词法分析器
【发布时间】:2011-02-07 18:21:38
【问题描述】:

我是 flex 新手。我正在尝试使用 flex 编写一个简单的可重入词法分析器/扫描器。词法分析器定义如下。我遇到编译错误,如下所示(yyg 问题):

可重入.l:

/* Definitions */

digit           [0-9]
letter          [a-zA-Z]
alphanum        [a-zA-Z0-9]
identifier      [a-zA-Z_][a-zA-Z0-9_]+
integer         [0-9]+
natural         [0-9]*[1-9][0-9]*
decimal         ([0-9]+\.|\.[0-9]+|[0-9]+\.[0-9]+)

%{
    #include <stdio.h>

    #define ECHO fwrite(yytext, yyleng, 1, yyout)

    int totalNums = 0;
%}

%option reentrant
%option prefix="simpleit_"

%%

^(.*)\r?\n     printf("%d\t%s", yylineno++, yytext);

%%
/* Routines */

int yywrap(yyscan_t yyscanner)
{
    return 1;
}

int main(int argc, char* argv[])
{
    yyscan_t yyscanner;

    if(argc < 2) {
        printf("Usage: %s fileName\n", argv[0]);
        return -1;
    }

    yyin = fopen(argv[1], "rb");

    yylex(yyscanner);

    return 0;
}

编译错误:

vietlq@mylappie:~/Desktop/parsers/reentrant$ gcc lex.simpleit_.c 
reentrant.l: In function ‘main’:
reentrant.l:44: error: ‘yyg’ undeclared (first use in this function)
reentrant.l:44: error: (Each undeclared identifier is reported only once
reentrant.l:44: error: for each function it appears in.)

【问题讨论】:

    标签: thread-safety flex-lexer lexical-analysis reentrancy


    【解决方案1】:

    对于可重入词法分析器,所有通信都必须包含 state,它包含在 scanner 中。

    在您的程序中的任何地方(例如main 内),您都可以通过特殊函数访问状态变量,您可以将扫描仪传递给这些函数。 例如,在您原来的reentrant.l 中,您可以这样做:

    yyscan_t scanner;
    yylex_init(&scanner);
    yyset_in(fopen(argv[1], "rb"), scanner);
    yylex(scanner);
    yylex_destroy(scanner);
    

    我已重命名scanner 以避免在操作中与yyscanner 混淆。与一般的 C 代码相比,您的所有操作都发生在一个名为 yylex 的巨大函数中,该函数通过名称 yyscanner 传递给您的扫描仪。因此,yyscanner 可用于您的所有操作。此外,yylex 有一个名为 yyg 的局部变量,用于保存整个状态,大多数宏方便地引用yyg

    虽然您可以像在自己的答案中那样定义yyg,从而在main 中使用yyin 宏,但不建议这样做。对于可重入词法分析器,宏仅用于操作。

    要了解这是如何实现的,您可以随时查看生成的代码:

    
    /* For convenience, these vars
       are macros in the reentrant scanner. */
    #define yyin yyg->yyin_r
    ...
    
    /* Holds the entire state of the reentrant scanner. */
    struct yyguts_t
    ...
    
    #define YY_DECL int yylex (yyscan_t yyscanner)
    
    /** The main scanner function which does all the work.
     */
    YY_DECL
    {
        struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
    ...
    }
    

    flex 文档中有更多关于reentrant 选项的内容,其中包括一个干净编译的示例。 (Google "flex reentrant",并查找 flex.sourceforge 链接。)与 bison 不同,flex 有一个相当简单的模型重入。我强烈建议将可重入 flexLemon Parser 一起使用,而不是与 yacc/bison 一起使用。

    【讨论】:

    • 除了上述初始化还有什么需要的吗?我在内部发生了崩溃,在分配给 yyg->yy_c_buf_p 之后,yy_cp 似乎是一个空指针。
    • 通过cmets很难调试。我在 OP 的 reentrant.l 中的 main() 中发布的内容对我有用。
    • 我知道这真的很老 - 但是我一直在尝试使用 lex。我发现如果我使用 BEGIN 或任何启动条件宏,它们仍然会收到 yyg undeclared 消息。我和你一样,能够让这个简单的 main() 词法分析器正常工作。我将尝试在我的函数中定义 yyg 以查看是否可以为我尝试更改统计条件的其他函数修复它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    • 2012-01-15
    相关资源
    最近更新 更多