我有这个[讨厌的]正则表达式来捕获包含桶中所有部分的VBA过程签名:
public static string ProcedureSyntax
{
get
{
return
@"(?:(?<accessibility>Friend|Private|Public)\s)?(?:(?<kind>Sub|Function|Property\s(Get|Let|Set)))\s(?<identifier>(?:[a-zA-Z][a-zA-Z0-9_]*)|(?:\[[a-zA-Z0-9_]*\]))\((?<parameters>.*)?\)(?:\sAs\s(?<reference>(((?<library>[a-zA-Z][a-zA-Z0-9_]*))\.)?(?<identifier>([a-zA-Z][a-zA-Z0-9_]*)|\[[a-zA-Z0-9_]*\]))(?<array>\((?<size>(([0-9]+)\,?\s?)*|([0-9]+\sTo\s[0-9]+\,?\s?)+)\))?)?";
}
}
部分内容是过度杀戮,并且会匹配非法数组语法(在程序签名的上下文中),但这不是我现在关注的问题。
问题在于这一部分:
\((?<parameters>.*)?\)
当函数(或属性getter)返回一个数组时,会中断,因为签名看起来像这样:
Public Function GetSomeArray() As Variant()
或者像这样:
Public Function GetSomeArray(ByVal foo As Integer) As Variant()
这使得函数的返回类型完全变为borked,因为parameters
捕获组将会接受这个:
ByVal foo As Integer) As Variant(
我知道为什么它正在发生 - 因为我的正则表达式假设最后一个大括号是划分parameters
捕获组的那个。< / p>
有没有办法修复我的正则表达式来改变它,而不会影响性能太多?
问题在于这是一个有效的签名:
Public Function DoSomething(foo As Integer, ParamArray bar()) As Variant()
我有另一个单独的正则表达式来处理单个参数,它会很好用......如果这个没有与数组返回类型混淆。
这就是我得到的:
我需要的是一个parameters
组,它不包含) As Variant(
部分,就像返回类型不是数组时一样:
答案 0 :(得分:18)
你走了......
(?:(?<accessibility>Friend|Private|Public)\s)?(?:(?<kind>Sub|Function|Property\s(Get|Let|Set)))\s(?<identifier>(?:[a-zA-Z][a-zA-Z0-9_]*)|(?:\[[a-zA-Z0-9_]*\]))\((?<parameters>(?:\(\)|[^()])*)?\)(?:\sAs\s(?<reference>(((?<library>[a-zA-Z][a-zA-Z0-9_]*))\.)?(?<identifier1>([a-zA-Z][a-zA-Z0-9_]*)|\[[a-zA-Z0-9_]*\]))(?<array>\((?<size>(([0-9]+)\,?\s?)*|([0-9]+\sTo\s[0-9]+\,?\s?)+)\))?)?
您的原始正则表达式有哪些更改?
我刚刚将原始正则表达式中的\((?<parameters>.*)?\)
部分更改为\((?<parameters>(?:\(\)|[^()])*)?\)
。也就是说,您的模式中的.*
将与最后一个)
符号进行贪婪匹配,但此(?:\(\)|[^()])*
匹配()
部分或任何不属于(
的字符或)
零次或多次。所以这匹配foo
或foo()bar
..