小于等于运算符 (<=) 的 Scala 正则表达式
Scala Regex for less than equal to operator (<=)
我正在尝试用 (<, <=, >=, >) 解析表达式。除了 <= 之外的所有内容都可以正常工作。有人可以帮助可能是什么问题。
代码:
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)
}
}
<= 条件错误:
Parsing failed with error: string matching regex `[a-zA-Z0-9\.]+' expected but `=' found
您需要更改选项的顺序以便首先检查最长的选项。
expression ~ ( "<=" | ">=" | ">" | "<") ~ expression ^^ {
如果最短的备选方案最先匹配,则根本不考虑其他备选方案。
另请注意,句点不必在字符 class 内转义,这样就可以了:
"""[a-zA-Z0-9.]+""".r
您的问题是“<”与<= 匹配,因此它继续尝试表达式。如果您更改顺序,使“<=”排在第一位,那么它将被匹配,并且您将获得所需的结果。
@Prateek:它不起作用,因为正则表达式引擎就像布尔 OR 一样工作。如果 or-chain 中的模式之一在某一点得到满足,它不会进一步搜索。
所以,当在模式之间使用 |
时,如果两个或多个模式有共同的子字符串,你必须把最长的放在第一个.
作为一般规则:从最长到最短的顺序排列模式。
像这样更改相关行使其有效:
// It works as expected with '>= / >' also before for the same reason
expression ~ ("<=" | "<" | ">=" | ">") ~ expression ^^ {
或者您想遵循一般规则:
expression ~ ("<=" | ">=" | "<" | ">") ~ expression ^^ {
我正在尝试用 (<, <=, >=, >) 解析表达式。除了 <= 之外的所有内容都可以正常工作。有人可以帮助可能是什么问题。 代码:
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)
}
}
<= 条件错误:
Parsing failed with error: string matching regex `[a-zA-Z0-9\.]+' expected but `=' found
您需要更改选项的顺序以便首先检查最长的选项。
expression ~ ( "<=" | ">=" | ">" | "<") ~ expression ^^ {
如果最短的备选方案最先匹配,则根本不考虑其他备选方案。
另请注意,句点不必在字符 class 内转义,这样就可以了:
"""[a-zA-Z0-9.]+""".r
您的问题是“<”与<= 匹配,因此它继续尝试表达式。如果您更改顺序,使“<=”排在第一位,那么它将被匹配,并且您将获得所需的结果。
@Prateek:它不起作用,因为正则表达式引擎就像布尔 OR 一样工作。如果 or-chain 中的模式之一在某一点得到满足,它不会进一步搜索。
所以,当在模式之间使用 |
时,如果两个或多个模式有共同的子字符串,你必须把最长的放在第一个.
作为一般规则:从最长到最短的顺序排列模式。
像这样更改相关行使其有效:
// It works as expected with '>= / >' also before for the same reason
expression ~ ("<=" | "<" | ">=" | ">") ~ expression ^^ {
或者您想遵循一般规则:
expression ~ ("<=" | ">=" | "<" | ">") ~ expression ^^ {