如何使 parboiled2 匹配整个输入?
How to make parboiled2 match the whole input?
我编写了以下 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 只解析了输入的一部分,而忽略了它无法解析的其余部分。这是预期的行为吗?有没有办法强制解析器解析整个输入,如果不能解析则失败?
这是预期的行为。 parboiled2 是一个 PEG 解析器,如文档中 Common Mistakes 部分所述,它会吃掉它能找到的所有东西。
为避免此类问题,请确保您期望字符串末尾有输入结束符号:
def Expr: Rule1[Int] = rule { Sum ~ EOI }
如果我输入“1+(2+3*4)+5”,解析就会失败。定义另一个根规则并保留 Expr 原样即可解决问题:
def InputLine = rule { Expr ~ EOI }
def Expr: Rule1[Int] = rule { Sum }
我编写了以下 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 只解析了输入的一部分,而忽略了它无法解析的其余部分。这是预期的行为吗?有没有办法强制解析器解析整个输入,如果不能解析则失败?
这是预期的行为。 parboiled2 是一个 PEG 解析器,如文档中 Common Mistakes 部分所述,它会吃掉它能找到的所有东西。
为避免此类问题,请确保您期望字符串末尾有输入结束符号:
def Expr: Rule1[Int] = rule { Sum ~ EOI }
如果我输入“1+(2+3*4)+5”,解析就会失败。定义另一个根规则并保留 Expr 原样即可解决问题:
def InputLine = rule { Expr ~ EOI }
def Expr: Rule1[Int] = rule { Sum }