Regex для анализа объявлений функций C / C ++ - PullRequest
3 голосов
/ 04 августа 2010

Мне нужно разобрать и разделить функции C и C ++ на основные компоненты (тип возвращаемого значения, имя функции / класс и метод, параметры и т. Д.).

Я работаю либо из заголовков, либо из списка, где подписи принимают форму:

public: void __thiscall myClass :: method (int, class myOtherClass *)

У меня есть следующее регулярное выражение, которое работает для большинства функций:

(?<expo>public\:|protected\:|private\:) (?<ret>(const )*(void|int|unsigned int|long|unsigned long|float|double|(class .*)|(enum .*))) (?<decl>__thiscall|__cdecl|__stdcall|__fastcall|__clrcall) (?<ns>.*)\:\:(?<class>(.*)((<.*>)*))\:\:(?<method>(.*)((<.*>)*))\((?<params>((.*(<.*>)?)(,)?)*)\)

Есть несколько функций, которые он не любит анализировать, но которые соответствуют шаблону. Меня не беспокоит сопоставление функций, которые не являются членами класса в данный момент (с этим можно справиться позже). Выражение используется в программе на C #, поэтому <label> предназначены для простого извлечения групп.

Мне интересно, есть ли стандартное регулярное выражение для разбора всех функций или как улучшить мое для обработки нечетных исключений?

Ответы [ 3 ]

4 голосов
/ 04 августа 2010

C ++, как известно, трудно анализировать; невозможно написать регулярное выражение, которое ловит все случаи. Например, может быть неограниченное количество вложенных скобок, что показывает, что даже это подмножество языка C ++ не является регулярным.

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

Не зная «странных исключений», которые он не уловил, трудно сказать, как улучшить регулярное выражение.

2 голосов
/ 04 августа 2010

Взгляните на Boost.Spirit , это библиотека наддува, которая позволяет реализовать анализаторы рекурсивного спуска с использованием только кода C ++ и без препроцессоров. Вы должны указать грамматику BNF , а затем передать строку для ее анализа. Вы даже можете сгенерировать абстрактно-синтаксическое дерево (AST), которое полезно для обработки проанализированных данных.

Спецификация BNF выглядит как список целых чисел, или разделенные слова могут выглядеть следующим образом:

using spirit::alpha_p;
using spirit::digit_p;
using spirit::anychar_p;
using spirit::end_p;
using spirit::space_p;

// Inside the definition...
integer    = +digit_p;                      // One or more digits.
word       = +alpha_p;                      // One or more letters.
token      = integer | word;                // An integer or a word.
token_list = token >> *(+space_p >> token)  // A token, followed by 0 or more tokens.

Для получения дополнительной информации обратитесь к документации, библиотека вначале немного сложна, но потом становится проще (и более мощной).

0 голосов
/ 04 августа 2010

Нет. Даже прототипы функций могут иметь произвольные уровни вложенности, поэтому не могут быть выражены одним регулярным выражением.

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

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