Hallo,
ich habe gerade begonnen mich mit Java-Script zu beschäftigen. Dazu habe
ich versucht eine einfache Syntax-Highlighting Funktion für eine HTML zu
schreiben. Jetzt habe ich in meinem Script ein Problem mit der
Formatierung von Kommentaren festgestellt (siehe Beispiel).
Wenn ich Schlüsselwörter in den Kommentartexten verwende werden diese
auch als Schlüsselwörter formatiert. Ich hätte allerdings gerne wenn
diese in den Kommentaren ignoriert würden.
Die Schlüsselwörter habe ich mit folgender Anweisung formatiert:
Ich müsste jetzt entweder das Wort 'return' innerhalb des Kommentars
ignorieren oder erkennen, dass das Wort 'return' innerhalb eines
Kommentars steht. Kann das irgendwie direkt mit RegEx gelöst werden?
Gruß
Michael
Genau sowas ist das grundsätzliche Problem, wenn man Sprachen mit
Regular-Expressions parsed.
Ich sage nicht, dass es nicht geht. Man kommt recht weit, wenn man
anfängt, solche Ausnahmeregeln einzubauen. Direkt in der Regex würde ich
eher nicht versuchen, die werden irgendwann bis zur Unleserlichkeit
kompliziert.
Der theoretisch "richtigere" Weg wäre ein Parser mit einer
HTML-Grammatik. Der könnte dir dann sagen, das ist ein Kommentar, das
ein Schlüsselwort etc.
Theoretisch sage ich absichtlich: richtig ist er, weil man damit das
Problem vollständig erschlagen kann. ABER so ein Parser fügt deinem Code
auch einen ordentlichen Sockel an Komplexität hinzu.
Es ist gut möglich, dass die Regex-Lösung (+ einige Ausnahmeregeln) für
dich reicht.
Tilo R. schrieb:> Ich sage nicht, dass es nicht geht.
Nein, es ist unmöglich, kontextfreie Sprachen (das sind die meisten
Programmiersprachen inkl. JS oder HTML) mit regulären Ausdrücken zu
parsen. Wenn du eine RegEx-Bibliothek hast die das kann, ist das kein
echter regulärer Ausdruck mehr. Beweis: Reguläre Ausdrücke können mit
endlichen Automaten implementiert werden, welche nur endlich viel
Speicher haben, mit welchem sich nicht abspeichern lässt, wie viele
öffnende Klammern bisher gekommen sind (kontextfreie Sprachen erlauben
konzeptuell beliebig viele), was man aber können muss, um die
schließenden Klammern korrekt zu zählen.
Zum "richtigen" Parsen braucht es die Grammatik, einen Tokenizer und
einen Parser für kontextfreie Grammatiken, z.B. einen
nichtdeterministischen Kellerautomaten. Das ist alles nicht ganz
trivial, lernt man im Informatik Studium. Für die Einarbeitung in die
Programmierung ist das etwas zu viel.
Prüf doch einfach als erstes auf Kommentar und ignoriere das dann eben.
Also mach nach deinen Kommentar regex einfach ein return und ignoriere
die Zeilen?
Ich nutze gern und viel PCRE ( grep -P ... ), weiss nun nicht was
JS-RegEs alles umfasst...
Ein Bastelversuch könnte darin bestehen, alles zwischen "/*" und "*/" zu
ignorieren.
Wehe aber wenn auch nur eine dieser 2 Sequenzen in einem Stringliteral
auftaucht...
Von mehrzeiligen Kommentare haben wir gar noch nicht gesprochen.
Ditto auch für Schlüsselwörter in Stringliterale.
Die von Thilo und Programmierer eingebrachten Äusserungen treffen auf
jeden Fall zu.
Die "Bemalung" von vorhandenem Code soll ja nur auf tatsächlichem Code
angewendet werden.
Also könnte ein mehrstufiges Vorgehen darin bestehen, erstmal allen
Nicht-Code zu identifizieren (Kommentar, Stringliterale, ...??) und wie
auch immer auszublenden, bevor die "Codebemalung" ran darf.
Die Nicht-Code Teile gehören danach aber wieder an ihre ursprünglichen
Stellein eingesetzt...
Hallo,
vielen Dank für die schnellen Antworten. Es ist wohl nicht der beste weg
dieses Problem über RegEx zu lösen. Ich werde mich damit noch ein
Weilchen beschäftigen und versuchen das Problem mit Java-Script zu
lösen. Ich will mich damit ja ohnehin etwas mehr beschäftigen.
Vielen Dank
Michael
@Programmierer:
wir stehen auf der selben Seite! Was du schreibst ist mir alles klar und
du hast meine Zustimmung.
Deswegen wollte ich dem TO sagen, wie es richtig geht.
Gleichzeitig wollte ich ihn aber nicht entmutigen, weil ich weiß, dass
man mit Regexes (+ Zusatzlogik) recht weit kommen kann.
Dazu ein lustiger Schwank aus meinem früheren Entwicklerdasein:
Ich war mal in einem Projekt, da musste im Wesentlichen HTML geparsed
werden, um dann ein paar Spezialelemente durch personalisierte Daten zu
ersetzen (Herr/Frau, Vorname, Nachname, vorbereitete Kontent-Blöcke).
Mein erster Vorschlag war, dafür eine Template-Engine zu nehmen. Das
wurde abgelehnt. Ich kam später in das Projekt "und sie hatten da schon
was", das sie auch weiter für die Personalisierung von E-Mails verwenden
wollten. Meine Aufgabe war es, etwas ähnliches fürs Web zu bauen (Idee:
personalisierte Landing Pages und Formulare).
Also habe ich mir den E-Mail-Code angeschaut und eine
Regex-Replace-Hölle mit Ausnahmeregeln gefunden.
Wenig begeistert schlug ich einen richtigen Parser mit Grammatik vor.
Beim E-Mail-Versand hätte das zusätzlich den Vorteil gehabt, dass man
den geparsten AST aufbewahren kann. Für jede neue personalisierte Mail
muss dann nur einmal der AST traversiert werden, anstelle bei jeder
neuen Mail ein halbes dutzend mal mit Regexes drüberlaufen zu müssen.
Das wurde auch abgelehnt, weil der Entwickler der Regex-Lösung eine Art
Guru-Status hatte. Aber immerhin verstand ich langsam, warum man eine
fast dreistellige Anzahl an Servern für den Mailversand brauchte...
Nach langem Hin und Her durfte ich es wenigstens in meinem Teil richtig
machen. Als Parser habe ich ANTLR ausgewählt und ich weiß daher aus
Erfahrung, dass das etliche Tage dauern kann, wenn man es das erste mal
macht. Selbst wenn man ein anständiger Programmierer ist und die Worte
Grammatik und kontextfrei schon mal gehört hat.
Im Ergebnis haben beide Lösungen funktioniert.
Änderungen an meinem Code, z.B. ein neues Element hinzufügen, musste ich
allerdings selber machen, weil der Code "so kompliziert" war.
Aber eigentlich war es einfach: 1. Grammatik anpassen, so dass für das
neue Knotenelement eine neue Klasse instantiiert wird. 2. Neue
Knotenklasse mit zusätzlicher Funktionalität schreiben.
Auf der anderen Seite war das schwieriger. Die ganze Parserei war in
einem File, das mit jedem neuen Element größer wurde. Und dann gab es
darin einen (für mich unverständlichen) Wust an Bedingungen und
Sonderregeln, die bei jedem neuen Element teilweise angepasst oder
repliziert werden mussten.
Und dann gab es immer wieder unerwartete Einschränkungen: z.B. waren
Anführungszeichen und spitze Klammern in einzeiligen Kommentaren
abgefangen, spitze Klammern in einem Attributwert dagegen nicht.
Aber letztlich konnte man damit trotzdem arbeiten. Sowas macht man dann
halt nicht, mit der Zeit lernt man die Eigenheiten des Systems kennen.
Und auch auf meiner Seite will ich nicht verschweigen, dass es bei
ungültigen (d.h. nicht der Grammatik entsprechenden) Eingabedaten gar
nicht so leicht ist, eine Fehlermeldung mit hilfreicher Angabe zur
Problemstelle zu geben.