我正在尝试在 C++ 源文件中查找作业:
x = 10;
我正在使用 libclang 来解析它并遍历 AST。有一个
CXCursor_BinaryOperator
代表二元运算符。有没有办法确定它是赋值还是任何其他二元运算符(如 +
或 <=
或 !=
)?如果不是,那么我如何确定表达式是否是赋值?
提前致谢。
clang_getCursorBinaryOperatorKind()
来获取此信息。
历史信息:该问题于 2016 年首次提交为 issue 29138。它在提交7fbc9de455中得到修复,并流入 Clang 17.0.1,并于 2023-09-09 发布。
(这是最初的答案,仍然适用于 Clang 17 作为如何获取令牌的演示,尽管获取二进制表达式的运算符的特定任务不再需要它。)
@notetau 的答案只是搜索带有文本
=
的任何标记,但是当该标记出现在表达式中而不是顶层的某个位置时,就会失败。
这是一个获取左侧操作数中所有标记之后第一个标记的文本的版本:
// Get the first child of 'cxNode'.
static CXCursor getFirstChild(CXCursor cxNode)
{
struct Result {
CXCursor child;
bool found;
} result;
result.found = false;
clang_visitChildren(cxNode,
[](CXCursor c, CXCursor parent, CXClientData client_data) {
Result *r = (Result*)client_data;
r->found = true;
r->child = c;
return CXChildVisit_Break;
},
&result);
assert(result.found);
return result.child;
}
// Get the operator of binary expression 'cxExpr' as a string.
std::string getBinaryOperator(CXTranslationUnit cxTU, CXCursor cxExpr)
{
// Get tokens in 'cxExpr'.
CXToken *exprTokens;
unsigned numExprTokens;
clang_tokenize(cxTU, clang_getCursorExtent(cxExpr),
&exprTokens, &numExprTokens);
// Get tokens in its left-hand side.
CXCursor cxLHS = getFirstChild(cxExpr);
CXToken *lhsTokens;
unsigned numLHSTokens;
clang_tokenize(cxTU, clang_getCursorExtent(cxLHS),
&lhsTokens, &numLHSTokens);
// Get the spelling of the first token not in the LHS.
assert(numLHSTokens < numExprTokens);
CXString cxString = clang_getTokenSpelling(cxTU,
exprTokens[numLHSTokens]);
std::string ret(clang_getCString(cxString));
// Clean up.
clang_disposeString(cxString);
clang_disposeTokens(cxTU, lhsTokens, numLHSTokens);
clang_disposeTokens(cxTU, exprTokens, numExprTokens);
return ret;
}
但是,在某些涉及宏的情况下,即使这样也会失败,例如:
#define MINUS -
int f(int a, int b)
{
return a MINUS b;
}
对于这段代码,
getBinaryOperator
将返回MINUS
,除了首先进行预处理(作为单独的步骤),然后将预处理后的输出传递给clang
进行进一步分析之外,我还没有找到任何解决该问题的方法.
以下代码可能适合您:
CXToken *tokens;
unsigned numTokens;
CXSourceRange range = clang_getCursorExtent(cursor);
clang_tokenize(tu, range, &tokens, &numTokens);
for(unsigned i=0; i<numTokens; i++) {
CXString s = clang_getTokenSpelling(tu, tokens[i]);
const char* str = clang_getCString(s);
if( strcmp(str, "=") == 0 ) {
/* found */
}
clang_disposeString(s);
}
clang_disposeTokens(tu, tokens, numTokens);