I wrote the following hello-world parboiled2 parser:
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) }
}
This works mostly as expected, e.g. it successfully parses "1 + 2" as 3.
If I give it invalid input such as "1 + (2", I would expect the parse to fail. But it actually succeeds, with 1 as the result.
It looks like parboiled2 is only parsing part of the input, and ignoring the remainder that it cannot parse. Is this expected behaviour? Is there any way to force the parser to parse the whole input and fail if it cannot do so?
This is expected behavior. parboiled2 is a PEG parser, and as described in the Common Mistakes section in the documentation, it eats everything it can find.
To avoid such a problem, make sure that you expect the end-of-input symbol at the end of your string: