如何使parboiled2匹配整个输入?

时间:2015-02-05 11:41:44

标签: scala parsing parboiled parboiled2

我编写了以下hello-world parboiled2解析器:

class MyParser(val input: ParserInput) extends Parser {

 /*
  Expr     <- Sum
  Sum      <- Product ('+') Product)*
  Product  <- Value (('*') Value)*
  Value    <- Constant | '(' Expr ')'
  Constant <- [0-9]+
  */

  def Expr: Rule1[Int] = rule { Sum }

  def Sum: Rule1[Int] = rule { oneOrMore(Product).separatedBy(" + ") ~> ((products: Seq[Int]) => products.sum) }

  def Product: Rule1[Int] = rule { oneOrMore(Value).separatedBy(" * ") ~> ((values: Seq[Int]) => values.product) }

  def Value: Rule1[Int] = rule { Constant | ('(' ~ Expr ~ ')') }

  def Constant: Rule1[Int] = rule { capture(oneOrMore(Digit)) ~> ((digits: String) => digits.toInt) }

}

这主要按预期工作,例如它成功地将“1 + 2”解析为3。

如果我给它输入无效的输入,例如“1 +(2”,我希望解析失败。但它实际上是成功的,结果是1。

看起来parboiled2只解析输入的一部分,并忽略它无法解析的余数。这是预期的行为吗?有没有办法强制解析器解析整个输入,如果不能这样做就会失败?

2 个答案:

答案 0 :(得分:3)

这是预期的行为。 parboiled2是一个PEG解析器,如文档中的Common Mistakes部分所述,它会吃掉它能找到的所有东西。

要避免此类问题,请确保您希望字符串末尾的输入结束符号符合:

def Expr: Rule1[Int] = rule { Sum ~ EOI }

答案 1 :(得分:1)

如果我输入“1+(2 + 3 * 4)+5”,则解析将失败。定义另一个根规则并保留 Expr ,因为它可以解决这个问题:

def InputLine = rule { Expr ~ EOI }
def Expr: Rule1[Int] = rule { Sum }