Наш инструментарий реинжиниринга программного обеспечения DMS с поддержкой C ++ 11 C ++ Front End может сделать это.
DMS - система преобразования программ общего назначения для произвольных языков программирования; внешний интерфейс C ++ позволяет ему обрабатывать C ++. DMS анализирует, строит AST и таблицы символов, которые являются точными (это трудно сделать для C ++), обеспечивает поддержку запроса свойств узлов и деревьев AST, допускает процедурные и исходные преобразования в дереве. После внесения всех изменений модифицированное дерево можно восстановить с сохранением комментариев.
Ваша проблема требует, чтобы вы нашли производные виртуальные методы и изменили их. Правило преобразования источника в источник в DMS, которое будет выглядеть примерно так:
source domain Cpp. -- tells DMS the following rules are for C++
rule insert_virtual_keyword (n:identifier, a: arguments, s: statements):
method_declaration -> method_declaration " =
" void \n(\a) { \s } " -> " virtual void \n(\a) { \s }"
if is_implicitly_virtual(n).
Такие правила соответствуют синтаксическим деревьям, поэтому они не могут не совпадать с комментарием, строкой или чем-либо еще. Смешные кавычки не являются строковыми кавычками C ++; они являются мета-кавычками, позволяющими языку правил знать, что то, что находится внутри них, должно рассматриваться как синтаксис целевого языка («Cpp»). Обратная косая черта - это экранирование от текста на целевом языке, что позволяет сопоставлять произвольные структуры, например, \ a указывает на необходимость «a», которое определено как синтаксическая категория «аргументы».
Вам потребуется больше правил для обработки случаев, когда функция возвращает не пустые результаты и т. Д., Но вам не нужно их много.
Интересная часть - реализация предиката (возвращающего TRUE или FALSE), управляющего применением преобразования: is_implicitly_virtual. Этот предикат принимает (абстрактное синтаксическое дерево) имя метода n.
Этот предикат будет обращаться к полной таблице символов C ++, чтобы определить, что в действительности представляет собой n. Мы уже знаем, что это метод только из его синтаксической установки, но мы хотим знать, в каком контексте класса.
Таблица символов обеспечивает связь между методом и классом, а информация таблицы символов для класса говорит нам, от чего наследуется класс, и для тех классов, какие методы они содержат и как они объявлены, что в конечном итоге приводит к открытию (или не) что метод родительского класса является виртуальным. Код для этого должен быть реализован как процедурный код, идущий против API таблицы символов C ++. Однако вся тяжелая работа выполнена; таблица символов верна и содержит ссылки на все другие необходимые данные. (Если у вас нет этой информации, вы не можете принять алгоритмическое решение, и любые изменения кода, скорее всего, будут ошибочными).
В прошлом DMS использовался для внесения значительных изменений в код C ++ с использованием программных преобразований (см. Раздел «Статьи» на веб-сайте по темам реархитектуры C ++).
(Я не эксперт по C ++, просто архитектор DMS, поэтому, если я ошибаюсь, пожалуйста, прости.)