我正在使用 flex+bison 作为工具包开发简单的 aql 解析器。现在,我正在尝试在发生语法错误时提供有用的反馈。我想向用户展示这样的想法:
Syntax error:
<line_index>: INSERT { name: "John Doe", 1123: 2, is_working: true } IN users
^^^^
我已经获得了发生语法错误的信息(行和列),但我真的无法想出获取错误行。我尝试存储全局行缓冲区current_line并在YY_USER_ACTION宏中写入yytext的内容。这样:
#define YY_USER_ACTION \
strcpy(current_line+cl_length, yytext); \
for(int i = 0; yytext[i] != '\0'; i++) { \
if(yytext[i] == '\n') { \
memset(current_line, 0, cl_length);
cl_length = 0;
} else {
cl_length++;
}
}
}
但是由于使用类似 python 的缩进范围的词法开始条件,我在行首得到了重复的字符。
是否有不同的方法可以使用 Flex 宏或其他方法来做到这一点?
Lex 不是面向行的,因此不提供任何有关“行号”等概念的明确帮助。正则表达式运算符 ^,$ 混淆了区别,但您可以使用以下规则轻松处理扫描仪中的行号:
\n { my_lineno++; }
这使得像
yywrap()
这样的东西可以轻松地将多个文件透明地传输到 lex 扫描器:
extern char *files[];
extern int nfiles;
int yywrap() {
static int curfile = 0
static FILE *lastfile = NULL;
FILE *fp = NULL;
if (lastfile) {
fclose(lastfile);
}
while (curfile < nfiles && fp == NULL) {
fp = fopen(files[curfile++], "r");
}
yyin = lastfile = fp;
return fp == NULL;
}
可能还有其他带有 flex 的方法,它大大增强了 lex。