2

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

3
  • My apologies. raising this question allowed me enough information to solve it myself. I would delete it but cannot do so. I think I have the ~> around the else wrong. If I just use "if" ~> condition ~ inputList ~ yes ~ "else" ~ no ^^ { case c ~ i ~ y ~ e ~ n => println("c: " + c + " i: " + i) then everything works. :( Commented May 2, 2013 at 10:17
  • You can post an answer to your own question (as an answer, not only as a comment) - it will help others who run into the same issue. Commented May 2, 2013 at 11:54
  • I'll do that as soon as the timeout let's me Commented May 2, 2013 at 12:00

1 Answer 1

0

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.