Funktionsname inkl. Parameter mit RegEx filtern

  • Hallo liebe Leute,

    ich reiße mir nun schon seit Stunden ein Bein aus, bekomme es aber nicht hin, einen Funktionsname inkl. Parameter mit RegEx so zu filtern, dass es in allen Fällen passt.

    Hier das Ergebnis meiner bisherigen Versuche...

    Das Ergebnis sollte aber so aussehen...

  • Ich glaub nicht, dass du das in jedem Fall mit Regex alleine hinbekommst weil du Nesting (von selben Zeichen bzw. von der selben Gruppe) hast.

    Das selbe Problem hatte ich, als ich mir einen XML-Parser geschrieben hatte. Sobald gleiche Strukturen ineinander liegen kannst du sie mit Regex, nach meinem derzeitigen Wissensstand, nicht erkennen.

    Bei meinem Problem hatte ich Regex dort genutzt wo kein Nesting auftrat, und dort wo es Probleme machte, habe ich einen eigenen Parser geschrieben.

    Dieser hatte immer Kenntnis darüber wie viele Tags (welche nesten) auf und zu gingen (bin Tag für Tag durch den Code gegangen mit StringInStr, etc...) um den richtigen Bereich zu parsen.

    Ich schätze mal du brauchst sowas auch.

    Setzt du allerdings als kein Nesting als Prämisse voraus solltest du ein Pattern hinbekommen.

    Dein Pattern ist schon mal nicht schlecht aber du hast ein paar Sachen übersehen.

    Das (?:\R+)? am Ende steht in der Klammer drin, aber das willst du ja nicht catchen, also musst du es hinter die letzte Klammer schieben, du kannst es sowieso durch ein \R* ersetzen (Erklärung weiter unten).

    Deine Klammer-auf am Anfang ist falsch, du escapest Klammer-zu, du hast wohl das falsche Zeichen genommen. Also statt \) \( nehmen (beim Func\s(.*\)).

    Außerdem hast du vieles ziemlich umständlich beschrieben, z.B. das don't-catch possible existing whitespace mit (?:\s+)?.

    Nimm doch direkt \s* das matcht 0...unendlich und catcht nicht.

    Ohne Nesting kann man dein Pattern bisschen anpassen und es funktioniert.

    Das ist bestimmt ziemlich scheusslich, aber zu so später Stund krieg ichs nicht besser hin.

  • Mit ein bisschen RegEx-Magie kann man auch das Nesting abbilden. ;)

    Ich habe mal alpines' Pattern als Basis genommen. Würde allerdings statt \s definitiv \h bevorzugen. Vertikale Whitespaces sind an diesen Stellen nämlich nicht zulässig.

    Pattern:

    Code
    ^Func\h*(\w+\h*(\(((?:[^()]*)|(?2))*\)))\h*(;.*)?\h*\R*$

    Ergebnis:

    Aber ganz unrecht hat alpines trotzdem nicht. An gewissen Stellen geht auch das "kaputt". Man füge mal zu dem Test-Skript folgendes hinzu: _Strip(10, 'Func _SciTE_ShowFuncName("Das hier ist böse. ;)")')...

    Das könnte man eventuell mit einer Art Doppel-Rekursion lösen (außen Klammern, innen Anführungszeichen). Wobei bei den Anführungszeichen dann wieder eine Backreference nötig wäre, um " und ' gerecht zu werden. Da wäre es fast einfacher, vorher alle Strings rauszuparsen.

  • Schönes Pattern :thumbup:, hätte nicht gedacht, dass man das damit hinbekommt, aber meine Regex-Künste sind da auch sehr bescheiden.

    Sobald man unausgeglichene Klammern hat kommts leider ins Stolpern, möchte man einen 100% sicheren Parser haben dann führt glaube ich der Weg an einem nicht-regex Parser nicht vorbei.

    Dass \s auch vertikale matcht hatte ich ehrlich gesagt nie auf dem Schirm, da ich immer (wenn ich einen Zeilenumbruch hatte) automatisch \R gesetzt habe.

    Gut zu wissen, dass es auch \h gibt, dann werde ich das von nun an auch verwenden.

  • Da wäre es fast einfacher, vorher alle Strings rauszuparsen.

    Diese Vermutung drängt sich mir auch auf !

    Andy hat es vor kurzem in einem Beitrag treffend ausgedrückt :

    Regex "Multipattern" möglich?

    Zitat

    Ich zumindest nutze RegExe dann, wenn der Aufwand, ein String"problem" abzuwickeln, mit den Standard-Stringfunktionen deutlich aufwendiger abzuwickeln wäre, bzw. es per Regex deutlich einfacher (auch zu debuggen) ist.

    Wobei ich persönlich auch keine Skrupel habe, unterschiedlichste RegEx- und Stringfunktionen so zu mischen, dass es passt. Nirgendwo steht geschrieben, dass RegExe Einzeiler sein müssen, obwohl viele "Profis" das so verstehen (wollen).

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Die Flinte nicht so schnell ins Korn werfen. RegEx kann ziemlich viel. :D

    Das Pattern ist jetzt zwar etwas ausgeartet, aber es funktioniert einwandfrei. Zumindest habe ich nichts gefunden, was falsch gematcht wird.

    Code
    ^Func\h*(\w+\h*(\(((('|")((((?!\5).)*)|(?4))*\5)|([^()]*)|(?2))*\)))\h*(;.*)?\h*\R*$

    Das ist dann jetzt wie angekündigt eine doppelte Rekursion mit Backreference Match.

    Sogar das hier wird korrekt gematcht:

    Code
    _Strip(11, "Func _SciTE_ShowFuncName('Das hier ist ""böse"". ;)')")
  • Das Pattern ist korrekt. Ich nutze zur "Entwicklung" von regulären Ausdrücken fast immer regex101.com. Da muss nichts escaped werden. Für die Verwendung mit AutoIt muss dann entweder das Apostroph oder die Gänsefüßchen maskiert werden, bspw. so:

    Code
    ^Func\h*(\w+\h*(\((((''|")((((?!\5).)*)|(?4))*\5)|([^()]*)|(?2))*\)))\h*(;.*)?\h*\R*$

    Hatte ich jetzt gerade beim Posten nicht drüber nachgedacht. ^^

  • Das Pattern ist korrekt. Ich nutze zur "Entwicklung" von regulären Ausdrücken fast immer regex101.com.

    Sehr zu empfelen, nutze ich nämlich auch ;)

    Es lies mir gestern Abend schlicht keine Ruhe und ich habe mit allen Mitteln und Wegen versucht dein Pattern kaputtzukriegen und habs letzendlich auch geschafft.

    Und ja, es handelt sich um eine gültige Funktionsdeklaration!!! :rofl:

    Einfach auf mehrere Zeilen unterteilen und Kommentare reinhauen die das Nesting kaputtmachen :)

    Beim 1. Beispiel crasht dein Pattern (wenn man hinter der letzten Kommentarklammer noch etwas hinzufügt), und beim 2. gibt er den Kommentar am Ende mit aus.

    Du kannst die Funktionen auch gerne testen, sie funktionieren einwandfrei wenn man sie normal callt.

    Edit: Es geht auch einfacher, einfach Klammern unbalancen (Beispiel 3).

    Edit2: Und noch einfacher gehts (dazu werde ich jetzt kein Beispiel posten), wenn ich einfach ein Leerzeichen vor dem Func setze, aber das ist sehr einfach fixbar.

    1. Beispiel
    Code
    Func Bla( $a, _ ; " (
     $b) ; blubb) a
    
    
    EndFunc
    2. Beispiel
    Code
    Func Bla( $a, _ ; " (
     $b) ; blubb)
    
    
    EndFunc
    3. Beispiel
  • Inspiriert durch das SciTE_Interface von BugFix , dass ich um einige Funktionen erweitert und auch an vielen Stellen geändert habe, bin ich auf die Idee gekommen, mir ein Tool zu schreiben, dass mir in allen Scite-Instanzen den Funktionsnamen (mit oder ohne Parameter) in der SciTE-Toolbar anzeigt, wenn sich das Caret in einer Func/EndFunc-Zeile oder dazwischen befindet, denn mich hat es schon immer sehr genervt, dass ich bei sehr langen Funktionen nirgends sehen konnte, in welcher Funktion ich mich gerade befinde und welche Parameter sie hat.

    In der erstes Version habe ich es mit einem Label (Alpha, einfach zu händeln, aber der Text ist nur einfarbig) gemacht, in der zweiten mit RichEdit (Beta), wo jedes Zeichen eine beliebige Farbe und auch Schriftart/-stil haben kann, die aber schwerer zu händlen ist. Ich habe euch beide Versionen (mit dem RexEx-Pattern von chesstiger , dass schon sehr gut funktioniert) inkl. nötiger Includes in den Anhang gelegt, damit ihr euch ein Bild davon machen könnt.

    Da ich in der SciTE-Toolbar nur den Funktionsnamen inkl. Parameter sehen will, brauche ich ein RegEx-Pattern, dass mir den nachfolgenden Teil ausfiltert, der nicht mehr zur Funktion gehört.

    Nimm doch direkt \s* das matcht 0...unendlich und catcht nicht.

    Ja, hatte ich in meiner ersten Version auch so gemacht... jetzt würde ich natürlich \h* nehmen... aber du kennst das sicher auch, wenn du dich stundenlang im Kreis drehst, siehst du nachher den Wald vor lauter Bäumen nicht...

    Oha, sieht ja echt mega aus... aber wärst du bitte so lieb und würdest mir das nach AutoIt portieren... bekomme es einfach nicht hin, dass es dann auch funktioniert. 8|

    • Offizieller Beitrag

    Ich finde es auch nicht verwerflich mit einer Kombination von RegEx und Stringfunktionen zu arbeiten. Ich hatte zu diesem Thema mal diese Funktion erstellt: