我正在使用Antlr4来解析C代码。 我想解析多行#defines和C.g4提供的 C.g4
但上面链接中提到的语法不支持预处理程序指令,因此我添加了以下新规则来支持预处理。
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]*
;
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
;
如果删除MultiBlock规则,它仅适用于单行预处理器指令 但对于多行#defines,它无效。
任何帮助将不胜感激
By Multiline #define我的意思是
#define MACRO(num, str) {\
printf("%d", num);\
printf(" is");\
printf(" %s number", str);\
printf("\n");\
}
基本上我需要找到一个可以解析上面块的语法
答案 0 :(得分:1)
我无耻地从here复制部分答案:
这是因为ANTLR的词法分析器匹配"先到先得"。那 意味着它将托盘以匹配给定输入与第一个指定的输入 (在源代码中)规则,如果那个可以匹配输入,它 不会试图将它与其他的匹配。
在您的情况下,输入序列DefineStart \\\r\n
(其中DefineStart
代表与相应规则相对应的输入序列)将由DefineBlock
匹配,因为\\
是由~[\r\n]*
构造消耗。
您现在有两种可能性:要么调整当前的规则集以避免此问题,要么(我的消化)您只需使用一条规则来匹配define-statement(单行和多行)。
这样的合并规则可能如下所示:
DefineBlock:
DefineStart (~[\\\r\n] | '\\\\' '\r'? '\n' | '\\'. )*
;
请注意,此代码未经测试,但应如下所示:匹配DefineStart
,然后匹配以下模式的任意长字符序列:当前字符不是\
,{{1} }或\r
,它是一个转义的换行符或反斜杠后跟一个任意字符。
这应该允许所希望的换行符。