自动修改C ++代码:将代码从解析树转换回源代码

问题描述 投票:0回答:1

我正在尝试修改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之后输入我的代码?

c++ antlr transformation
1个回答
0
投票

[一种可能的解决方案是将生成的分析树用于令牌位置(每个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;
}

此代码取自MySQL Workbench parser module

© www.soinside.com 2019 - 2024. All rights reserved.