类型Parser.Parser [Nonterminal]的表达式不符合Parser.Parser [TypeParameter]

时间:2016-04-05 08:32:29

标签: scala parsing inheritance parser-combinators

我正在搞乱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)TypeParameterNonterminal的实现因此,从我所看到的,不应该产生任何错误。

此处发生了什么以及如何解决此错误?

1 个答案:

答案 0 :(得分:1)

由于优先权,案件并不是您认为的。你的两个案例是:

"(" ~> typeDef <~ ")"

identifier ^^ {
  case td: TypeDefinition => TypeParameter(Left(td))
  case id: Identifier => TypeParameter(Right(id))
}

因为动画笑脸仅适用于identifier"(" ~> typeDef <~ ")"的类型为Parser[TypeDefinition],而不是Parser[TypeParameter]。因此,Scala看到您正在Parser[TypeDefinition]Parser[TypeParameter]进行ORing,并确定结果必须是Parser[NonTerminal],因为它是最具体的常见超类。

要解决此问题,您只需在"(" ~> typeDef <~ ")" | identifier周围添加括号即可使其优先于您的预期,或者将动画笑脸分别应用于两种情况,这也可以避免您进行模式匹配:

def typeParam: Parser[TypeParameter] =
  "(" ~> typeDef <~ ")" ^^ {
    td => TypeParameter(Left(td))
  } | identifier ^^ {
    id => TypeParameter(Right(id))
  }