I took this from a project that claims to parse real numbers, but it somehow eats the pre-decimal part:
object Main extends App {
import org.parboiled.scala._
val res = TestParser.parseDouble("2.3")
println(s"RESULT: ${res.result}")
object TestParser extends Parser {
def RealNumber = rule {
oneOrMore(Digit) ~ optional( "." ~ oneOrMore(Digit) ) ~> { s =>
println(s"CAPTURED '$s'")
s.toDouble
}
}
def Digit = rule { "0" - "9" }
def parseDouble(input: String): ParsingResult[Double] =
ReportingParseRunner(RealNumber).run(input)
}
}
This prints:
CAPTURED '.3'
RESULT: Some(0.3)
What is wrong here? Note that currently I cannot go from Parboiled-1 to Parboiled-2, because I have a larger grammar that would have to be rewritten.
As stated in parboiled documentation, action rules like
~>
take the match of the immediately preceding peer rule. In the rule sequenceoneOrMore(Digit) ~ optional( "." ~ oneOrMore(Digit) )
the immediately preceding rule isoptional( "." ~ oneOrMore(Digit) )
, so you get only its match".3"
in the action rule.To fix that you may, for example, extract the first two elements into a separate rule:
Or push both parts onto the stack and then combine them: