1

私は非常に読みにくいコードを生成する多面体コンパイラを使用していました。ここに小さなサンプルがあります:

for (t2=2*t1;t2<=min(floord(2*T+N-3,32),floord(64*t1+N+61,32));t2++) {
  for (t3=max(ceild(32*t2-N-27,32),2*t1);t3<=min(min(floord(2*T+N-3,32),floord(64*t1+N+61,32)),floord(32*t2+N+27,32));t3++) {
    if ((t1 <= floord(32*t3-N+1,64)) && (t2 <= t3-1)) {
      if ((N+1)%2 == 0) {
        for (t5=max(32*t2,32*t3-N+4);t5<=32*t2+31;t5++) {
          a[-32*t3+t5+N-2][N-2]=b[-32*t3+t5+N-2][N-2];;
        }
      }
    }
    if ((t1 <= floord(32*t2-N+1,64)) && (t2 >= t3)) {
      if ((N+1)%2 == 0) {
        for (t6=max(32*t3,32*t2-N+4);t6<=min(32*t2,32*t3+31);t6++) {
          a[N-2][-32*t2+t6+N-2]=b[N-2][-32*t2+t6+N-2];;
        }
      }
    }

生成されたコードの算術式を配列インデックスの printf に変換することで、コンパイラの一部をデバッグしようとしていました。たとえば、次の式です。

a[-32*t3+t5+N-2][N-2]=b[-32*t3+t5+N-2][N-2];;

このprintfになるはずです:

printf("a[%d][%d] = b[%d][%d]\n",-32*t3+t5+N-2,N-2,-32*t3+t5+N-2,N-2);

私は awk を試してみて、変更する文字列を識別し、プログラムの残りの部分を変更しないようにするこの単純なプログラムを作成しました。

awk '{if ($0 ~ "^[ ]*[a,b]") print "printf("; else print $0;}'

ただし、配列アクセスのインデックスを削除しながら、その構造を残すために算術式を解析する方法がわかりません。while ループを試してみましたが、今のところ行き詰まっています。awk はそのような置換を行うことができるはずですが、他の言語での提案は大歓迎です!

update算術式は、次のような任意の算術式にすることができます。

b[t3][t4]=0.2*(a[t3][t4]+a[t3][t4-1]+a[t3][1+t4]+a[1+t3][t4]+a[t3-1][t4]);;
4

2 に答える 2

2

コード:

awk '/\[/ { \
    sub(/^ */, ""); \
    sub(/;*$/, ""); \
    print \
        "printf(\"" \
        gensub("\\[[^]]*\\]", "[%d]", "g") \
        "\"" \
        gensub("[^\\[]*\\[([^]]*)\\][^\\[]*", ",\\1", "g") \
        ");" \
    ; \
    next; \
}1'

説明:

  • awk '/\[/ { ........; next; }1'........文字が見つかった任意の行で実行され[、それ以外の場合はそのままの行を出力します。
  • sub(/^ */, "");現在の行から先頭のスペース文字を削除します
  • sub(/;*$/, "");現在の行から末尾のセミコロン文字を削除します
  • この後に、print5 ビットを連結するステートメントが続きます。
  • gensub("\\[[^]]*\\]", "[%d]", "g")は、現在の行のコピーを返します。角かっこで囲まれたステートメントは に置き換えられ[%d]ます。ネストされた角括弧はこれを壊すことに注意してください。subまた、 とは対照的に、このgensubコマンドは現在の行を実際に変更しないことに注意してください。
  • gensub("[^\\[]*\\[([^]]*)\\][^\\[]*", ",\\1", "g")また、現在の行のコピーを取得し、見つかった角かっこで囲まれた式ごとに、次の 3 つのことを行います。
    • [^\\[]*先頭の非[文字を削除します
    • \\[([^]]*)\\]角かっこで囲まれた式に一致",\\1"し、カンマ文字とそれに続く角かっこ内の文字に置き換えます
    • [^\\[]*末尾の非文字を削除[します (次の角括弧式または行末まで)
  • 先頭と末尾の両方の非[文字を削除することは、角括弧で囲まれた 2 つの式の間で冗長ですが、行の最初と最後では役に立ちます。

入力:

for (t2=2*t1;t2<=min(floord(2*T+N-3,32),floord(64*t1+N+61,32));t2++) {
  for (t3=max(ceild(32*t2-N-27,32),2*t1);t3<=min(min(floord(2*T+N-3,32),floord(64*t1+N+61,32)),floord(32*t2+N+27,32));t3++) {
    if ((t1 <= floord(32*t3-N+1,64)) && (t2 <= t3-1)) {
      if ((N+1)%2 == 0) {
        for (t5=max(32*t2,32*t3-N+4);t5<=32*t2+31;t5++) {
          a[-32*t3+t5+N-2][N-2]=b[-32*t3+t5+N-2][N-2];;
        }
      }
    }
    if ((t1 <= floord(32*t2-N+1,64)) && (t2 >= t3)) {
      if ((N+1)%2 == 0) {
        for (t6=max(32*t3,32*t2-N+4);t6<=min(32*t2,32*t3+31);t6++) {
          a[N-2][-32*t2+t6+N-2]=b[N-2][-32*t2+t6+N-2];;
        }
      }
    }


    b[t3][t4]=0.2*(a[t3][t4]+a[t3][t4-1]+a[t3][1+t4]+a[1+t3][t4]+a[t3-1][t4]);;

出力:

for (t2=2*t1;t2<=min(floord(2*T+N-3,32),floord(64*t1+N+61,32));t2++) {
  for (t3=max(ceild(32*t2-N-27,32),2*t1);t3<=min(min(floord(2*T+N-3,32),floord(64*t1+N+61,32)),floord(32*t2+N+27,32));t3++) {
    if ((t1 <= floord(32*t3-N+1,64)) && (t2 <= t3-1)) {
      if ((N+1)%2 == 0) {
        for (t5=max(32*t2,32*t3-N+4);t5<=32*t2+31;t5++) {
printf("a[%d][%d]=b[%d][%d]",-32*t3+t5+N-2,N-2,-32*t3+t5+N-2,N-2);
        }
      }
    }
    if ((t1 <= floord(32*t2-N+1,64)) && (t2 >= t3)) {
      if ((N+1)%2 == 0) {
        for (t6=max(32*t3,32*t2-N+4);t6<=min(32*t2,32*t3+31);t6++) {
printf("a[%d][%d]=b[%d][%d]",N-2,-32*t2+t6+N-2,N-2,-32*t2+t6+N-2);
        }
      }
    }

printf("b[%d][%d]=0.2*(a[%d][%d]+a[%d][%d]+a[%d][%d]+a[%d][%d]+a[%d][%d])",t3,t4,t3,t4,t3,t4-1,t3,1+t4,1+t3,t4,t3-1,t4);
于 2012-06-21T17:27:23.073 に答える
1

式を分割するには:

a[N-2][-32*t2+t6+N-2]=b[N-2][-32*t2+t6+N-2];

配列にするには、分割を使用します。

split( $0, ar, "[][]" )

この呼び出しの後ar[2] = "N-2"ar[4] = "-32*t2+t6+N-2"、 など。 split の正規表現は少し奇妙に見えますが、基本的には または のいずれかで分割しているだけ[です]。明らかに、これは非常に脆弱であり、完全なパーサーが最適ですが、これは役立つはずです。

于 2012-06-19T17:01:39.193 に答える