I am trying to create a simple parser as below. However, I am not sure why combinator parser is complaining on not recognizing 'floatingPointNumber' when there are 'dates' format. It recognizes when it is 'ident'
Below is the code with error.
Many thanks for help!
import scala.util.parsing.combinator.JavaTokenParsers
class MyParser extends JavaTokenParsers {
def dates = repsep(date, ";")
def date = """\d{2}-[a-zA-Z]{3}-\d{4}""".r
def value = ident | dates | date | floatingPointNumber
def obj = "("~>repsep(value,",")<~")"
}
object MyParser extends MyParser {
def main(args: Array[String]): Unit = {
println(parseAll(obj, "(22-Jan-2016;09-Mar-2015)"))
println(parseAll(obj, "(22-Jan-2016;09-Mar-2015,blah3)"))
println(parseAll(obj, "(22-Jan-2016;09-Mar-2015,32)"))
}
}
[1.26] parsed: List(List(22-Jan-2016, 09-Mar-2015))
[1.32] parsed: List(List(22-Jan-2016, 09-Mar-2015), blah3)
[1.26] failure: `)' expected but `3' found
(22-Jan-2016;09-Mar-2015,32)
^
Assuming you want at least one date
to be present in dates
, using
def dates = rep1sep(date, ";")
seems to fix the problem.
I believe the reason is that the dates
parser is able to accept an empty string (i.e. "" would parse as Nil
), and that causes the floatingPointNumber
part of the value
parser to never be evaluated. If you change dates
so it cannot accept an empty input, the parse succeeds:
def fixedDates = rep1sep(date, ";")
def fixedValue = ident | fixedDates | date | floatingPointNumber
def fixedObj = "("~>repsep(fixedValue,",")<~")"
parseAll(fixedObj, "(22-Jan-2016;09-Mar-2015,32)")
// MyParser.ParseResult[List[Object]] =
// [1.29] parsed: List(List(22-Jan-2016, 09-Mar-2015), 32)