Scala Regex小于等于运算符(< =)

时间:2015-10-21 14:46:41

标签: regex scala parser-combinators

我试图用(<,< =,> =,>)解析表达式。除了< =之外的所有工作都很好。有人可以帮助解决问题。 代码:

object MyTestParser extends RegexParsers {
  override def skipWhitespace = true

  private val expression: Parser[String] = """[a-zA-Z0-9\.]+""".r

  val operation: Parser[Try[Boolean]] =
    expression ~ ("<" | "<=" | ">=" | ">") ~ expression ^^ {
      case v1 ~ op ~ v2 => for {
        a <- Try(v1.toDouble)
        b <- Try(v2.toDouble)
      } yield op match {
        case "<" => a < b
        case "<=" => a <= b
        case ">" => a > b
        case ">=" => a >= b
      }
  }
}

测试:

"MyTestParser" should {
    "successfully parse <= condition" in {
      val parser = MyTestParser.parseAll(MyTestParser.operation, "10 <= 20")
      val result = parser match {
        case MyTestParser.Success(s, _) => s.get
        case MyTestParser.Failure(e, _) =>
          println(s"Parsing failed with error: $e")
          false
        case MyTestParser.Error(e, _) =>
          println(s"Parsing error: $e")
          false
      }
      result === true
    }

    "successfully parse >= condition" in {
      val result = MyTestParser.parseAll(MyTestParser.operation, "50 >= 20").get
      result === scala.util.Success(true)
    }
  }

&lt; = condition:

的错误
Parsing failed with error: string matching regex `[a-zA-Z0-9\.]+' expected but `=' found

3 个答案:

答案 0 :(得分:2)

您需要更改备选方案的顺序,以便可以先检查最长的选项。

expression ~ ( "<=" | ">=" | ">" | "<") ~ expression ^^ {

如果最短的替代品首先匹配,则根本不考虑其他替代品。

另请注意,句点不必在字符类中进行转义,这样做:

"""[a-zA-Z0-9.]+""".r

答案 1 :(得分:2)

你的问题是“&lt;”与&lt; =匹配,因此它继续尝试表达式。如果您更改顺序以便首先出现“&lt; =”,那么将匹配,您将获得所需的结果。

答案 2 :(得分:2)

@Prateek:它不起作用,因为正则表达式引擎就像布尔OR一样工作。如果在某个点满足or-chain中的一个模式,它不会进一步搜索。

因此,在模式之间使用|时,如果两个或多个模式具有共同的子字符串则必须放置最长的

作为一般规则订购从最长到最短的模式。

更改相关的行,使其有效:

 // It works as expected with '>= / >' also before for the same reason
 expression ~ ("<=" | "<" | ">=" | ">") ~ expression ^^ {

或者您想要遵循一般规则

 expression ~ ("<=" | ">=" | "<" | ">") ~ expression ^^ {