我需要一个不那么复杂的语言的解析器。唯一的问题是,我从不希望解析器在收到格式错误的输入时引发错误。相反,我希望它继续,尽可能多地理解输入,类似于 Web 浏览器中的 HTML 解析器所做的。
我很自然地想使用解析器生成器,但我对它们没有太多经验,而且我看到的所有关于 Bison 和 Antlr 的示例都具有脆弱的解析器,一旦遇到语法错误就会放弃。这对他们可行吗,还是我应该考虑手动滚动它?考虑到语言,它可能(我认为)不会那么困难。
您需要在设计语法时考虑到检查点。检查点是指 C 的分号、Python 的换行符或 COBOL 的句点(例如)。这个检查点是多少编译器恢复,以便他们可以报告的不仅仅是发现的第一个错误。
我没有使用 Bison,但 YACC 允许您覆盖错误处理,我希望等效的 GNU 工具至少与我们的旧 UNIX 旧工具一样强大。
我以前用配置文件 YACC 语法做过这个。假设您有以下正确形成的段:
item = "bread" {
quantity = 7
price = 1.50
taxrate = 10
}
由于某些奇怪的原因,用户拼错了“数量”,使其不正确。在您的回调中,您可以只引发一个错误标志,该标志将阻止进一步处理,直到到达检查点。您让解析器继续运行(捕获并忽略进一步的错误)并确保您的回调不做任何事情来响应损坏语法中的任何虚假成功。
这可以通过简单地忽略所有进一步的节直到右括号,或者甚至通过设置价格的默认值并且只忽略到换行符(这样你至少得到一个部分形成的对象)。
不管你怎么做,只要在你到达检查点时重置错误标志,你就可以继续处理。
我仍然会确保通知用户,有时认为继续使用客户不想要的数据是不好的形式:-)。
在一般情况下,我不确定您是否能够使用解析器生成器来做到这一点。至少,不是以完全自动的方式。考虑以下格式错误的表达式:
a - b + c ) * d
解析器甚至应该对此做什么?当它遇到第一个非法令牌,即右括号时,它可能会以某种方式猜测用户打算在某处使用左括号,但在哪里?它可以放在任何地方都会导致不同的值。
相反,它可以假装之前发生的一切都没有发生过。然后它会结束
* d
这仍然是畸形的。