В моем приложении Python мне нужно написать регулярное выражение, которое соответствует циклу С++ for
или while
, который был прерван точкой с запятой (;
). Например, он должен соответствовать этому:
for (int i = 0; i < 10; i++);
... но не это:
for (int i = 0; i < 10; i++)
Это выглядит тривиально с первого взгляда, пока вы не поймете, что текст между открывающей и закрывающей скобками может содержать другую скобку, например:
for (int i = funcA(); i < funcB(); i++);
Я использую модуль python.re. Прямо сейчас мое регулярное выражение выглядит так (я оставил свои комментарии, чтобы вы могли понять это проще):
# match any line that begins with a "for" or "while" statement:
^\s*(for|while)\s*
\( # match the initial opening parenthesis
# Now make a named group 'balanced' which matches a balanced substring.
(?P<balanced>
# A balanced substring is either something that is not a parenthesis:
[^()]
| # …or a parenthesised string:
\( # A parenthesised string begins with an opening parenthesis
(?P=balanced)* # …followed by a sequence of balanced substrings
\) # …and ends with a closing parenthesis
)* # Look for a sequence of balanced substrings
\) # Finally, the outer closing parenthesis.
# must end with a semi-colon to match:
\s*;\s*
Это отлично работает для всех вышеперечисленных случаев, но он ломается, как только вы пытаетесь сделать третью часть цикла for, содержать функцию, например:
for (int i = 0; i < 10; doSomethingTo(i));
Я думаю, что это ломается, потому что, как только вы помещаете какой-либо текст между открывающей и закрывающей скобками, "сбалансированная" группа соответствует тому, что содержит текст, и, следовательно, часть (?P=balanced)
больше не работает, поскольку она не будет (из-за того, что текст внутри скобки отличается).
В моем коде Python я использую флаги VERBOSE и MULTILINE и создаю регулярное выражение следующим образом:
REGEX_STR = r"""# match any line that begins with a "for" or "while" statement:
^\s*(for|while)\s*
\( # match the initial opening parenthesis
# Now make a named group 'balanced' which matches
# a balanced substring.
(?P<balanced>
# A balanced substring is either something that is not a parenthesis:
[^()]
| # …or a parenthesised string:
\( # A parenthesised string begins with an opening parenthesis
(?P=balanced)* # …followed by a sequence of balanced substrings
\) # …and ends with a closing parenthesis
)* # Look for a sequence of balanced substrings
\) # Finally, the outer closing parenthesis.
# must end with a semi-colon to match:
\s*;\s*"""
REGEX_OBJ = re.compile(REGEX_STR, re.MULTILINE| re.VERBOSE)
Может ли кто-нибудь предложить улучшение этого регулярного выражения? Мне становится слишком сложно, чтобы я опустил голову.