10

最好的方法是评估如下表达式:
(A And B) Or (A And C) Or (Not B And C)
or
(A && B) || (A && C) || (!B && C)

在运行时,我计划将上述表达式转换为以下表达式:
(True And False) Or (True And False) Or (Not False And True)
or
(True && False) || (真 && 假) || (!假 && 真)

条件: 1) 直到运行时才知道逻辑表达式。2) number 变量及其值直到运行时才知道。3) 变量值永远不会为空。

我知道我可以使用在运行时根据输入生成的类和方法创建一个简单的组合,但有没有更好的方法。我以前做过。使用字符串生成器编写代码,然后调用编译器。之后,您加载程序集并调用该方法。

建议?

谢谢。

4

9 回答 9

8

如果您使用的是 .NET3.5,那么您可以解析文本并使用 Expression 类创建一个抽象语法树。然后创建一个合适的 LambdaExpression 实例并将其编译为委托,然后您可以执行该委托。

为这种相当简单的语法构建解析器和语法树构建器是一项非常有趣的练习,并且执行起来会比调用编译器快一些(在我看来它也更整洁)。

如果您不使用 .NET3.5,那么自己实现解释的抽象语法树也并不复杂。

于 2008-12-08T17:15:03.140 回答
5

请注意:您所说的两个最终条件不一定是等价的。C# 中的 && 运算符将使用短路求值,而AndVB 中的逻辑运算符则不使用。如果您想确保语句是等价的,请将一个用户翻译AndAndAlso和一个用户翻译OrOrElse

对于简单的表达式,您可能不会注意到差异。但是,如果条件可能会产生副作用,或者如果两者之间的性能差异是一个问题,那么这可能很重要。

于 2008-12-08T17:16:29.380 回答
3

您可以通过以下方式轻松做到这一点:

  1. 一个解析器生成器(如上面提到的 ANTLR),它将布尔表达式作为输入并生成一个中缀列表和
  2. 评估反向波兰表示法堆栈的代码。

语法看起来像这样:

program: exprList ;

exprList: expr { Append($1); }
    | expr OR exprList { Append(OR); }
    | expr AND exprList { Append(AND); }
    | NOT exprList { Append(NOT); }
    | ( exprList ) { /* Do nothing */ }
    ;

expr: var { Append($1); }
    | TRUE { Append(True); }
    | FALSE { Append(False); }
    ;

要进行评估,请执行以下操作:

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()

对于符号,您必须在运行时替换真值。

于 2008-12-08T20:33:20.853 回答
3

您可以使用https://github.com/mrazekv/logicalparser

它是编写逻辑表达式的简单库(使用优先表评估,允许 OR、NOT、AND 运算符和 >、>=、<=、< 整数变量和 = 字符串变量)

于 2012-12-01T07:48:49.310 回答
0

您可以编写一个简单的解释器/解析器。使用ANTLR 之类的东西并重用现有的语法。

于 2008-12-08T17:12:59.807 回答
0

如果您使用的是 .NET 3.5,则可以创建 Lambda 表达式。然后您可以从中创建一个委托并作为标准委托/方法调用。互联网上有很多关于 Lambda 表达式的示例。

于 2008-12-08T17:18:21.823 回答
0

一种解决方案是将表达式组装为字符串,然后将其发送到 SQL Server 或任何您的数据库进行评估。用 1=1 或 0=1 分别替换 True 和 False 的实际变量,您最终会得到如下查询:

SELECT 1 WHERE (1=1 And 0=1) Or (1=1 And 1=1) Or (Not 0=1 And 1=1)

然后,当您运行查询时,当结果为真时,您会得到 1。可能不是最优雅的解决方案,但它会起作用。很多人可能会建议不要这样做,但无论如何我都会把它作为一种可能的解决方案扔出去。

于 2008-12-08T17:24:00.253 回答
0

这不是最好的答案,但我自己前段时间遇到了这个问题。

这是我的旧代码:VB.Net - 根本没有保修!

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)

这段代码使用多个 '(', ')', 'and', 'or' 加上 'other things' 的字符串,并通过用布尔值替换这些东西来将逻辑分解为布尔值。所以:

无论我想评估什么“其他事情”,我都必须在“'funktionen ausführen und zurückgeben,einzelwert!”的评论中输入 Function resolveTerm() 。在第 2 页。现在唯一的评估是“如果数字大于 1”

问候

于 2016-04-25T16:48:06.480 回答
0

看看我的图书馆,Proviant。它是一个 .NET 标准库,使用Shunting Yard 算法来评估布尔表达式。

它还可以为您的表达式生成一个真值表。

您也可以实现自己的语法。

于 2019-04-04T19:51:53.373 回答