我正在开发一个项目,其中有一个可以解析自定义语言的 Bison 解析器。我遇到了一个问题,解析器在遇到输入文件中的第一个错误后停止,但我需要它继续解析并捕获多个错误。
当解析器遇到错误(例如语法错误)时,它会调用 yyerror() 函数来报告错误。但是,在报告第一个错误后,解析器将停止处理进一步的输入并返回给调用者。因此,即使输入文件中有多个错误,我一次也只能捕获并报告一个错误。 例如 : 在我的输入文件中,我有一系列变量声明,但有故意的语法错误来测试错误处理机制。这是输入文件 (.txt) 的简化版本:
int a;
int b;
int c;
int d, e,f;
int
flot
float g, i,k;
int
k
int b;
我希望我的 Bison 解析器能够报告出现语法错误的每一行。例如,在此输入文件中,我希望看到第 5、6、7 和 8 行报告的错误。
目前,我的 Bison 解析器仅报告遇到的第一个语法错误
我正在寻求有关如何修改解析器以处理多个错误并继续解析直到输入文件末尾的指导。理想情况下,我希望解析器报告所有遇到的错误并提供有关其各自行号的信息。
这是我的 Flex 和 Bison 文件的简化版本:
文件.l: `
`%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Part_B.tab.h"
%}
// Lexical rules...
%%
// Lexical rules...
%%
int yywrap() {
return 1;
}
int yyerror(FILE* fp, const char* msg) {
fprintf(stderr, "Error | Line: %d %s\n", yylineno, msg);
return 0;
}
文件.y:
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Part_B.tab.h"
// External declarations...
%}
// Bison rules...
%%
// Bison rules...
%%
int main() {
//file
FILE *input_file = fopen(file_path, "r");
if (input_file == NULL) {
fprintf(stderr, "Error: Unable to open input file");
return 1;
}
// Redirect input to the file
yyrestart(input_file);
yyparse(input_file);
return 0;
}
这是语言语法的一部分,所以在不知道的情况下不可能给出准确的答案。
Bison 具有错误恢复功能,其中之一是保留的 名为
error
的规则,它将匹配语法错误。
您的语法中可能有类似的内容:
statement:
...
| declaration ';'
;
如果在那里添加错误规则,当 Bison 遇到错误时,它将终止当前语句并继续。
statement:
expression ';'
| declaration ';'
| error
但这不是你想要的——无论错误发生在哪里,这都会开始一个新的语句。您想首先丢弃格式错误的语句的其余部分,这意味着丢弃直到下一个分号(这就是语言使用分号的确切原因)。
error
不仅匹配错误,而且还匹配后面的所有内容,直到规则的其余部分匹配为止。只需添加 ';'
即可。
statement:
expression ';'
| declaration ';'
| error ';'
您还想在包含
yyerrok
宏的错误规则之后添加一个操作:
| error ';' { yyerrok; }
这告诉 bison 重置错误状态。否则,如果两个连续的语句中有错误,您可能会得到一些有趣的结果。
您还需要记住,错误恢复将跳过出错规则上的任何操作,这可能会导致错误。
您可以有多个
error
规则,例如,如果 ()
内部发生错误,您可能想跳到 `)