6

次の形式のCコード式を変換できるツールを探していました。

a = (A) ? B : C;

if/elseステートメントを使用して「デフォルト」構文に追加します。

if (A)
  a = B
else
  a = C

誰かがそのような変換を行うことができるツールを知っていますか?

私はGCC4.4.2を使用して、前処理されたファイルを作成しますが、-Eそのような構造は必要ありません。

編集:次のコードも変換する必要があります:

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

5 に答える 5

12

Coccinelleはこれを非常に簡単に行うことができます。

Coccinelleは、Cコードで目的の一致と変換を指定するための言語SmPL(セマンティックパッチ言語)を提供するプログラム一致および変換エンジンです。Coccinelleは当初、Linuxで担保の進化を実行することを目的としていました。このような進化には、ライブラリAPIの進化に応じてクライアントコードに必要な変更が含まれ、関数の名前変更、値がコンテキストに依存する関数引数の追加、データ構造の再編成などの変更が含まれる場合があります。Coccinelleは、付随的な進化を超えて、システムコードのバグを見つけて修正するために(私たちや他の人たちによって)うまく使用されています。

編集: セマンティックパッチの例:

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

ドキュメントから:

パターン!x&y。この形式の式は、ブール演算子とビット演算子を組み合わせているため、ほとんどの場合意味がありません。特に、yの右端のビットが0の場合、結果は常に0になります。このセマンティックパッチは、yが定数の場合に焦点を当てています。

ここに良い例があります。

メーリングリストは本当に活発で役に立ちます。

于 2010-03-11T18:28:52.833 に答える
4

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;
于 2010-03-13T10:53:44.253 に答える
1

DMS Software Reengineering Toolkitは、プログラム変換を適用することにより、これを行うことができます。

特定の例に一致する特定の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などの多くの言語に適用できます)。

于 2010-04-23T05:50:34.257 に答える
0

三項演算子がロジックのショートカットとして言語仕様に組み込まれていることを私は知りません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;
于 2010-03-11T18:34:40.717 に答える
0

ステートメントがこのように非常に規則的である場合は、小さな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

もちろん、テキストパターンが投稿したものほど規則的でない場合、それはますます難しくなります。しかし、無料で、すばやく、簡単に試すことができます。

于 2010-03-11T18:42:39.953 に答える