C:转换A? B : C 进入 if (A) B else C

发布于 2024-08-24 23:41:14 字数 359 浏览 7 评论 0原文

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

a = (A) ? B : C;

为带有 if/else 语句的“默认”语法:

if (A)
  a = B
else
  a = C

有人知道有一种工具能够做这样的改造吗?

我使用 GCC 4.4.2 并使用 -E 创建一个预处理文件,但不希望其中包含此类结构。

编辑: 以下代码也应该进行转换:

a = ((A) ? B : C)->b;

I was looking for a tool that can convert C code expressions for the form:

a = (A) ? B : C;

into the 'default' syntax with if/else statements:

if (A)
  a = B
else
  a = C

Does someone know a tool that's capable to do such a transformation?

I work with GCC 4.4.2 and create a preprocessed file with -E but do not want such structures in it.

Edit:
Following code should be transformed, too:

a = ((A) ? B : C)->b;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一抹淡然 2024-08-31 23:41:15

我不知道三元运算符作为 if 逻辑的快捷方式内置在语言规范中......我能想到的唯一方法是手动查找这些行并将其重写为使用 if 的形式...作为普遍共识,三元运算符的工作方式如下:

expr_is_true ? exec_if_expr_is_TRUE : exec_if_expr_is_FALSE;

如果表达式被评估为 true,则执行 ? 之间的部分:,否则执行 :; 之间的最后一部分。如果表达式的计算结果为 false,则情况相反

expr_is_false ? exec_if_expr_is_FALSE : exec_if_expr_is_TRUE;

I am not aware of such a thing as the ternary operator is built-into the language specifications as a shortcut for the if logic... the only way I can think of doing this is to manually look for those lines and rewrite it into the form where if is used... as a general consensus, the ternary operator works like this

expr_is_true ? exec_if_expr_is_TRUE : exec_if_expr_is_FALSE;

If the expression is evaluated to be true, execute the part between ? and :, otherwise execute the last part between : and ;. It would be the reverse if the expression is evaluated to be false

expr_is_false ? exec_if_expr_is_FALSE : exec_if_expr_is_TRUE;
凉栀 2024-08-31 23:41:15

如果这些语句像这样非常有规律,为什么不通过一个小的 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

当然,如果文本模式不像您发布的那样规则,它会变得越来越难。但免费、快速且易于尝试。

If the statements are very regular like this why not run your files through a little Perl script? The core logic to do the find-and-transform is simple for your example line. Here's a bare bones approach:

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

You'd run it like so:

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

Of course it gets harder and harder if the text pattern isn't as regular as the one you posted. But free, quick and easy to try.

你另情深 2024-08-31 23:41:14

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 can do this quite easily.

Coccinelle is a program matching and
transformation engine which provides
the language SmPL (Semantic Patch
Language) for specifying desired
matches and transformations in C code.
Coccinelle was initially targeted
towards performing collateral
evolutions in Linux. Such evolutions
comprise the changes that are needed
in client code in response to
evolutions in library APIs, and may
include modifications such as renaming
a function, adding a function argument
whose value is somehow
context-dependent, and reorganizing a
data structure. Beyond collateral
evolutions, Coccinelle is successfully
used (by us and others) for finding
and fixing bugs in systems code.

EDIT:
An example of semantic patch:

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

From the documentation:

The pattern !x&y. An expression of this form is almost always meaningless, because it combines a boolean operator with a bit operator. In particular, if the rightmost bit of y is 0, the result will always be 0. This semantic patch focuses on the case where y is a constant.

You have a good set of examples here.

The mailing list is really active and helpful.

赠我空喜 2024-08-31 23:41:14

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;

The following semantic patch for Coccinelle will do the transformation.

@@
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;
眼眸里的快感 2024-08-31 23:41:14

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 ; ".

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

转换对源代码结构而不是文本进行操作,因此布局和注释不会影响识别或应用。规则中的引号不是传统的字符串引号,而是元语言引号,它将规则语法语言与用于指定要更改的具体语法的模式语言分开。

如果您打算保留预处理指令,则会出现一些问题。由于您显然愿意使用预处理器扩展的代码,因此您可以要求 DMS 将预处理作为转换步骤的一部分;它内置了完整的 GCC4 和 GCC4 兼容预处理器。

正如其他人所观察到的,这是一个相当简单的情况,因为您指定它在完整语句的级别上工作。如果您想删除代码中与此语句类似的任何赋值,并且将此类赋值嵌入到各种上下文(初始化程序等)中,您可能需要一组更大的转换来处理各种特殊情况,并且您可能需要制造其他代码结构(例如,适当类型的临时变量)。像 DMS 这样的工具的好处是它可以显式计算任意表达式的符号类型(从而任何所需临时值的类型声明),并且您可以相当直接地编写这样一个更大的集合并应用所有它们。

尽管如此,我不确定执行三元条件表达式消除操作的真正价值。一旦编译器获得结果,您可能会获得类似的目标代码,就好像您根本没有进行转换一样。毕竟,编译器也可以应用保留等价的转换。

不过,总的来说,定期进行更改显然是有价值的。

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

The DMS Software Reengineering Toolkit can do this, by applying program transformations.

A specific DMS transformation to match your specific example:

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 ; ".

You'd need another rule to handle your other case, but it is equally easy to express.

The transformations operate on source code structures rather than text, so layout out and comments won't affect recognition or application. The quotation marks in the rule not traditional string quotes, but rather are metalinguistic quotes that separate the rule syntax language from the pattern langu age used to specify the concrete syntax to be changed.

There are some issues with preprocessing directives if you intend to retain them. Since you apparantly are willing to work with preprocessor-expanded code, you can ask DMS to do the preprocessing as part of the transformation step; it has full GCC4 and GCC4-compatible preprocessors built right in.

As others have observed, this is a rather easy case because you specified it work at the level of a full statement. If you want to rid the code of any assignment that looks similar to this statement, with such assignments embedded in various contexts (initializers, etc.) you may need a larger set of transforms to handle the various set of special cases, and you may need to manufacture other code structures (e.g., temp variables of appropriate type). The good thing about a tool like DMS is that it can explicitly compute a symbolic type for an arbitrary expression (thus the type declaration of any needed temps) and that you can write such a larger set rather straightforwardly and apply all of them.

All that said, I'm not sure of the real value of doing your ternary-conditional-expression elimination operation. Once the compiler gets hold of the result, you may get similar object code as if you had not done the transformations at all. After all, the compiler can apply equivalence-preserving transformations, too.

There is obviously value in making regular changes in general, though.

(DMS can apply source-to-source program transformations to many langauges, including C, C++, Java, C# and PHP).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文