Regex, охватывающий несколько строк / распознавание закомментированных строк - PullRequest
1 голос
/ 31 мая 2009

Я хочу проанализировать код VB6 через Regex. Однако, будучи новичком в Regex, я столкнулся с несколькими проблемами, касающимися использования регулярных выражений. В настоящее время у меня проблемы с распознаванием этих конструкций:

' Subs
' Sub Test
Private Sub Test(ByVal x as Integer)
    'Private Sub Test(ByVal y as Integer)
    Dim dummy as String
    dummy = "Private Sub Test(ByVal y as Integer)"
End Sub 

У меня есть в основном эти 2 проблемы: Как мне написать регулярное выражение, которое соответствует определению Sub и включает все строки комментария (и пустые) выше его определения? И как я могу предотвратить несоответствие определений Sub, которые либо отключены комментарием, либо включены в строки? Кроме того, мне нужно поддерживать определения, которые состоят из нескольких строк, например:

' Subs
' Sub Test
Private Function Test2( _
   ByVal x as Integer _
) As Long
    'Private Sub Test(ByVal y as Integer)
    Dim dummy as String
    dummy = "Private Sub Test(ByVal y as Integer)"
End Function

Любая подсказка будет очень оценена. Решения, которые я придумаю, не работают с несколькими строками и не содержат более одного дополнительного определения. Затем он просто совпадает с концом последнего вхождения End Sub из-за жадного сопоставления.

Моя попытка в C # в настоящее время выглядит так:

(('(?<comment>[\S \t]+[\n\r]+))*((?<accessmodifier>(Private|Public))\s+_?)(?<functiontype>(Sub|Function))\s+_?(?<name>[\S]+)\((?<parameters>[\S \t]*)\)([ \t]+As[ \t]+(?<returntype>\w+))?)|(?<endfunction>End (Sub|Function))

Я использую Multiline, Singleline, IgnoreCase, ExplicitCapture.

Спасибо за вашу помощь!

Ответы [ 5 ]

2 голосов
/ 01 июня 2009

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

Тем не менее, самая большая проблема, которую я вижу с вашим регулярным выражением, заключается в том, что вы неправильно обрабатываете продолжения строки. Это: \s+_? соответствует одному или нескольким пробельным символам, за которыми необязательно следует подчеркивание. Но если есть подчеркивание, оно должно сопровождаться символом новой строки, который вам не подходит. Это достаточно легко исправить - \s+(_\s+)? - но я не уверен, что вам нужно быть таким конкретным. Я подозреваю, что: [\s_]+ будет так же хорошо.

Что касается избежания явных объявлений подфункций / функций внутри комментариев и строк, то самым простым способом было бы сопоставить их только с левым полем, возможно, с некоторыми вкладками или пробелами для отступа. Это обман, я знаю, но это может быть достаточно для того, что ты делаешь. Я сильно полагался на этот трюк, когда писал сценарий навигации по файлу на Java *1009* для EditPad Pro. Вы не можете делать подобные вещи с регулярными выражениями без использования множества уловок и упрощения предположений. Попробуйте это регулярное выражение:

^(?>('(?<comment>.*[\n\r]+))*)
[ \t]*(?<accessmodifier>(Private|Public))
[\s_]+(?<functiontype>(Sub|Function))
[\s_]+(?<name>\S+)
[\s_]*\((?<parameters>[^()]*)\)
([\s_]+As[\s_]+(?<returntype>\w+))?
|
^[ \t]*(?<endfunction>End (Sub|Function))

Конечно, вам нужно сначала собрать его. Он должен быть скомпилирован с параметрами Multiline, IgnoreCase и ExplicitCapture, но не Singleline.

2 голосов
/ 31 мая 2009

Я подозреваю, что это будет невозможно для всех, кроме самых простых случаев. С помощью регулярных выражений вы не можете анализировать рекурсивные структуры, и языки (такие как VB) будут иметь рекурсивные функции. См. эту запись в блоге CodingHorror для получения дополнительной информации.

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

1 голос
/ 31 мая 2009

Не пытайтесь написать одно регулярное выражение, чтобы сделать это для вас (это не может быть по своей природе) Что вам нужно, это парсер. Вероятно, самое простое решение - использовать парсер рекурсивного спуска . Я не использую C #, но быстрый поиск показал Spart .

1 голос
/ 31 мая 2009

Знаете, в конце концов наступает момент, когда регулярных выражений просто недостаточно. Разбор на этом уровне - один из них.

Попробуйте вместо этого написать простой реальный парсер, возможно, с использованием рекурсивного спуска.

0 голосов
/ 31 мая 2009

Учитывая сложность и сложность Visual Basic, вам, вероятно, потребуется проанализировать код с помощью токенизатора / анализатора. Вы не можете полагаться на регулярные выражения для всего ;)

Для чего стоит формальная грамматика VB доступна здесь . Веселись!

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