代码之家  ›  专栏  ›  技术社区  ›  Ritwik Bhar

Antlr-解析多行#为C.g4定义

  •  1
  • Ritwik Bhar  · 技术社区  · 6 年前

    我正在使用Antlr4解析C代码。 我想分析多行定义以及中提供的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
        ;
    

    如果删除了多块规则,则它仅适用于单行预处理器指令 但对于多行#定义,它不起作用。

    任何帮助都将不胜感激

    多行定义我的意思是

    #define MACRO(num, str) {\
                printf("%d", num);\
                printf(" is");\
                printf(" %s number", str);\
                printf("\n");\
               }
    

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

    1 回复  |  直到 6 年前
        1
  •  2
  •   Raven Bill Karwin    6 年前

    我无耻地抄袭了 here :

    这是因为ANTLR的lexer匹配“先来先发球”。那个 意味着它将托盘以匹配给定的输入和第一个指定的 (在源代码中)规则,如果该规则与输入匹配,则 不会尝试将其与其他的匹配。

    在您的情况下,输入序列 DefineStart \\\r\n (其中 DefineStart 表示对应于相应规则的输入序列)将由 DefineBlock 因为 \\ 正在被 ~[\r\n]* 建筑

    现在有两种可能性:要么调整当前的规则集以避免此问题,要么(我的建议)只需使用一个规则来匹配define语句(单行和多行)。

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

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

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