Ho un convertitore bbcode -> html che risponde all'evento change in una textarea. Attualmente, questo viene fatto usando una serie di espressioni regolari, e ci sono un certo numero di casi patologici. Ho sempre voluto affinare la matita su questa grammatica, ma non volevo entrare nella rasatura degli yak. Ma ... di recente sono venuto a conoscenza di pegjs, che sembra un'implementazione abbastanza completa della generazione di parser PEG. Ho specificato la maggior parte della grammatica, ma ora mi chiedo se questo sia un uso appropriato di un parser completo.Utilizzo di PEG Parser per l'analisi di BBCode: pegjs o ... cosa?
Le mie domande specifiche sono:
Come la mia applicazione si basa sulla traduzione di quello che posso per HTML e lasciando il resto come testo grezzo, non attuare bbcode utilizzando un parser in grado di fallire su un errore di sintassi ha senso ? Ad esempio: ci si aspetta che il numero
[url=/foo/bar]click me![/url]
abbia successo una volta inserita la parentesi di chiusura sul tag di chiusura. Ma cosa vedrebbe l'utente nel frattempo? Con regex, posso semplicemente ignorare le cose non corrispondenti e trattarle come testo normale per scopi di anteprima. Con una grammatica formale, non so se questo sia possibile perché mi sto affidando alla creazione dell'HTML da un albero di analisi e quello che fallisce nel parse è ... cosa?Non sono chiaro dove devono essere eseguite le trasformazioni. In un parser formale basato su lex/yacc, avrei file di intestazione e simboli che denotavano il tipo di nodo. In pegjs, ottengo array annidati con il testo del nodo. Posso emettere il codice tradotto come azione del parser generato da pegjs, ma sembra un odore di codice per combinare un parser e un emettitore. Tuttavia, se chiamo
PEG.parse.parse()
, torno qualcosa di simile:
[
[
"[",
"img",
"",
[
"/",
"f",
"o",
"o",
"/",
"b",
"a",
"r"
],
"",
"]"
],
[
"[/",
"img",
"]"
]
]
dato una grammatica come:
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")
che sto abbreviare la grammatica, ovviamente, ma si avere l'idea Quindi, se si nota, non ci sono informazioni contestuali nella matrice di array che mi dice che tipo di nodo ho e sono lasciato a fare il confronto di stringhe ancora anche se il parser lo ha già fatto. Mi aspetto che sia possibile definire i callback e utilizzare le azioni per eseguirli durante un'analisi, ma sul Web sono disponibili scarse informazioni su come si potrebbe farlo.
Sto abbaiando dall'albero sbagliato? Devo tornare alla scansione regolare e dimenticare l'analisi?
Grazie
Steve, la tua domanda è molto interessante (+1), voglio solo fare la stessa cosa in un'estensione: analizzare il BBCode in una textarea (purtroppo questo è il formato utilizzato da un forum) e creare un "live" "anteprima dal testo digitato utilizzando PEG.js o qualsiasi altra cosa tranne le espressioni regolari. Sei riuscito a creare la grammatica per il parser di BBCode? Non potresti per favore condividere la tua soluzione tramite GitHub o altro? Questo mi aiuterebbe molto. Grazie mille in anticipo! – Sk8erPeter
Ho usato [parser bbcode di patorjk] (https://github.com/patorjk/Extendible-BBCode-Parser). Funziona alla grande e può essere ottimizzato per le tue esigenze se hai tag speciali. –
Grazie, ho già visto questa libreria, ma usa espressioni regolari, che volevo evitare, perché teoricamente, l'analisi del BBCode usando le espressioni regolari non può essere eseguita senza errori ([»» link] (http: // kore- nordmann.de/blog/do_NOT_parse_using_regexp.html)) in alcuni casi, ad es. quando li annidiamo l'uno nell'altro, ecc. Ecco perché volevo farlo usando il formalismo grammaticale di espressione parsing. Quindi non hai provato a migliorare la grammatica che hai iniziato? :) Non potresti condividere la base di esso? :) – Sk8erPeter