[REGEX] rekursive tags

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [REGEX] rekursive tags

    Ich bin gerade dabei ein eigenes template system zu schreiben und komme nicht weiter bei den regex.
    Für die Variablen benutze ich eine eigene Syntax, die es erlaubt andere Variablen in der aufgerufenen Variablen aufzurufen, beliebig oft und beliebig verschachtelt. So sieht es aus:

    Normaler Aufruf: {keyname}
    Die vorher definierte Variable "keyname" wird aufgerufen.

    Bedingter Aufruf: {if.keyname:abc|xyz}
    Nur wen "keyname" definiert wurde wird "abc" ausgegeben, andernfalls "xyz".

    Rekursiver Aufruf: {if.keyname: {key2}|{if.key3:xyz}}
    Wenn "keyname defniert wurde, dann die Variable "key2" aufrufen, andernfalls, wenn "key3" definiert wurde, "xyz" ausgeben.

    usw.

    Wie kriege ich eine brauchbare Rekursion hin?
    (Ich will nicht das regex für diese Syntax, da es nur ein kleines Beispiel war. Ich will nur wissen, wie ich generell Verschachtelungen mit regex hinbekommen kann.)
    arrays sind klasse

  • #2
    http://www.php.net/manual/en/referen...ern.syntax.php Abschnitt Recursive patterns.
    Die rekursiven RegEx decken aber nur eine Teilmenge der Sprache ab, die man mit echter, handgeklöppelter Rekursion erschlagen kann.

    Kommentar


    • #3
      Schwer! Wahrscheinlich ist eine richtige Rekursion gar nicht notwendig. Es muss nur richtig erkannt werden. Den Rest mache ich dann mit einer rekursiv aufgreufenen Funktion.

      Das ist möglich:
      ...{if.a: {if.b: {if.c: {if.d: ausgabe1}}}}...{if.a: {if.b: {if.c: {if.d: ausgabe2}}}}...

      Ich möchte, dass diese beiden tags komplett erkannt werden. Mein Problem ist aber, dass er entweder nach dem ersten } bereits abbricht, oder aber bis zum letzten } geht und damit beide tags zusammenliest.
      Wie kann ich da vorgehen?
      arrays sind klasse

      Kommentar


      • #4
        Verwende doch einen rekursiven Pattern (Pseudocode):
        Code:
        \{(if\.)?[a-z_](\:(.*?|(?R))?(\|(.*?|(?R)))?\}
        Die Regeln | rtfm | register_globals | strings | SQL-Injections | [COLOR=silver][[/COLOR][COLOR=royalblue]–[/COLOR][COLOR=silver]][/COLOR]

        Kommentar


        • #5
          Ich reduziere mal den code auf das eigentliche Problem:

          {{{{{}}}}}

          Wie schaffe ich, dass er nicht bereits nach dem ersten } abbricht?

          {{{}}} {{{}}}

          Wie schaffe ich es darüberhinaus, dass er nicht beide tags als einen erkennt?

          Und das geht auch noch:

          {{a}{b}}

          Weil zwischen den syntax immanenten symbolen { und } auch noch eine beliebige Zeichenkette stehen kann, wird es umso schwieriger:

          anfangstext{a{b{ccc}d}e}mitteltext{{y{xxx1}{xxx2}}z}endtext

          Das sollte hierbei das Ergebnis sein, wenn ich den template-string mit preg_split auslese:

          0 => 'anfangstext'
          1 => '{a{b{ccc}d}e}'
          2 => 'mitteltext'
          3 => '{{y{xxx1}{xxx2}}z}'
          4 => 'endtext'

          Zuletzt geändert von Maranello-550; 08.10.2007, 17:03.
          arrays sind klasse

          Kommentar


          • #6
            In dem du gierig nach der nächsten Klammer suchst, eine öffnende Klammer aber verbietest.
            Code:
            [^\{a-z]*\}
            (Was rekursives wäre natürlich trotzdem sinnvoll.)
            Die Regeln | rtfm | register_globals | strings | SQL-Injections | [COLOR=silver][[/COLOR][COLOR=royalblue]–[/COLOR][COLOR=silver]][/COLOR]

            Kommentar


            • #7
              Dann ließt er doch nur bis zu ersten schließenden Klammer.
              arrays sind klasse

              Kommentar


              • #8
                Dann ließt er doch nur bis zu ersten schließenden Klammer.
                Eigentlich nicht.
                Die Regeln | rtfm | register_globals | strings | SQL-Injections | [COLOR=silver][[/COLOR][COLOR=royalblue]–[/COLOR][COLOR=silver]][/COLOR]

                Kommentar


                • #9
                  Habe ein wenig mehr rumprobiert und dabei bin ich auf diese Lösung gestoßen:

                  #({(?:[^{}]+|(?R))*})#

                  Noch ein wenig anpassen und es sollte auch auf die Syntax matchen

                  Danke für eure Hilfe.
                  arrays sind klasse

                  Kommentar


                  • #10
                    (Nicht das onemorenerd von Anfang an schon von Rekursion gesprochen hat.)
                    Die Regeln | rtfm | register_globals | strings | SQL-Injections | [COLOR=silver][[/COLOR][COLOR=royalblue]–[/COLOR][COLOR=silver]][/COLOR]

                    Kommentar


                    • #11
                      Ich habs mit und ohne versucht. Letzteres hat dann funktioniert
                      arrays sind klasse

                      Kommentar

                      Lädt...
                      X