Error handling 为什么解析器组合器在发生故障时不回溯?

Error handling 为什么解析器组合器在发生故障时不回溯?,error-handling,parser-combinators,peg,Error Handling,Parser Combinators,Peg,我查看了解析器组合器,它说我们需要将failuremsg附加到语法规则中,以使错误报告对用户有意义 def value: Parser[Any] = obj | stringLit | num | "true" | "false" | failure("illegal start of value") 这打破了我对这些解析器中使用的递归机制的理解。一方面,《Artima指南》指出,如果所有产品都失败了,那么解析器将到达返回给用户的值的failureunligal开始。然而,一旦我们理解

我查看了解析器组合器,它说我们需要将failuremsg附加到语法规则中,以使错误报告对用户有意义

def value: Parser[Any] =
    obj | stringLit | num | "true" | "false" | failure("illegal start of value")
这打破了我对这些解析器中使用的递归机制的理解。一方面,《Artima指南》指出,如果所有产品都失败了,那么解析器将到达返回给用户的值的failureunligal开始。然而,一旦我们理解了语法不是价值选择列表而是一棵树,它就没有意义了。也就是说,值解析器是在输入端检测到值时调用的节点。这意味着调用解析器(也是父级)会检测到值解析失败,并继续使用值同级替代方法。假设所有替代价值的方法都失败了。祖父母会尝试其他选择。依次失败,进程向上展开,直到启动符号解析器失败。那么,错误消息是什么?似乎最顶层解析器的最后一个备选方案是错误的

为了弄清楚谁是对的,我创建了一个演示程序,其中程序是最顶级的起始符号解析器

import scala.util.parsing.combinator._

object ExprParserTest extends App with JavaTokenParsers {

    // Grammar
    val declaration = wholeNumber ~ "to" ~ wholeNumber | ident | failure("declaration not found")
    val term = wholeNumber | ident ; lazy val expr: Parser[_] = term ~ rep ("+" ~ expr)
    lazy val statement: Parser[_] = ident ~ " = " ~ expr | "if" ~ expr ~ "then" ~ rep(statement) ~ "else" ~ rep(statement)
    val program  = rep(declaration) ~ rep(statement)

    // Test
    println(parseAll(program, "1 to 2")) // OK
    println(parseAll(program, "1 to '2")) // failure, regex `-?\d+' expected but `'' found at '2
    println(parseAll(program, "abc")) // OK


}
由于额外的勾号,它以1到2失败。是的,它似乎卡在程序->声明->num-to-num规则中,甚至不尝试ident和failuredeclaration-not-found替代方案!出于同样的原因,我也没有追溯到这些陈述。所以,无论是我的猜测还是Artima指南,似乎都不对解析器组合器实际上在做什么。我想知道:解析器组合器中规则感知、回溯和错误报告背后的真正逻辑是什么?为什么错误消息表明没有回溯到声明->标识失败,也没有出现语句?Artima指南建议,如果没有达到我们所看到的或忽略的程度(回溯逻辑应该是这样的),那么将失败放在最后有什么意义


parser combinator不就是一个简单的哑钉吗?信息技术我期望它是PEG,因此,启动符号解析器应该返回所有失败的分支,并想知道实际的解析器为什么/如何选择最合适的失败。

许多解析器组合返回,除非它们在“或”块中。作为一种速度优化,他们将致力于第一个成功的“或”项,而不是回溯。因此,1在语法中尽量避免使用“|”,2如果不可避免地要使用“|”,请将最长或最不可能匹配的项目放在第一位。

你自相矛盾。说第一个备选方案成功后解析失败毫无意义。如果解析失败,则尝试了alternative,但未成功。@LittleAlien如果后续项失败,则无法回溯成功项或尝试其他PAHT。我希望这更明显。你的意思是,如果a是从a~b~c|d|e取的,那么第一个分支是可逆取的吗?