2014-09-13 5 views
3

Я пытаюсь создать регулярное выражение питона, для СЛОЯ, который будет соответствовать комментарии видаPython regex для сопоставления одной строки и нескольких строк комментариев.

// some comment 

и

/* comment 
    more comment */ 

Так что я попытался

t_COMMENT = r'//.+ | /\*.+\*/' 

, но это Безразлично 't допускает многострочные комментарии и когда я пытаюсь решить эту проблему, используя опции «dot matches all», такие как

t_COMMENT = r'//.+ | (?s) /\*.+\*/' 

это приводит к типу комментариев «//», соответствующему многим строкам. Кроме того, если я пытаюсь иметь два отдельных регулярных выражений, как

t_COMMENT = r'//.+' 
t_COMMENT2 = r'(?s) /\*.+\*/' 

«//» комментарий типа до сих пор соответствует несколько строк, как если точка соответствует выбран все опции.

Кто-нибудь знает, как это решить?

+1

Я сильно подозреваю, что это плохая идея. Попытка сделать слишком большой (грамматический) синтаксический анализ с использованием сложных регулярных выражений является антитезой создания системы lexer/parser. Я бы предположил, что у вас есть маркеры для комментариев в одной строке, а начало и конец нескольких строк. Грамматика, построенная вокруг этого анализатора, может отбросить весь вход, найденный между многострочным началом и концом. –

+0

Можете ли вы дать ответ на основе вашей идеи? – Zvika

ответ

3

Ниже регулярное выражение будет соответствовать как тип комментариев,

(?://[^\n]*|/\*(?:(?!\*/).)*\*/) 

DEMO

>>> s = """// some comment 
... 
... foo 
... bar 
... foobar 
... /* comment 
... more comment */ bar""" 
>>> m = re.findall(r'(?://[^\n]*|/\*(?:(?!\*/).)*\*/)', s, re.DOTALL) 
>>> m 
['// some comment', '/* comment\n more comment */'] 
+0

не нужно eacape переднюю косую черту ... – isedev

0

Вот незначительные изменения по решению АВИНАШ в.

pat = re.compile(r'(?://.*?$)|(?:/\*.*?\*/)', re.M|re.S)

2

По PLY Doc это может быть достигнуто с 'Условный Lexing'. Это может быть более читаемым и более легким для отладки, чем сложное регулярное выражение. Пример, который они дают, немного сложнее, поскольку он отслеживает уровни вложенности и содержимое внутри блока. Однако ваш случай проще, поскольку вам не нужна вся эта информация.

Кода для многострочного комментария должен быть что-то вроде этого:

# I'd prefer 'multi_line_comment', but it appears that 
# state names cannot have underscore in them 
states = (
    ('multiLineComment','exclusive'), 
) 

def t_multiLineComment_start(t): 
    r'/\*' 
    t.lexer.begin('multiLineComment')   

def t_multiLineComment_end): 
    r'\*/' 
    t.lexer.begin('INITIAL')   

def t_multiLineComment_newline(t): 
    r'\n' 
    pass 

# catch (and ignore) anything that isn't end-of-comment 
def t_multiLineComment_content(t): 
    r'[^(\*/)]' 
    pass 

Конечно, вы будете иметь другое правило, в рамках регулярного государства, для // комментариев.

0

Это может быть полезно повторно

(/\*(.|\n)*?*/)|(//.*) 
Смежные вопросы