3

C++ または C# ファイルを指定すると、ファイル内の行数をカウントし、コメント内およびデザイナーが生成したコード ブロック内の行数をカウントする、C# で記述されたプログラムがあります。ファイルに含まれる関数の数と、それらの関数に含まれる行数をカウントする機能を追加したいと考えています。行 (または一連の行) が関数 (またはメソッド) の開始であるかどうかを判断する方法がよくわかりません。

少なくとも、関数宣言は、識別子と引数リストが続く戻り値の型です。トークンが有効な戻り値の型であることを C# で判断する方法はありますか? そうでない場合、コード行が関数の開始であるかどうかを簡単に判断する方法はありますか? 基本的に、次のようなものを確実に区別できる必要があります。

bool isThere() 
{
...
}

から

bool isHere = isThere()

そしてから

isThere()

他の関数宣言の類似物と同様に。

4

5 に答える 5

2

これを行う際の問題は、正確に行うことです。C# 関数を定義できるすべての可能な方法を考慮する必要があります。本質的に、パーサーを作成する必要があります。そうすることは、単純な SO 回答の範囲を超えています。

この質問には、正規表現の形式で多くの回答があり、一般的なケースでは機能しますが、次のようなコーナーケースではうまくいかない可能性があります。

int
?
/* this 
is */
main /* legal */ (code c) { 
}
于 2010-01-18T21:33:17.530 に答える
1

おそらく正規表現を使用するでしょうが、データ型と宣言オプション、およびユーザー定義の型/クラスの数を考えると、それは自明ではありません。関数呼び出しから割り当てを取得することを単純に回避するには、次のような Regex (テストされていない) から始めることができます。

(private|public|internal|protected|virtual)?\s+(static)?\s+(int|bool|string|byte|char|double|long)\s+([A-Za-z][A-Za-z_0-9]*)\s*\(

これは(長い目で見れば)すべてをキャッチするわけではなく、調整する必要があります。

関数宣言を決定するためにリフレクションを使用する別の方法もありますが、静的ソース コード分析を行う場合はおそらく適切ではありません。

于 2010-01-18T21:33:22.557 に答える
1

スコープをスキャンすることから始めます。ファイルを処理する際に、左中括弧 { と右中括弧 } を数えて、現在のスコープを把握する必要があります。また、ファイルをスキャンするときに // と /* ... */ を解析する必要があります。 、そのため、何かが実際のコードではなくコメントに含まれていることを知ることができます。#if もありますが、これらを解釈する方法を知るには、コードをコンパイルする必要があります。

次に、スコープの開き中かっこの直前のテキストを解析して、それらが何であるかを判断する必要があります。関数は、グローバル スコープ、クラス スコープ、または名前空間スコープにある可能性があるため、名前空間とクラスを解析して、対象のスコープのタイプを識別できる必要があります。通常は、かなり単純な構文解析で問題を解決できます (ほとんどのプログラマーは同様のスタイルを使用します。たとえば、「class Fred」とその開き中括弧の間に空白行を入れることは一般的ではありません。しかし、「class Fred {」と書く場合があります。 'template class __DECLSPEC MYWEIRDMACRO Fred {' のように、余分なジャンクを行に追加する可能性もあります。ただし、非常に単純な「行には、両側に空白がある「クラス」という単語が含まれていますか?ほとんどの場合に機能するヒューリスティック。

OK、名前空間とクラスの内部にいることがわかり、新しいオープン スコープが見つかりました。メソッドですか?

メソッドの主な識別機能は次のとおりです。

  • リターンタイプ。これは任意の文字列であり、多くのトークン ("__DLLEXPORT const unsigned myInt32typedef * &") である可能性があります。プロジェクト全体をコンパイルしない限り、チャンスはありません。
  • 関数名。単一のトークン (ただし、"operator=" などに注意してください)
  • ゼロ個以上のパラメーターまたは「空」を含む括弧のペア。これが一番の手がかりです。
  • 関数宣言には、多くのスコープの前にある特定の予約語 (enum、class、struct など) は含まれません。また、つまずいてはならない予約語 (template、const など) を使用する場合があります。

したがって、空白行または ; で終わる行を検索できます。前のステートメント/スコープの終わりを示す { または }。次に、そのポイントとスコープの左中括弧の間のすべてのテキストを取得します。次に、トークンのリストを抽出し、パラメーター リストのブラケットとの一致を試みます。トークンが予約語 (enum、struct、class など) でないことを確認します。

これにより、メソッドがあるという「合理的な信頼度」が得られます。かなり高い精度を得るために多くの解析は必要ありません。「パーサー」を混乱させるすべての特殊なケースを見つけるのに多くの時間を費やすことができますが、合理的に一貫性のあるコードベース (つまり、自社のコードのみ) で作業している場合は、おそらくすべてのパーサーを特定できるでしょう。メソッドをコードに簡単に組み込むことができます。

于 2010-01-18T22:04:52.470 に答える
0

本物のパーサーを書きたい場合(私はあなたが書きたくないかもしれないことを知っています)、ANTLRを試してください。他に何もなければ、それは楽しいプロジェクトになります

于 2010-01-18T22:19:49.737 に答える
-1

トークンが有効な戻り値の型であることを C# で判断する方法はありますか?

それが戻り値の型であるかエラーであるかは、非常に簡単に判断できます (その位置にある可能性のある他のものではないことを確認することによって)。また、無効なコードに対して「正しい」動作を保証する必要はおそらくありません。

次に、括弧を探します。

于 2010-01-18T21:32:53.963 に答える