7

我编写了一个基于 Scala 解析器组合器的解析器:

class SxmlParser extends RegexParsers with ImplicitConversions with PackratParsers {
    [...]
    lazy val document: PackratParser[AstNodeDocument] =
        ((procinst | element | comment | cdata | whitespace | text)*) ^^ {
            AstNodeDocument(_)
        }
    [...]
}
object SxmlParser {
    def parse(text: String): AstNodeDocument = {
        var ast = AstNodeDocument()
        val parser = new SxmlParser()
        val result = parser.parseAll(parser.document, new CharArrayReader(text.toArray))
        result match {
            case parser.Success(x, _) => ast = x
            case parser.NoSuccess(err, next) => {
                tool.die("failed to parse SXML input " +
                    "(line " + next.pos.line + ", column " + next.pos.column + "):\n" +
                    err + "\n" +
                    next.pos.longString)
            }
        }
        ast
    }
}

通常产生的解析错误消息相当不错。但有时它变得只是

sxml: ERROR: failed to parse SXML input (line 32, column 1):
`"' expected but `' found
^

如果引号字符未关闭并且解析器到达 EOT,则会发生这种情况。我想在这里看到的是 (1) 解析器在预期 '"' (我有多个)和 (2) 在输入中该生成开始解析的位置(这是一个指示符开始报价在输入中)。有谁知道我如何改进错误消息并在错误发生时包含有关实际内部解析状态的更多信息(也许像生产规则堆栈跟踪或任何可以在此处合理给出的东西以更好地识别错误位置)顺便说一句,上面的“第 32 行,第 1 列”实际上是 EOT 位置,因此当然在这里没有用处。

4

2 回答 2

3

我还不知道如何处理(1),但是当我找到这个网页时,我也在寻找(2):

https://wiki.scala-lang.org/plugins/viewsource/viewpagesrc.action?pageId=917624

我只是复制信息:

一个有用的增强是记录重要标记的输入位置(行号和列号)。为此,您必须做三件事:

  • 使每个输出类型扩展 scala.util.parsing.input.Positional
  • 调用 Parsers.positioned() 组合器
  • 使用记录行和列位置的文本源

最后,确保源跟踪位置。对于流,您可以简单地使用 scala.util.parsing.input.StreamReader; 对于字符串,使用 scala.util.parsing.input.CharArrayReader。

我目前正在使用它,所以稍后我将尝试添加一个简单的示例

于 2010-06-25T13:19:17.840 回答
1

在这种情况下,您可以使用err,failure~!使用专门设计的生产规则来匹配错误。

于 2010-05-25T22:25:14.863 回答