当前位置: 首页 > 知识库问答 >
问题:

Antlr4预处理器文法与C文法的集成

康锦
2023-03-14

我是ANTLR4的新人。我正在使用Antlr4和Antlr4适配器来解析C文件并生成PSI树。

我知道C预处理器应该处理#include和#define部分,并将结果传递给C lexer和C parser。但是我需要为C.G4解析#include和#define,这样我的插件就可以在没有预处理器的情况下处理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;
}

有人能帮我提高语法能力吗?这样我的语法就可以在不使用任何预处理器的情况下将#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
;

共有1个答案

竺展
2023-03-14

我试着解决了我自己的问题。

诀窍是换行符应该像下面的语法一样跳过,它不应该使用通道(隐藏)。

Newline
:   (   '\r' '\n'?
|   '\n'
)
-> channel(HIDDEN)
;

应更改为

Newline
:   (   '\r' '\n'?
    |   '\n'
    )
    -> skip
;
 类似资料:
  • 预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。 所有的预处理器指令都是以井号(#)开头,只有空格字符可以出现在预处理指令之前。预处理指令不是 C++ 语句,所以它们不会以分号(;)结尾。 我们已经看到,之前所有的实例中都有 #include 指令。这个宏用于把头文件包含到源文件中。 C++ 还支持很多预处理指令,比如 #include、#define、#if、#else、#line

  • 主要内容:1. 预处理器示例,2. 预定义的宏,3. 预处理器运算符,4. 参数化宏Objective-C预处理器不是编译器的一部分,而是编译过程中的一个单独步骤。 简单来说,Objective-C预处理器只是一个文本替换工具,它指示编译器在实际编译之前进行必要的预处理。 我们将Objective-C预处理器称为OCPP。 所有预处理器命令都以井号()开头。它必须是第一个字符(前面不能有空格),并且为了便于阅读,预处理器指令应该从第一列开始。 以下部分列出了所有重要的预处理程序指

  • 句子分割text_to_word_sequence keras.preprocessing.text.text_to_word_sequence(text, filters='!"#$%&()*+,-./:;<=>?@[\]^_`{|}~\t\n',

  • 句子分割text_to_word_sequence keras.preprocessing.text.text_to_word_sequence(text, filters=base_filter(), lower=True, split=" ") 本函数将一个句子拆分成单词构成的列表 参数 text:字符串,待处理的文本 filters:需要滤除的字符的列表或连接形成的字符串,例如标

  • 本文向大家介绍C#预处理器指令的用法实例分析,包括了C#预处理器指令的用法实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#预处理器指令的用法。分享给大家供大家参考。具体用法分析如下: C#预处理器指令是在编译时调用的。预处理器指令(preprocessor directive)告诉C#编译器要编译哪些代码,并指出如何处理特定的错误和警告。C#预处理器指令还可以告诉C#编辑器有关