我目前正尝试将预处理器实现为ANTLR4 for c#,并且在查找有关此问题的任何信息时遇到了很多麻烦。 我通过C#项目的GitHub源代码挖掘并不是真的成功了......
我的目标是保留令牌偏移量(以便预处理流不会抛出列和行) 示例粗略解释:
#define foo(bar) foobar(bar + bar * bar / 0.2)
int smthng = 2;
smthng += foo(12); //the ; should be at the same spot like the macro was a function
希望您能指出正确的文档或在某处提供简单的示例解决方案
亲切地问,Marco
PS 要注意:我不寻求一种解决方案,我将已经预处理的流传递给ANTLR4,因为它会摆脱代码的偏移。
答案 0 :(得分:1)
预处理程序指令解析有两种策略:
第二种方式不适合您,因为宏扩展导致文本位置损坏。
使用第一种方法,您可以在单个公共词法分析器中对预处理程序指令进行标记,从而保存正确的文本位置。
请参阅“在Objective-C中解析预处理程序指令”一文中的Objective-C grammar和One-step Processing部分:
一步处理涉及同时解析主要语言的指令和令牌。 ANTLR引入了一个按其类型隔离令牌的通道系统。例如,主要语言的标记和隐藏标记(空格和注释)。可以将指令令牌添加到单独的命名通道中。
在某些情况下,指令令牌也可以包含在公共频道中。它更方便。请参阅令牌NS_OPTIONS
和规则enumSpecifier
,例如:
enumSpecifier
: 'enum' (identifier? ':' typeName)? (identifier ('{' enumeratorList '}')? | '{' enumeratorList '}')
| ('NS_OPTIONS' | 'NS_ENUM') LP typeName ',' identifier RP '{' enumeratorList '}'
;
您还可以将预处理程序指令解析为简单字符串,并在以后解析它:
DEFINE: '#define' ~[\r\n]*
。
在Swiftify,Objective-C到Swift转换器,我们使用一步处理方法。我将很快更新Objective-C语法。
答案 1 :(得分:0)
取决于您如何预处理流。如果您使用换行符替换所有预处理器行(以及由于#ifdef等而不可见的那些行),您的整个行号将不会被搞砸。实际上我甚至建议在正常的解析运行之外进行预处理(例如输入流就已经这样做了)。
多年前I wrote a Windows .rc file parser。这些资源文件在很多方面都像C头文件一样,所以你需要一个预处理器,带有字符串化和charizing支持的宏处理以及更多的东西。我为ANTLR 2.7编写了它(现在你看到如何旧的:-))。但我仍然相信这是一个很好的例子,如何使预处理工作(包括#include
)。