Reputation: 2098
I am learning how to use the Scala Parser Combinators, which by the way are lovely to work with.
Unfortunately I am getting a compilation error. I have read, and recreated the worked examples from: http://www.artima.com/pins1ed/combinator-parsing.html <-- from Chapter 31 of Programming in Scala, First Edition, and a few other blogs.
I've reduced my code to a much simpler version to demonstrate my problem. I am working on parser that would parse the following samples
if a then x else y
if a if b then x else y else z
with a little extra that the conditions can have an optional "/1,2,3" syntax
if a/1 then x else y
if a/2,3 if b/3,4 then x else y else z
So I have ended with the following code
def ifThenElse: Parser[Any] =
"if" ~> condition ~ inputList ~ yes ~> "else" ~ no
def condition: Parser[Any] = ident
def inputList: Parser[Any] = opt("/" ~> repsep(input, ","))
def input: Parser[Any] = ident
def yes: Parser[Any] = "then" ~> result | ifThenElse
def no: Parser[Any] = result | ifThenElse
def result: Parser[Any] = ident
Now I want to add some transformations. I now get a compilation error on the second ~ in the case:
def ifThenElse: Parser[Any] =
"if" ~> condition ~ inputList ~ yes ~> "else" ~ no ^^ {
case c ~ i ~ y ~ n => null
^ constructor cannot be instantiated to expected type; found : SmallestFailure.this.~[a,b] required: String
When I change the code to
"if" ~> condition ~ inputList ~ yes ~> "else" ~ no ^^ {
case c ~ i => println("c: " + c + ", i: " + i)
I expected it not to compile, but it did. I thought I would need a variable for each clause. When executed (using parseAll) parsing "if a then b else c" produces "c: else, i: c". So it seems like c and i are the tail of the string.
I don't know if it is significant, but none of the example tutorials seem to have an example with more than two variables being matched, and this is matching four
Upvotes: 2
Views: 438
Reputation: 14842
You do not have to match the "else"
:
def ifThenElse: Parser[Any] =
"if" ~> condition ~ inputList ~ (yes <~ "else") ~ no ^^ {
case c ~ i ~ y ~ n => null
}
Works as expected.
Upvotes: 0