如何在yacc/bison中找到错误报告的不平衡分隔符?

如何在yacc/bison中找到错误报告的不平衡分隔符?,bison,yacc,Bison,Yacc,我有一个使用括号和方括号作为分隔符的语法。当bison生成的解析器使用不平衡的分隔符输入时,传递给yyerror的YYLTYPE*中的错误位置就是输入的结束。因此,例如,在输入xx(yy)时,在void yyerror(YYLTYPE*yylloc,Context*ctx,const char*msg)内我有一个yylloc->first_column==yylloc->last_column==5。不幸的是,输入的结尾不是指示不匹配分隔符的最突出位置。更有用的是左括号或左方括号的位置,因为没有

我有一个使用括号和方括号作为分隔符的语法。当bison生成的解析器使用不平衡的分隔符输入时,传递给
yyerror
YYLTYPE*
中的错误位置就是输入的结束。因此,例如,在输入
xx(yy
)时,在
void yyerror(YYLTYPE*yylloc,Context*ctx,const char*msg)内
我有一个
yylloc->first_column==yylloc->last_column==5
。不幸的是,输入的结尾不是指示不匹配分隔符的最突出位置。更有用的是左括号或左方括号的位置,因为没有匹配。(在本例中,这将是偏移量2处的左括号。)我推测此信息在解析堆栈中可用——必须有一些n,使得
$-n
是不匹配的
[
token和
@-n
是保持其位置的
YYLTYPE
结构,但是
yyerror
中似乎没有任何一个结构可用。我知道我可以保留一个自己的堆栈来跟踪分隔符的偏移量,并将其存储在
上下文
中,我已经传递到
yyerror
,但这似乎很有用不雅和重复,因为野牛已经开始追踪了


因此:如何从bison中撬出输入中遇到的第一个不平衡分隔符的位置,以便在生成解析错误消息时可用?

查看bison中的错误标记:

我想象这样的事情会起作用(我还没有测试):


您应该能够添加以下规则之一:

atom: '(' error    { /* unmatched left paren at @1 */ }

获取有关不匹配左括号的信息。不同之处在于,第一条规则将匹配不匹配的括号,该括号后面没有任何可解析的内容(例如在输入的末尾),而第二条规则仅在后面有看起来像有效的
alt
的内容时才匹配

如果语法中有任何其他错误生成(链接语法中没有),则可能会出现问题,在这种情况下,可能会首先触发不同的错误生成。因为没有其他错误规则,所以第一种选择更好


请注意,使用yacc/bison错误恢复规则不会以任何方式抑制语法错误,它只是在语法错误后运行一些代码以尝试恢复。这些代码可以打印其他错误消息,然后中止,而不是尝试恢复,但这些消息将在语法错误消息后打印。

您能分享您的错误吗语法(至少是处理paren的部分)?它是。括号在第187行处理。嗯。我不能以换行结束,因为我的输入都没有。当我添加
|'('alt error
,该产品从未匹配。未匹配的左参数最终会像以前一样成为常规的分析错误。当您遇到未匹配的左参数时,您想要什么行为?您只是在寻找干净的错误报告,还是希望能够忽略某些输入并保持分析?我不需要实际的恢复--我很抱歉发生错误后不会继续解析。我只想知道不匹配左参数的偏移量。(顺便说一句,我已经阅读了关于错误恢复的部分并尝试了,看看是否可以通过这种方式获得偏移量。)如果我错了,请纠正我,但听起来你有两个问题需要解决。首先,你想知道是哪个括号造成了不平衡。其次,你想知道该括号的行/列。对吗?我不知道这两个东西有什么不同。唯一区别左括号和其他括号的是它的位置。问题在您为我解决问题的回答中,您的回答是“请注意,使用yacc/bison错误恢复规则不会以任何方式抑制语法错误,它只是在语法错误后运行一些代码以尝试恢复。”这使我意识到与错误规则相关联的操作从未运行过,因为我在
yyerror
中抛出了一个异常。经过调整后,我可以看到我确实在错误规则上找到了匹配项。谢谢@chris dodd和@uckelman!我也犯了同样的错误。
atom: '(' error    { /* unmatched left paren at @1 */ }
atom: '(' alt error    { /* unmatched left paren at @1 */ }