我写了一个解析器来充当词法分析器。此词法分析器解析文件并返回一个标记列表,每个标记都是一个扩展共同特征的案例类或对象。
我现在正在尝试为词法分析器的输出编写一个解析器,但是我遇到了一个非常令人困惑的障碍。解析器很乐意隐式地转换我的case对象,但如果我甚至尝试手动调用apply(classHere)
,则会引发一个拟合。
以下是我的代码的简化版本:
// CODE
trait Token
case class StringWrapperIgnoresCase(val string: String) {
private case class InnerWrapper(s: String)
lazy val lower = string.toLowerCase
override lazy val hashCode = InnerWrapper(lower).hashCode
override def equals(that: Any) =
that.isInstanceOf[StringWrapperIgnoresCase] &&
lower == that.asInstanceOf[StringWrapperIgnoresCase].lower
}
case class ID(val text: String)
extends StringWrapperIgnoresCase(text)
with Token {
override def toString = "ID(" + text + ")"
}
case object PERIOD extends Token
object Parser extends Parsers {
type Elem = Token
def doesWork: Parser[Token] = PERIOD
def doesNotWork: Parser[Token] = ID
}
编译器报告以下有关doesNotWork
的消息:
// ERROR MESSAGE
type mismatch; found : alan.parser.ID.type (with underlying type object alan.parser.ID) required: alan.parser.Parser.Parser[alan.parser.Token]
我该如何解决这个问题?
答案 0 :(得分:2)
更新:我不清楚你的问题究竟是什么问题,但是现在你已经指定你想要一个与答案中任何ID
匹配的解析器,这里有一个更惯用的解决方案:
val id: Parser[ID] = accept("ID", { case i: ID => i })
在这里,您已经提供了解析器想要的内容(用于错误消息)以及以ID
为其域的部分函数的描述。您也可以使用xiefei在评论中提供的acceptIf
版本。
当您引用没有参数列表的案例类(而不是案例对象)时,您将获得自动生成的伴随对象,该对象不是类本身的实例。请考虑以下事项:
sealed trait Foo
case class Bar(i: Int) extends Foo
case object Baz extends Foo
现在Baz: Foo
很好,但Bar: Foo
会出现与您所看到的非常相似的错误。
另请注意,此处发生的事情并非严格施放。 Parsers
特征具有以下签名的方法:
implicit def accept(e: Elem): Parser[Elem]
当你这样写:
def doesWork: Parser[Token] = PERIOD
您尝试将Elem
键入为Parser[Elem]
,并且隐式转换会启动(有关隐式转换的详细信息,请参阅the spec的第7.3节)。当你写这篇文章时,另一方面:
def doesNotWork: Parser[Token] = ID
您尝试键入ID
随播广告对象(其类型为ID.type
,而不是ID
或Token
,因此不是Elem
) Parser[Elem]
,并且没有隐式转换可以实现这一点。
至少现在,你最好写出accept(PERIOD)
和accept(ID("whatever"))
,并且在你尝试编译代码时遵守以下说明的弃用警告:
案例到案例继承具有潜在的危险错误 不太可能被修复。
答案 1 :(得分:0)
使用TravisBrown和drstevens所说的,我已经为解析器添加了一个新的产品:
def id = {
acceptIf(
_ match {
case ID(_) => true
case _ => false
}
)("'ID(_)' expected but " + _ + " found")
}
def nowWorks = id
我暂不接受这个作为答案暂时允许某人提供比这更优雅的解决方案。这对我的口味来说看起来有些混乱,而且我确信更习惯于功能性编程方法的人会把它变成优雅的单行。