Метод re.findall
Python в основном работает так же, как и большинство лексеров: он последовательно возвращает самый длинный матч, начиная с предыдущего окончания.Все, что требуется для получения дизъюнкции всех лексических моделей:
(<pattern 1>)|(<pattern 2>)|...|(<pattern n>)
В отличии от большинства лексеров, он не требует спичек, чтобы быть смежными, но это не существенная разница, так как вы всегда можете просто добавить (.)
как последний шаблон, чтобы сопоставить все иначе непревзойденные символы в отдельности.
Важной особенностью re.findall
является то, что если в регулярном выражении есть группы, тогда будут возвращаться только группы. Следовательно, вы можете исключить альтернативы, просто оставляя круглые скобки, или изменяя их не-захвата скобки:
(<pattern 1>)|(?:<unimportant pattern 2>)|(<pattern 3)
Имея это в виду, давайте взглянем на то, как разметить C достаточно, чтобы признать комментарии. Мы должны иметь дело с:
- однострочные комментарии:
// Comment
- Многоканальный Комментарии:
/* Comment */
- двойные кавычки:
"Might include escapes like \n"
- Single цитируемый персонаж:
'\t'
- (см ниже для еще нескольких раздражающих случаев)
Имея это в виду, давайте c reate regexen для каждого из вышеперечисленных.
- Две косые следует ничего, кроме символа новой строки:
//[^\n]*
- Это регулярное выражение является утомительным объяснить:
/*[^*]*[*]+(?:[^/*][^*]*[*]+)*/
Обратите внимания, что она использует (?:...)
, чтобы избежать захвата неоднократной группы.
- Цитата, любое повторение символа, отличное от цитирования и обратной косой черты, или обратная косая черта, сопровождаемая любым символом. Это не точное определение последовательности побега, но это достаточно хорошо, чтобы определить, когда " завершает строку, которая нас интересует:
"(?:[^"\\]|\\.*)"
- же, как (3), но с одинарными кавычками:
'(?:[^'\\]|\\.)*'
Наконец, цель состояла в том, чтобы найти текст комментариев в стиле с Итак, нам необходимо, чтобы избежать захватов в любой из других групп Следовательно:..
p = re.compile('|'.join((r"(//[^\n])*"
,r"/*[^*]*[*]+(?:[^/*][^*]*[*]+)*/"
,'"'+r"""(?:[^"\\]|\\.)*"""+'"'
,r"'(?:[^'\\]|\\.)*'")))
return [c[2:] for c in p.findall(text) if c]
Abo ве, я оставил некоторые неясные случаи, которые вряд ли возникнут:
В качестве #include <...>
директивы, то <...>
существу строка.Теоретически, он может содержать кавычки или последовательности, которые выглядят как комментарии, но на практике вы никогда не увидите:
#include </*This looks like a comment but it is a filename*/>
линия, которая заканчивается \ продолжается на следующей строке; \ и следующий символ новой строки просто удаляются с ввода. Это происходит до того выполняется любое лексическое сканирование, так что следующий является совершенно законным комментарием (на самом деле два комментариев):
/\
**************** Surprise! **************\
//////////////////////////////////////////
Для того, чтобы выше хуже, триграф ??/
таким же, как \ , и что замена происходит до обработки продолжения.
/************************************//??/
**************** Surprise! ************??/
//////////////////////////////////////////
Вне конкурсов обфускации никто не использует триграфы. Но они все еще в стандарте. Самый простой способ справиться с обоими из этих вопросов было бы предварительное сканирование строки:
return [c[2:]
for c in p.findall(text.replace('//?','\\').replace('\\\n',''))
if c]
Единственный способ справиться с #include <...>
вопрос, если вы действительно заботились о нем, можно было бы добавить еще один узор, что-то вроде #define\s*<[^>\n]*>
.
Невозможно разобрать C с регулярным выражением. Возможно, используйте что-то еще, например GCC-XML или front-end CLang. –
Я представляю его как txt-файл или как строку – CRS
Ваше воображение не меняет реальности. В этом случае на самом деле это можно сделать с регулярным выражением (очень гладким, Casimir!), Но бывают случаи, когда регулярные выражения имеют либо большую сложность, либо плоские выходы не могут этого сделать (сопоставление скобок является классическим примером, если только вы используя, например, Oniguruma, который имеет очень нерегулярные расширения). Это как: «Могу ли я есть суп с вилкой? Я представляю это как еду». Что вы можете. Это действительно лучший способ? – Amadan