Scala:如何组合来自不同对象的解析器组合器 [英] Scala: How to combine parser combinators from different objects
问题描述
给定一个实现解析器组合器的对象家族,我如何组合解析器?由于 Parsers.Parser
是一个内部类,在Scala中,内部类绑定到外部对象 ,故事变得有些复杂.
Given a family of objects that implement parser combinators, how do I combine the parsers? Since Parsers.Parser
is an inner class, and in Scala inner classes are bound to the outer object, the story becomes slightly complicated.
这是一个示例,试图组合来自不同对象的两个解析器.
Here's an example that attempts to combine two parsers from different objects.
import scala.util.parsing.combinator._
class BinaryParser extends JavaTokenParsers {
def anyrep: Parser[Any] = rep(any)
def any: Parser[Any] = zero | one
def zero: Parser[Any] = "0"
def one: Parser[Any] = "1"
}
object LongChainParser extends BinaryParser {
def parser1: Parser[Any] = zero~zero~one~one
}
object ShortChainParser extends BinaryParser {
def parser2: Parser[Any] = zero~zero
}
object ExampleParser extends BinaryParser {
def parser: Parser[Any] = (LongChainParser.parser1
||| ShortChainParser.parser2) ~ anyrep
def main(args: Array[String]) {
println(parseAll(parser, args(0) ))
}
}
这将导致以下错误:
<console>:11: error: type mismatch;
found : ShortChainParser.Parser[Any]
required: LongChainParser.Parser[?]
def parser: Parser[Any] = (LongChainParser.parser1
||| ShortChainParser.parser2) ~ anyrep
我已经找到了解决此问题的方法,但是自从提出以来 最近在scala用户ML(将一个解析器注入另一个解析器中),也可能值得将其放在这里.
I've found the solution to this problem already, but since it was brought up recently on scala-user ML (Problem injecting one parser into another), it's probably worth putting it here too.
推荐答案
快速答案是使用trait
而不是在object
s中托管解析器:
The quick answer is to use the trait
s instead of hosting the parsers in object
s:
import scala.util.parsing.combinator._
trait BinaryParser extends JavaTokenParsers {
def anyrep: Parser[Any] = rep(any)
def any: Parser[Any] = zero | one
def zero: Parser[Any] = "0"
def one: Parser[Any] = "1"
}
trait LongChainParser extends BinaryParser {
def parser1: Parser[Any] = zero~zero~one~one
}
trait ShortChainParser extends BinaryParser {
def parser2: Parser[Any] = zero~zero
}
object ExampleParser extends LongChainParser with ShortChainParser {
def parser: Parser[Any] = (parser1 ||| parser2) ~ anyrep
def main(args: Array[String]) {
println(parseAll(parser, args(0) ))
}
}
因为像~
和|
这样的组合运算符是针对内部类编写的,所以说BinaryParser#Parser[_]
对您没有任何帮助,从而将解析器引用升级到类级别.使用特征可以解决所有内部类问题,因为LongChainParser
和ShortChainParser
中的Parser[Any]
现在都引用ExampleParser
对象的内部类.
Because the combinator operators like ~
and |
are written against the inner class, escalating the parser references to class-level by saying BinaryParser#Parser[_]
doesn't do you any good. Using traits solves all that inner-class issues since both Parser[Any]
from LongChainParser
and ShortChainParser
now refer to the inner class of ExampleParser
object.
这篇关于Scala:如何组合来自不同对象的解析器组合器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!