如何在Scala fastparse库中提供显式的错误/失败消息?

dxxyhpgq  于 2023-02-19  发布在  Scala
关注(0)|答案(1)|浏览(190)

我正在使用李浩义的FastParse库。我有几种情况,我想提供明确的失败消息。
例如:

def courseRE[p: P]: P[Regex] =
    P(CharIn("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.|*+[]()-^$").repX(1).!).map { re =>
      try { re.r }
      catch { case e => failure(s"Ill-formed regular expression: ${re}.") }
    }

但是(显然)没有failure函数。
有什么建议的解决方法吗?简单地抛出一个异常不会给出任何上下文信息。

hjzp0vay

hjzp0vay1#

我还没有找到一个好的解决方案。我不喜欢@user2963757提出的解决方案,因为它丢失了解析器的所有信息,包括它要查找的内容,它要查找的位置等等。
这个问题在GitHub上的FastParse问题列表中被多次提出,参见issue 213issue 187issue 243,和pull request 244。有一些模糊的建议,但据我所知,拉取请求还没有被执行(截至2023年2月9日)。
到目前为止,我发现的最好的方法是在一个可访问的位置定义它:

// Fail with a message.  See https://github.com/com-lihaoyi/fastparse/issues/213
  // The message shows up as "Expected ..."; phrase it appropriately.
  private def Fail[T](expected: String)(implicit ctx: P[_]): P[T] = {
    val res = ctx.freshFailure()
    if (ctx.verboseFailures) ctx.setMsg(ctx.index, () => expected)
    res
  }

使用方法:

P(CharIn("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.|*+[]()-^$").repX(1).!).flatMap(re =>
      Try(re.r)
        .map(Pass(_))
        .getOrElse(Fail("<Well-formed regular expression>"))
    )

尝试解析"^CS1[1345"生成

Expected <Well-formed regular expression>:1:10, found ""

注意失败消息必须以预期的方式陈述,而不是实际的问题。异常抛出的实际错误消息通常在这种情况下不能很好地工作。我也没有得到它找到的片段。
不幸的是,即使是这个消息通常也是不可用的。例如,解析我的输入的较大部分会导致

Expected (courseSpecDef | minUnits | xOf | courseSpec):1:14, found "^CS1[1345 "

我希望能够表面更准确的错误“未封闭的字符类”,但似乎不能。
顺便说一下,我在文档、源代码和示例解析器(PythonParse和ScalaParse)中查找了Fail解析器的使用示例,但没有找到任何示例。唯一的示例是文档中显示的示例,它没有与其他解析器组合。
如果有人有更好的解决办法,我还是很想听听。

相关问题