Irgendwie habe ich das Gefühl, dass die Problemstellung nicht ganz
rübergekommen ist.
Um mal ganz grundlegend und ausholend zu erläutern:
Es handelt sich um ein Parsermodul (genannt "parser"), welcher ein
Textabschnitt analysiert und ein Strukturabbild macht. Er selbst
führt keine Befehle aus, sondern kennt nur generische "Arten" von
Tags. Diese Arten sind nicht durch ihre konkreten Namen oder
inhalte definiert, sondern abstrakt und rekursiv!
Zur Interpretation nimmt er ein Modul (genannt "interpreter")
bei welchem er sich laufend während des parsens meldet und anfragt,
ob diese generischen tags existieren. der interpreter verarbeitet
und liefert die antworten dem parser zurück, der parser wiederum
entfernt die ursprünglichen tags und ersetzt diese durch die vom
Interpreter neu errechneten. Speziell ist, dass es tags geben kann,
welche rekursionen enthalten - also das durch den interpreter
interpretierte und eingesetzte nochmals geparst wird. Bei jedem
Ersetzen eines tags durch den interpreter wird die ersetzungsart
definiert.
Der Parser also weiss nichts über den genauen Laut der Tags,
kennt nur deren Struktur und weiss auch nicht wieviele Optionen
es sind. Er baut anhand der Struktur von jedem Tag ein Options-
Array auf und liefert dieses dem Interpreter, der mit diesem
Array Entscheidungen treffen kann.
Ein Tag kann bsp. so aussehen:
// Einfaches Tag (SingleTag)
ich werde italic // Standard Tag (Zwangsabschluss)
Jedes Tag kann also weiter nach dem Namen einen Abstand haben
und dahinter BELIEBIG viele Optionen! Jede Option kann wiederum
vom Typ "SET" sein, also nur ein Optionsname, kann aber auch ein
Wert zugewiesen haben! Der zugewiesene Wert kann dabei
entweder gequotet werden, oder aber auch nicht. Das Quoting ist
dabei eindeutig, das heisst In-Quoting muss geescaped werden!
[absatz fett] // Könnte ein Absatz sein, mit Attribut fett gesetzt
[absatz schrift=Arial] // Könnte ein Absatz sein, beidem eine Option
namens Schrift mit den Attribut Arial gesetzt wurde
[absatz schrift="Arial"] // Wie oben, nur gequotet!
Natürlich kann aus Sicht des Parsers (Da er ja kein TAG kennt)
jedes Tag beliebig viele Optionen haben!
[absatz fett kursiv schrift="Arial" size=7]
Müsste also korrekt analysiert werden.
Der Parser nun kann das schon alles seit ewigkeiten, der Interpreter
auch (Saubere Klassenimplementationen, wobei man je nach Anwendung
einfach durch Ableiten des generischen Interpreters ein angepassten
Wortschatz (Tag-Library) machen kann.
Das Problem liegt darin, dass wenn beim oberen Beispiel der text:
[absatz fett kursiv schrift="Arial" size=7]
erkannt wurde, die Variable "options" folgenden Inhalt hat:
$options=' fett kursiv schrift="Arial" size=7'
Dies kann effizienter mit einem regulären Ausdruck zerlegt werden,
als mit einem handgeschriebenen Parser in PHP, da regexp einfach
schneller ist (Implementation der core auf tieferer ebene).
Es handelt sich dabei um einen ausdruck, welcher rekursiv auf
diesen obigen $options-string angewendet wird! Dabei muss allerdings
das Problem Optionales Quoting, als auch In-Quote-Quoting (ge-
escaped) via regexp korrekt gehandlet werden!
'schrift="The ""Ultrafont"""'
Dabei heisst die Schrift selber 'The "Ultrafont"'
Der einheitliche Ausdruck muss also:
- Rekursiv anwendbar sein
- SET-Options matchen
- Einfache Optionen matchen (unquoted)
- Gequotete Optionen matchen, und geescapte Quotes überlesen
Pro Option gilt es, einen Match rekursiv auszuführen und dieselben
nicht nachträglich zusammenzusetzen!
Ohne Lookahead und Lookbehind Assertions keine chance, und wenn
ich deine Reg-Ausdrücke ansehe, scheinst du nicht zu wissen von
was ich rede .. Ein hochinteressantes Thema mit welchem man
sich ein Leben lang auseinandersetzen kann!!
Die jetzige Lösung (Siehe mein erstes Posting) kann das auch alles,
erlaubt einfach keine In-Quote-Quotes. Mit anderen Worten, es ist
nicht möglich ein Optionsinhalt zu definieren, welcher das Zeichen
' enthält, da er immer gleich das Ende des Optionsinhalts annimmt.
"#^( *)([a-zA-Z0-9]*)(=[\']{0,1}(.*?)[\']{0,1})? +(.*)#s"
entspricht dabei der definition dieses Matchings!
Da lass ich mich einmal mehr überraschen auf die Antwort ;)
GrEeZ: Miro Dietiker
als Antwort auf: [#52064]