Подтвердить что ты не робот

Разбор подписей с регулярным выражением, имеющий "забаву" с возвращаемыми значениями массива

У меня есть это [противное] регулярное выражение для захвата сигнатуры процедуры 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()

И это делает тип возвращаемой функции полностью запутанным, потому что группа захвата parameters получит это:

ByVal foo As Integer) As Variant(

Я знаю, почему это происходит - потому что мое регулярное выражение принимает последнюю закрывающую фигуру, которая ограничивает группу захвата parameters.

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

Ловушка заключается в том, что это допустимая подпись:

Public Function DoSomething(foo As Integer, ParamArray bar()) As Variant()

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

Это то, что я получаю:

enter image description here

Что мне нужно, это группа parameters, которая не включает в себя часть ) As Variant(, например, когда тип возвращаемого значения не является массивом:

enter image description here

4b9b3361

Ответ 1

Здесь вы идете....

(?:(?<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?)+)\))?)?

DEMO

Каковы изменения, внесенные в исходное регулярное выражение?

Я просто изменил эту часть \((?<parameters>.*)?\) в исходном регулярном выражении на \((?<parameters>(?:\(\)|[^()])*)?\). То есть .* в вашем шаблоне сделает жадное соответствие до последнего символа ), но этот (?:\(\)|[^()])* соответствует части () или любому символу не ( или ) ноль или более раз. так что это соответствует строкам типа foo или foo()bar..