我在玩弄Scala的解析器组合器,我被一个我似乎不太理解的错误所困扰。
以下是相关代码:
trait ASTNode
trait Terminal extends ASTNode
trait Nonterminal extends ASTNode
case class Identifier(id: String) extends Terminal
case class TypeDefinition(identifier: Identifier, optionalType: Option[TypeParameters]) extends Nonterminal
case class TypeParameters(params: List[TypeParameter]) extends Nonterminal
case class TypeParameter(typeDef: Either[TypeDefinition, Identifier]) extends Nonterminal
object Parser extends RegexParsers {
def identifier: Parser[Identifier] = """([a-zA-Z_][\w'-]*)""".r ^^ Identifier
def typeDef: Parser[TypeDefinition] = identifier ~ opt("of" ~> typeParams) ^^ {
case id ~ optional => TypeDefinition(id, optional)
}
// the bit causing the error
def typeParam: Parser[TypeParameter] = "(" ~> typeDef <~ ")" | identifier ^^ {
case td: TypeDefinition => TypeParameter(Left(td))
case id: Identifier => TypeParameter(Right(id))
}让我烦恼的是,a) typeParam返回一个TypeParameter,b) TypeParameter是Nonterminal的实现,因此在我看来,不应该产生错误。
这里发生了什么,我如何纠正这个错误?
发布于 2016-04-05 08:47:14
由于优先级的原因,案件不是你所认为的那样。你的两个案件是:
"(" ~> typeDef <~ ")"和
identifier ^^ {
case td: TypeDefinition => TypeParameter(Left(td))
case id: Identifier => TypeParameter(Right(id))
}因此,由于动画微笑只适用于identifier,所以"(" ~> typeDef <~ ")"的类型是Parser[TypeDefinition],而不是Parser[TypeParameter]。所以Scala会看到ORing,一个带有Parser[TypeParameter]的Parser[TypeDefinition],并决定结果必须是一个Parser[NonTerminal],因为这是他们最具体的超类。
要解决这一问题,您只需在"(" ~> typeDef <~ ")" | identifier周围添加括号,使其具有您想要的优先级,或者将动画笑脸分别应用于这两种情况,这也可以避免您不得不进行模式匹配:
def typeParam: Parser[TypeParameter] =
"(" ~> typeDef <~ ")" ^^ {
td => TypeParameter(Left(td))
} | identifier ^^ {
id => TypeParameter(Right(id))
}https://stackoverflow.com/questions/36421057
复制相似问题