2017-04-14 553 views
2

我是新来的flex和野牛,所以忍受着我。我试图在yyerror中使用yylloc打印错误发生的位置以及文件名。我知道这需要我重新定义YYLTPYE以包含char *文件名,我可以使用它来跟踪文件名。按照Flex和野牛的书我有,它建议我使用YY_USER_ACTION宏来初始化.L文件YYLTYPE,所以我包括在它下面,如何解决yylloc未声明的错误?

#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中提供的解决方案,但它并没有帮助我解决问题。任何和所有帮助解决这个错误是非常apprecaited。

下面是.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

的need.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); 
} 

回答

2

由于yylloc通常在野牛生成的解析器定义,不具有输入野牛文件将是一个比特滋扰的。

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

  1. 您在野牛序幕指令%locations,或

  2. 您参考一个位置(@n一些n)在任何野牛行动。

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

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


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

+0

感谢您的信息,我能够通过添加%位置并将YYLTYPE的定义放在.y文件中的%code requires块中来解决错误。现在它说几次未定义的'yylloc'引用,然后命中collect @:错误:ld返回1退出状态。这是因为我的解析器还没有任何东西,或者我错过了什么。 –

+0

您是否将野牛生成的解析器链接到可执行文件中? – rici

+0

这里是我的makefile: 号:numbers.l numbers.y \t野牛-d numbers.y \t柔性numbers.l \t GCC的lex.yy.c numbers.tab.h -lfl –

相关问题