我正在尝试修改C ++代码。我得到了一段代码和行号,我需要在给定的行号上应用代码。像这样:
1 void foo(){
2 int a = 5;
3 int b = 10;
4 }
行号:2,3。现在我想在行号后自动插入代码:
1 void foo(){
2 int a = 5;
3 newcode();
4 int b = 10;
5 newcode();
6 }
在另一个Thread中,人们说antlr是实现这一目标的好方法。所以我尝试使用antlr运行时api。易于生成解析树。我还找到了修改它的方法。但是现在我不知道如何从解析树中获取源代码?我真的不需要源代码,将解析树编译成可执行程序也就足够了。我该怎么办?
也许有更简单的方法来解决我的问题?也许只是阅读代码,计算\ n,然后在2和3 \ n之后输入我的代码?
[一种可能的解决方案是将生成的分析树用于令牌位置(每个TerminalNode
都有一个Token
实例,该实例附加了原始源代码中的信息)。这样一来,您就可以开始从原始源流中复制未修改的文本,然后插入属于此位置的自己的文本。之后,复制下一个未修改的代码部分,然后插入下一个修改。循环执行此操作,直到达到EOF。
这种情况不适合最终的格式,但我认为这可能不相关-您的任务听起来像是您正在对某些度量进行代码检测。
这里是给定两个解析树节点的代码,用于检索原始源代码:
std::string MySQLRecognizerCommon::sourceTextForRange(tree::ParseTree *start, tree::ParseTree *stop, bool keepQuotes) {
Token *startToken = antlrcpp::is<tree::TerminalNode *>(start) ? dynamic_cast<tree::TerminalNode *>(start)->getSymbol()
: dynamic_cast<ParserRuleContext *>(start)->start;
Token *stopToken = antlrcpp::is<tree::TerminalNode *>(stop) ? dynamic_cast<tree::TerminalNode *>(start)->getSymbol()
: dynamic_cast<ParserRuleContext *>(stop)->stop;
return sourceTextForRange(startToken, stopToken, keepQuotes);
}
//----------------------------------------------------------------------------------------------------------------------
std::string MySQLRecognizerCommon::sourceTextForRange(Token *start, Token *stop, bool keepQuotes) {
CharStream *cs = start->getTokenSource()->getInputStream();
size_t stopIndex = stop != nullptr ? stop->getStopIndex() : std::numeric_limits<size_t>::max();
std::string result = cs->getText(misc::Interval(start->getStartIndex(), stopIndex));
if (keepQuotes || result.size() < 2)
return result;
char quoteChar = result[0];
if ((quoteChar == '"' || quoteChar == '`' || quoteChar == '\'') && quoteChar == result.back()) {
if (quoteChar == '"' || quoteChar == '\'') {
// Replace any double occurence of the quote char by a single one.
replaceStringInplace(result, std::string(2, quoteChar), std::string(1, quoteChar));
}
return result.substr(1, result.size() - 2);
}
return result;
}