我目前正在开发一个Java应用程序,我需要实现一个用于构建BPF表达式的系统。我还需要实现检测等效BPF表达式的机制。
构建表达式并不太难。我可以使用Interpreter设计模式构建语法树,并实现toString
以获取BPF语法。
但是,检测两个表达式是否相同则要困难得多。一个简单的例子如下:
A: src port 1024 and dst port 1024
B: dst port 1024 and src port 1024
为了检测A和B是等价的,我可能需要在比较它们之前将每个表达式转换为“标准化”形式。对于上面的示例,这很容易,但是,当使用嵌套的AND
,OR
和NOT
操作的组合时,它变得越来越难。
有谁知道我应该如何最好地解决这个问题?
答案 0 :(得分:6)
比较布尔表达式的一种方法可能是将两者都转换为disjunctive normal form (DNF),并比较DNF。这里,变量将是Berkeley Packet Filter标记,并且在两个表达式中的任何一个中出现的相同标记(例如port 80
)都需要被赋予相同的变量名称。
在http://www.izyt.com/BooleanLogic/applet.php有一个看起来很有趣的小程序 - 遗憾的是我现在无法通过浏览器中的Java问题试一试。
答案 1 :(得分:2)
我非常确定检测等效表达式是np-hard或np-complete问题,即使对于仅布尔表达式也是如此。这意味着要完美地完成它,最佳方法基本上是建立所有可能的输入组合和结果的完整表格,然后比较表格。
也许BPF表达式在某种程度上受到限制而改变了吗?我不知道,所以我假设没有。
如果您的问题很小,那可能不是问题。我将完全作为决策树设计算法的一部分。
或者,不要试图做到完美。允许一些漏报(相同的情况,但你不会发现)。
一种简单的方法可能是做一个正常表达式 - 评估的变体,但是评估表达式的替代表示而不是结果。对交换运算符强加一个排序。在评估期间应用一些明显的简化。用最小的基本运算符集替换富运算符集 - 例如使用de-morgans来消除OR运算符。
此替代表示形式表示一组等效表达式的所有成员的规范表示。它应该是一个等价类,在这个意义上,你总是为该集合的任何成员找到相同的规范形式。但这只是等价类的集理论/抽象代数意义 - 它并不意味着所有等价表达都在同一个等价类中。
对于有效的字典查找,您可以使用基于该规范表示的散列或比较。
答案 2 :(得分:1)
我肯定会使用语法规范化。也就是说,就像aix建议的那样,使用DNF转换布尔值并重新排序抽象语法树,使得词法最小的参数位于左侧。将所有比较标准化为<和< =。然后,两个等效表达式应该具有等效的语法树。