scala.util.parsing.combinator.RegexParsers 构造函数无法实例化为预期类型

scala.util.parsing.combinator.RegexParsers constructor cannot be instantiated to expected type

我希望能够使用 Scala 解析器组合器解析如下所示的字符串。

aaa22[bbb33[ccc]ddd]eee44[fff]

在每个左方括号之前,保证存在一个整数文字。

我目前的代码:

import scala.util.parsing.combinator.RegexParsers

trait AST
case class LetterSeq(value: String) extends AST
case class IntLiteral(value: String) extends AST
case class Repeater(count: AST, content: List[AST]) extends AST

class ExprParser extends RegexParsers {
  def intLiteral: Parser[AST] = "[0-9]+".r ^^ IntLiteral
  def letterSeq: Parser[AST] = "[a-f]+".r ^^ LetterSeq
  def term: Parser[AST] = letterSeq | repeater
  def expr: Parser[List[AST]] = rep1(term)
  def repeater: Parser[AST] = intLiteral ~> "[" ~> expr <~ "]" ^^ {
    case intLiteral ~ expr => Repeater(intLiteral, expr)
  }
}

我收到的消息:

<console>:25: error: constructor cannot be instantiated to expected type;
 found   : ExprParser.this.~[a,b]
 required: List[AST]
           case intLiteral ~ expr => Repeater(intLiteral, expr)

有什么想法吗?

稍后编辑:按照@sepp2k 的建议进行更改后,我仍然遇到相同的错误。变化是:

def repeater: Parser[AST] = intLiteral ~ "[" ~> expr <~ "]" ^^ {

错误消息告诉您,您正在根据 ~ 构造函数对列表进行模式匹配,这是不允许的。为了在您的模式中使用 ~,您需要在解析器中使用 ~

在这种情况下,问题很简单,就是您使用 ~> 丢弃了 intLiteral 的值,而您并不是故意的。如果您在这里使用 ~ 而不是 ~> 并添加括号 1,那应该可以解决您的问题。

1 括号是必须的,所以下面的~>只是丢掉括号而不是intLiteral ~ "["的结果。 intLiteral ~ "[" ~> expr <~ "]" 被解析为 (intLiteral ~ "[") ~> expr <~ "]",它仍然会丢弃 intLiteral。您想要 intLiteral ~ ("[" ~> expr <~ "]") 只会丢弃 [].