Возможным решением может быть использование сгенерированного дерева разбора для позиций токенов (к каждому 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 .