Reputation: 121
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
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