【问题标题】:How to resolve a yylloc undeclared error?如何解决 yylloc 未声明的错误?
【发布时间】:2017-09-11 04:31:31
【问题描述】:

我是 flex 和 bison 的新手,所以请多多包涵。我正在尝试在 yyerror 中使用 yylloc 来打印出错误发生的位置以及文件名。我知道这需要我重新定义 YYLTPYE 以包含一个 char* 文件名,我可以使用它来跟踪文件名。根据我手上的Flex and Bison book,它建议我使用YY_USER_ACTION宏来初始化.l文件中的YYLTYPE,所以我在里面包含了以下内容,

#define YY_USER_ACTION yylloc.filename = filename; yylloc.hel = 0;  \
        yylloc.first_line = yylloc.last_line = yylineno;            \
        yylloc.first_column = yycolumn; yylloc.last_column = yycolumn+yyleng-1; \
        yycolumn += yyleng;

但是当我尝试编译项目时,我得到了 yylloc 未声明的错误。

我已经尝试了 Chris Dodd 在 question 中提供的解决方案,但它并没有帮助我解决问题。非常感谢解决此错误的任何和所有帮助。

这是 .l 中的完整代码:

%option noyywrap nodefault yylineno case-insensitive
%{
    #include "need.h"
    #include "numbers.tab.h"

    int yycolumn = 1;

    #define YY_USER_ACTION yylloc.filename = filename; yylloc.hel = 0;  \
        yylloc.first_line = yylloc.last_line = yylineno;            \
        yylloc.first_column = yycolumn; yylloc.last_column = yycolumn+yyleng-1; \
        yycolumn += yyleng;

%}

Integers    [-]?(0|[1-9][0-9]*)
Float       [.][0-9]+
Exp         [eE][-]?(0|[1-9][0-9]*)
Octal       [-]?(00|0[1-7][0-7]*)
Hexa        [-]?(0[xX][0-9A-F]+)
tomsNotNumbers [^ \t\n\v\f\r]+

%%

{Integers}{Float}?{Exp}?    {
                                printf("%s is a number.\n", yytext);
                                possibleNumbers++;  // increment by 1 as an input was given -M
                                actualNumbers++;    // increment by 1 as an input did match our pattern -M
                            }

{Octal} {
            printf("%s is a number.\n", yytext);
            possibleNumbers++;  // increment by 1 as an input was given -M
            actualNumbers++;    // increment by 1 as an input did match our pattern -M
        }

{Hexa}  {
            printf("%s is a number.\n", yytext);
            possibleNumbers++;  // increment by 1 as an input was given -M
            actualNumbers++;    // increment by 1 as an input did match our pattern -M
        }

{tomsNotNumbers}    {
                    printf("%s is not a number.\n", yytext);
                    yyerror(warning, "This isn't a number.");
                    possibleNumbers++;  // increment by 1 as an input was given -M
                    failedNumbers++;    // increment by 1 as the input has failed to match our patterns -M
                }

[\n]    /*Do nothing for newline*/

.   /*Do nothing for anything else*/

%%

.y 现在只是空的,只有一个包含 need.h 和一个 .tab.h

需要.h:

#include <stdlib.h>
#include <stdarg.h>
#include <string.h>

int possibleNumbers = 0;
int actualNumbers = 0;
int failedNumbers = 0;

typedef struct YYLTYPE
{
    int first_line;
    int first_column;
    int last_line;
    int last_column;
    char *filename; /* use to keep track of which file we're currently in */
    int hel;    /* no errors = 0, warning = 1, error = 2, fatal = 3 */
} YYLTYPE;

char *name; /*using for test purposes*/

# define YYLTYPE_IS_DECLARED 1

