2014-12-02 2 views
3

Мне интересно узнать синтаксический анализ кода на C++ с помощью regexp. То, что я до сих пор (с помощью рубин) позволяет мне извлечь объявления классов и их родительских классов (если таковые имеются):Ruby Regex: разбор классов C++

/(struct|class)\s+([^{:\s]+)\s*[:]?([^{]+)\s*\{/ 

Вот в Rubular example. Заметьте, что я могу правильно зафиксировать части «объявления» и «наследование».

Точка в месте, где я застреваю, является захватом класса корпус. Если я использую следующее расширение исходного регулярного выражения:

/(struct|class)\s+([^{:\s]+)\s*[:]?([^{]+)\s*\{[^}]*\};/ 

Тогда я могу захватить тело класса только если он не содержит никаких фигурных скобок, и, следовательно, любое определение класса или функции. На этом этапе я пробовал много вещей, но ни один из них не сделал это лучше. Например, если я включу в regexp тот факт, что тело может содержать фигурные скобки, оно будет захватывать объявление первого класса, а затем все последующие классы, как если бы они были частью тела первого класса!

Что мне не хватает?

ответ

1

group capturing может помочь:

#     named v backref   v 
/(struct|class)\s+(?<match>{((\g<match>|[^{}]*))*})/m 

Здесь мы находим соответствия фигурную скобку для одного последующего struct/class декларации. Вероятно, вам захочется настроить регулярное выражение, я разместил его, чтобы сделать решение максимально ясным.

0

Что я могу предложить вам это:

(struct|class)\s+([^{:\s]+)\s*[:]?([^{]+)\{([^{}]|\{\g<4>\})*\}; 

Где \g<4> рекурсивное применение четвертой группы захвата, которая ([^{}]|\{\g<4>\}).

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

4

Регулярные выражения не рекомендуемый способ анализа кода.

Большинство компиляторов и переводчиков используют lexers и парсеров для преобразования кода в abstract syntax tree перед компиляцией или запуском кода.

Ruby имеет несколько камней lexer, например this, вы можете попробовать и включить в свой проект.

+1

В целом, это правильно. Однако в некоторых случаях регулярное выражение может быть просто «достаточно хорошим». Например. для быстрого эвристического анализа некоторого кода. –

+1

@undur_gongor - указав первое предложение OP - «Мне любопытно разобрать код на C++ с помощью regexp» - это звучит как общее, поскольку они приходят :). Я согласен с тем, что для некоторых задач, читающих HTML или код с использованием regexp, достаточно, если код не является произвольным (вы точно откуда и как он строится) –

+0

Спасибо Uri. Хотя ваш ответ кажется довольно полезным, я только «играл» с возможностями синтаксического анализа кода C++ (например, подсчета количества методов в классе и т. Д.). Я соглашусь с ответом mudasobwa, так как это очень помогло мне, но с учетом вашего ценного совета;) –

Смежные вопросы