我需要一个快速的运行时表达式解析器。

32

我需要找到一个快速、轻量级的表达式解析器。

理想情况下,我希望能够将一组名称/值对(例如变量)和包含要评估的表达式的字符串传递给它。我只需要从它那里得到一个真/假值。

表达式的类型应该是类似于:

varA == "xyz" and varB==123

基本上,只是一个简单的逻辑引擎,其表达式在运行时提供。

更新
至少需要支持==、!=、>、>=、<、<=

关于速度,我预计每个请求执行大约5个表达式。我们将看到大约100个/秒的请求。我们当前的页面 tend to 在50ms之内执行。通常任何表达式中只会涉及2或3个变量。但是,在执行之前我需要加载大约30个变量到解析器中。

更新2012/11/5
关于性能的更新。我们实现了nCalc近2年。自那以后,我们扩展了它的使用,使其平均覆盖300多个变量的40多个表达式进行后续处理。现在每秒发生数千次后续处理,而完全没有性能下降。

我们还扩展了它,包括一些额外的函数,也没有性能损失。简而言之,nCalc满足了我们的所有需求,并超出了我们的期望。


不知道有没有现成的,但自己写起来似乎并不太难(取决于需求)。“==”是唯一的比较器吗?变量是否区分大小写,像C#那样,还是不区分大小写,像vb.net那样?允许布尔运算符(and or not)。试图弄清楚这是否可以是您可以在代码中编写的任何表达式,或者用户仅限于A = B。 - Suraj
很多时候,你只需要解析字符串一次,之后就要经常进行评估。例如,将其编译为动态方法可能需要一点时间,但之后评估它的性能与用 C# 编写的函数相同。 - CodesInChaos
1
很多时候,您只需解析字符串一次,然后经常使用它(例如使用不同的参数)。下面提到的NCalc通过一个缓存实现了这一点,可以在多个线程中工作。 - GreyCloud
请参见https://dev59.com/cXVD5IYBdhLWcg3wNIvc。 - nawfal
我过去使用过ncalc,但是尽管ncalc相当古老。Jace是新的和更快的 :) Jace的Github存储库 - NicoJuicy
显示剩余3条评论
5个回答

35

你有看过https://ncalc.codeplex.com/https://github.com/sheetsync/NCalc吗?

它是可扩展的,快速的(例如具有自己的缓存),可以通过处理EvaluateFunction / EvaluateParameter事件在运行时提供自定义函数和变量。 它可以解析的示例表达式:

Expression e = new Expression("Round(Pow(Pi, 2) + Pow([Pi2], 2) + X, 2)");

  e.Parameters["Pi2"] = new Expression("Pi * Pi");
  e.Parameters["X"] = 10;

  e.EvaluateParameter += delegate(string name, ParameterArgs args)
    {
      if (name == "Pi")
      args.Result = 3.14;
    };

  Debug.Assert(117.07 == e.Evaluate());

它还可以原生地处理Unicode和多种数据类型。如果你想要改变语法,它带有一个Antler文件可以帮助你。此外,还有一个支持MEF来加载新功能的分支。

它也支持逻辑运算符,日期/时间字符串和if语句。


刚刚测试了一下,看起来很不错。虽然还需要进行负载测试,但是这个项目实现起来非常容易。 - NotMe
ace,如果你有任何问题,请随时在Ncalc讨论页面发帖。 - GreyCloud
谢谢Chris,很高兴听到这个好消息 :) 我真的很喜欢使用这个框架工作。 - GreyCloud
有人知道这个求值器是否使用惰性排序吗?例如:(eval(a) || eval(b)) => eval(b)永远不会执行,因为eval(a)返回了true。顺便说一下,这里还有一个克隆版本,仍在维护中:https://github.com/pitermarx/NCalc-Edge。 - NickLokarno
1
我可以在代码的单元测试中看到,有一个测试来检查布尔表达式是否被短路,所以我想答案是肯定的。 - NickLokarno
显示剩余2条评论

14

我看到过这个,但不确定是否有人真正使用过它。你有实际的使用经验吗? - NotMe
@Chris - 我在调试自己的表达式解析器时遇到了它。它的确像广告中所说的那样工作,但我的要求不包括快速,因此您可能需要进行基准测试。此外,它可能是轻量级的,具体取决于您如何定义它;)。 - Corbin March
我曾经给你点了赞,但最终还是决定不使用这个。在下载后,我发现它全部都是VB代码;虽然我相信这没问题,但是我的内心(可能是20多年的开发经验)拒绝与任何VB相关的东西一起工作,如果有选择的话。 ;) - NotMe
对我来说,它比NCalc更快。 - ISCI
或者试试这个老掉牙了的东西。我今天仍在使用它,它工作得非常好。https://www.codeproject.com/Articles/19768/Flee-Fast-Lightweight-Expression-Evaluator - Fandango68

8

Hisystems的解释器支持自定义函数、运算符和字面量,代码轻巧纯洁的C#便携式代码。目前能够在iOS上通过MonoTouch运行,并且应该也可以在其他任何Mono环境以及Windows上运行。商业使用免费。可在GitHub上获取:https://github.com/hisystems/Interpreter


3
我很欣赏这个答案,尽管有些晚了,但我想提供我的解决方案,因为我相信它可以在使用NCalc的基础上增加更多功能,如果有人希望在多个平台上使用这些表达式。
-- 更新 --
我已经为C#创建了一个解析器,并计划在未来几个月内将其实现为Java和Swift。这意味着您可以在不需要每个平台单独调整的情况下在多个平台上评估表达式。
虽然计划支持Java和Swift,但从未成为完全发布版。相反,现在支持.NET Standard,使Xamarin应用程序得到支持。
-- 结束更新 --
Expressive是工具,可在GitHubNuget上获得。
该网站有相当数量的文档,但为了防止链接失效,这里是如何使用它的示例: 变量支持
var expression = new Expression("1 * [variable]");
var result = expression.Evaluate(new Dictionary<string, object> { ["variable"] = 2);

功能

var expression = new Expression("sum(1,2,3,4)");
var result = expression.Evaluate();

它的设计尽可能与NCalc匹配,但它增加了对诸如“null”关键字之类的支持。

1

自我推广,我为C#编写了一个通用解析器生成器https://github.com/b3b00/csly。您可以在我的Github上找到一个表达式解析器作为示例。您可能需要根据自己的需求进行定制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接