我写了一个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;}"时,它给了我ann错误:"行1:0不匹配的输入'void'期望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' ;
此外,我建议在解析过程中忽略换行符和空格的通道。