我最近一直在玩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中是否有任何惯用的方法可以正确地执行此操作,还是需要再次考虑应用程序的一般设计?
答案 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)
}
}