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)

それぞれの「何か」メソッドは、パスが囲んでいるクラス(OuterparserまたはInnerparser)に固有のパーサー型を定義しています。Outerparserの「quoted」メソッドは、タイプOuterparser.this.Parserのインスタンスを想定していますが、Innerparser#Parserを取得しています。

このクラスまたは他のクラスから取得したパーサーでquotedを使用できるようにしたいと思います。どうやってやるの?

4

2 に答える 2

2

良くも悪くも、通常 Scala パーサー コンビネーター ライブラリを使用する方法は、トレイトまたはextendsトレイトが好きなオブジェクトですべてをラップすること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 に答える