Antlr - 为C.g4解析多行#define

时间:2018-01-18 11:25:48

标签: java antlr antlr4

我正在使用Antlr4来解析C代码。 我想解析多行#defines和C.g4提供的 C.g4

但上面链接中提到的语法不支持预处理程序指令,因此我添加了以下新规则来支持预处理。

Link to my previous question

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");\
           }

基本上我需要找到一个可以解析上面块的语法

1 个答案:

答案 0 :(得分:1)

我无耻地从here复制部分答案:

  

这是因为ANTLR的词法分析器匹配"先到先得"。那   意味着它将托盘以匹配给定输入与第一个指定的输入   (在源代码中)规则,如果那个可以匹配输入,它   不会试图将它与其他的匹配。

在您的情况下,输入序列DefineStart \\\r\n(其中DefineStart代表与相应规则相对应的输入序列)将由DefineBlock匹配,因为\\是由~[\r\n]*构造消耗。

您现在有两种可能性:要么调整当前的规则集以避免此问题,要么(我的消化)您只需使用一条规则来匹配define-statement(单行和多行)。

这样的合并规则可能如下所示:

DefineBlock:
    DefineStart (~[\\\r\n] | '\\\\' '\r'? '\n' | '\\'. )*
;

请注意,此代码未经测试,但应如下所示:匹配DefineStart,然后匹配以下模式的任意长字符序列:当前字符不是\,{{1} }或\r,它是一个转义的换行符或反斜杠后跟一个任意字符。 这应该允许所希望的换行符。