0
最近我一直在玩Scala,当使用解析器组合器时,我遇到了一些扩展它们的问题。基本上,我想要做的就是这样的事情。在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
方法BazStatement
,但上面的代码,我递归调用BazStatement
的方法,所以没办法将正常工作。
我已经看了一下周围的答案,我知道我可以扩展类并使用抽象覆盖,或者像这样的一些思考,但我认为这不会有什么意义,因为BazStatement
是真的有一个额外的功能,我想混入我的基本解析器。我绝对不希望有一些随机的东西,如
object StrangeInheritance extends BazStatement
授权的代码。
在Scala中会不会有任何习惯的方式来正确地做到这一点,还是我需要再次考虑应用程序的一般设计?
对不起,对于迟到的答案。关于这个代码的事情是'对象FooBar扩展BazStatement'完全可以工作,我可以使用'FooBarLanguageParser'中的所有方法,因为我想'BazStatement'是一个额外的功能我的'FooBarLanguageParser'。 –
实际上mixin(traits)是非常惯用的scala方式,提供了特别的模块性。我认为这是默认选项,如果你想提供一种方法来将一组谨慎的行为组合成一个运行时对象。你可能是对的,确实mixin可能无法在这里工作,因为很难以可扩展的方式设计你的顶级解析器。也许在一些实用特征中有一组通用规则,然后在这个“通用规则”特征的帮助下构建“具体”底层解析器,然后尝试使用继承是更好的选择。 – vitalii
感谢您的回答。我想我会像你说的那样用顶级特质定义一般规则和一些具体实现。 –