我从我的配置文件中读到这样的内容:
metric1.critical = "<2000 || >20000"
metric1.okay = "=1"
metric1.warning = "<=3000"
metric2.okay = ">0.9 && < 1.1 "
metric3.warning ="( >0.9 && <1.5) || (<500 &&>200)"
Run Code Online (Sandbox Code Playgroud)
我有一个
metric1.value = //have some value
Run Code Online (Sandbox Code Playgroud)
我的目标是基本评估
if(metric1.value<2000 || metric1.value > 20000)
metric1.setAlert("critical");
else if(metric1.value=1)
metric.setAlert("okay");
//and so on
Run Code Online (Sandbox Code Playgroud)
我对正则表达式并不是很好,所以我会尝试不使用它.我在Scala中编码,想知道现有的库是否可以帮助解决这个问题.也许我需要放置占位符来填补空白然后评估表达式?但是,如何最有效地评估表达式并减少开销?
编辑:在java中如何我们有表达式评估器库我希望我能找到类似的代码.也许我可以在配置文件中添加占位符,如"?" 这些替换我的metric1.value(读取变量),然后使用评估器?或者有人可以为此建议一个好的正则表达式吗?提前致谢!
这听起来像是要使用解析器组合器库定义自己的语法.
scala类库中内置了一个解析器组合器.由于scala库已经模块化,现在它是一个独立的项目,位于https://github.com/scala/scala-parser-combinators.
更新:每个人都在寻找一个解析器组合库,它在概念上类似于scala-parser-combinators,应该看看fastparse.它非常快,不使用宏.因此它可以作为scala-parser-combinators的替代品.
有关如何在Scala编程中使用它的一些示例,第33章"组合器解析".
这里有一个小语法,ast和评估员,可以帮助你入门.这缺少很多东西,如空格处理,操作符优先级等.您也不应该使用字符串来编码不同的比较运算符.但是我认为,通过这个以及Scala编程中的章节,您应该能够提出适合您需求的内容.
import scala.util.parsing.combinator.{JavaTokenParsers, PackratParsers}
sealed abstract class AST
sealed abstract class BooleanExpression extends AST
case class BooleanOperation(op: String, lhs: BooleanExpression, rhs:BooleanExpression) extends BooleanExpression
case class Comparison(op:String, rhs:Constant) extends BooleanExpression
case class Constant(value: Double) extends AST
object ConditionParser extends JavaTokenParsers with PackratParsers {
val booleanOperator : PackratParser[String] = literal("||") | literal("&&")
val comparisonOperator : PackratParser[String] = literal("<=") | literal(">=") | literal("==") | literal("!=") | literal("<") | literal(">")
val constant : PackratParser[Constant] = floatingPointNumber.^^ { x => Constant(x.toDouble) }
val comparison : PackratParser[Comparison] = (comparisonOperator ~ constant) ^^ { case op ~ rhs => Comparison(op, rhs) }
lazy val p1 : PackratParser[BooleanExpression] = booleanOperation | comparison
val booleanOperation = (p1 ~ booleanOperator ~ p1) ^^ { case lhs ~ op ~ rhs => BooleanOperation(op, lhs, rhs) }
}
object Evaluator {
def evaluate(expression:BooleanExpression, value:Double) : Boolean = expression match {
case Comparison("<=", Constant(c)) => value <= c
case Comparison(">=", Constant(c)) => value >= c
case Comparison("==", Constant(c)) => value == c
case Comparison("!=", Constant(c)) => value != c
case Comparison("<", Constant(c)) => value < c
case Comparison(">", Constant(c)) => value > c
case BooleanOperation("||", a, b) => evaluate(a, value) || evaluate(b, value)
case BooleanOperation("&&", a, b) => evaluate(a, value) && evaluate(b, value)
}
}
object Test extends App {
def parse(text:String) : BooleanExpression = ConditionParser.parseAll(ConditionParser.p1, text).get
val texts = Seq(
"<2000",
"<2000||>20000",
"==1",
"<=3000",
">0.9&&<1.1")
val xs = Seq(0.0, 1.0, 100000.0)
for {
text <- texts
expression = parse(text)
x <- xs
result = Evaluator.evaluate(expression, x)
} {
println(s"$text $expression $x $result")
}
}
Run Code Online (Sandbox Code Playgroud)