DelFusa Blog 総本山

プログラミングの話題とかです。

NEW | PAGE-SELECT | NEXT

≫ EDIT

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

| スポンサー広告 | --:-- | comments(-) | trackbacks(-) | TOP↑

≫ EDIT

リハビリ


           _________
   ∧,,∧∩  / 
  ミ,,゚Д゚彡 <  リハビリー
   ミつ旦.ミ   \ 
 @ミ   ミ     ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   ∪''∪  ロカビリー


ちょっとやらなきゃいけないことがあるのですが
なんとなく、Delphiコードをろくに書いてなかったので
感覚を取り戻す事にしてみました。

元Sourceは、こちらですが

DelphiCommentDelete.dpr


これを、PascalSourceからコメントアウト部分を削除するだけじゃなくて
CやC++系(JavaやC#)ソースコードからコメントアウト部分を削除するという
関数を書いてみました。

※それにしても未だにD2007以前コードなのはちょっと恥ずかしいなあ。
  誰か改造してくれよ...


オープンソースで公開する場合でも、コメントアウト部分に
やばい事が書いてある場合、全部削除しておけば
ちょっと安心かも~~

そんな感じに使えるコードです。

ドゾ。っていうか、あまり高速化は考えられてないコードですし
C/C++に馴染んでもいないので
微妙なところで抜けがあるかもしれません。
そしたらオシエテくださいな。

unit SourceComment;

interface

uses
 StringUnit,
uses_end;

function PascalCommentDelete(S: WideString): WideString;
function CCommentDelete(S: WideString): WideString;
function CppCommentDelete(S: WideString): WideString;

implementation

const
 EndOfLine = #13;

type
 TBraceInfo = record
  beginMark: WideString;
  endmark: WideString;
  remove: boolean;
 end;

type
 TBraceTable = array of TBraceInfo;

function CommentDelete(S: WideString; BraceTable: TBraceTable): WideString;


 function findCommentStart( const str: WideString; var index: integer;
  var braceInfo: TBraceInfo ): boolean;
 var
  bt: Integer;
  i: integer;
 begin
  index := MaxInt;
  for bt := Low(BraceTable) to High(BraceTable) do
  begin
   i := WidePosForward( braceTable[bt].beginMark, str );
   if i > 0 then
    if i < index then
    begin braceInfo := BraceTable[bt];
     index := i;
    end;
  end;
  result := False;
  if index < MaxInt then
   result := True;
 end;

var
 index: integer;
 removeLen: integer;
 bi: TBraceInfo;
 Str: WideString;
begin
 Str := S;
 Result := '';
 while findCommentStart(Str, index, bi) do
 begin
  Result := Result + Copy(Str, 1, index - 1);
  Delete(Str, 1, index-1);
  if not bi.remove then
   Result := Result + bi.beginMark;
  Delete(Str, 1, Length(bi.beginMark));

  if bi.endmark<>'' then
  begin
   index := WidePosForward( bi.endMark, Str );
   if index = 0 then
   begin
    if not bi.remove then
     Result := Result + Str;
    Exit;
   end;
   removeLen := index - 1;
   if bi.EndMark <> EndOfLine then
    Inc(removeLen, Length(bi.EndMark));
   //↑EndMarkが改行の時だけは改行分を削除していない
   if not bi.remove then
    Result := Result + Copy(Str, 1, removeLen);
   Delete(Str, 1, removeLen);
  end;
 end;
 Result := Result + Str;
end;

function PascalCommentDelete(S: WideString): WideString;
(*-----------------------------------
ソース中の文字列、つまりシングルクウォーテーションで囲まれた中の文字に対しては
『//』や『{』『}』や、その他のコメントアウト記号が存在したとしても
コメントアウト記号とはみなさないのでremove falseを指定
同様にコンパイル指令である『{$xxx}』という文字の内部も
コメントアウト記号とはみなさないのでremove falseを指定

その他はコメントアウト記号とみなすのでremove trueを指定している。
//-----------------------------------*)
var
 braceTable: TBraceTable;
begin
 SetLength(braceTable, 5);
 with braceTable[0] do
 begin beginMark := ''''; endmark := ''''; remove := False; end;
 with braceTable[1] do
 begin beginMark := '{$'; endmark := '}'; remove := False; end;
 with braceTable[2] do
 begin beginMark := '{'; endmark := '}'; remove := True; end;
 with braceTable[3] do
 begin beginMark := '(*'; endmark := '*)'; remove := True; end;
 with braceTable[4] do
 begin beginMark := '//'; endmark := EndOfLine; remove := True; end;

 Result := CommentDelete(S, braceTable);
end;

function CCommentDelete(S: WideString): WideString;
(*-----------------------------------
純粋なCは『/*』~『*/』で囲われたものしかコメントとしてみなしていないので
そのように記述する。『//』で行コメントアウトができるのはC++の仕様なので
そちらの仕様を適応したい場合は
function CppCommentDelete(S: String): String;
で実装する。

ソース中の文字列、つまりダブルクウォーテーションで囲まれた中の文字に対しては
『/*』『*/)』が存在していたとしても
コメントアウト記号とはみなさないのでremove falseを指定
//-----------------------------------*)
var
 braceTable: TBraceTable;
begin
 SetLength(braceTable, 3);
 with braceTable[0] do
 begin beginMark := '\"'; endmark := ''; remove := False; end;
 with braceTable[1] do
 begin beginMark := '"'; endmark := '"'; remove := False; end;
 with braceTable[2] do
 begin beginMark := '/*'; endmark := '*/'; remove := True; end;

 Result := CommentDelete(S, braceTable);
end;

function CppCommentDelete(S: WideString): WideString;
(*-----------------------------------
C++のコメントアウトの仕様は
『/*』~『*/』で囲まれた部分と
『//』~改行で囲まれた部分になる。
JavaでもC#でも同じ仕様です。

ソース中の文字列、つまりダブルクウォーテーションで囲まれた中の文字に対しては
『/*』『*/)』が存在していたとしても
コメントアウト記号とはみなさないのでremove falseを指定
//-----------------------------------*)
var
 braceTable: TBraceTable;
begin
 SetLength(braceTable, 4);
 with braceTable[0] do
 begin beginMark := '\"'; endmark := ''; remove := False; end;
 with braceTable[1] do
 begin beginMark := '"'; endmark := '"'; remove := False; end;
 with braceTable[2] do
 begin beginMark := '/*'; endmark := '*/'; remove := True; end;
 with braceTable[3] do
 begin beginMark := '//'; endmark := EndOfLine; remove := True; end;

 Result := CommentDelete(S, braceTable);
end;

end.

テストコードユニットは次の通り

unit testSourceComment;

interface

uses
 SourceComment,
 XPtest,
uses_end;

procedure testPascalCommentDelete;
procedure testCppCommentDelete;

implementation

procedure testPascalCommentDelete;
begin
 Check('あいうえおさしすせそ', PascalCommentDelete('あいうえお{かきくけこ}さしすせそ'));
 Check('あいうえおさしすせそ', PascalCommentDelete('あいうえお(*かきくけこ*)さしすせそ'));
 Check('あいうえお'#13#10#13#10'さしすせそ',
  PascalCommentDelete('あいうえお'#13#10'//かきくけこ'#13#10'さしすせそ'));

 Check('かきくけこさしすせそ', PascalCommentDelete('{あいうえお}かきくけこさしすせそ'));
 Check('かきくけこさしすせそ', PascalCommentDelete('(*あいうえお*)かきくけこさしすせそ'));
 Check(#13#10'かきくけこ'#13#10'さしすせそ',
  PascalCommentDelete('//あいうえお'#13#10'かきくけこ'#13#10'さしすせそ'));

 Check('あいうえおかきくけこ', PascalCommentDelete('あいうえおかきくけこ{さしすせそ}'));
 Check('あいうえおかきくけこ', PascalCommentDelete('あいうえおかきくけこ(*さしすせそ*)'));
 Check('あいうえお'#13#10'かきくけこ'#13#10,
  PascalCommentDelete('あいうえお'#13#10'かきくけこ'#13#10'//さしすせそ'));

 Check('かきくけこ', PascalCommentDelete('{あいうえお}かきくけこ(*さしすせそ*)'));
 Check('かきくけこ', PascalCommentDelete('(*あいうえお*)かきくけこ{さしすせそ}'));
 Check(#13#10'かきくけこ'#13#10,
  PascalCommentDelete('//あいうえお'#13#10'かきくけこ'#13#10'{さしすせそ}'));

 Check('あい''{うえ(*''お*)', PascalCommentDelete('あい''{うえ(*''お{かき''くけこ}*)'));

 Check('かきくけこ', PascalCommentDelete('{あいうえお}かきくけこ(*さしすせそ'));
 Check('かきくけこ', PascalCommentDelete('(*あいうえお*)かきくけこ{さしすせそ'));
 Check(#13#10'かきくけこ'#13#10,
  PascalCommentDelete('//あいうえお'#13#10'かきくけこ'#13#10'{さしすせそ'));

 Check('あいうえお}かきくけこ', PascalCommentDelete('あいうえお}かきくけこ(*さしすせそ'));
 Check('あいうえお*)かきくけこ', PascalCommentDelete('あいうえお*)かきくけこ{さしすせそ'));
 Check('あい'#13#10'かきくけこ'#13#10,
  PascalCommentDelete('あい//うえお'#13#10'かきくけこ'#13#10'{さしすせそ'));

 Check('さしすせそ*)', PascalCommentDelete('(*あいうえお(*かきくけこ*)さしすせそ*)'));


 Check('あいうえお{$かきくけこ}さしすせそ', PascalCommentDelete('あいうえお{$かきくけこ}さしすせそ'));

 Check('{$あいうえお}かきくけこさしすせそ', PascalCommentDelete('{$あいうえお}かきくけこさしすせそ'));

 Check('あいうえおかきくけこ{$さしすせそ}', PascalCommentDelete('あいうえおかきくけこ{$さしすせそ}'));

 Check('{$あいうえお}かきくけこ', PascalCommentDelete('{$あいうえお}かきくけこ(*さしすせそ*)'));
 Check('かきくけこ{$さしすせそ}', PascalCommentDelete('(*あいうえお*)かきくけこ{$さしすせそ}'));
 Check(#13#10'かきくけこ'#13#10'{$さしすせそ}',
  PascalCommentDelete('//あいうえお'#13#10'かきくけこ'#13#10'{$さしすせそ}'));

 Check('あい''{$うえ(*''お{$かき''くけこ}*)', PascalCommentDelete('あい''{$うえ(*''お{$かき''くけこ}*)'));

 Check('{$あいうえお}かきくけこ', PascalCommentDelete('{$あいうえお}かきくけこ(*さしすせそ'));
 Check('かきくけこ{$さしすせそ', PascalCommentDelete('(*あいうえお*)かきくけこ{$さしすせそ'));
 Check(#13#10'かきくけこ'#13#10'{$さしすせそ',
  PascalCommentDelete('//あいうえお'#13#10'かきくけこ'#13#10'{$さしすせそ'));

 Check('あいうえお*)かきくけこ{$さしすせそ', PascalCommentDelete('あいうえお*)かきくけこ{$さしすせそ'));
 Check('あい'#13#10'かきくけこ'#13#10'{$さしすせそ',
  PascalCommentDelete('あい//うえお'#13#10'かきくけこ'#13#10'{$さしすせそ'));

end;

procedure testCppCommentDelete;
begin
 Check('あいうえおさしすせそ', CppCommentDelete('あいうえお/*かきくけこ*/さしすせそ'));
 Check('あいうえお'#13#10#13#10'さしすせそ',
  CppCommentDelete('あいうえお'#13#10'//かきくけこ'#13#10'さしすせそ'));

 Check('かきくけこさしすせそ', CppCommentDelete('/*あいうえお*/かきくけこさしすせそ'));
 Check(#13#10'かきくけこ'#13#10'さしすせそ',
  CppCommentDelete('//あいうえお'#13#10'かきくけこ'#13#10'さしすせそ'));

 Check('あいうえおかきくけこ', CppCommentDelete('あいうえおかきくけこ/*さしすせそ*/'));
 Check('あいうえお'#13#10'かきくけこ'#13#10,
  CppCommentDelete('あいうえお'#13#10'かきくけこ'#13#10'//さしすせそ'));

 Check('かきくけこ', CppCommentDelete('/*あいうえお*/かきくけこ/*さしすせそ*/'));
 Check(#13#10'かきくけこ'#13#10,
  CppCommentDelete('//あいうえお'#13#10'かきくけこ'#13#10'/*さしすせそ*/'));

 Check('あい"/*うえ/*"お*/', CppCommentDelete('あい"/*うえ/*"お/*かき"くけこ*/*/'));


 Check('かきくけこ', CppCommentDelete('/*あいうえお*/かきくけこ/*さしすせそ'));
 Check(#13#10'かきくけこ'#13#10,
  CppCommentDelete('//あいうえお'#13#10'かきくけこ'#13#10'/*さしすせそ'));

 Check('あいうえお*/かきくけこ', CppCommentDelete('あいうえお*/かきくけこ/*さしすせそ'));
 Check('あい'#13#10'かきくけこ'#13#10,
  CppCommentDelete('あい//うえお'#13#10'かきくけこ'#13#10'/*さしすせそ'));

 Check('さしすせそ*/', CppCommentDelete('/*あいうえお/*かきくけこ*/さしすせそ*/'));

////////////////////////////////////////////////////////////
 Check(' fprintf(fout, "%s/*", tag_com);', CCommentDelete(' fprintf(fout, "%s/*", tag_com);'));
 Check(' fprintf(fout, "%s/*", tag_com);', CppCommentDelete(' fprintf(fout, "%s/*", tag_com);'));

 Check('case ''\"'': fputs(""", fout); break;',
  CppCommentDelete('case ''\"'': fputs(""", fout); break;/*aa*/'));

end;

end.

   ∧,,∧ ∩  
  ミ,,゚Д゚ミ彡 フンフンフンフン!!  
  (ミ ⊂彡
 @ミ ,,, ミ  
   し' `J


久しぶりに腕が鳴っている感じでなかなかよさげです。

今回の改造は高速化目的ではなかったのですが
ご興味ある方は、汎用性高い機能だと思うので
高速化してあっさり漏れを超えてくださいな~

ただし、テストコードは通過してねん。
スポンサーサイト

| 未分類 | 21:56 | comments:2 | trackbacks(-) | TOP↑

COMMENT

高速化してみました。
ソースは後日公開。

基本的に
SetLength(Result, Length(Source);
Result[ResultIndex] := Source[SourceIndex];
Inc(ResultIndex); Inc(SourceIndex);
と書き換えただけでごじゃる。

いまだにWideStringでの実装だけど...
まあ、D2009ではStringに置き換えればすぐにうごくからいいかな。

自作のユニット、StringUnit.pasは、後日AnsiStringUnit.pasに命名変更かな。

| ミ・д・彡 | 2008/11/14 09:32 | URL | ≫ EDIT

No title

すっかり、VBで開発することを忘れていた!!

ということで
braceTable周りと、テストコード、
VB版で誰か作りませんか?

文字列囲みとシングルクウォートでのコメントアウト
くらいはわかるけど、

C/C++でいうところの『"』のような特殊文字の
仕様がわからんのですよ。

Delphiのシングルクウォートと同じ扱いでダブルクウォーテション二つで処理はすむのかしら?

| ミ・д・彡 | 2008/11/18 17:57 | URL | ≫ EDIT















非公開コメント

PREV | PAGE-SELECT | NEXT

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。