【问题标题】:Constructing a type check parser with parser combinators使用解析器组合器构造类型检查解析器
【发布时间】:2013-04-17 00:32:04
【问题描述】:

目前,我正在尝试在 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(_) }
                          ^

有人知道是否以及如何构建这样的东西吗? 谢谢!

【问题讨论】:

  • 您是否尝试将工作中的acceptIfInstanceOf_.asInstanceOf[T] 组合在一起?就像那样acceptIf(_.getClass == m.runtimeClass)("" + _ + " is not of type " + m) ^^ {_.asInstanceOf[T] }
  • 我完全监督了这一点。是的,_.asInstanceOf[T] 有效。谢谢!但是,我必须调整我的代码,因为它不考虑子类型。例如。使用class BToken extends AToken,则acceptIfInstanceOf[AToken] 不接受任何BTokens - 理想情况下应该这样做。

标签: scala generics casting parser-combinators


【解决方案1】:

huynhjl 所述,使用_.asInstaceOf[T] 代替m.runtimeClass.cast(_) 解决了最初的问题:

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 中已弃用,我将 Manifest 替换为 TypeTag 并现在使用以下内容:

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 获得了上述解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    相关资源
    最近更新 更多