1

I am writing parser and grammer using scala.util.parsing.combinator . My input is ":za >= 1 alok && :ft == 9"

case class Expression(op1:Operand,operator:Operator,op2:Operand)

def word: Parser[String] = """[a-z\\\s]+""".r ^^ { _.toString }

def colonWord:Parser[Operand]=":"~> word ^^{case variable => Operand(variable)}

def constant:Parser[Operand]="""^[a-zA-Z0-9\\\s-]*""".r ^^ {case constant => Operand(constant)}

def expression:Parser[Expression] = colonWord ~ operator ~ constant  ^^{ case op1~operator~op2 => Expression(op1, operator, op2)}

def expressions = expression ~ opt(" && " ~> expression)* 

but when I parse sample String , the result is not expected. The second expression after && is not parsed. Please note there can be multiple expression joined using &&.

When i execute:

val expr= ":za >= 1 alok && :ft == 9"
    parse(expressions, expr) match {
      case Success(matched, _) => println(matched)
      case ..}

Output is :

List((Expression(za ,>= ,1 alok )~None))

I dont see the second expression being parsed. Can anyone help what have i missed here?

EDIT -----------------------------------

The requirement is to get List[Expression]. when I say, incorporting the changes mentioned in Ans :

def expressions = expression ~ ("&&" ~> expression)* 

The return type of expressions is not List[Expression]. For eg: If I write another def :

case class Condition(exprs: List[Expression], st:Statement)
def condition = expressions ~","~statement ^^{
    case exprs~commaa~statement => Condition(exprs,statement) //This is giving error.

the error is: type mismatch; found : ~[Expression,Expression]] required: Expressions.

So how do i convert [Expression, Expression] to List[Expressions]?

Thanks

3
  • In your output List((Expression(za ,>= ,1 alok )~None)). Try to notice that extra space after 1 alok. And extra space is the culprit, as your next expressions parser expects two expressions to be delimited by a <space>&&<space> Commented Sep 19, 2016 at 8:46
  • That is why, it is a good practice to have <space> as a first class member of your grammar. Don't ever belittle space. Commented Sep 19, 2016 at 8:49
  • Thanks. Yes , that is the problem . I tried removing spaces from <space>&&<space>. It worked in this case. But i gave another expression => ":za >= 1&&:ft == 9&&:wq == 12" , In this case it took 2 expression , rather than 3 . The output i get is List((Expression(za ,>= ,1)~Some(Expression(ft ,== ,9)))) Commented Sep 19, 2016 at 10:02

1 Answer 1

2

The correction needed was:

expression ~ opt("&&" ~> expression)*

Remove space across && and it should work. This is because you are already covering space in your constant parser.

Edit: Based on edited question, is this what you want:

 def expressions = expression ~ (("&&" ~> expression)*) ^^{
    case x ~ y => x :: y
  }

Now the return type of expressions is List[Expression]. Your condition will now compile

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

4 Comments

Thanks. Yes , that is the problem . I tried removing spaces from <space>&&<space>. It worked in this case. But i gave another expression => ":za >= 1&&:ft == 9&&:wq == 12" , In this case it took 2 expression , rather than 3 . The output i get is List((Expression(za ,>= ,1)~Some(Expression(ft ,== ,9))))
I believe the problem is also with def expressions = expression ~ opt(" && " ~> expression)* . I was expecting this to return me List[Expression] . But it returns [Expression, Option[Expression]]
because you have opt in opt(" && " ~> expression). Now since you are using * which means 0 or more you do not need that opt.
But this would not solve the problem . To make the problem more clearer , I have edited it.

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.