我编写了一个基于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位置,因此当然没有用。
答案 0 :(得分: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;对于Strings,请使用scala.util.parsing.input.CharArrayReader。
我正在玩它,所以我稍后会尝试添加一个简单的例子
答案 1 :(得分:1)
在这种情况下,您可以将err
,failure
和~!
与专门用于匹配错误的制作规则一起使用。