Автоматическое изменение кода C ++: преобразование кода из дерева разбора обратно в исходный код - PullRequest
0 голосов
/ 26 марта 2020

Я пытаюсь изменить код 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 }

В другой теме люди сказали, что antlr - хороший способ для этого. Поэтому я попытался использовать API времени выполнения AntLR. Легко создать дерево разбора. Я также нашел способы изменить это. Но теперь я не знаю, как вернуть исходный код из дерева разбора? Мне действительно не нужен исходный код, его также будет достаточно, чтобы просто скомпилировать дерево разбора в исполняемую программу. Как я могу это сделать?

Может быть, есть более простой способ решить мою проблему? Может быть, просто прочитайте код, посчитайте \ n и после 2 и 3 \ ni введите мой код?

Редактировать: Для моей дипломной работы я получаю кусок параллельного кода и мне нужно заставить его выполнить данное чередование. Поэтому у меня есть задача написать инструмент для автоматической вставки таких инструкций, как «EnterCriticalSection (...)» и «LeaveCriticalSection (...)» в заданные строки в коде. Теперь я получил другую работу, чтобы переименовать основную функцию и вставить свою собственную основную функцию. Я думаю, что это не будет работать с подсчетом строк.

1 Ответ

0 голосов
/ 27 марта 2020

Возможным решением может быть использование сгенерированного дерева разбора для позиций токенов (к каждому TerminalNode прикреплен экземпляр Token с информацией о том, где он находится в исходном исходном коде). Имея это под рукой, вы можете начать копировать неизмененный текст из исходного потока источника, а затем вставить свой собственный текст, который принадлежит этой позиции. После этого скопируйте следующую часть неизмененного кода и вставьте следующую модификацию. Делайте это в al oop, пока не достигнете 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 .

...