2014-12-15 22 views
12

ho questa regex [brutta] per catturare un VBA firma procedura con tutte le parti in un secchio:Analisi firme con regex, avendo "divertimento" con ritorno a valori di allineamento

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?)+)\))?)?"; 
     } 
    } 

Parte di esso è eccessivo e corrisponderà alle sintassi di array illegali (nel contesto della firma di una procedura), ma non è la mia preoccupazione al momento.

Il problema è che questa parte:

\((?<parameters>.*)?\) 

rompe quando una funzione (o getter proprietà) restituisce un array, perché poi la firma sarà simile a questo:

Public Function GetSomeArray() As Variant() 

O come this:

Public Function GetSomeArray(ByVal foo As Integer) As Variant() 

E che rende il tipo di ritorno della funzione completamente bloccato, perché il gruppo parameters acquisizione riprenderà questo:

ByVal foo As Integer) As Variant(

so perché sta accadendo - perché il mio regex sta assumendo la parentesi dell'ultima chiusura è quella che delimita il gruppo parameters cattura.

C'è un modo per correggere la mia espressione regolare per cambiarlo, senza influire troppo sulle prestazioni?

Il problema è che si tratta di una firma valida:

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

ho un altro regex separato per gestire i singoli parametri, e sarebbe grande lavoro ... se questa non ha ottenuto confuso con tipi di ritorno dell'array.

Questo è quello che sto ottenendo:

enter image description here

cosa ho bisogno, è un gruppo parameters che non include la parte ) As Variant(, come fa quando il tipo di ritorno non è un array :

enter image description here

+0

Qual è il tuo output previsto? Come sarebbero i gruppi? –

+0

@AvinashRaj modificato; per favore fatemi sapere se avete bisogno di ulteriori dettagli;) –

+0

potete controllare questo https://regex101.com/r/dM9pG7/1? –

risposta

18

Qui si va ....

(?:(?<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

Quali sono le modifiche apportate nella regex originale?

Ho appena cambiato questa parte \((?<parameters>.*)?\) nella regex originale a \((?<parameters>(?:\(\)|[^()])*)?\). Cioè, .* nel tuo modello farà una partita avido fino all'ultimo simbolo ), ma questo (?:\(\)|[^()])* corrisponde a parte o qualsiasi carattere non di ( o ) zero o più volte. quindi questo corrisponde alle stringhe come foo o foo()bar ..

+3

Grazie mille, la tua risposta ha appena [chiuso un problema su GitHub] (https://github.com/retailcoder/Rubberduck/issues/117);) –

+0

@retailcoder usa questo https://regex101.com/r/dM9pG7/2 se necessario. Sei sempre il benvenuto :) –

+0

@retailcoder abbiamo bisogno di aggiungere un altro ringraziamento speciale. =;) - – RubberDuck