0

我在这里阅读了一些关于 Scala 解析器组合器和更好的错误处理的帖子,但是很多“解决方案”似乎都说“只使用'~!'”或“使用语法规则预测失败案例”。

所以我尝试实施其中的一些建议,但我无法理解失败/错误解析器的工作原理:

val foo: Parser[String] = """foo""".r | err("Custom Message")
val test: Parser[List[String]] = repsep(foo, ",") | err("Custom Message Repsep")
val r = parseAll(foo, ""bar") //[1.1] error: Custom Message -- YAY
val r = parseAll(test, "foo, bar") //[1.2] failure: string matching regex `foo' expected but `b' found -- NOOOOOO

我的问题基本上是:如果foo因为 被反复尝试对输入字符串进行尝试repsep,那么为什么 - 因为它的定义包括一个|on failure to try and force an err- 来自生产中最左边的终端的错误消息foo被显示?

有没有办法在解析结果中查看一堆错误消息并始终找到我的并显示给用户?还是我需要实现我自己的版本repsep或什么?我相信我错过了关于正在发生的事情的概念模型的一些东西:(

4

2 回答 2

1

根据我上面的评论:我最终通过使用 FastParse (lihaoyi.com/fastparse) 解决了这个问题。有一种方法 opaque 可以包装解析器并生成自定义错误消息,该错误消息在失败时很有用。例如:

val test = foo.rep(1,",").opaque("Custom Message Repsep")

总的来说,我发现 FastParse 比 Scala Parser Combinators 更快,更容易使用。

于 2016-03-16T13:31:33.147 回答
0

不,您不需要重新编写repsep或跟踪您自己的错误消息。解析器组合器的行为似乎就像您要求的那样。它匹配“foo”一次,然后找到“,”。但后来它在“bar”上失败了,但由于它已经吞噬了“foo”和“,”,它不能把它们还给它们,然后尝试第二种选择(你的错误消息)。如果这确实是您想要的行为,您可以尝试使用 packrat 解析器。

于 2016-03-11T05:12:30.923 回答