我在这里已经阅读了一些关于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
,那么为什么 - 因为它的定义包括|
未能尝试强制执行err
- 是否显示foo
作品中最左边的终端的错误消息?
有没有办法在解析结果中查看一堆错误消息并始终找到我的并显示给用户?或者我是否需要实现自己的repsep
版本?我相信我错过了关于正在发生的事情的概念模型:(
答案 0 :(得分:0)
不,您不需要重新编写{{1}}或跟踪自己的错误消息。解析器组合器的行为似乎就像你要求的那样。它匹配" foo"一次,然后找到","。但是后来它失败了" bar"但是因为它已经吞噬了#34; foo"和",",它无法回馈它们,然后尝试第二种选择(您的错误信息)。如果这真的是你想要的行为,你可以尝试使用packrat解析器。
答案 1 :(得分:0)
根据我上面的评论:我最终使用FastParse(lihaoyi.com/fastparse)解决了这个问题。有一个opaque方法包装解析器并产生一个在失败时有用的自定义错误消息。 E.g:
val test = foo.rep(1,",").opaque("Custom Message Repsep")
总的来说,我发现FastParse比Scala Parser Combinators更快,更容易使用。