我有一个使用括号和方括号作为分隔符的语法。当bison生成的解析器被赋予带有不平衡分隔符的输入时,传递给YYLTYPE*
的{{1}}中的错误位置是输入的结束。因此,例如,在输入yyerror
上,在xx(yy
内我有void yyerror(YYLTYPE* yylloc, Context* ctx, const char* msg)
。不幸的是,输入的结尾不是指示不匹配分隔符的最显着位置。更有用的是左括号或左方括号的位置,没有匹配。 (在示例中,这将是偏移量2处的左括号。)我收集到该信息在解析堆栈中可用 - 必须有一些 n ,以便{{1} }是不匹配的yylloc->first_column == yylloc->last_column == 5
或$-n
令牌,(
是保持其位置的[
结构 - 但似乎没有@-n
可用。我知道我可以保留一堆我自己用于跟踪分隔符的偏移并隐藏在YYLTYPE
我已经传递给yyerror
,但这看起来不那么优雅和重复,就像野牛一样已经在跟踪这个了。
那么:如何从bison中获得它在输入中遇到的第一个不平衡分隔符的位置,以便在为解析错误生成消息时可以使用它?
答案 0 :(得分:6)
您应该可以添加规则:
atom: '(' error { /* unmatched left paren at @1 */ }
或
atom: '(' alt error { /* unmatched left paren at @1 */ }
获取有关不匹配的左括号的信息。不同之处在于第一个规则将匹配一个不匹配任何可解析的不匹配的括号(例如在输入的末尾),而第二个规则只匹配如果它后面跟一个看似有效的{{1 }}
如果您的语法中有任何其他错误产生(您没有在链接语法中),则可能存在问题,在这种情况下,可能首先触发不同的错误产生。由于没有其他错误规则,第一种选择更好。
请注意,使用yacc / bison错误恢复规则不会以任何方式抑制语法错误,它只是在语法错误后运行一些代码以尝试恢复。该代码可以打印其他错误消息,然后中止而不是尝试恢复,但这些消息将在语法错误消息后打印。
答案 1 :(得分:1)
查看野牛中的错误令牌:http://www.gnu.org/software/bison/manual/html_node/Error-Recovery.html#Error-Recovery
我想这样的事情会起作用(我还没有测试过):
atom: '(' alt ')' { $$ = $2; }
| '(' alt error '\n' { /* this handles an extra left paren */ }
| error alt ')' { /* this handles an extra right paren */ }
| literal
;