syat #6157(2008/04/08 16:09 GMT) [ C# ] Rating0/0=0.00
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; } }
Rating0/0=0.00-0+
1 reply [ reply ]
syat
#6157()
[
C#
]
Rating0/0=0.00
1文字ずつ結構まじめに解析してます。
お題のソースの変換ができてることを確認しました。
一番外側の変数しか変換しないという仕様を満たすのがしんどかったです。
よーく見ると実はバグで動いてたりするのは内緒。(正規表現のあたり)
Rating0/0=0.00-0+
1 reply [ reply ]