Search code examples
scalaparsingparser-combinators

Scala Parser: but it is neither contained in the delimiters list, nor in the reserved keyword list of lexical


I have written a scala parser using parser combinator:

  case class KW(str: String) {

    val parser: Parser[String] = str
  }

  implicit class SymbolView(symbol: Symbol) {

    val $: KW = {
      KW(symbol.name.toLowerCase())
    }
  }

  implicit def ks2Parser(ks: KW): Parser[String] = ks.parser

  val _DELETE = 'delete $
  val _REMOVE = 'remove $
  val _DROP = 'drop $
  val DELETE = _DELETE | _REMOVE | _DROP

  lexical.reserved ++= Seq("delete", "remove", "drop")

  val scanner: lexical.Scanner = new lexical.Scanner("delete")

  phrase(DELETE).apply(scanner)

However scala parser give me this error:

failure: You are trying to parse "drop", but it is neither contained in the delimiters list, nor in the reserved keyword list of your lexical object

I'm very sure both "delete" and "drop" are both contained in the reserved keyword list of lexical (I've found both in debug mode). So this error information is obviously wrong. Is it a bug in scala parser combinator? What should I do to fix it?


Solution

  • When you use $, StandardTokenParsers.keyword eventually gets invoked implictly in the line val parser: Parser[String] = str. It uses the contents of lexical.reserved at the time of invocation. And those invocations happen when you create _DELETE/_REMOVE/_DROP parsers, which is before you add tokens to lexical.reserved.

    So either move the line to add reserved tokens before parsers creation:

    lexical.reserved ++= Seq("delete", "remove", "drop")
    
    val _DELETE = 'delete $
    val _REMOVE = 'remove $
    val _DROP = 'drop $
    val DELETE = _DELETE | _REMOVE | _DROP
    

    Or make parser definitions defs (or lazy vals) instead of vals:

    def _DELETE = 'delete $
    def _REMOVE = 'remove $
    def _DROP = 'drop $
    def DELETE = _DELETE | _REMOVE | _DROP