FallingSkies
FallingSkies

Reputation: 121

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

I want to be able to parse strings like the one below with Scala parser combinators.

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

Before every open square bracket an integer literal is guaranteed to exist.

The code I have so far:

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)
  }
}

The message I get:

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

Any ideas?

Later Edit: After making the change suggested by @sepp2k I still get the same error. The change being:

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

Upvotes: 0

Views: 264

Answers (1)

sepp2k
sepp2k

Reputation: 370357

The error message is telling you that you're pattern matching a list against the ~ constructor, which isn't allowed. In order to use ~ in your pattern, you need to have used ~ in the parser.

It looks like in this case the problem is simply that you discarded the value of intLiteral using ~> when you did not mean to. If you use ~ instead of ~> here and add parentheses1, that should fix your problem.

1 The parentheses are required, so that the following ~> only throws away the bracket instead of the result of intLiteral ~ "[". intLiteral ~ "[" ~> expr <~ "]" is parsed as (intLiteral ~ "[") ~> expr <~ "]", which still throws away the intLiteral. You want intLiteral ~ ("[" ~> expr <~ "]") which only throws away the [ and ].

Upvotes: 1

Related Questions