Search code examples
scalaparsingparser-combinators

Scala parser combinator: Failure - eol (end of line) expected


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?


Solution

  • 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.