使用正则表达式解析签名,使用数组返回值"有趣"

Mat*_*don 12 c# regex parsing signature

我有这个[讨厌的]正则表达式来捕获包含桶中所有部分的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?)+)\))?)?";
        }
    }
Run Code Online (Sandbox Code Playgroud)

部分内容是过度杀伤并且会匹配非法数组语法(在程序签名的上下文中),但这不是我现在关注的问题.

问题是这部分:

\((?<parameters>.*)?\)
Run Code Online (Sandbox Code Playgroud)

函数(或属性getter)返回数组时中断,因为签名看起来像这样:

Public Function GetSomeArray() As Variant()
Run Code Online (Sandbox Code Playgroud)

或者像这样:

Public Function GetSomeArray(ByVal foo As Integer) As Variant()
Run Code Online (Sandbox Code Playgroud)

这使得函数的返回类型完全变为borked,因为parameters捕获组将接收到:

ByVal foo As Integer) As Variant(
Run Code Online (Sandbox Code Playgroud)

我知道它为什么会发生 - 因为我的正则表达式假设最后一个结束括号是分隔parameters捕获组的那个.

有没有办法修复我的正则表达式来改变它,而不会影响性能太多?

问题是这是一个有效的签名:

Public Function DoSomething(foo As Integer, ParamArray bar()) As Variant()
Run Code Online (Sandbox Code Playgroud)

我有另一个单独的正则表达式来处理单个参数,它会工作得很好......如果这个没有与数组返回类型混淆.

这就是我得到的:

在此输入图像描述

我需要的是一个parameters不包含该) As Variant(部分的组,就像返回类型不是数组时一样:

在此输入图像描述

Avi*_*Raj 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?)+)\))?)?
Run Code Online (Sandbox Code Playgroud)

DEMO

原始正则表达式有哪些变化?

我只是将\((?<parameters>.*)?\)原始正则表达式中的这部分更改为\((?<parameters>(?:\(\)|[^()])*)?\).也就是说,.*在你的模式中,你会对最后一个)符号进行贪婪的匹配,但这会(?:\(\)|[^()])*匹配()部分或任何不符合()零次或多次的字符.所以这匹配字符串像foofoo()bar..

  • 万分感谢,你的回答只是[在GitHub上关闭了一个问题](https://github.com/retailcoder/Rubberduck/issues/117);) (3认同)