在C#或VB中动态逻辑表达式解析/评估?

时间:2008-12-08 17:05:20

标签: c# vb.net expression

最好的方法是评估如下表达式:
(A和B)或(A和C)或(不是B和C)

(A&& B)|| (A&& C)|| (!B&& C)

在运行时,我计划将上述表达式转换为以下内容:
(真与假)或(真与假)或(不是假与真)

(真&& False)|| (真&& False)|| (!False&& True)

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

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

建议?

感谢。

9 个答案:

答案 0 :(得分:8)

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

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

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

答案 1 :(得分:4)

警告:你所谈论的两个最终条件不一定相同。和&& C#中的运算符将使用短路评估,而VB中的逻辑And运算符则不会。如果您想确保这些陈述是等效的,请将用户And转换为AndAlso,将用户Or转换为OrElse

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

答案 2 :(得分:3)

您可以通过以下方式轻松完成此操作:

  1. 解析器生成器(如上面提到的ANTLR),它将布尔表达式作为输入并生成中缀列表,并且
  2. 用于评估反向波兰表示法堆栈的代码。
  3. 语法看起来像这样:

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

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

答案 3 :(得分:3)

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

它只是简单的库来编写逻辑表达式(用先验表表示,允许OR,NOT,AND运算符和>,> =,< =,<对整数变量和=对字符串变量)

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

答案 6 :(得分: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)

此代码使用多个'(',')','和','或'plus'其他东西'来执行String,并通过用布尔值替换事物将逻辑分解为布尔值。 因此:

无论我想评估什么'其他'我必须放入函数resolveTerm() 在评论“'funktionenausführenundzurückgeben,einzelwert!” 在第2页。 那里唯一的评价权是“如果数字是> 1”

问候

答案 7 :(得分:0)

看看我的图书馆Proviant。这是一个使用Shunting Yard algorithm评估布尔表达式的.NET标准库。

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

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

答案 8 :(得分:-1)

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

SELECT 1 WHERE(1 = 1和0 = 1)或(1 = 1和1 = 1)或(不是0 = 1和1 = 1)

然后,当您运行查询时,如果结果为true,则返回1。可能不是最优雅的解决方案,但它会起作用。很多人可能会建议不要这样做,但我只是想把它扔出去作为一种可能的解决方案。