# define YYLLOC_DEFAULT(Current, Rhs, N)                                                    \
    do                                                                                      \
        if (N)                                                                              \
        {                                                                                   \
            (Current).first_line = YYRHSLOC (Rhs, 1).first_line;                            \
            (Current).first_column = YYRHSLOC (Rhs, 1).first_column;                        \
            (Current).last_line = YYRHSLOC (Rhs, N).last_line;                              \
            (Current).last_column = YYRHSLOC (Rhs, N).last_column;                          \
            (Current).filename = YYRHSLOC (Rhs, 1).filename;                                \
            (Current).hel   = YYRHSLOC (Rhs, 1).hel;                                        \
        }                                                                                   \
        else                                                                                \
        { /* empty RHS */                                                                   \
            (Current).first_line = (Current).last_line = YYRHSLOC (Rhs, 0).last_line;       \
            (Current).first_column = (Current).last_column = YYRHSLOC (Rhs, 0).last_column; \
            (Current).filename  = NULL;                                                     \
            (Current).hel = 0;                                                              \
        }                                                                                   \
    while (0)

typedef enum errorSeverity
{
    warning = 1, error, fatal
} errorLevel;

void yyerror(errorLevel errlvl, char *s, ...)
{
    va_list ap;
    va_start(ap, s);
    char *errLvls[3] = {"Warning", "Error", "Fatal"};  

    fprintf(stderr, "%s: %s: , %n", name, errLvls[errlvl - 1], yylloc.first_line);
    vfprintf(stderr, s, ap);
    fprintf(stderr, "\n");
}

main(int argc, char **argv)
{
    printf("argv[0] = %s, argv[1] = %s.\n", argv[0], argv[1]);
    if(argc > 1)
    {
        if((yyin = fopen(argv[1], "r")) == NULL)
        {
            perror(argv[1]);
            exit(1);
        }
        name = argv[1];
    } else
        name = "(stdin)";

    printf("Filename1: %s", name);
    yylex();
    printf("Filename2: %s", name);
    // print out the report. -M
    printf("Out of %d possible numbers, there were %d numbers, and %d not numbers.\n", possibleNumbers, actualNumbers, failedNumbers);
}

【问题讨论】:

    标签: c bison flex-lexer


    【解决方案1】:

    由于yylloc 通常在野牛生成的解析器中定义,因此没有野牛输入文件会有点麻烦。

    Bison 将在生成的解析器中定义yylloc,并在生成的头文件中放置一个声明,如果:

    1. 您在野牛序言中包含指令%locations,或者

    2. 您在任何野牛行动中都引用了一个位置(@n 表示某些 n)。

    如果在任何规则中没有明确引用位置,通常最好添加指令。

    正如 Chris Dodd 在链接问题中所说,重要的是在 #includeing 野牛生成的头文件之前包含 YYLTYPE 的定义。或者,您可以直接在 %code requires 部分的野牛序言中插入结构的定义或适当的 #include%code requires 部分被复制到生成的标题中,这样就无需担心 flex 文件中的定义。


    顺便说一句,我认为你的意思是使用YY_USER_INIT初始化 yyllocYY_USER_INIT 的扩展只执行一次,在 flex 扫描器自己的初始化之前。 YY_USER_ACTION 的扩展在每个扫描器操作(包括空操作)之前执行,并且可能用于使用当前令牌更新 yylloc 结构。

    【讨论】:

    • 感谢您的信息,我能够通过添加 %locations 并将 YYLTYPE 的定义放在 .y 文件中的 %code requires 块中来解决错误。它现在多次提到未定义的“yylloc”引用,然后点击 collect@: error: ld returned 1 exit status。这是因为我的解析器还没有任何东西,还是我错过了什么。
    • 您是否将野牛生成的解析器链接到可执行文件中?
    • 这是我的生成文件: numbers: numbers.l numbers.y bison -d numbers.y flex numbers.l gcc lex.yy.c numbers.tab.h -lfl
    • @havikiv:numbers.tab.c。你永远不会编译.h 文件。
    • 我早些时候尝试过,但这给了我更多的错误,而不是 1 个错误,这似乎是更好的选择 XD。通过链接 .tab.c,我收到一个错误:yyerror yyerror (YY_("syntax error")) 的参数 1 的类型不兼容;从进一步阅读错误列表来看,似乎没有调用我对 yyerror 的定义,而是默认内置的,如果我没看错
    猜你喜欢
    • 1970-01-01
    • 2020-08-05
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 1970-01-01
    • 2023-02-22
    • 2015-03-26
    • 1970-01-01
    相关资源
    最近更新 更多