首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用megaparsec报告多个错误?

如何使用megaparsec报告多个错误?
EN

Stack Overflow用户
提问于 2020-01-08 13:43:45
回答 1查看 259关注 0票数 5

每百万秒的文档,"Since version 8, reporting multiple parse errors at once has become much easier."我还没能找到一个这样做的例子。我唯一找到的就是this。然而,它只展示了如何解析换行符分隔的玩具语言,也没有展示如何combine multiple errors到ParseErrorBundle中。这个SO discussion不是决定性的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-11 03:17:24

您希望结合使用withRecoveryregisterParseError (或registerFailureregisterFancyFailure)从兆秒级生成的错误中恢复,以便“注册”这些错误(或您自己生成的错误)以进行延迟处理。

在解析结束时,如果没有注册解析错误,则解析成功,而如果注册了一个或多个解析错误,则一次性打印所有错误。如果您注册了解析错误,然后还触发了一个未恢复的错误,解析将立即终止,并且将打印所有已注册的错误和最终的未恢复的错误。

下面是一个非常简单的示例,它解析一个逗号分隔的数字列表:

代码语言:javascript
复制
import Data.Void
import Text.Megaparsec
import Text.Megaparsec.Char

type Parser = Parsec Void String

numbers :: Parser [Int]
numbers = sepBy number comma <* eof
  where number = read <$> some digitChar
        comma  = recover $ char ','
        -- recover to next comma
        recover = withRecovery $ \e -> do
          registerParseError e
          some (anySingleBut ',')
          char ','

在良好的输入上:

代码语言:javascript
复制
> parseTest numbers "1,2,3,4,5"
[1,2,3,4,5]

在有多个错误的输入上:

代码语言:javascript
复制
> parseTest numbers "1.2,3e5,4,5x"
1:2:
  |
1 | 1.2,3e5,4,5x
  |  ^
unexpected '.'
expecting ','

1:6:
  |
1 | 1.2,3e5,4,5x
  |      ^
unexpected 'e'
expecting ','

1:12:
  |
1 | 1.2,3e5,4,5x
  |            ^
unexpected 'x'
expecting ',', digit, or end of input

这里有一些微妙之处。对于以下情况,仅处理第一个解析错误:

代码语言:javascript
复制
> parseTest numbers "1,2,e,4,5x"
1:5:
  |
1 | 1,2,e,4,5x
  |     ^
unexpected 'e'
expecting digit

您必须仔细研究解析器以了解原因。sepBy成功地交替使用了numbercomma解析器来解析"1,2,"。当到达e时,它将应用失败的number解析器(因为some digitChar至少需要一个数字字符)。这是一个无法恢复的错误,因此解析会立即结束,不会注册其他错误,因此只会打印一个错误。

此外,如果您从numbers的定义中删除了<* eof (例如,使其成为更大解析器的一部分),您会发现:

代码语言:javascript
复制
> parseTest numbers "1,2,3.4,5"

在句点上给出一个分析错误,但是:

代码语言:javascript
复制
> parseTest numbers "1,2,3.4"

解析正常。另一方面:

代码语言:javascript
复制
> parseTest numbers "1,2,3.4\n hundreds of lines without commas\nfinal line, with comma"

在文件末尾的句号和逗号上提供分析错误。

问题是sepBy使用comma解析器来确定逗号分隔的数字列表何时结束。如果解析器成功(它可以通过恢复来完成,在下一个逗号之前吞噬数百行),sepBy将尝试继续运行;如果解析器失败(最初都失败,并且因为恢复代码在扫描整个文件后找不到逗号),sepBy将完成。

最后,编写可恢复的解析器是一件很棘手的事情。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59640023

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档