在C#中解析带有嵌套括号的复杂公式字符串

huangapple go评论82阅读模式
英文:

Parse complex formula string with nested parenthesis in C#

问题

我正在寻找一种解析复杂的VFP计算字符串的方法。

其中一个这些公式的示例是:

ABS((ABS(-48) - ABS(245 + 34 - 98))) + ABS(ABS(10 + 9)) > 100

如您所见,我已经用其各自的值替换了所有变量模式 - 我的问题在于解析ABS()调用,以便我可以将它们替换为C# Math.Abs()。

在我的情况下,我想接收一个字符串列表:

  • ABS(-48)
  • ABS(245 + 34 - 98)
  • ABS(10 + 9)

我曾考虑使用正则表达式模式匹配,但我无法弄清楚如何定义一个可以确保我从原始公式中得到像"ABS(245 + 34 - 98)"这样的结果的模式。

我很愿意要么知道我需要使用的模式,要么看到别人成功解析类似内容的示例(我尝试过许多SO的解决方案,但从未正确解析它们...),或者更好的是一个建议的库,可以评估(返回true或false)原样计算(我曾尝试使用Datatable.Compute(),但它返回ABS(x)为null...)。

此外,为了避免大家都评论这个问题,我没有编写这些计算...我只是试图在C#中解析它们,而不必更改已经存在的字符串公式。

提前感谢!

英文:

I am looking for a way to parse complex VFP calculations strings.

An example of one of these formulas would be :

ABS((ABS(-48) - ABS(245 + 34 - 98))) + ABS(ABS(10 + 9)) > 100

As you can see, I have already substituted all variable patterns with there respective values - my issue is in parsing out the ABS() calls so I can substitute them out with C# Math.Abs().

In my case, I want to receive a list of string:

  • ABS(-48)
  • ABS(245 + 34 -98)
  • ABS(10 + 9)

I thought using regex pattern matching would be the ticket, but I cannot figure out how to define a pattern that would give me (with 100% accuracy) something like "ABS(245 + 34 -98)" out of the original formula.

I would love to either know the pattern I need to use, or see someone else's example of parsing something like this successfully (I have tried many SO solutions that never parse it correctly....), or even better a suggested library that can evaluate (returns true or false) that calculation in as it is (I thought I had it with Datatable.Compute() - but it returns ABS(x) as null....).

Also, so everyone does not comment about it, I did not write these calculations...I am only trying to parse them out in C# wihtout having to change the string formulas that already exist.

Thanks in advance!

答案1

得分: 1

如果您只想匹配inmost调用(而不是正确的抽象语法树):

您可以尝试使用类似这样的正则表达式模式:

[A-Za-z]+\s*\([0-9\+\*\-\s]+\)

C#代码如下:

using System.Text.RegularExpressions;
using System.Linq;

...

string text = "ABS((ABS(-48) - ABS(245 + 34 - 98))) + ABS(ABS(10 + 9)) > 100";

List<string> result = Regex
  .Matches(text, @"[A-Za-z]+\s*\([0-9\/\+\/\*\-\s]+\)")
  .Cast<Match>()
  .Select(match => match.Value)
  .ToList();

Console.WriteLine(string.Join(Environment.NewLine, result));

输出:

ABS(-48)
ABS(245 + 34 - 98)
ABS(10 + 9)

Fiddle

英文:

If you want to match inmost calls only (not a proper abstract syntax tree):

>I want to receive a list of string:
> - ABS(-48)
> - ABS(245 + 34 -98)
>- ABS(10 + 9)

you can try regular expression with a pattern like this:

[A-Za-z]+\s*\([0-9\+\*\-\s]+\)

C# code will be

using System.Text.RegularExpressions;
using System.Linq;

...

string text = &quot;ABS((ABS(-48) - ABS(245 + 34 - 98))) + ABS(ABS(10 + 9)) &gt; 100&quot;;

List&lt;string&gt; result = Regex
  .Matches(text, @&quot;[A-Za-z]+\s*\([0-9\/\+\/\*\-\s]+\)&quot;)
  .Cast&lt;Match&gt;()
  .Select(match =&gt; match.Value)
  .ToList();

Console.WriteLine(string.Join(Environment.NewLine, result));

Output:

ABS(-48)
ABS(245 + 34 - 98)
ABS(10 + 9)

Fiddle

答案2

得分: 0

以下是翻译好的内容:

这没有什么诀窍,解释如何做这个超出了stackoverflow问题的范围。这是一项复杂的任务,您只需要逐步完成它。

一个简单得多的方法是使用现有工具,比如我的SoftCircuits.ExpressionEvaluator

这个库支持您问题中的所有表达式,除了布尔操作。它也是开源的,所以您可以精确查看它是如何解析的。

SoftCircuits.Silk是我另一个库。它实现了一种解释型编程语言,完全支持布尔表达式。显然,这个库更复杂。但同样地,如果您想查看它是如何完成的,它也是开源的。

英文:

There is no trick to this and explaining how to do it is out of the scope of a stackoverflow question. It's a complex task and you'll just need to work through it.

A far simpler approach would be to use an existing tool such as my SoftCircuits.ExpressionEvaluator.

This library supports all the expressions in your question except the boolean operations. It's also open source, so you can review exactly how it parses it.

SoftCircuits.Silk is another one of my libraries. This implements an interpreted programming language and fully supports boolean expressions. Obviously, this library is more complex. But, again, it's all open source if you want to review how it's done.

答案3

得分: 0

自从我们放松了对工具的推荐(无论出于何种原因)。

我一直在使用NCalc很长时间了。https://github.com/ncalc/ncalc

尽管如此,我建议寻找一个新的且活跃维护的库,例如支持最新的.NET类型,如System.Int128会很不错。

因此,在GitHub上搜索似乎是最好的选择
https://github.com/search?q=math+formula+language%3AC%23&type=repositories

而且正如之前提到的,正则表达式不是这项工作的正确工具。

这里是一个运行中的演示:

https://dotnetfiddle.net/0vPKkd

注意:

我需要将ABS更改为Abs,我想你可以指定忽略大小写,但我相信像你这样的大人物会弄清楚的。

英文:

Since we are chill with recommending tools (for what ever reason).

I have been using NCalc for ages now. https://github.com/ncalc/ncalc

Though, I would recommend looking for a new and activly mainted library eg. support for the latest .net type as System.Int128 would be nice.

There for searching on github seems your best bet
https://github.com/search?q=math+formula+language%3AC%23&amp;type=repositories

and as was already mentioned, Regular expression isn't the right tool for the job.

Here a running demo:

https://dotnetfiddle.net/0vPKkd

Notice:

I needed to change ABS to Abs, I would assume you can specify to ignore-case, but I am sure a big boy like you will figure it out.

huangapple
  • 本文由 发表于 2023年7月4日 23:31:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76614080.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定