2013-04-16 25 views
0

當前,我試圖解析Scala中的一個Reader[Token]。因此,我想在分析步驟中檢查Token是否是特定類的元素(例如AToken)。 我可以用下面的代碼做到這一點很容易:使用解析器組合器構造類型檢查解析器

def aToken = acceptIf(_.isInstanceOf[AToken])("Token " + _ + " is not of type AToken") 
    ^^ { _.asInstanceOf[AToken] } 

這工作完全正常。但我有幾種類型需要檢查。所以對於每一種類型,我都需要再次寫出整個事物。 所以我想要一些抽象的acceptIfInstanceOf[T]方法自動(神奇地?)爲T類型創建一個。

我當前的解決方案仍是一個兩步的事情:

def acceptIfInstanceOf[T](implicit m: Manifest[T]) : Parser[Elem] = 
    acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m) 
def aToken = acceptIfInstanceOf[AToken] ^^ { _.asInstanceOf[AToken] } 

這工作過,但我想擺脫aToken的功能應用,並直接將其包含在acceptIfInstanceOf。 可悲的是,這並不工作:

def acceptIfInstanceOf[T](implicit m: Manifest[T]) : Parser[T] = 
    acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m) 
    ^^ { m.runtimeClass.cast(_) } 

我從Scala編譯器以下錯誤消息:

scala: type mismatch; 
found : _$1 where type _$1 
required: T 
def acceptIfInstanceOf[T](implicit m: Manifest[T]): Parser[T] = 
    acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m) 
    ^^ { m.runtimeClass.cast(_) } 
         ^

是否有人知道是否以及如何能夠構建這樣的事情? 謝謝!

+1

您是否試圖用'_.asInstanceOf [T]'來編寫工作'acceptIfInstanceOf'?像這樣'acceptIf(_。getClass == m.runtimeClass)(「」+ _ +「不是類型」+ m)^^ {_.asInstanceOf [T]}' – huynhjl

+0

我完全監督這一點。是的,'_.asInstanceOf [T]'起作用。謝謝!但是,我必須調整我的代碼,因爲它不考慮子類型。例如。 'class BToken extends Atoken',然後'acceptIfInstanceOf [AToken]'不接受任何'BToken's - 它應該理想的。 – r0estir0bbe

回答

1

使用_.asInstaceOf[T]代替m.runtimeClass.cast(_)huynhjl規定解決了最初的問題:

def acceptIfInstanceOf[T](implicit m: Manifest[T]) : Parser[T] = 
    acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m) 
    ^^ { _.asInstanceOf[T] } 

然而,檢查_.getClass == m.runtimeClass顯然忽略所有亞型語義_.isInstanceOf包含 - 僅僅是因爲我們檢查兩個Class對象的平等。

如果我要保持isInstanceOf語義,我不得不使用下面的測試:

reflect.ClassManifest.singleType(_) <:< m 

但由於這是在2.10過時,我通過TypeTag取代Manifest和現在用的以下內容:

def acceptIfInstanceOf[T](implicit tag: TypeTag[T]): Parser[T] = 
    acceptIf(currentMirror.reflect(_).symbol.toType <:< typeOf[T]) 
    ("" + _ + " is not of type " + tag.tpe) 
    ^^ { _.asInstanceOf[T] } 

我在Stack Overflow上從another question得到了上面的解決方案。