English 中文(简体)
计算类计数的部分语法
原标题:Partial grammar for counting class count

I need to count the number of classes in correct C# source file. I wrote the following grammar:

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
        :  //  ~( 
 | 
 )* {$channel=HIDDEN;}
        |    /*  ( options {greedy=false;} : . )*  */  {$channel=HIDDEN;}
        ;

WHITESPACE
        : (  	  |     |  
  |  
 |  u000C  )+ { $channel = HIDDEN; }
        ; 

此解析器正确地计算具有空类主体的空类(以及嵌套类):

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

我需要计算不为空的类,例如:

class TestClass
{
    int a = 42;

    class Nested { }
}

I need to somehow ignore all the code that is "not a class declaration". In the example above ignore

int a = 42;

How can I do this? May be example for other language?
Please, help!

最佳回答

当您只对源文件的某些部分感兴趣时,可以在选项{…}部分中设置filter=true。这将使您只能定义那些您感兴趣的令牌,而您没有定义的令牌将被lexer忽略。

请注意,这只适用于lexer语法,而不适用于组合(或解析器)语法。

一个小演示:

lexer grammar CSharpClassLexer;

options {
  language=CSharp2;
  filter=true;
}

@namespace { Demo }

Comment
  :   //  ~( 
  |  
 )*
  |   /*  .*  */ 
  ;

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

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

Space
  :      |  	  |  
  |  
 
  ;

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

标识符保留在其中非常重要,因为您不希望Xclass Foo被标记为:[X,class,Foo]。有了标识符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=
" + source + "
-------------------------");
            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#),但这个演示应该会给你一个开始。

祝你好运

问题回答

暂无回答




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签