2010-08-05 41 views
4

我有下面的代碼被編譯反對斯卡拉2.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」的返回值?

回答

5

您需要在最後一行變成

case class PrimitiveType[+T]() 

這使得PrimitiveType [INT] <:PrimitiveType時要合併PrimitiveType [布爾]及PrimitiveType結果[這是需要[AnyVal] Int]解析器通過|。

順便說一句,我還建議編寫的

PrimitiveType[AnyVal] 

代替

PrimitiveType[_] 

,因爲這是你的情況更精確。

+0

啊,很好的答案。我正在收回我的。 – 2010-08-05 10:43:36

+0

謝謝,當然這解決了我的問題。但是,我仍然缺少爲什麼在|中需要U>:T。 – 2010-08-05 16:24:04

+0

@kmels'U'必須是'T'的超類型,因爲'|'構造了一個複合解析器,它將產生'T'或'U'。在實踐中,給定'T | S',編譯器將在類型層次結構中搜索「T」和「S」的最小上界*,並調用「U」。 – 2010-08-05 18:05:13

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