2011-02-06 58 views
3

我需要計算正確的C#源文件中的類的數量。 我寫了下面的語法:計算班級計數的部分語法

grammar CSharpClassGrammar; 

options 
{ 
     language=CSharp2; 

} 

@parser::namespace { CSharpClassGrammar.Generated } 
@lexer::namespace { CSharpClassGrammar.Generated } 

@header 
{ 
     using System; 
     using System.Collections.Generic; 

} 

@members 
{ 
     private List<string> _classCollector = new List<string>(); 
     public List<string> ClassCollector { get { return 
_classCollector; } } 

} 

/*------------------------------------------------------------------ 
* PARSER RULES 
*------------------------------------------------------------------*/ 

csfile : class_declaration* EOF 
     ; 

class_declaration 
     : (ACCESSLEVEL | MODIFIERS)* PARTIAL? 'class' CLASSNAME 
      class_body 
      ';'? 
      { _classCollector.Add($CLASSNAME.text); } 
     ; 

class_body 
     : '{' class_declaration* '}' 
     ; 

/*------------------------------------------------------------------ 
* LEXER RULES 
*------------------------------------------------------------------*/ 

ACCESSLEVEL 
     : 'public' | 'internal' | 'protected' | 'private' | 'protected 
internal' 
     ; 

MODIFIERS 
     : 'static' | 'sealed' | 'abstract' 
     ; 

PARTIAL 
     : 'partial' 
     ; 

CLASSNAME 
     : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* 
     ; 

COMMENT 
     : '//' ~('\n'|'\r')* {$channel=HIDDEN;} 
     | '/*' (options {greedy=false;} : .)* '*/' {$channel=HIDDEN;} 
     ; 

WHITESPACE 
     : ('\t' | ' ' | '\r' | '\n'| '\u000C')+ { $channel = HIDDEN; } 
     ; 

這個解析器正確計算空類(和嵌套類太)空類體:

internal class DeclarationClass1 
{ 
    class DeclarationClass2 
    { 
     public class DeclarationClass3 
     { 
      abstract class DeclarationClass4 
      { 
      } 
     } 
    } 
} 

我需要計算與非空體類,例如作爲:

class TestClass 
{ 
    int a = 42; 

    class Nested { } 
} 

我需要以某種方式忽略所有「不是類聲明」的代碼。 在上例中忽略

int a = 42; 

我該怎麼做?可能是其他語言的例子嗎?
請幫忙!

+1

請注意部分班級;請注意,部分類可以在一個文件中多次,一次只在一個文件中,或者分散在多個文件中。 Assembly.GetTypes()不是一個選項嗎? – 2011-02-06 15:11:10

+0

謝謝,我記得部分課程。 Assembly.GetTypes()不適合我,我需要在源代碼級別處理這個。 – 2011-02-06 15:14:08

回答

3

當您只對源文件的某些部分感興趣時,可以在選項{012}}中設置filter=true部分。{...}部分。這將使您只能定義您感興趣的那些標記,而您沒有定義的標記被詞法分析器忽略。

請注意,這隻適用於詞法分析器語法,不適用於組合(或解析器)語法。

小演示:['X', 'class', 'Foo']

lexer grammar CSharpClassLexer; 

options { 
    language=CSharp2; 
    filter=true; 
} 

@namespace { Demo } 

Comment 
    : '//' ~('\r' | '\n')* 
    | '/*' .* '*/' 
    ; 

String 
    : '"' ('\\' . | ~('"' | '\\' | '\r' | '\n'))* '"' 
    | '@' '"' ('"' '"' | ~'"')* '"' 
    ; 

Class 
    : 'class' Space+ Identifier 
    {Console.WriteLine("Found class: " + $Identifier.text);} 
    ; 

Space 
    : ' ' | '\t' | '\r' | '\n' 
    ; 

Identifier 
    : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')* 
    ; 

你離開Identifier在那裏,因爲你不希望Xclass Foo被符號化的做到這一點是非常重要的。隨着Identifier在那裏,Xclass將成爲整個標識符。

using System; 
using Antlr.Runtime; 

namespace Demo 
{ 
    class MainClass 
    { 
     public static void Main (string[] args) 
     { 
      string source = 
@"class TestClass 
{ 
    int a = 42; 

    string _class = ""inside a string literal: class FooBar {}...""; 

    class Nested { 
     /* class NotAClass {} */ 

     // class X { } 

     class DoubleNested { 
      string str = @"" 
       multi line string 
       class Bar {} 
      ""; 
     } 
    } 
}"; 
      Console.WriteLine("source=\n" + source + "\n-------------------------"); 
      ANTLRStringStream Input = new ANTLRStringStream(source); 
      CSharpClassLexer Lexer = new CSharpClassLexer(Input); 
      CommonTokenStream Tokens = new CommonTokenStream(Lexer); 
      Tokens.GetTokens(); 
     } 
    } 
} 

產生以下輸出:

語法可以用下面的類進行測試

source= 
class TestClass 
{ 
    int a = 42; 

    string _class = "inside a string literal: class FooBar {}..."; 

    class Nested { 
     /* class NotAClass {} */ 

     // class X { } 

     class DoubleNested { 
      string str = @" 
       multi line string 
       class Bar {} 
      "; 
     } 
    } 
} 
------------------------- 
Found class: TestClass 
Found class: Nested 
Found class: DoubleNested 

注意,這僅僅是一個快速演示,我不知道如果我處理在語法中正確的字符串文字(我不熟悉C#),但這個演示應該給你一個開始。

祝你好運!