16

给定一系列实现解析器组合器的对象,我如何组合解析器?由于Parsers.Parser是一个内部类,并且在 Scala 中,内部类绑定到外部对象,所以故事变得稍微复杂一些。

这是一个尝试组合来自不同对象的两个解析器的示例。

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-user ML 上提出的(将一个解析器注入另一个解析器时出现问题),因此可能也值得将它放在这里。

4

1 回答 1

17

快速的答案是使用traits 而不是在 s 中托管解析器object

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[_]对您没有任何好处。使用特征解决了所有内部类问题,因为Parser[Any]fromLongChainParserShortChainParsernow 都引用对象的内部类ExampleParser

于 2010-04-16T02:49:45.980 回答