9

我是弯曲的新手。我正在尝试使用 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.)
4

1 回答 1

13

对于可重入词法分析器,所有通信都必须包含状态,该状态包含在扫描仪中。

在程序中的任何地方(例如内部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中,该函数通过 name 传递给您的扫描仪yyscanner。因此,yyscanner可用于您的所有操作。此外,yylex有一个名为的局部变量yyg保存整个状态,大多数宏方便地引用yyg.

虽然确实可以通过在自己的答案中定义来使用yyin内部宏,但不建议这样做。对于可重入词法分析器,宏仅用于操作。mainyyg

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


/* 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选项的内容,其中包括一个干净编译的示例。(谷歌“ flex reentrant ”,并查找链接。)与bison不同,flex有一个相当直接的可重入模型。我强烈建议将 reentrant flexLemon Parser一起使用,而不是与yacc/bison一起使用。flex.sourceforge

于 2010-12-06T23:51:51.437 回答