Currently, I'm trying to parse a Reader[Token]
in Scala. Therefore, I'd like to check during the parsing steps if a Token
is element of a specific class (e.g. AToken
).
I can do that easily with the following code:
def aToken = acceptIf(_.isInstanceOf[AToken])("Token " + _ + " is not of type AToken")
^^ { _.asInstanceOf[AToken] }
This works perfectly fine. But I have several types to check. So for every type, I need to write that whole thing above again.
So I'd like some abstract acceptIfInstanceOf[T]
method that automatically (magically?) creates one for type T
.
My current solution is still a two-step thing:
def acceptIfInstanceOf[T](implicit m: Manifest[T]) : Parser[Elem] =
acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m)
def aToken = acceptIfInstanceOf[AToken] ^^ { _.asInstanceOf[AToken] }
This works too, but I'd like to get rid of the function application in aToken
and include it directly in acceptIfInstanceOf
.
Sadly, this doesn't work:
def acceptIfInstanceOf[T](implicit m: Manifest[T]) : Parser[T] =
acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m)
^^ { m.runtimeClass.cast(_) }
I get the following error message from the Scala compiler:
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(_) }
^
Does someone know if and how it is possible to construct such a thing? Thanks!
Using _.asInstaceOf[T]
instead m.runtimeClass.cast(_)
as stated by huynhjl solves the initial problem:
def acceptIfInstanceOf[T](implicit m: Manifest[T]) : Parser[T] =
acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m)
^^ { _.asInstanceOf[T] }
However, the check _.getClass == m.runtimeClass
obviously ignores all subtype semantics that _.isInstanceOf
contains - simply because we check equality of two Class
objects.
If I want to maintain the semantics of isInstanceOf
, I have to use the following test:
reflect.ClassManifest.singleType(_) <:< m
But as this is deprecated in 2.10, I replaced Manifest
by TypeTag
and use now the following:
def acceptIfInstanceOf[T](implicit tag: TypeTag[T]): Parser[T] =
acceptIf(currentMirror.reflect(_).symbol.toType <:< typeOf[T])
("" + _ + " is not of type " + tag.tpe)
^^ { _.asInstanceOf[T] }
I got the above solution from another question on Stack Overflow.