我正在寻找一种工具,可以转换C代码表达式的形式:

a = (A) ? B : C;

if / else语句 '默认' 语法:

if (A)
  a = B
else
  a = C

是否有人知道一个工具,是能够做这样的转型?

我用GCC 4.4.2工作,并创建一个-E预处理文件,但不希望它这样的结构。

编辑: 下面的代码应转变,也:

a = ((A) ? B : C)->b;
有帮助吗?

解决方案

Coccinelle的可以做到这一点很容易。

  

Coccinelle的是一个程序和匹配   转换引擎提供   语言SMPL(语义补丁   语言),用于指定所需的   匹配和变换中的C代码。   Coccinelle的最初目标   对执行担保   变阵在Linux中。这样的变阵   包括需要的更改   在响应于客户机代码   变阵在库API,并可   包括修饰如重命名   一个函数,加入函数的参数   它的值是莫名其妙   上下文相关的,并且重新组织   数据结构。除了抵押   变阵,Coccinelle的是成功   查找二手(由我们和其他人)   和在系统代码修正错误。

修改 语义补丁的示例:

@@ expression E; constant C; @@
(
  !E & !C
|
- !E & C
+ !(E & C)
)

从文档:

  

在图案!X和Y。这种形式的表达是几乎总是毫无意义的,因为它结合布尔逻辑运算符有位运算符。特别地,如果y的最右边的位是0,则结果将始终为0这种语义补丁着重于其中y是一个恒定的情况。

您拥有一套良好的例子这里

在邮件列表是真的活性的和有益的。

其他提示

有Coccinelle的以下语义补丁将做转换。

@@
expression E1, E2, E3, E4;
@@

- E1 = E2 ? E3 : E4;
+ if (E2)
+   E1 = E3;
+ else
+   E1 = E4;

@@
type T;
identifier E5;
T *E3;
T *E4;
expression E1, E2;
@@

- E1 = ((E2) ? (E3) : (E4))->E5;
+ if (E2)
+   E1 = E3->E5;
+ else
+   E1 = E4->E5;


@@
type T;
identifier E5;
T E3;
T E4;
expression E1, E2;
@@

- E1 = ((E2) ? (E3) : (E4)).E5;
+ if (E2)
+   E1 = (E3).E5;
+ else
+   E1 = (E4).E5;

DMS软件再造工具包可以通过应用程序变换为此,

一个特定DMS变换以匹配特定示例:

domain C.

rule ifthenelseize_conditional_expression(a:lvalue,A:condition,B:term,C:term):
stmt -> stmt
=  " \a = \A ? \B : \C; "
-> " if (\A) \a = \B;  else \a=\C ; ".

您会需要另一个规则来处理你的其他情况,但同样容易表达。

在变换源代码结构,而不是文本操作,所以布局出和评论不会影响识别或应用。规则中的引号不是传统意义上的字符串引号,而是是分开用于指定具体语法的模式语言翻译年龄规则语法语言的元语言报价进行更改。

有一些问题,预处理指令,如果你打算留住他们。既然你apparantly愿意与预处理程序扩展代码工作,你可以问DMS做预处理的转换步骤的一部分;它具有内建在充分GCC4和GCC4兼容的预处理器。

正如其他人所观察到的,这是因为你指定它在一个完整的语句级别上工作是一个比较简单的情况。如果你想摆脱类似于这样的语句,嵌入在各种情况下(初始化等),这样的分配任何任务的代码,你可能需要一个更大的集变换处理各种集的特殊情况下,你可能需要制造其它代码的结构(例如,适当类型的温度变量)。关于像DMS工具的好处是,它可以明确地计算符号类型的任意表达式(因此任何需要临时工的类型声明),并且你可以写这样的大集,而直截了当和应用这些。

所有这一切说,我不知道做你三元条件表达式删除操作的真正价值。一旦编译器得到结果的保持,你可能会因为如果你没有做过的事情的转变都得到类似的目标代码。毕竟,编译器可以应用等价保留变换得。

有明显在使一般规律的变化,虽然值。

(DMS可以应用源到源程序变换到许多汉语语言,包括C,C ++,Java和C#和PHP)。

我不知道作为三元运算符内置到语言规范作为if逻辑的捷径这样的事情......我能想到这样做的唯一方法是手动寻找那些线和重写入其中if用于...作为一般的共识的形式,三元运算符是这样工作的

expr_is_true ? exec_if_expr_is_TRUE : exec_if_expr_is_FALSE;

如果该表达式评估为真,则执行?:之间的部分,否则执行:;之间的最后部分。这将是相反的,如果该表达式评估为假

expr_is_false ? exec_if_expr_is_FALSE : exec_if_expr_is_TRUE;

如果语句都是这样非常有规律的,为什么不通过一个小Perl脚本运行您的文件吗?核心逻辑做了查找和转换是简单的为您的示例行。这里的一个裸露的骨头的方法:

use strict;
while(<>) {
    my $line = $_;
    chomp($line);
    if ( $line =~ m/(\S+)\s*=\s*\((\s*\S+\s*)\)\s*\?\s*(\S+)\s*:\s*(\S+)\s*;/ ) {
        print "if(" . $2 . ")\n\t" . $1 . " = " . $3 . "\nelse\n\t" . $1 . " = " . $4 . "\n";
    } else {
        print $line . "\n";
    }
}
exit(0);

您想这样运行:

perl transformer.pl < foo.c > foo.c.new

当然,如果文本模式并不像您发布的一个定期它越来越难。然而,自由,快速和容易尝试。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top