Comment detail

α置換 (Nested Flatten)
Cのソースを変換します。
1文字ずつ結構まじめに解析してます。
お題のソースの変換ができてることを確認しました。

一番外側の変数しか変換しないという仕様を満たすのがしんどかったです。
よーく見ると実はバグで動いてたりするのは内緒。(正規表現のあたり)
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

class AlphaReader {
  public bool IsDebug = false;
  void DBG(String s, params Object[] args) {
    if (!IsDebug) return;
    Console.WriteLine(s, args);
  }
  TextReader input;
  String before;  //変換前文字列
  String after;   //変換後文字列
  enum State {    //状態
    Global,  Func,  Struct,      //グローバル, 関数定義, 構造体(共用体・列挙体)
    Block, Name, Comment, InStr  //ブロック, 識別子, コメント, 文字列
  }
  String IdDelimiter = "\t (){};,=+-*/%&|^!?";  //識別子分離文字
  Stack<State> state;   //現在のReaderの状態
  int targetDepth;      //変換対象のスコープ(stateの深さ)
  int targetHideDepth;  //変換対照が再定義された深さ

  //コンストラクタ
  public AlphaReader(TextReader input,
             String before, String after) {
    this.input = input;
    this.before = before;
    this.after = after;
    
    this.state = new Stack<State>();
    this.state.Push(State.Global);
    this.targetDepth = int.MaxValue;
    this.targetHideDepth = int.MaxValue;
  }
  //行を読み込んで変換処理するメソッド
  public String ReadLine() {
    String strIn = this.input.ReadLine();
    if (strIn == null) {
      return null;
    }
 DBG("## [{0}]", strIn);
    
    StringBuilder buf = new StringBuilder();  //バッファ
    StringBuilder name = new StringBuilder();  //識別子バッファ

    /* 変数宣言の判定 */
    /* この判定は、変数宣言と演算が別の行にわかれていること、
       および、変数宣言が比較的シンプルなことを前提としています。 */
    String decVar = @".*(\w+|(struct|union)\s+\w+)(\s+[^;,]+,)*\s+"
                  + before + @"\s*[=,;\)].*";  //型+(変数, ...)+変換前文字列
    bool hasDecVar = false;
    if ((new Regex(decVar)).IsMatch(strIn)) {
 DBG("## 変数宣言発見");
      hasDecVar = true;
    }

    /* 行を1文字ずつ解析 */
    for (int pos = 0; pos < strIn.Length; pos++) {
      State st = this.state.Peek();
      char c = strIn[pos];
      String cs = strIn.Substring(pos);
 DBG("## pos={0} c={1} state={2} depth={3}", pos, c, st.ToString(), state.Count);
      
      switch (st) {
      case State.InStr:  //文字列リテラルの中
        if (c == '\\') {
          buf.Append(c);
          if (++pos < strIn.Length) {
            buf.Append(strIn[pos]);
          }
        } else if (c == '"') {
          buf.Append(c);
          this.state.Pop();
        }
        break;
      case State.Comment:  //コメントの中
         buf.Append(c);
        if (cs.StartsWith("*/")) {
          buf.Append(strIn[++pos]);
          this.state.Pop();
        }
        break;
      case State.Name:    //識別子の中
        if (IdDelimiter.IndexOf(c) < 0) {
          name.Append(c);      //識別子続行
        } else if (cs.StartsWith("->")) {
          name.Append("->");  //識別子続行
          pos++;
        } else {
          //識別子を抽出
          String id = name.ToString();
          this.state.Pop();
          st = this.state.Peek();
          switch (st) {
          case State.Struct:    //構造体の中は変換対象外
            buf.Append(id);
            break;
          default:              //変換対象
            if (hasDecVar && id == this.before) {        //変数宣言
              if (this.state.Count < this.targetDepth) {  //新たに宣言の場合
                this.targetDepth = this.state.Count;      //targetDepthをセット
              } else if (this.state.Count < this.targetHideDepth
                      && this.targetDepth < this.state.Count) {  //再宣言した場合
                this.targetHideDepth = this.state.Count;  //targetHideDepthをセット
              }
 DBG("## set targetDepth:{0} hideDepth:{1}", targetDepth, targetHideDepth);
            }
            if (this.targetDepth <= this.state.Count
                && this.state.Count < this.targetHideDepth) {
              //変換対象スコープの場合
              if (id == this.before) {
                buf.Append(this.after);
              } else if ((new Regex(this.before + @"[\.\-]")).IsMatch(id)) {
                                //変換対象変数のメンバを参照してる場合
                buf.Append(this.after);
                buf.Append(id.Substring(this.before.Length));
              } else {
                buf.Append(id);  //変換なし
              }
            } else {
              buf.Append(id);    //変換なし
            }
            break;
          }
          buf.Append(c);
          if (st == State.Global && c == '(') {  //関数宣言の場合
            this.state.Push(State.Func);
          }
          name = new StringBuilder();
        }
        break;
      default:  //その他の状態
        if (cs.StartsWith("/*")) {  //コメント開始
          buf.Append("/*");
          pos++;
          this.state.Push(State.Comment);
        } else if (c == '"') {      //文字列開始
          buf.Append(c);
          this.state.Push(State.InStr);
        } else if (IdDelimiter.IndexOf(c) >= 0) {  //識別子外文字
          buf.Append(c);
          if (c == '{') {
            if (st != State.Struct) {
              this.state.Push(State.Block);
            }
          } else if (c == '(') {
            if (st == State.Global) {
              this.state.Push(State.Func);
            }
          } else if (c == '}') {
            if (st == State.Block) {
              this.state.Pop();
              if (this.state.Peek() == State.Func) {
                this.state.Pop();
              }
            } else if (st == State.Struct) {
              this.state.Pop();
            }
            if (this.state.Count < this.targetDepth)
              this.targetDepth = int.MaxValue;
            if (this.state.Count < this.targetHideDepth)
              this.targetHideDepth = int.MaxValue;
 DBG("## unset targetDepth:{0} hideDepth:{1}", targetDepth, targetHideDepth);
          } else if (c == ';') {
            if (st == State.Func) {
              this.state.Pop();
            }
          }
        } else if (cs.StartsWith("struct ")  //構造体・共用体・列挙体のブロック内は
                 || cs.StartsWith("union ")  //変換を行わない
                 || cs.StartsWith("enum ")) {
          int index = cs.IndexOf(" ");
          pos += index;
          name.Append(cs.Substring(0, index + 1));
          this.state.Push(State.Struct);
        } else {                    //識別子開始
          name.Append(c);
          this.state.Push(State.Name);
        }
        break;
      }
    }
    if (name.Length > 0) {
      buf.Append(name.ToString());
      if (this.state.Peek() == State.Name) {
        this.state.Pop();
      }
    }
    return buf.ToString();
  }
}

class Driver {
  public static int Main(String[] args) {
    if (args.Length < 2) {
      Console.WriteLine("alpha.exe  before after [debug]");
      return -1;
    }
    AlphaReader ar = new AlphaReader(
        Console.In, args[0], args[1]);
    if (args.Length >= 3 && args[2] == "debug") {
      ar.IsDebug = true;
    }

    String line;
    while ((line = ar.ReadLine()) != null) {
      Console.WriteLine(line);
    }
    return 0;
  }
}

文字列の処理がうまくいってませんでした。。。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
--- alpha.cs.release1   2008-04-09 01:11:32.000000000 +0900
+++ alpha.cs.release2   2008-04-09 01:14:15.000000000 +0900
@@ -65,13 +65,12 @@
       
       switch (st) {
       case State.InStr:  //文字列リテラルの中
+        buf.Append(c);
         if (c == '\\') {
-          buf.Append(c);
           if (++pos < strIn.Length) {
             buf.Append(strIn[pos]);
           }
         } else if (c == '"') {
-          buf.Append(c);
           this.state.Pop();
         }
         break;

Index

Feed

Other

Link

Pathtraq

loading...