Как найти все взаимные дружеские отношения в большом дереве исходного кода C ++? - PullRequest
1 голос
/ 09 декабря 2010

В большом исходном дереве C ++, где определено около 600 классов, я хочу найти все пары классов, где каждый объявляет другого своим другом.

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

Ответы [ 4 ]

2 голосов
/ 09 декабря 2010

I) Некоторые изящные способы:

1) Doxygen (http://www.doxygen.nl/) может дать вам то, что вам нужно. (Если он еще не дает эту информацию, вы можете немного взломать парсер Doxygen C ++, чтобы получить то, что вам нужно).

2) Существуют также файлы грамматики ANTLR для C ++.

II) Более быстрый путь (возможно, правильный подход здесь):

Regex должен быть вполне подходящим для вашей цели, как предлагают другие. Рассмотрим следующий псевдокод:

rm -f result_file;
foreach source_file
do
  sed 's/[ \t\n]\+/ /g' $source_file >  temp_file;  ## remove newlines, etc
  grep -o -P -i "friend [^;]*;"  >> result_file; ## you can improve this regex for eliminating some possible unwanted matches or post-process result_file later
done

Теперь у вас есть все отношения с друзьями в result_file. Вы можете удалить «функции друзей», используя другое простое регулярное выражение, и / или обработать файл результата в соответствии с потребностями.

2 голосов
/ 09 декабря 2010

Вы могли бы реализовать своего рода тройной цикл здесь;алгоритм может быть следующим:

  1. Первый цикл: найти все классы, у которых есть друзья, и запомнить имя друга и имя фактического класса;
  2. Затем выполнить внутреннийвыполните цикл для всех классов и найдите класс с именем друга из шага 1.
  3. Затем выполните другой внутренний цикл для всех друзей класса, найденных на шаге 2. Если вы нашли класс с именем изшаг 1 - вуаля - они общие друзья.

Я считаю, что Perl и регулярные выражения - лучшие инструменты для таких вещей.

PS уверен, что этот подход имеет свои пределы, потому что не всев C ++ можно было разобрать с помощью регулярных выражений (using namespace вещи - это первое, что пришло мне в голову).Но, в некоторой степени, это рабочий подход, и если у вас нет альтернатив, вы можете попробовать.

EDIT: Идея пришла мне в голову сегодня утром, пока я все ещележал в моей кровати.:) Идея довольно проста и понятна (как и все утренние идеи): используйте SQL!Естественно, представьте, что у вас есть таблица классов с 2 столбцами, где первый столбец - имя класса, а второй столбец - имя друга.Скажем, что-то вроде этого:

ClassName FriendName
C1        C2
C1        C3
C1        C4
C2        C1
C2        C8
C3        C1
C3        C2
...       ...

Тогда вы можете выполнить простой запрос к нему.Скажем, что-то вроде этого (извините, у меня нет удобной базы данных SQL, поэтому я не проверил запрос, но я надеюсь, что вы поймете идею и реализуете ее по мере необходимости:

SELECT ClassName as c, FriendName as f FROM T
WHERE c in 
  (SELECT FriendName FROM T
     WHERE FriendName = c AND ClassName = f)

Идея этого варианта заключается в том, что мы должны использовать те сборы, которые точно соответствуют задаче. Что может сравниться с SQL, когда вам нужно обработать некоторые наборы данных?

1 голос
/ 09 декабря 2010

Этот ответ похож на @ user534498, но я собираюсь вдаваться в подробности, так как предложение "разбирать C ++ с помощью регулярных выражений" настолько безумно, что я не думаю, что оно заслуживает рассмотрения.

Я также не думаю, что вы найдете автоматизированный инструмент, который уже может сделать это для вас. Если бы это была управляемая область кода, я бы предложил что-то вроде Nitriq , но я не думаю, что подобное работает на C ++.

Если вы не беспокоитесь о вложенных классах, я думаю, что вы можете без особых затруднений создать пару классов для друзей. Вы можете найти экземпляры класса ключевого слова, за которыми следуют фигурные скобки, и в фигурных скобках искать предложения друзей. Это должно без особых затруднений дать вам список классов, у которых есть друзья.

Как только вы это сделаете, вы можете легко проверить наличие дубликатов ссылок. (Зависит от языка, который вы используете ... если вы находитесь в C ++, вы бы поместили свои результаты в std::multimap с ключами, являющимися именем класса, и значениями, являющимися друзьями)

Полагаю, это похоже на то, что предлагает @Haspemulator ... но я хочу сказать, что, вероятно, будет легче разделить синтаксический анализ, а затем реализовать циклическую проверку ссылок с точки зрения наборов или карт, тогда это будет чтобы попытаться переплетать эти операции.

0 голосов
/ 09 декабря 2010

Используйте perl, python или c ++ regex для разбора всех файлов, записи всех пар класса-друзейСоответствие должно быть тривиальным для этих 600 пар

...