1

I am writing a parser for a search expression. Ex.

a = "zyx" and ( b < 5 or c > 9)

I wrote this parser but it's not able to match the parentheses, getting this error:

failure: identifier expected
a = "zyx" and ( b < 5 or c > 9)
              ^

What can I do to be able to match the paretheses

class SearchQueryParser extends StandardTokenParsers {
  def expr: Parser[Expression] = orExp | "(" ~> orExp ~ ")"

  def orExp: Parser[Expression] = {
    andExp *("or" ^^^ {(a: Expression, b: Expression) => BoolExp("OR", (a, b))})
  }

  def andExp: Parser[Expression] = {
    compareExp *("and" ^^^ {(a: Expression, b: Expression) => BoolExp("AND", (a, b))})
  }

  def compareExp: Parser[Expression] = {
    identifier ~ rep(
      ("=" | "!=" | "<" | ">") ~ literal ^^ {
        case op ~ rhs => (op, rhs)
      }
    ) ^^ {
      case (acc, ("=", rhs: Expression)) => Binomial("=", acc, rhs)  
      case (acc, ("!=", rhs: Expression)) => Binomial("!=", acc, rhs)
      case (acc, ("<", rhs: Expression)) => Binomial("<", acc, rhs)
      case (acc, (">", rhs: Expression)) => Binomial(">", acc, rhs)
    }
  }
}
2
  • Your compareExp rule looks strange to me. It allows x < 5 > 1, but not 1 < x < 5. I'm not sure whether that's what you intended or not. Commented Jul 31, 2019 at 15:05
  • thanks for your comment. I actually don't need any of the expression as only Binomials should be allowed. I change my grammar accordingly. Commented Jul 31, 2019 at 15:30

2 Answers 2

1

Your current grammar only allows parentheses in the expr rule, which I assume is your main rule, and the expr rule is never used by any other rule. So parentheses are only allowed around the entire expression.

What you want to do is to put "(" ~ expr ~ ")" in the lowest place where parenthesized expressions would be allowed. As I understand your grammar, that would probably meaning allowing it as an alternative to compareExp in andExp (assuming you don't want to allow parentheses inside compareExps).

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

Comments

1

As @sepp2k mentioned you need to put your parentheses on the lowest place where parentheses is allowed. In your case it should be in the compareExp:

  def compareExp: Parser[Expression] = {
    "(" ~> expr <~ ")" | identifier ~ rep(
      ("=" | "!=" | "<" | ">") ~ literal ^^ {
        case op ~ rhs => (op, rhs)
      }
    ) ^^ {
      case (acc, ("=", rhs: Expression)) => Binomial("=", acc, rhs)  
      case (acc, ("!=", rhs: Expression)) => Binomial("!=", acc, rhs)
      case (acc, ("<", rhs: Expression)) => Binomial("<", acc, rhs)
      case (acc, (">", rhs: Expression)) => Binomial(">", acc, rhs)
    }
  }

and exp method should not handle the parentheses

 def expr: Parser[Expression] = orExp

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.