1

在一个特征中,我无法使用从另一个特征中的方法返回的解析器。编译器抱怨类型不匹配,在我看来问题是由于路径相关类造成的。我不知道如何得到我想要的。

trait Outerparser extends RegexParsers {

  def inner: Innerparser

  def quoted[T](something: Parser[T]) = "\"" ~> something <~ "\""
  def quotedNumber = quoted(inner.number)     // Compile error
  def quotedLocalNumber = quoted(number)      // Compiles just fine
  def number: Parser[Int] = ("""[1-9][0-9]*"""r) ^^ {str => str.toInt}

}

trait Innerparser extends RegexParsers {

  def number: Parser[Int] = ("""[1-9][0-9]*"""r) ^^ {str => str.toInt}

}

和错误:

[error] /Path/to/MyParser.scala:6: type mismatch
[error]  found   : minerals.Innerparser#Parser[Int]
[error]  required: Outerparser.this.Parser[?]
[error]   def quotedNumber = quoted(inner.number)

我有点明白了:每个“某事”方法都定义了一个 Parser 类型,其路径特定于封闭类(Outerparser 或 Innerparser)。Outerparser 的“引用”方法需要一个 Outerparser.this.Parser 类型的实例,但正在获取 Innerparser#Parser。

我喜欢能够使用从此类或其他类获得的解析器引用。我怎样才能做到这一点?

4

2 回答 2

2

无论好坏,您通常使用 Scala 解析器组合库的方式是将所有内容包装在一个封闭的 trait 或extendstrait 之类的对象中RegexParsers。我不太清楚为什么 API 是这样设计的。

但是,无论如何,一旦它们都属于 的同一个实例RegexParsers,它们都会看到相同的Parser类型:

trait Everything extends RegexParsers {
    trait Outerparser {
        ...
    }

    trait Innerparser {
        ...
    }
}

每个人都很高兴。


不要认为它把所有东西都放在同一个范围内;将其视为解析器组合器 API 导入名称的怪异方式,即,您可以很容易地做到

import scala.util.parsing.combinator._
import scala.util.parsing.input._

object blah extends RegexParsers
import blah._

trait Outerparser {
    ...
}

trait Innerparser {
    ...
}
于 2012-09-19T01:30:16.327 回答
1

您可以使用自类型注释使其编译,同时仍保持模块化:

trait OuterParser extends RegexParsers { this: InnerParser =>
  def quoted[T](something: Parser[T]) = "\"" ~> something <~ "\""
  def quotedNumber = quoted(number)     // Compile error
}

trait InnerParser extends RegexParsers {
  def number: Parser[Int] = ("""[1-9][0-9]*"""r) ^^ {str => str.toInt}
}

object MyCompleteParser extends OuterParser with InnerParser

自类型注释基本上说 OuterParser 依赖于 InnerParser (它们必须混合在一起才能创建适当的可实例化类)。因此,编译器肯定知道在 OuterParser 和 InnerParser 中,Parser指的是相同的类型。

于 2012-09-22T11:52:04.377 回答