我是刚学会弯曲和野牛的,所以请容忍我我试图在yyerror中使用yylloc打印出错误发生的位置和文件名我知道这需要我重新定义YYLTPYE以包含一个char*文件名,我可以使用它来跟踪文件名根据Flex和Bison的书,它建议我使用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在本文中提供的解决方案,但它并没有帮助我解决这个问题解决这个错误的任何帮助都是显而易见的。
这是完整的代码。我:
%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现在只是空的,只有一个include for need.h和一个for.tab.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);
}
最佳答案
由于yylloc
通常是在bison生成的解析器中定义的,因此没有bison输入文件会有点麻烦。
Bison将在生成的解析器中定义yylloc
,并在生成的头文件中放置声明,如果:
你可以在野牛序幕中加入指令,或者
你在任何野牛行动中都引用了一个位置(%locations
,有些@n
)。
如果在任何规则中没有对位置的显式引用,通常最好添加该指令。
正如Chris Dodd在链接的问题中所说,在使用bison生成的头文件之前包含n
的定义是很重要的或者,您可以在bison序言的YYLTYPE
部分直接插入结构的定义或适当的#include
#include
节被复制到生成的头中,这样就不必担心flex文件中的定义。
顺便说一下,我想你是想用%code requires
初始化%code requires
在flex scanner自己初始化之前,YY_USER_INIT
的扩展只执行一次yylloc
的扩展在每个扫描器操作(包括空操作)之前执行,并且可能用于用当前令牌更新YY_USER_INIT
结构。
关于c - 如何解决yylloc未声明的错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43419585/