我目前正在Scala中编写一个解析器,我正在尝试创建一个eat
函数来检查下一个Token
是否属于某个案例类,如果是,则使用它。我目前的尝试如下并正常工作:
def eat[T](tokenType: TypeTag[T]) = currentToken match {
case Plus() => if (tokenType == typeTag[Plus]) currentToken = lexer.getNextToken() else throw new Exception(tokenType.toString ++ " expected, " ++ currentToken.toString)
case Minus() => if (tokenType == typeTag[Minus]) currentToken = lexer.getNextToken() else throw new Exception(tokenType.toString ++ " expected, " ++ currentToken.toString)
}
Token
定义如下:
trait Token
case class Plus() extends Token
case class Minus() extends Token
case class IntConst(n: Int) extends Token
case class FloatConst(x: Float) extends Token
之前我使用字符串来指定类型,但是传递TypeTag
已经消除了尝试吃非现有类型的可能性。
然而, tldr,我想要实现的是能够传递一个类型或类作为参数,并检查currentToken是否属于该类。
我确实找到了如何将一个类作为参数传递给def something(c: class[_])
,但后来我只知道如何将它与给定类型进行比较,比如Int
。但是,我想将它与currentToken的类型进行比较。任何人都可以指出我朝着正确的方向努力实现这一目标吗?
感谢。
目前,我有工作代码,这是一种相对有效的方式(我认为)。但是,对于添加的每个Token
个案类,即使eat
函数回答的主要问题没有改变,也必须添加此函数的新行。在一个理想的世界里,我希望写出类似下面的伪代码:
def eat(tokenClass: Class) = {
if (classOf(currentToken) == tokenClass) getNextToken else throw exception
}
永远不必延长。 (顺便说一下,如果参数只允许是特征令牌的案例类,那就更好了。)
答案 0 :(得分:2)
由于你想要比较的是实际的运行时类(而不是编译时类型),你可以这样做:
def eat[T](implicit T: ClassTag[T]) =
if (T.runtimeClass == currentToken.getClass) getNextToken else throw exception
但是,如果您的类具有类型参数(因为类型擦除),这将导致问题。