发生语法错误时,是否有已知的方法生成"预期令牌"列表?我使用Lemon作为解析器生成器。
这似乎有效:
%syntax_error {
int n = sizeof(yyTokenName) / sizeof(yyTokenName[0]);
for (int i = 0; i < n; ++i) {
int a = yy_find_shift_action(yypParser, (YYCODETYPE)i);
if (a < YYNSTATE + YYNRULE) {
printf("possible token: %sn", yyTokenName[i]);
}
}
}
它尝试所有可能的令牌,并打印那些在当前解析器状态下适用的令牌。
请注意,当出现不正确的令牌时,解析器不会立即调用syntax_error,但它会尝试减少堆栈上的内容,希望之后可以移动令牌。只有当不能减少其他内容并且不能移动当前令牌时,解析器才会调用syntax_error。减少将更改解析器状态,这意味着您可能会看到比减少之前适用的令牌更少的令牌。不过,它应该足以用于错误报告。
Lemon中没有直接的方法来生成这样的列表。但您可以尝试使用Lemon工具的调试输出和生成的解析器的调试跟踪来实现这一点。在调用ParseTrace函数后,生成的解析器打印Shifts和Reduce列表,并将其应用于输入流。语法错误前的最后一个Shift包含错误前的当前状态数。在解析器的*.out文件中找到这个状态,并查看它的预期标记列表。
Lemon的现代版本使用如下内容:
%syntax_error {
for (int32_t i = 1, a = 0; i < YYNTOKEN; ++i) {
a = yy_find_shift_action((YYCODETYPE)i, yypParser->yytos->stateno);
if (a != YY_ERROR_ACTION) {
// 'a' is a valid token.
}
}
}