我最近开始使用libclang来解析C文件。我遇到的问题是,显然,libclang在生成AST之前启动预处理器。我想禁止预处理程序运行,而是给出预处理程序指令在文件中的信息......
我使用以下python脚本(cindex.py和libclang)
import codecs
from clang.cindex import *
class SourceFile(object):
def __init__(self, path):
with codecs.open(path, 'r', 'utf-8') as file:
self.file_content = file.read()
index = Index.create()
root_node = index.parse(path)
for included in root_node.get_includes():
print included.include
self.print_declerations(root_node.cursor)
def print_declerations(self, root, recurse=True):
print root.kind.name, root.spelling
if root.kind.is_declaration():
node_def = root.get_definition()
if node_def is not None:
start_offset = node_def.extent.start.offset
end_offset = node_def.extent.end.offset + 1
print self.file_content[start_offset:end_offset], '\n'
if recurse:
for child in root.get_children():
self.print_declerations(child, False)
if __name__ == '__main__':
path = 'Sample.cpp'
print 'Translation unit:', path
source = SourceFile(path)
哪个输出
Translation unit: Sample.cpp
/mingw/include\stdio.h
/mingw/include\_mingw.h
/mingw/include\sys/types.h
TRANSLATION_UNIT None
TYPEDEF_DECL __builtin_va_list
STRUCT_DECL _iobuf
TYPEDEF_DECL FILE
VAR_DECL _iob
UNEXPOSED_DECL
FUNCTION_DECL main
int main()
{
printf(HELLO_WORLD);
return 0;
}
对于以下C代码:
#include <stdio.h>
#define HELLO_WORLD "HELLO!"
int main()
{
printf(HELLO_WORLD);
return 0;
}
我想要的是在代码中为我的#define获取DEFINE_DECL HELLO_WORLD(目前我什么都没得到)。当然,我的#include也会得到类似的陈述。这可能吗?
编辑:基本上,我想在没有扩展预处理程序指令的情况下解析文件。
答案 0 :(得分:24)
如果将PARSE_DETAILED_PROCESSING_RECORD添加为对index.parse()的调用选项,则可以访问预处理器节点。
index = clang.cindex.Index.create()
tu = index.parse(filename, options=clang.cindex.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD)
此选项映射到以下libclang C API选项值。那里有一个评论,其中包含更多背景信息。
/**
* \brief Used to indicate that the parser should construct a "detailed"
* preprocessing record, including all macro definitions and instantiations.
*
* Constructing a detailed preprocessing record requires more memory
* and time to parse, since the information contained in the record
* is usually not retained. However, it can be useful for
* applications that require more detailed information about the
* behavior of the preprocessor.
*/
CXTranslationUnit_DetailedPreprocessingRecord = 0x01,
答案 1 :(得分:4)
几天前,我在#llvm freenode irc频道上提出了同样的问题。答案是“宏不是AST的一部分,所以你不能”,但很可能“-fsyntax-only”选项和clang插件而不是libclang可能对你有所帮助。
编辑:看起来现在实际上是可行的,请参阅bradtgmurray的答案
答案 2 :(得分:1)
如果您使用命令行参数作为调用libclang的方法,那么这里是libclang C API实现的相关代码:
// Do we need the detailed preprocessing record?
if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
Args->push_back("-Xclang");
Args->push_back("-detailed-preprocessing-record");
}