Scala解析器组合器中的MatchError解析查询字符串

时间:2019-07-10 19:56:29

标签: scala parsing

我正在创建一个解析器来解析这样的查询字符串

e = "500.3" AND dt = "20190710" AND s in ("ERROR", "WARN") OR cat = "Conditional"

对于前面的字符串,我得到以下内容: Exception in thread "main" scala.MatchError: (Identifier(e),(=,StringLiteral(500.3))) (of class scala.Tuple2)

我认为我的语法很好(也许不是)。也许有人可以帮助找出为什么我会收到此错误。这是我的解析器。

class SearchQueryParser extends StandardTokenParsers {
  lexical.reserved += ("OR", "AND")
  lexical.delimiters += ( "<", "=", "<>", "!=", "<=", ">=", ">",  "(", ")")

  def expr: Parser[QueryExp] = orExp
  def orExp: Parser[QueryExp] = andExp *("OR" ^^^ {(a: QueryExp, b: QueryExp) => BoolExp("OR", (a, b))})
  def andExp: Parser[QueryExp] = compareExp *("AND" ^^^ {(a: QueryExp, b: QueryExp) => BoolExp("AND", (a, b))})

  def compareExp: Parser[QueryExp] = {
    identifier ~ rep(("=" | "<>" | "!=" | "<" | "<=" | ">" | ">=") ~ literal ^^ {
      case op ~ rhs => (op, rhs)
    }) ^^ {
      case lhs ~ elems =>
        elems.foldLeft(lhs) {
          case (id, ("=", rhs: String)) => Binomial("=", id.str, rhs)
          case (id, ("<>", rhs: String)) => Binomial("!=", id.str, rhs)
          case (id, ("!=", rhs: String)) => Binomial("!=", id.str, rhs)
          case (id, ("<", rhs: String)) => Binomial("<", id.str, rhs)
          case (id, ("<=", rhs: String)) => Binomial("<=", id.str, rhs)
          case (id, (">", rhs: String)) => Binomial(">", id.str, rhs)
          case (id, (">=", rhs: String)) => Binomial(">=", id.str, rhs)
        }
      }
  }

  def literal: Parser[QueryExp] = stringLit ^^ (s => StringLiteral(s))
  def identifier: Parser[QueryExp] = ident ^^ (s => Identifier(s))

  def parse(queryStr: String): Option[QueryExp] = {
    phrase(expr)(new lexical.Scanner(queryStr)) match {
      case Success(r, _) => Option(r)
      case x => println(x); None
    }
  } 
}

1 个答案:

答案 0 :(得分:0)

我能够找到问题。似乎是由于foldLeft(lhs)语句中的部分函数与元组(=,StringLiteral(500.3))

不匹配而产生错误

如您所见,在每种情况下,对部分函数的声明,我都在尝试匹配String类型的rhs

...
 case (id, ("=", rhs: String)) => Binomial("=", id.str, rhs)
 case (id, ("<>", rhs: String)) => Binomial("!=", id.str, rhs)
 case (id, ("!=", rhs: String)) => Binomial("!=", id.str, rhs)
...

但是,正如您在错误Exception in thread "main" scala.MatchError: (Identifier(e),(=,StringLiteral(500.3))) (of class scala.Tuple2)中所看到的那样,输入被解析为“ =”和StringLiteral的元组。

解决方案是更改rhs参数的类型:

...
 case (id, ("=", rhs: StringLiteral)) => Binomial("=", id.str, rhs.toString)
 case (id, ("<>", rhs: StringLiteral)) => Binomial("!=", id.str, rhs.toString)
 case (id, ("!=", rhs: StringLiteral)) => Binomial("!=", id.str, rhs.toString)
...