如何在flex/lex中获取当前词法分析行用于yyerror错误提示
问题:Flex+Bison开发AQL解析器时,如何正确获取语法错误所在行内容?
我正在用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宏实现的方法?
可行解决方案
方法1:调整行缓存维护逻辑,规避起始条件重复扫描
问题根源是缩进起始条件下,flex可能重复扫描行首内容,导致YY_USER_ACTION重复写入行缓存。可以针对性修改逻辑:
- 仅在非缩进起始条件下写入行内容
- 严格控制换行时的缓存重置操作
修改后的YY_USER_ACTION示例:
#define YY_USER_ACTION \ /* 替换成你的缩进起始条件判断宏 */ \ if (!IN_INDENT_SCOPE) { \ /* 用strncat避免缓冲区溢出 */ \ strncat(current_line, yytext, sizeof(current_line) - cl_length - 1); \ } \ for(int i = 0; yytext[i] != '\0'; i++) { \ if(yytext[i] == '\n') { \ memset(current_line, 0, sizeof(current_line)); \ cl_length = 0; \ yylineno++; \ } else { \ if (!IN_INDENT_SCOPE) { \ cl_length++; \ } \ } \ }
方法2:将行内容维护放在词法规则中,替代YY_USER_ACTION
放弃在YY_USER_ACTION中统一处理,转而在flex的词法规则里针对性维护行内容,能更灵活地避开起始条件的干扰:
char current_line[256]; int current_col = 0; %option yylineno %% \n { memset(current_line, 0, sizeof(current_line)); current_col = 0; } .|\t { /* 仅在非缩进起始条件下更新行内容 */ if (!IN_INDENT_SCOPE && current_col < sizeof(current_line)-1) { current_line[current_col++] = *yytext; } } /* 你的其他词法规则,包括缩进相关的起始条件规则 */ %%
方法3:错误发生时从输入流回溯读取目标行
如果维护行缓存的问题难以解决,可以直接在错误触发时,从输入流中定位并读取目标行:
void print_syntax_error(int line_num, int col_num) { char error_line[256]; long current_pos = ftell(yyin); // 回溯到文件开头,定位到目标行 fseek(yyin, 0, SEEK_SET); for(int i = 1; i < line_num; i++) { while(fgetc(yyin) != '\n' && !feof(yyin)); } // 读取错误行内容 fgets(error_line, sizeof(error_line), yyin); // 恢复输入流到错误前的位置 fseek(yyin, current_pos, SEEK_SET); // 打印错误提示 printf("Syntax error:\n%d: %s", line_num, error_line); // 打印错误位置标记 printf("%*s^^^^\n", col_num - 1, ""); }
内容的提问来源于stack exchange,提问作者vlad613
相关产品推荐
相关产品推荐

