用于解析 C 源代码文件并从中获取函数的 Antlr 语法

Antlr grammar for parsing C source code files and getting functions from them

我写了一个 Antlr 语法来解析来自 C 源代码文件的函数:

grammar newCfunctions;

options
{
    language = CSharp;
}
@parser::namespace { Generated }
@lexer::namespace  { Generated }

func
    :function+ { Console.WriteLine("hello"); } //this is for debugging
    ;
NAME
    :[a-zA-Z]+[a-zA-Z0-9]*
    ;
TYPENAME
    :   'void'
    |   [a-zA-Z]+
    |   'char'
    |   'short'
    |   'int'
    |   'long'
    |   'float'
    |   'double'
    |   'signed'
    |   'unsigned'
    |   '_Bool'
    |   '_Complex'
    |   '__m128'
    |   '__m128d'
    |   '__m128i'
    |   NAME
    ;
arguments
    :   (TYPENAME NAME)*
    ;
Newline
    :   '\r'? '\n' ;
FUNCTIONBODY
    :   ([a-zA-Z0-9]|Newline)*;
function 
    :   TYPENAME ' ' NAME '(' arguments ')' ' '? Newline? '{' FUNCTIONBODY '}' Newline?
    ;

我生成了 C# 文件并将它们包含到测试项目中。它的主要功能:

            try
            {
                AntlrInputStream input = new AntlrInputStream(Console.In);
                newCfunctionsLexer lexer = new newCfunctionsLexer(input);
                CommonTokenStream tokens = new CommonTokenStream(lexer);
                newCfunctionsParser parser = new newCfunctionsParser(tokens);
                parser.func();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            Console.ReadKey();

当我写“void foo(int a){return a;}”时,它给我一个错误:"line 1:0 mismatched input 'void' expecting TYPENAME"。请帮我解决这个语法问题!我在网上看到了 C 语法,但是它有 800 多行,我不知道如何处理它。如果你知道如何使用它,请提示我。谢谢!

正如所说 NAME 规则应该放在 TYPENAME 规则之后。此外,词法 TYPENAME 不应包含词法 NAME[a-zA-Z]+.

所以,最终版本:

grammar newCfunctions;

options
{
    language = CSharp;
}
@parser::namespace { Generated }
@lexer::namespace  { Generated }

func
    : function+ { Console.WriteLine("hello"); } //this is for debugging
    ;
function 
    : typename ' ' NAME '(' arguments ')' ' '? Newline? '{' functionBody '}' Newline?
    ;
arguments
    : (typename NAME)*
    ;
typename
    : TYPENAME
    | NAME
    ;
functionBody
    : (TYPENAME | NAME | Newline)*
    ;
TYPENAME
    :   'void'
    |   'char'
    |   'short'
    |   'int'
    |   'long'
    |   'float'
    |   'double'
    |   'signed'
    |   'unsigned'
    |   '_Bool'
    |   '_Complex'
    |   '__m128'
    |   '__m128d'
    |   '__m128i'
    ;
NAME
    : [a-zA-Z]+ [a-zA-Z0-9]*
    ;
Newline
    :   '\r'? '\n' ;

我还建议在解析过程中使用忽略换行符和空格的通道。