2014-12-15 15 views
12

Tôi có này [nasty] regex để chụp một chữ ký thủ tục VBA với tất cả các bộ phận trong một cái xô:Phân tích chữ ký với regex, có "vui vẻ" với lợi nhuận mảng giá trị

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

Một phần của nó là quá mức cần thiết và sẽ khớp với các cú pháp mảng bất hợp pháp (trong ngữ cảnh chữ ký của thủ tục), nhưng đó không phải là mối quan tâm của tôi ngay bây giờ.

Vấn đề là phần này:

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

phá vỡ khi một chức năng (hoặc getter tài sản) trả về một mảng, bởi vì khi đó chữ ký sẽ giống như thế này:

Public Function GetSomeArray() As Variant() 

Hoặc như này:

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

Và điều đó làm trả về của hàm gõ hoàn toàn borked, vì nhóm parameters chụp sẽ nhặt này:

ByVal foo As Integer) As Variant(

tôi biết lý do tại sao nó đang xảy ra - vì regex của tôi là giả định nẹp đóng cửa cuối cùng là một phân chia ranh giới các nhóm parameters chụp.

Có cách nào sửa chữa regex của tôi để thay đổi điều đó, mà không ảnh hưởng đến hiệu suất quá nhiều không?

Việc nắm bắt được rằng đây là một chữ ký hợp lệ:

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

Tôi có một regex riêng biệt để xử lý các thông số cá nhân, và nó sẽ làm việc tuyệt vời ... nếu cái này không bị lẫn lộn với các kiểu trả về mảng.

Đây là những gì tôi nhận được:

enter image description here

gì tôi cần, là một nhóm parameters mà không bao gồm phần ) As Variant(, giống như nó khi kiểu trả về không phải là một mảng :

enter image description here

+0

Sản lượng mong đợi của bạn là gì? Các nhóm sẽ trông như thế nào? –

+0

@AvinashRaj đã chỉnh sửa; xin vui lòng cho tôi biết nếu bạn cần thêm chi tiết;) –

+0

bạn có thể kiểm tra https://regex101.com/r/dM9pG7/1 này không? –

Trả lời

18

Ở đây bạn đi ....

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

Thay đổi được thực hiện trong regex gốc của bạn là gì?

Tôi vừa thay đổi điều này \((?<parameters>.*)?\) một phần trong bản gốc của bạn thành \((?<parameters>(?:\(\)|[^()])*)?\). Tức là, .* trong mẫu của bạn sẽ thực hiện một kết quả tham lam tối đa biểu tượng ) cuối cùng, nhưng (?:\(\)|[^()])* khớp với () một phần hoặc bất kỳ ký tự nào không phải là ( hoặc ) không hoặc nhiều lần. điều này khớp với các chuỗi như foo hoặc foo()bar ..

+3

Cảm ơn một triệu, câu trả lời của bạn chỉ [đóng một vấn đề trên GitHub] (https://github.com/retailcoder/Rubberduck/issues/117);) –

+0

@retailcoder sử dụng https://regex101.com/r/dM9pG7 này/2 nếu cần thiết. Bạn luôn được chào đón :) –

+0

@retailcoder, chúng tôi cần thêm một lời cảm ơn đặc biệt khác. =;) - – RubberDuck

Các vấn đề liên quan