是否有任何 C++ 代码解析器可以寻找可以使用布尔代数简化的布尔表达式?
我知道编译器已经这样做了,但是如果有一个工具可以提供这样的东西,这样人们就可以真正提高代码的可读性了。
是否有任何 C++ 代码解析器可以寻找可以使用布尔代数简化的布尔表达式?
我知道编译器已经这样做了,但是如果有一个工具可以提供这样的东西,这样人们就可以真正提高代码的可读性了。
这是个坏主意!程序员编写反映他们思维过程的代码。因此,人类编写的布尔表达式已经自动优化以供人类理解。任何以编程方式改进这一点的尝试都注定要失败。它可能有意义的唯一上下文是工具生成的源代码的后处理。
您需要的是一个可以解析 C++、确定其符号含义、挑选布尔方程并对其应用不违反语义的布尔简化规则的工具。
可以做到这一点的工具是我们的DMS Software Reengineering Toolkit及其C++ Front End。DMS 旨在对代码进行程序分析和源到源转换。使用 C++ 前端,它可以将 C++ 解析为 AST,建立符号表,推断表达式的类型,并应用重写规则。
可以像这样编写重写规则:
domain Cpp. -- tell DMS to use the C++ front end
rule factor_common_and_term(e1: condition, e2:condition, e3: condition):
disjunctive_expression -> disjunctive_expression =
" \e1 && \e2 || \e1 && \e3 " -> " \e1 && ( \e2 || \e3 ) "
if no_side_effects(e1) /\ no_side_effects(e2);
排除一个常见的条件。该规则具有名称“factor_common_and_term”,以将其与通常可能编写的数百条其他规则(例如,“distribute_term”等)区分开来。e1,e2,e3 是表示任意子表达式的元变量(根据语法规则属于“条件”类型)。重写仅对 disjunction_expressions 进行;你可以让它成为“只是表达式”,但是你不会得到嵌套在其他条件表达式中的析取。重写有一个模式(左)和一个替换(右),都用元引号"来区分模式中的 C++ 代码与其周围的规则语言语法。\e1是 C++ 语法的转义,并指示元变量可以匹配的位置。元变量匹配相应类别的任何语法,因此看到\e1的位置可以是任意复杂的“条件”。在模式中两次提到 e1 的事实迫使出现相同。
可以编写一组重写规则来编码有关简化任意复杂的布尔方程的知识;几十条规则就可以做到。我们已经将这些应用于具有数十万项的非 C++ 布尔方程系统,以及 C 和 C++ 预处理器条件。
对于 C++,您需要检查重写是否安全,如果 e1 有副作用,或者 e2 有副作用,则不是。此检查是通过辅助函数调用进行的,该函数调用必须以保守的方式确定此答案。对于 C++ 来说,确定没有副作用实际上非常复杂:您必须知道表达式的所有元素是什么,并且它们都没有副作用。
可以使用检查所有表达式元素的 DMS 的属性语法(一种有组织的树爬网)来执行此检查。简单的常量和变量(需要一个符号表)不需要。函数调用(包括构造函数等)可能;必须找到它们的定义(同样需要一个符号表),并进行类似的处理。表达式元素可能会调用单独编译的函数;在这种情况下,保守的答案是“不知道”,因此“假设有副作用”。DMS 实际上可以同时读取多个编译单元,因此如果您想走那么远,可以找到、解析/符号解析和爬取单独编译的函数。
所以布尔重写部分非常简单;副作用分析不是。
我们使用 DMS 对 C++ 代码进行了大量更改;我们经常通过对这样的复杂分析做出假设来作弊。通常我们会像程序员感到惊讶一样感到惊讶(“你是什么意思,有副作用?”)。大多数情况下它工作得很好。我们对2500万行的C系统做了详细的副作用分析;C++ 还没有。
只有当某些子表达式可能被多次评估时,副作用分析才有意义。OP 的示例,在评论中给出,不需要它们,可以通过以下规则处理:
rule not_on_disjunction(e1:condition, e2:condition):
condition -> condition =
" ! (\e1 || \e2) " -> " !\e1 && !\e2";
rule double_not(e:condition):
condition -> condition =
" ! ! \e " --> " \e ";
一个完整但简单的工作示例和更详细的描述是这个传统代数和一些微积分的代数简化示例。
对于特定的代码转换是否会使代码更具可读性,显然存在争议。恕我直言,那是因为代码的形状通常是一种艺术判断,我们似乎都不同意艺术。这与让其他人修改您的代码没有什么不同。
虽然它不能直接用于 C/C++ 布尔表达式,但我发现一个对简化复杂布尔逻辑非常有用的工具是Logic Friday。不幸的是,它仅适用于 Windows,但幸运的是它是免费的。
您可以通过减少需要检查的“if”数量来提高代码效率。但不能自动进行更简化和更好的可读性。
http://www.freewarepalm.com/educational/booleanfunctionsimplificationtool.shtml
也许值得尝试一下。
然而,通常最好自己做 - 因为可读性和可理解性更重要 - 并让编译器进行简化。