I've been playing around with Scala recently, and when working with parser combinators, I kind of had some problems extending them. Basically, what I'm trying to do is something like this.
import scala.util.parsing.combinator.RegexParsers
abstract class Statement
case object Foo extends Statement
case object Bar extends Statement
case object Baz extends Statement
class Program(statements: List[Statement])
class FooBarLanguageParser extends RegexParsers {
def program: Parser[Program] = rep(statement) ^^ (v => new Program(List() ++ v))
def statement: Parser[Statement] = foo|bar
def foo: Parser[Statement] = "foo" ^^ (_ => Foo)
def bar: Parser[Statement] = "bar" ^^ (_ => Bar)
}
trait BazStatement { this: FooBarLanguageParser =>
override def statement: Parser[Statement] = baz|this.statement // inifinite recursion
def baz: Parser[Statement] = "baz" ^^ (_ => Baz)
}
object Main {
def main(args: Array[String]) {
val normalFooBar = new FooBarLanguageParser()
val fooBarProgram = normalFooBar.parseAll(normalFooBar.program, "foo bar")
val extendedFooBar = new FooBarLanguageParser() with BazStatement
val extendedFooBarProgram = extendedFooBar.parseAll(extendedFooBar.program,
"foo bar baz")
println(fooBarProgram.successful)
println(extendedFooBarProgram.successful)
}
}
Here, I would like to call FooBarLanguageParser
's statement
method in BazStatement
, but with the above code I'm recursively calling BazStatement
's method, so no way it would work properly.
I already took a look at the answers around, and I know that I could extend the class and use abstract override, or somethink like this, but I don't think it would really make any sense here, as BazStatement
is really an additional feature I want to mixin with my basic parser. I definitely don't want to have some random things like
object StrangeInheritance extends BazStatement
authorized in the code.
Would there be any idiomatic way to do this properly in Scala or do I need to think again about the general design of the app?