我是Antlr4的新手。我正在使用Antlr4和antlr4 adaptor来解析C文件并生成PSI树。
我知道C预处理程序应该处理#include和#define部分,并将结果传递给C lexer和C解析器。但是我需要为C.g4解析#include和#define,以便我的插件无需预处理程序即可处理C文件。
我调查了此link并尝试了解决方案,但是当遇到除预处理程序语句之外的其他内容时,它将无法解决。
示例C代码
#include <stdio.h>
int main()
{
int i,j;
for(i=1;i<=9;)
{
for(j=1;j<=9;j)
{
if(i>=j)
{
printf("%d*%d=%d ",j,i,j*i);
}
j++;
}
printf("\n");
i++;
}
return 0;
}
结果树就是这样
您可以在图像中看到,在包含块之后,所有元素都不是一棵树。
我删除了示例C代码中的#include行,并使用了原始的C.g4语法,它可以像下面这样解析一个好的PSI树:
有人会帮助我改善语法打击吗?这样我的语法就可以在不使用任何预处理器的情况下将#include和#define解析为PSI树中的预处理器块。
谢谢
Whitespace
: [ \t]+
-> channel(HIDDEN)
;
Newline
: ( '\r' '\n'?
| '\n'
)
-> channel(HIDDEN)
;
BlockComment
: '/*' .*? '*/'
;
LineComment
: '//' ~[\r\n]*
;
IncludeBlock
: '#' Whitespace? 'include' ~[\r\n]*
;
DefineStart
: '#' Whitespace? 'define'
;
DefineBlock
: DefineStart (~[\\\r\n] | '\\\\' '\r'? '\n' | '\\'. )*
;
MultiDefine
: DefineStart MultiDefineBody
;
MultiDefineBody
: [\\] [\r\n]+ MultiDefineBody
| ~[\r\n]
;
preprocessorDeclaration
: includeDeclaration
| defineDeclaration
;
includeDeclaration
: IncludeBlock
;
defineDeclaration
: DefineBlock | MultiDefine
;
comment
: BlockComment
| LineComment
;
declaration
: declarationSpecifiers initDeclaratorList ';'
| declarationSpecifiers ';'
| staticAssertDeclaration
| preprocessorDeclaration
| comment
;
答案 0 :(得分:0)
我尝试并解决了自己的问题。
窍门是换行符应像下面的语法一样跳过,它不应该使用channel(HIDDEN)。
close()
应更改为
Newline
: ( '\r' '\n'?
| '\n'
)
-> channel(HIDDEN)
;
好的PSI树如下所示
good PSI tree with #include and #define
无论如何,我不完全了解channel(HIDDEN)和skip之间的区别。