Antlr - 为 C.g4 解析多行 #define
Antlr - Parsing Multiline #define for C.g4
我正在使用 Antlr4 来解析 C 代码。
我想解析多行#defines 以及 C.g4 中提供的
C.g4
但是上面link中提到的语法不支持预处理指令,所以我添加了以下新规则来支持预处理。
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
;
如果移除多块规则,它仅适用于单行预处理器指令
但是对于多行 #defines 它不起作用。
任何帮助将不胜感激
多行#define 我的意思是
#define MACRO(num, str) {\
printf("%d", num);\
printf(" is");\
printf(" %s number", str);\
printf("\n");\
}
基本上我需要找到一个可以解析上述块的语法
我无耻地复制了我在 的部分答案:
This is because ANTLR's lexer matches "first come, first serve". That
means it will tray to match the given input with the first specified
(in the source code) rule and if that one can match the input, it
won't try to match it with the other ones.
在您的情况下,输入序列 DefineStart \\r\n
(其中 DefineStart
代表对应于相应规则的输入序列)将与 DefineBlock
匹配,因为 \
正在被 ~[\r\n]*
构造消耗。
您现在有两种可能性:要么调整当前的规则集以规避此问题,要么(我的建议)您只使用一个规则来匹配定义语句(单行和多行)。
这样的合并规则可能如下所示:
DefineBlock:
DefineStart (~[\\r\n] | '\\' '\r'? '\n' | '\'. )*
;
请注意,此代码未经测试,但应如下所示:匹配 DefineStart
,然后匹配以下模式的任意长字符序列:当前字符不是 \
、\r
或 \n
,它是转义换行符或反斜杠后跟任意字符。
这应该允许希望的换行转义。
我正在使用 Antlr4 来解析 C 代码。 我想解析多行#defines 以及 C.g4 中提供的 C.g4
但是上面link中提到的语法不支持预处理指令,所以我添加了以下新规则来支持预处理。
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
;
如果移除多块规则,它仅适用于单行预处理器指令 但是对于多行 #defines 它不起作用。
任何帮助将不胜感激
多行#define 我的意思是
#define MACRO(num, str) {\
printf("%d", num);\
printf(" is");\
printf(" %s number", str);\
printf("\n");\
}
基本上我需要找到一个可以解析上述块的语法
我无耻地复制了我在
This is because ANTLR's lexer matches "first come, first serve". That means it will tray to match the given input with the first specified (in the source code) rule and if that one can match the input, it won't try to match it with the other ones.
在您的情况下,输入序列 DefineStart \\r\n
(其中 DefineStart
代表对应于相应规则的输入序列)将与 DefineBlock
匹配,因为 \
正在被 ~[\r\n]*
构造消耗。
您现在有两种可能性:要么调整当前的规则集以规避此问题,要么(我的建议)您只使用一个规则来匹配定义语句(单行和多行)。
这样的合并规则可能如下所示:
DefineBlock:
DefineStart (~[\\r\n] | '\\' '\r'? '\n' | '\'. )*
;
请注意,此代码未经测试,但应如下所示:匹配 DefineStart
,然后匹配以下模式的任意长字符序列:当前字符不是 \
、\r
或 \n
,它是转义换行符或反斜杠后跟任意字符。
这应该允许希望的换行转义。