Parsing 递归下降分析器中的错误报告

Parsing 递归下降分析器中的错误报告,parsing,language-agnostic,ebnf,recursive-descent,Parsing,Language Agnostic,Ebnf,Recursive Descent,我正在为配置文件编写递归下降解析器。这些文件大部分类似于ini文件。以下是某种类似EBNF的形式的语言: document ::= { category } category ::= title {entry} title ::= "[" <name> "]" entry ::= <key> ":" <value> 我可以在网上找到的所有示例都会解析输入,直到到达无效符号,然后在不打印有用错误消息的情况下退出。我有

我正在为配置文件编写递归下降解析器。这些文件大部分类似于ini文件。以下是某种类似EBNF的形式的语言:

document     ::= { category }
category     ::= title {entry}
title        ::= "[" <name> "]"
entry        ::= <key> ":" <value>
我可以在网上找到的所有示例都会解析输入,直到到达无效符号,然后在不打印有用错误消息的情况下退出。我有一个遵循这种行为的工作解析器,但我不确定如何实现有用的错误报告

例如,
文档
由零个或多个类别组成。当前两个类别的解析没有错误,但第三个类别包含语法错误时,我该怎么办?如果输入在第二个类别之后结束,而我无法解析第三个类别,因为没有留下任何标记(这不应产生错误消息),该怎么办?我如何区分这些情况?无效行可以通过两种方式生效:成为条目或成为标题。这使我困惑


我希望我的程序在到达上述输入的最后一行时打印类似于
第9行:预期条目或标题的内容。人们通常是如何在递归下降解析器中实现错误消息的?

我想你问了几个大的、不相关的问题,我将尝试回答它们:

当前两个类别的解析没有错误,但第三个类别包含语法错误时,我该怎么办

这当然取决于你的要求。从严格意义上讲,这将是验证失败,因为传入的文档实际上不符合您的语法规则,这是由于您提到的违反。它是否抛出错误、返回false、返回部分结果,都符合您的要求

如果输入在第二个类别之后结束,而我无法解析第三个类别,因为没有留下任何标记(这不应产生错误消息),该怎么办?我如何区分这些情况

正如您所说,这里没有问题,因为它符合
文档
符号。如果您对实际实现感到困惑,那么这就是实现细节(您没有提供任何代码)

也许您应该尝试将EBNF可视化为更基本的BNF形式,而不使用
{}
扩展,下面是一个示例:

document     ::= category
category     ::= title entries category | title entries
title        ::= "[" <name> "]"
entries      ::= entry | entries
entry        ::= <key> ":" <value>
文档::=类别
类别::=标题条目类别|标题条目
标题::=“[”“]”
条目::=条目|条目
条目::=“:”
我个人认为,用这种方式表示语法可以为需要递归的地方提供更多的指导。例如,在本例中,您需要尝试在
类别
符号解析中解析
类别
。代码的结构或多或少会遵循这一点——即,如果它不能将下一个符号解析为一个类别,那么无论如何都会返回true(因为第二个定义
标题条目紧随其后)

人们通常如何在递归下降解析器中实现错误消息

我自己也有同样的问题,但鉴于我找不到任何答案,我将按以下方式实施:

  • 当我解析和吃令牌时,我将存储消耗的长度
  • 当出现错误时,不要立即抛出它-将其与已解析的令牌数量一起存储
  • 在解析结束时(包括回溯),如果没有可解析的解决方案,抛出消耗最多符号的错误

  • 关键是#2。在实现带回溯的递归下降解析器时,可能会抛出多个误报。我认为就可用性而言,简单地抛出解析得最远的字符串通常是一种不错的启发式方法。

    我通常会这样做:“解析错误行42:找到“%”,预期“&.”使无效字符串有效是一项非常复杂的任务。首先做一个简单的错误报告,我同样找不到任何好的例子。好办法!
    document     ::= category
    category     ::= title entries category | title entries
    title        ::= "[" <name> "]"
    entries      ::= entry | entries
    entry        ::= <key> ":" <value>