4

次のコードをscala2.8.0に対してコンパイルしています。

import scala.util.parsing.combinator.{syntactical,PackratParsers}
import syntactical.StandardTokenParsers

object MyParser extends StandardTokenParsers with PackratParsers{
  lexical.reserved ++= Set("int","char","boolean")

  lazy val primitiveType:PackratParser[PrimitiveType[_]] = primitiveChar | primitiveInt | primitiveBool

  lazy val primitiveInt:PackratParser[PrimitiveType[Int]] = "int" ^^ { _ => PrimitiveType[Int]() }

  lazy val primitiveChar:PackratParser[PrimitiveType[Char]] = "char" ^^ { _ => PrimitiveType[Char]() }

  lazy val primitiveBool:PackratParser[PrimitiveType[Boolean]] = "boolean" ^^ { _ => PrimitiveType[Boolean]() }
}

object MyParser2 extends StandardTokenParsers with PackratParsers{
  lexical.reserved ++= Set("int","char","boolean")

  lazy val primitiveType:PackratParser[PrimitiveType[_]] =  primitiveChar | primitiveIntOrBool

  lazy val primitiveIntOrBool:PackratParser[PrimitiveType[_]] = "int" ^^ { _ => PrimitiveType[Int]() } | "boolean" ^^ {_ => PrimitiveType[Boolean]()}

  lazy val primitiveChar:PackratParser[PrimitiveType[Char]] = "char" ^^ { _ => PrimitiveType[Char]()} 
}

case class PrimitiveType[T]()

MyParser1をコンパイルすると、次のようになります。

error: inferred type arguments  [this.PrimitiveType[_ >: _1 with Boolean <: AnyVal]] do not conform to method |'s type parameter bounds [U >: this.PrimitiveType[_ >: Char with Int <: AnyVal]]

|のせいで失敗すると思います メソッドタイプシグネチャ。次のように定義されます。

def | [U >: T](q: => Parser[U]): Parser[U]

なぜUはTのスーパータイプでなければならないのですか?「primitiveType」の戻り値はどうあるべきですか?

4

2 に答える 2

5

最後の行をに変更する必要があります

case class PrimitiveType[+T]()

これにより、PrimitiveType [Int] <:PrimitiveType [AnyVal]が可能になります。これは、|を介してPrimitiveType[Boolean]パーサーとPrimitiveType[Int]パーサーの結果をマージする場合に必要です。

ところで、私も書くことをお勧めします

PrimitiveType[AnyVal]

それ以外の

PrimitiveType[_]

これはあなたの場合により正確だからです。

于 2010-08-05T10:34:55.317 に答える
3

case class PrimitiveType[T]ジェネリックをクラス階層に変更した方がよい場合があります。ジェネリック型パラメーターは実行時に使用できないため、解析結果で多くのことを行うことはできません...

これにより、次のようになります(テストされていないコードは現在テストされています)。

object MyParser extends StandardTokenParsers with PackratParsers{
  lexical.reserved ++= Set("int","char","boolean")

  lazy val primitiveType:Parser[PrimitiveType] = primitiveChar | primitiveInt | primitiveBool

  lazy val primitiveInt:PackratParser[PrimitiveType] = "int" ^^^ PrimitiveInt

  lazy val primitiveChar:PackratParser[PrimitiveType] = "char" ^^^ PrimitiveChar

  lazy val primitiveBool:PackratParser[PrimitiveType] = "boolean" ^^^ PrimitiveBoolean
}

sealed trait PrimitiveType
case object PrimitiveInt extends PrimitiveType
case object PrimitiveChar extends PrimitiveType
case object PrimitiveBoolean extends PrimitiveType
于 2010-08-05T12:32:04.307 に答える