Ich habe einen BBCode -> HTML-Konverter, der auf das Änderungsereignis in einem Textfeld reagiert. Gegenwärtig geschieht dies mit einer Reihe von regulären Ausdrücken, und es gibt eine Reihe von pathologischen Fällen. Ich wollte schon immer den Stift auf dieser Grammatik schärfen, wollte mich aber nicht in Yak rasieren. Aber ... kürzlich wurde ich auf pegjs aufmerksam, was eine ziemlich vollständige Implementierung der PEG-Parser-Generation zu sein scheint. Ich habe den größten Teil der Grammatik angegeben, aber ich frage mich jetzt, ob das ein richtiger Parser ist.Verwenden von PEG Parser für BBCode Parsing: pegjs oder ... was?
Meine spezifische Fragen sind:
Da meine Anwendung beruht auf übersetzen, was ich kann den Rest als Rohtext in HTML und verlassen, wird die Umsetzung bbcode einen Parser verwenden, die auf einem Syntaxfehler Sinn machen kann fehlschlagen ? Zum Beispiel:
[url=/foo/bar]click me![/url]
würde sicherlich erwartet, um erfolgreich zu sein, sobald die schließende Klammer auf dem Schließen-Tag eingegeben wird. Was aber sieht der Nutzer in der Zwischenzeit? Mit Regex kann ich nicht übereinstimmende Dinge einfach ignorieren und sie als normalen Text für Vorschauzwecke behandeln. Mit einer formalen Grammatik weiß ich nicht, ob dies möglich ist, weil ich mich darauf verlasse, den HTML-Code aus einem Parse-Baum zu erstellen, und was bei einer Syntaxanalyse fehlschlägt, ist ... was?Ich bin unklar, wo die Transformationen durchgeführt werden sollten. In einem formalen Lex/Yacc-basierten Parser hätte ich Header-Dateien und Symbole, die den Knotentyp bezeichnen. In pegjs bekomme ich geschachtelte Arrays mit dem Knoten Text. Ich kann den übersetzten Code als eine Aktion des von pegjs erzeugten Parsers ausgeben, aber es scheint wie ein Code-Geruch, einen Parser und einen Emitter zu kombinieren. Allerdings, wenn ich rufe
PEG.parse.parse()
, bekomme ich so etwas wie dies zurück:
[
[
"[",
"img",
"",
[
"/",
"f",
"o",
"o",
"/",
"b",
"a",
"r"
],
"",
"]"
],
[
"[/",
"img",
"]"
]
]
gegeben eine Grammatik wie:
document
= (open_tag/close_tag/new_line/text)*
open_tag
= ("[" tag_name "="? tag_data? tag_attributes? "]")
close_tag
= ("[/" tag_name "]")
text
= non_tag+
non_tag
= [\n\[\]]
new_line
= ("\r\n"/"\n")
ich die Grammatik Abkürzen, natürlich, aber Sie bekomme eine Vorstellung. Also, wenn Sie bemerken, gibt es keine kontextuellen Informationen in dem Array von Arrays, die mir sagt, was für ein Knoten ich habe und ich bin noch die String-Vergleiche wieder selbst wenn der Parser dies bereits getan hat. Ich erwarte, dass es möglich ist, Callbacks zu definieren und Aktionen zu verwenden, um sie während einer Analyse auszuführen, aber im Web gibt es kaum Informationen darüber, wie man das machen könnte.
Banne ich den falschen Baum an? Sollte ich zum Regex-Scan zurückkehren und das Parsing vergessen?
Dank
Steve, Ihre Frage ist sehr interessant (+1), ich möchte nur das Gleiche in einer Erweiterung tun: BBCode in einem Textarea analysieren (leider ist das das Format, das ein Forum immer noch benutzt), und ein "live "Vorschau vom eingegebenen Text mit PEG.js oder etwas anderem als regulären Ausdrücken. Hast du es geschafft, die Grammatik für den BBCode-Parser zu erstellen? Kannst du deine Lösung nicht über GitHub oder etwas anderes teilen? Das würde mir sehr helfen. Vielen Dank im Voraus! – Sk8erPeter
Ich habe [BBCode-Parser von Patorjk verwendet] (https://github.com/patorjk/Extendible-BBCode-Parser). Funktioniert gut und kann an Ihre eigenen Bedürfnisse angepasst werden, wenn Sie spezielle Tags haben. –
Danke, ich habe diese Bibliothek schon gesehen, aber sie verwendet reguläre Ausdrücke, die ich vermeiden wollte, weil das Parsen von BBCode mit regulären Ausdrücken theoretisch nicht ohne Fehler gemacht werden kann ([»» link] (http: // nordmann.de/blog/do_NOT_parse_using_regexp.html)) in einigen Fällen, z wenn sie ineinander verschachtelt werden, usw. Deshalb wollte ich es mit Parsing-Ausdruck-Grammatik-Formalismus machen. Hast du nicht versucht, die Grammatik, die du angefangen hast, zu verbessern? :) Könnten Sie nicht die Grundlage dafür teilen? :) – Sk8erPeter