Skip to content

Instantly share code, notes, and snippets.

@sdether
Last active January 19, 2017 06:50
Show Gist options
  • Save sdether/2c7bd811516929dc519698b3dc6fcf55 to your computer and use it in GitHub Desktop.
Save sdether/2c7bd811516929dc519698b3dc6fcf55 to your computer and use it in GitHub Desktop.
Expressing ABNF syntax as types and building grammar from those types
trait Rule {}
object ALPHA extends Rule
object DIGIT extends Rule
object OCTET extends Rule
case class Alternative(rules: Rule*) extends Rule
case class Concatenation(rules: Rule*) extends Rule
case class SpecificRepetition(rule: Rule, n: Int) extends Rule
case class VariableRepetition(rule: Rule, lower: Option[Int] = None, upper: Option[Int] = None) extends Rule
case class Terminal(value: String) extends Rule
case class Range(lower: Char, upper: Char) extends Rule
case class Single(c: Char) extends Rule
object CookieDateParser {
val timefield = VariableRepetition(DIGIT, Some(1), Some(2))
val hmsTime = Concatenation(timefield, Terminal(":"), timefield, Terminal(":"), timefield)
val nonDigit = Alternative(Range(0x00, 0x2f), Range(0x3a, 0xff))
val time = Concatenation(hmsTime, Concatenation(nonDigit, VariableRepetition(OCTET)))
val year = Concatenation(
VariableRepetition(DIGIT, Some(2), Some(4)),
Concatenation(nonDigit, VariableRepetition(OCTET))
)
val month = Concatenation(
Alternative(
Terminal("jan"), Terminal("feb"), Terminal("mar"), Terminal("apr"), Terminal("may"), Terminal("jun"),
Terminal("jul"), Terminal("aug"), Terminal("sep"), Terminal("oct"), Terminal("nov"), Terminal("dev")
),
VariableRepetition(OCTET)
)
val dayOfMonth = Concatenation(
VariableRepetition(DIGIT, Some(1), Some(2)),
Concatenation(nonDigit, VariableRepetition(OCTET))
)
val nonDelimiter = Alternative(
Range(0x00, 0x08),
Range(0x0a, 0x1f),
DIGIT,
Terminal(":"),
ALPHA,
Range(0x7f, 0xff)
)
val delimiter = Alternative(
Single(0x09),
Range(0x20, 0x2f),
Range(0x3b, 0x40),
Range(0x5b, 0x60),
Range(0x7b, 0x7e)
)
val dateToken = VariableRepetition(nonDelimiter, Some(1))
val dateTokenList = Concatenation(
dateToken,
VariableRepetition(Concatenation(VariableRepetition(delimiter, Some(1)), dateToken))
)
}
@sdether
Copy link
Author

sdether commented Jan 19, 2017

I can see how to write a parser that pattern matches over some Rule composition, but I cannot figure out how to weave the extracting into that parser. Clearly each definition above needs to instead be some monadic wrapper capturing both the rule composition and the resulting type, but I'm struggling making the leap to that abstraction

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment