I want to parse a LOLCODE
script using Scala parser combinators. Here is what I got by far:
class ValuePT(val value: String) extends ExpressionPT {
override def toString = value
}
def value: Parser[ValuePT] = (numericLit | stringLit) ^^ {
case a => new ValuePT(a)
}
def expression: Parser[ExpressionPT] = (...| id | value) ^^ {
case a => a
}
def statement: Parser[StatementPT] = (...|expression|...|loop) <~ eol ^^ {case a => a}
def condition: Parser[LoopConditionPT] = (value <~ "YR") ~ id ~ opt(("TIL"|"WILE") ~ expression) ^^ {
case a ~ b ~ Some(c ~ d) => new LoopConditionPT(a toString, b, Option(c -> d))
case a ~ b ~ None => new LoopConditionPT(a toString, b, Option("None" -> new IdentPT("-1")))
}
def loop: Parser[LoopPT] = ("IM IN YR" ~> id ~ opt(condition) <~ eol) ~ rep(statement) <~ "IM OUTTA YR" <~ id ^^ {
case a ~ b ~ c => new LoopPT(a, b, c)
}
My test case looks like this:
HAI 1.2
IM IN YR UntilLoop UPPIN YR Var TIL BOTH SAEM Var AN 3
VISIBLE "UntilLoop " Var
IM OUTTA YR UntilLoop
IM IN YR WhileLoop bla YR Var
VISIBLE "WhileLoop " Var
IM OUTTA YR WhileLoop
I HAS A x ITZ 1
I HAS A y ITZ 1
IM IN YR NestedLoop
IM IN YR InnerLoop
VISIBLE "NestedLoop " x " " y
GTFO
IM OUTTA YR InnerLoop
GTFO
IM OUTTA YR NestedLoop
KTHXBYE
But my function doesn't work, it raises an error:
[2.24] failure: eol expected
IM IN YR UntilLoop UPPIN YR Var TIL BOTH SAEM Var AN 3
^
I don't understand and I don't know what causes the error, is it says that I was missing eol
before UPPIN
?
What is clear from the code is that condition
is failing to match, which is fine from the parser's perspective because its opt(condition)
. But when it fails, it is expecting an eol
next.
It looks like you are expecting condition
to match the rest of the line. Because you get the error at eol
, that means that condition
fails on the first token, because otherwise Scala would have reported the error from the branch that made further progress. Without the definition of value
, it is impossible to tell what exactly is failing, but a general rule for debugging opt
parsers is to remove the opt
when testing examples. This way, you always get an error from the inside of opt
rather than letting opt
quietly match nothing.