在Scala中修改具有类型特征的类

时间:2013-06-01 05:50:02

标签: scala typetraits parser-combinators

我最近一直在玩Scala,在使用解析器组合器时,我遇到了一些扩展它们的问题。基本上,我想做的就是这样。

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)
  }
}

在这里,我想在FooBarLanguageParser中调用statement的{​​{1}}方法,但是使用上面的代码我会递归调用BazStatement的方法,所以它无法正常工作。

我已经看过周围的答案了,我知道我可以扩展类并使用抽象覆盖,或者像这样思考,但我不认为它在这里有任何意义,因为{{1我真的想要与我的基本解析器混合使用。我绝对不希望有一些随机的东西,比如

BazStatement

在代码中授权。

在Scala中是否有任何惯用的方法可以正确地执行此操作,还是需要再次考虑应用程序的一般设计?

1 个答案:

答案 0 :(得分:0)

使用super调用supertype的方法,也使用traits来定义顶级抽象。这个运行正常:

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])

trait 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 extends FooBarLanguageParser {
  override def statement: Parser[Statement] = baz| super.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)
  }
}