正则表达式跨越多行/识别注释行

时间:2009-05-31 15:00:23

标签: c# regex

我想通过Regex解析VB6代码。然而,对于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 

我基本上有这两个问题:如何编写与Sub定义匹配的Regex,并在其定义之上包含所有commment(和空)行?如何防止通过注释禁用或包含在字符串中的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

任何提示都会有很大的暗示。我提出的解决方案不适用于多行或捕获超过一个Sub定义。然后,由于贪婪匹配,它只匹配到最后一个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))

我正在使用MultilineSinglelineIgnoreCaseExplicitCapture

感谢您的帮助!

5 个答案:

答案 0 :(得分:2)

我怀疑除了最简单的情况之外,这对所有人来说都是不可能的。使用regexp,您无法解析递归结构,语言(如VB)将具有递归功能。有关详细信息,请参阅this CodingHorror blog entry

除非你的案例非常简单,否则我认为某种形式的解析器将成为前进的方向。

答案 1 :(得分:2)

为什么要解析此代码?如果您正在尝试创建自己的编译器,那么您需要的不仅仅是正则表达式。如果你正在编写一个语法高亮和预先输入完成的编辑器,正则表达式可以在第一个,但不是第二个上做得很好。

那就是说,我对你的正则表达式看到的最大问题是你没有正确处理续行。这个:\s+_?匹配一个或多个空格字符,可选地后跟下划线。但如果有一个下划线,则应该跟一个你不匹配的换行符。这很容易补救 - \s+(_\s+)? - 但我不确定你是否需要那样具体。我怀疑这一点:[\s_]+也会这样做。

至于避免在注释和字符串中明显的子/函数声明,最简单的方法是仅在左边距处匹配它们,可能还有一些标签或空格用于缩进。我知道,这是作弊,但无论你做什么,它都可能足够好。当我为EditPad Pro编写Java file navigation scheme时,我非常依赖这个技巧。如果不使用大量的噱头和简化假设,你就不能用正则表达式来做这种事情。试试这个正则表达式:

^(?>('(?<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))

当然你需要先重组它。它应该使用MultilineIgnoreCaseExplicitCapture选项进行编译,但不能使用Singleline进行编译。

答案 2 :(得分:1)

你知道,最终会出现正则表达式还不够的时候。解析这个级别就是其中之一。

考虑编写一个简单的真实解析器,可能使用递归下降。

答案 3 :(得分:1)

不要试图写一个正则表达式为你做这个(它本身不能)。你需要的是一个解析器。可能最简单的解决方案是使用recursive descent parser。我不使用C#,但快速搜索出现了Spart

答案 4 :(得分:0)

鉴于Visual Basic的复杂性和内在性,您可能需要使用tokenizer / parser解析代码。您不能依赖正则表达式所有;)

对于它的价值,VB formal grammar is available here。玩得开心!