I am writing an cron parser, but compiler complains illegal rule composition,
What's wrong with my parser?
import org.parboiled2._
sealed trait Part
case class Fixed(points: Seq[Int]) extends Part
case class Range(start: Int, end: Int) extends Part
case class Every(start: Int, interval: Int) extends Part
case object Full extends Part
case object Ignore extends Part
class CronParser(val input: ParserInput) extends Parser {
def number = rule { capture(digits) ~> (_.toInt) }
def digits = rule { oneOrMore(CharPredicate.Digit) }
def fixed = rule { oneOrMore(number).separatedBy(",") ~> Fixed }
def range = rule { digits ~ '-' ~ digits ~> Range }
def every= rule { digits ~ '/' ~ digits ~> Every }
def full= rule { '*' ~ push(Full) }
def ignore = rule { '?' ~ push(Ignore) }
def part = rule { fixed | range | every | full | ignore }
def expr = rule { part ~ part ~ part ~ part ~ part}
}
You're using digits
where I think you want to be using number
. The following should work just fine:
class CronParser(val input: ParserInput) extends Parser {
def number = rule { capture(digits) ~> (_.toInt) }
def digits = rule { oneOrMore(CharPredicate.Digit) }
def fixed = rule { oneOrMore(number).separatedBy(",") ~> Fixed }
def range = rule { number ~ '-' ~ number ~> Range }
def every = rule { number ~ '/' ~ number ~> Every }
def full = rule { '*' ~ push(Full) }
def ignore = rule { '?' ~ push(Ignore) }
def part = rule { fixed | range | every | full | ignore }
def expr = rule { part ~ part ~ part ~ part ~ part }
}
The problem was that digits
doesn't push a value, which meant that range
, etc. were rules that wanted to pop values off the stack, and these weren't able to be composed with ~
.