在 C# 或 VB 中动态逻辑表达式解析/评估?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/350181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dynamic logical expression parsing/evaluation in C# or VB?
提问by Bobby Ortiz
What is the best was to evaluate an expression like the following:
(A And B) Or (A And C) Or (Not B And C)
or
(A && B) || (A && C) || (!B && C)
最好的方法是评估如下表达式:
(A And B) Or (A And C) Or (Not B And C)
or
(A && B) || (A && C) || (!B&&C)
At runtime, I was planning on converting the above expressions to the following:
(True And False) Or (True And False) Or (Not False And True)
or
(True && False) || (True && False) || (! False && True)
在运行时,我计划将上述表达式转换为以下表达式:
(True And False) Or (True And False) Or (Not False And True)
or
(True && False) || (真&&假) || (!假&&真)
Conditions: 1) The logical expression is not known until runtime. 2) The number variable and their values are not known until runtime. 3) Variable values are never null.
条件: 1) 直到运行时才知道逻辑表达式。2) number 变量及其值直到运行时才知道。3) 变量值永远不会为空。
I know I could create a simple assemble with a class and a method that I generate at runtime based on the inputs, but is there a better way. I have done this before. Use a string builder to write the code, then call the compiler. After that, you load the assembly and call the method.
我知道我可以使用我在运行时根据输入生成的类和方法创建一个简单的汇编,但是有没有更好的方法。我以前做过这个。使用字符串生成器编写代码,然后调用编译器。之后,您加载程序集并调用该方法。
Suggestions?
建议?
Thanks.
谢谢。
采纳答案by Chris
If you're using .NET3.5 then you can parse the text and create an abstract sytax tree using the Expression classes. Then create a suitable LambdaExpression instance and compile it into a delegate, which you can then execute.
如果您使用 .NET3.5,那么您可以解析文本并使用 Expression 类创建抽象语法树。然后创建一个合适的 LambdaExpression 实例并将其编译成一个委托,然后您可以执行该委托。
Constructing a parser and syntax tree builder for this kind of fairly simple grammer is quite an interesting exercise, and will execute somewhat faster than invoking the compiler (and it's neater in my view as well).
为这种相当简单的语法构建解析器和语法树构建器是一项非常有趣的练习,并且比调用编译器的执行速度要快一些(在我看来它也更简洁)。
If you're not using .NET3.5, then it's also not complicated to implement an interpreted abstract syntax tree yourself.
如果您没有使用 .NET3.5,那么自己实现一个解释型抽象语法树也不复杂。
回答by Eugene Yokota
回答by Joel Coehoorn
Be warned: the two final conditions you're talking about are not necessarily equivalent. The && operators in C# will use short-circuit evalution, while the logical And
operator in VB does not. If you want to be sure the statements are equivalent, translate a user And
to AndAlso
and a user Or
to OrElse
.
请注意:您所谈论的两个最终条件不一定是等价的。C# 中的 && 运算符将使用短路评估,而And
VB 中的逻辑运算符则不使用。如果您想确保这些语句是等效的,请将用户转换And
为AndAlso
并将用户转换Or
为OrElse
。
For simple expresssions you probably won't notice a difference. But if the conditions can have side effects or if the performance difference between the two is a concern, this can be important.
对于简单的表达式,您可能不会注意到有什么不同。但如果条件可能有副作用,或者如果两者之间的性能差异令人担忧,这可能很重要。
回答by TcKs
If you are using .NET 3.5, you can create a Lambda Expression. Then you can create a delegate from it and call as standard delegate/method. On the internet is a lot of samples about Lambda Expressions.
如果您使用 .NET 3.5,则可以创建 Lambda 表达式。然后您可以从中创建一个委托并作为标准委托/方法调用。互联网上有很多关于 Lambda 表达式的示例。
回答by Kibbee
One solution would be to assemble the expression as a string, and then send it SQL Server, or whatever your database is for evaluation. Replace the actual variables with 1=1 or 0=1 for True and False respectively, and you would end up with a query like this:
一种解决方案是将表达式组装为字符串,然后将其发送到 SQL Server 或任何用于评估的数据库。分别将 True 和 False 的实际变量替换为 1=1 或 0=1,您将得到如下查询:
SELECT 1 WHERE (1=1 And 0=1) Or (1=1 And 1=1) Or (Not 0=1 And 1=1)
SELECT 1 WHERE (1=1 And 0=1) or (1=1 And 1=1) or (Not 0=1 And 1=1)
Then when you run the query, you get a 1 back when the result is true. May not be the most elegant solution, but it will work. A lot of people will probably advise against this, but I'm just going to throw it out there as a possible solution anyway.
然后,当您运行查询时,如果结果为真,您会得到一个 1。可能不是最优雅的解决方案,但它会起作用。很多人可能会建议不要这样做,但无论如何我都会把它作为可能的解决方案扔在那里。
回答by hughdbrown
You can do this easily with:
你可以很容易地做到这一点:
- a parser generator (like ANTLR, mentioned above) that takes boolean expressions as input and produces an infix list and
- code to evaluate a Reverse Polish Notation stack.
- 一个解析器生成器(如上面提到的 ANTLR),它将布尔表达式作为输入并生成一个中缀列表和
- 用于评估逆波兰表示法堆栈的代码。
The grammar looks something like this:
语法看起来像这样:
program: exprList ;
exprList: expr { Append(); }
| expr OR exprList { Append(OR); }
| expr AND exprList { Append(AND); }
| NOT exprList { Append(NOT); }
| ( exprList ) { /* Do nothing */ }
;
expr: var { Append(); }
| TRUE { Append(True); }
| FALSE { Append(False); }
;
To evaluate, you do this:
要进行评估,请执行以下操作:
for each item in list
if item is symbol or truth value, push onto RPN stack
else if item is AND, push (pop() AND pop())
else if item is OR, push (pop() OR pop())
else if item is NOT, push (NOT pop())
result = pop()
For symbols, you have to substitute the truth value at runtime.
对于符号,您必须在运行时替换真值。
回答by Vojta
You can use https://github.com/mrazekv/logicalparser
您可以使用https://github.com/mrazekv/logicalparser
Its simply library to write logical expression (evaulated with precenednce table, allows to OR, NOT, AND operator and >, >=, <=, < on integer variables and = on string variables)
它是编写逻辑表达式的简单库(使用优先表评估,允许 OR、NOT、AND 运算符和 >、>=、<=、< 在整数变量上和 = 在字符串变量上)
回答by Nibbels
This will not be the best answer, but I myself had this problem some time ago.
这不会是最好的答案,但我自己前段时间也遇到过这个问题。
Here is my old code: VB.Net - no warranty at all!
这是我的旧代码:VB.Net - 根本没有保修!
https://cloud.downfight.de/index.php/s/w92i9Qq1Ia216XB
https://cloud.downfight.de/index.php/s/w92i9Qq1Ia216XB
Dim BoolTermParseObjekt As New BoolTermParse
MsgBox(BoolTermParseObjekt.parseTerm("1 und (((0 oder 1 und (0 oder 4))) oder 2)").ToString)
This code eats a String with multiple '(', ')', 'and', 'or' plus 'other things' and breaks down the logic to a boolean by replacing the things with boolean values. therefore:
这段代码吃一个包含多个 '(', ')', 'and', 'or' 加上 'other things' 的字符串,并通过用布尔值替换事物来将逻辑分解为布尔值。所以:
Whatever 'other things' I wanted to evaluate I had to put in Function resolveTerm() at the comment "'funktionen ausführen und zurückgeben, einzelwert!" in page 2. There the only evaluation rightnow is "If number is > 1"
无论我想评估什么“其他事情”,我都必须在“'funktionen ausführen und zurückgeben,einzelwert!”的评论中放入Function resolveTerm()。在第 2 页。现在唯一的评估是“如果数字 > 1”
Greetings
你好
回答by Genfood
Take a look at my library, Proviant. It's a .NET Standard library using the Shunting Yard algorithmto evaluate boolean expressions.
看看我的图书馆,Proviant。它是一个 .NET Standard 库,使用Shunting Yard 算法来评估布尔表达式。
It could also generate a truth-table for your expressions.
它还可以为您的表达式生成真值表。
You could also implement your own grammar.
您也可以实现自己的语法。