Извлечение информации из данной программы C ++ / Java с использованием другой программы C / Java - PullRequest
1 голос
/ 16 сентября 2011

Может ли кто-нибудь дать мне представление о том, как извлечь информацию из заданной программы на C ++ или Java (исходный код)? Информация может быть именами классов или именами методов или сообщать о каком-либо отношении наследования или иерархии классов и т. Д. Вы должны написать программу на С ++ или Java для того же. Я пытался и мог сделать это, но это не совсем правильно. Прямо сейчас я построчно читаю данную программу и проверяю ключевое слово «class», и если я найду какое-либо такое слово, это означает, что слово, следующее за ним, является именем этого класса (для извлечения имени классов) . Я просто думаю, есть ли какие-нибудь встроенные библиотеки на C или Java, которые могут сделать эту работу более эффективно? И, пожалуйста, предложите несколько простых идей (не некоторые внешние библиотеки или плагины).

Ответы [ 6 ]

2 голосов
/ 16 сентября 2011

Если вам нужны только имена классов и методов внутри классов, вы можете настроить набор регулярных выражений для выбора различных токенов (идентификаторы, "{", "}", оператор, число, строка) и crummy parser (называемый "островным анализатором") для распознавания последовательности токенов, которые составляют объявления классов и объявлений методов. (Подсказка: для Java и C ++, убедитесь, что вы как-то соответствует соответствующий {...} ").

Этот трюк работает для классов и методов, потому что, по сути, так работают настоящие компиляторы: они разбивают входной поток на токены (обычно используя обобщение регулярных выражений, называемое "генераторы лексеров"), а затем используют анализатор для определения реальная структура кода, а также классы и методы довольно легко обнаружить в синтаксисе. (Это решение является некой чистой версией того, что написал ОП).

Если вы хотите получить любую другую информацию из исходного кода Java или C ++ (например, типы аргументов метода и т. Д.), Вам, вероятно, понадобится инструмент, который фактически анализирует языки и создает таблицы символов, чтобы у вас была возможность узнать, что означают идентификаторы, найденные в разных местах.

(РЕДАКТИРОВАТЬ: ОП указал, что он хочет выяснить, какая функция вызывает какую-либо другую функцию. Он не может сделать это разумно без полнофункционального интерфейса пользователя (парсер + таблица символов как минимум).

Вы можете получить различные инструменты для анализа C ++ (GCC, Clang, Elsa, ...) и различные другие инструменты для анализа Java (ANTLR, javacc, ...). Вы обнаружите, что GCC довольно трудно поддается общим задачам, Clang и Elsa менее проблематичны. ANTLR и Javacc будут анализировать код Java, но AFAIK не будут создавать таблицы символов, поэтому они не очень удобны для задач общего назначения. Вы обнаружите, что работа с инструментом C ++ окажется совершенно другой, чем работа с инструментом Java, поскольку ни один из этих инструментов не имеет общей инфраструктуры компилятора.

То, как вы извлекаете имена классов и методов из каждого из них, будет отличаться в деталях, но большинство из них предлагают какой-то способ пролезть через дерево разбора (и вы кодируете какое-то специальное совпадение для того, что вы хотите найти, например, , синтаксис объявления класса) и / или перемещаться по таблицам символов (и выплевывать символы, помеченные как имена «классов» или «методов»). Чтобы найти правильный синтаксис, вам необходимо детально знать структуру дерева и тестировать множество кодов для соответствия правильным структурам дерева.

Если вы действительно хотите обрабатывать оба языка и использовать для этого единую инфраструктуру, вы можете рассмотреть наш DMS Software Reengineering Toolkit . DMS не зависит от языка, но может быть настроен на произвольные языки, а затем анализировать эти языки, создавать таблицы абстрактных символов и различные виды анализа потоков. DMS имеет как полный C ++ Front end (со встроенным препроцессором и обработкой C ++ в его различных формах, включая новый стандарт C ++ 11), так и Java Front end , обрабатывающий все диалекты Java до 1.6 (с 1.7 происходит на мгновение).

Чтобы выполнить операции OP (изначально заявленные) по поиску классов и методов, вы должны указать DMS проанализировать файл и затем пролезть по деревьям или таблицам символов, как и для других инструментов. Вы можете кодировать специальное сопоставление деревьев в DMS, но проще писать шаблоны:

 pattern match_class_declaration(i: identifier, b: statements): class_declaration
 =  " class \i { \b } ";

может использоваться с DMS для соответствия тем деревьям, которые являются объявлениями классов, и будет возвращать «i» (и «b», которые нас не интересуют), связанные с соответствующими поддеревьями. «i», конечно, содержит имя класса, которое вы хотите. Другие шаблоны могут использоваться для распознавания других конструкций, таких как имена классов, которые наследуют, или реализуют интерфейсы, или методы, которые возвращают некоторый тип или методы, которые возвращают void. Дело в том, что вам не нужно знать древовидную структуру, чтобы использовать такие шаблоны.

Чтобы пойти дальше, кажется, что OP хочет это сделать (например, построить информацию о вызывающем абоненте / вызываемом абоненте), вам необходимо построить графы потоков управления, выполнить анализ точек и т. Д. DMS обеспечивает поддержку для этого.

Хорошая новость: одна инфраструктура поддерживает оба языка;Вы даже можете смешивать C ++ и Java в DMS, не путая их.Более сложная новость заключается в том, что DMS - довольно сложный зверь, но это потому, что он должен обрабатывать все сложности C ++ и Java (а также многих других языков).Все еще лучше, чем работать с двумя различными синтаксическими анализаторами языка с двумя радикально различными реализациями и, таким образом, с двумя полными наборами кривых обучения.

1 голос
/ 16 сентября 2011

вопрос звучит слишком расплывчато, чтобы на него отвечать.пожалуйста, уточните.

Из того, что я мог измерить, используйте Reflection, когда вы работаете с классами Java, чтобы выяснить почти все о классе и его методах.Существуют другие (статические) API, которые вы можете использовать для объекта Class (если у вас есть такая рука).Обратитесь к javadocs за дополнительной информацией.

0 голосов
/ 16 сентября 2011

Не уверен насчет текущей Java, но C ++ - настоящий кошмар для анализа, если вы хотите полностью извлечь семантическую информацию (учтите, что потребовалось ГОДОВ, чтобы 100% согласились на то, как и следует ли анализировать определенную конструкцию).

Обратите внимание, что хотя имя класса в C ++ достаточно просто (просто помните, что слово class или struct может также присутствовать перед параметром шаблона вместо typename, что вы можете иметь "вложенные классы" и что у вас может быть класс "предварительные объявления") для членов дела намного сложнее, потому что имя члена идет после типа и даже понимание того, что является типом, где тип заканчивается или что имя члена не тривиально ... рассмотрим

int (*foo)(int x, int y);
Node<Bar, Baz, Allocator<Foo, &Q::operator > >, 12> (*rex)(int);

в первом случае имя члена foo, а во втором случае имя члена rex (обратите внимание, что я не уверен, является ли второй пример допустимым кодом C ++ или, предположим, что он действителен, если распространен Компиляторы C ++ примут это).

Обратите внимание, что даже просто понимание того, где список членов класса начинается после имени класса, не является тривиальным (вы должны пропустить список наследования, который может включать шаблонные классы с параметрами, которые являются универсальными типами).

Таким образом, отказавшись от регулярного выражения (которое явно не в состоянии анализировать тип, являющийся сложной рекурсивной сущностью), единственное решение - использовать код, написанный кем-то другим.

Для этого задания (для C ++) вы можете попробовать, например, GCC-XML , который был написан именно по этой причине (он генерирует результат XML при разборе исходного кода C ++).

0 голосов
/ 16 сентября 2011

Вот пример , показывающий, как анализировать файл C ++ с использованием библиотек clang (llvm).Он длинный и довольно подробный, но вы должны быть в состоянии адаптировать его для того, что вам нужно (в любом случае для C и C ++ ... не знаю, хорошо ли llvm в обработке Java ... и не знаю, легко ли его адаптироватьподход для Java).

0 голосов
/ 16 сентября 2011

Когда вы пытаетесь проанализировать текстовый файл, будет достаточно сценария оболочки, основанного на awk и / или sed . Вам придется определить несколько простых регулярных выражений на основе ключевых слов и синтаксиса языков, чтобы извлечь необходимую информацию.

Например, это регулярное выражение будет соответствовать большинству объявлений классов исходного файла C ++: class *([A-Za-z_][A-Za-z_0-9]*) *\{?$ Скобки позволяют извлечь искомый идентификатор, он называется группа захвата .

Если вы действительно хотите сделать это на C / C ++ / Java, вам нужно найти библиотеку, которая предоставляет средства регулярных выражений (стандартная библиотека Java уже предоставляет некоторые). Возможно Повышение регулярных выражений для программы на C ++.

0 голосов
/ 16 сентября 2011

Вы можете попробовать использовать какой-нибудь источник из компиляторов, например, gcc.Там уже есть весь синтаксический анализ и предварительная обработка, так что вы можете сэкономить кучу времени.

Для скомпилированной Java вы также можете использовать библиотеки манипулирования байт-кодом (например, asm ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...