Implementando analizador para lenguaje similar a markdown
Tengo un lenguaje de marcado que es similar al markdown y al que usa SO.
El analizador heredado se basó en expresiones regulares y fue una completa pesadilla de mantenimiento, por lo que se me ocurrió mi propia solución basada en la gramática EBNF e implementada a través de mxTextTools / SimpleParse.
Sin embargo, hay problemas con algunos tokens que pueden incluirse entre sí, y no veo una forma "correcta" de hacerlo.
Aquí está parte de mi gramática:
newline := "\r\n"/"\n"/"\r"
indent := ("\r\n"/"\n"/"\r"), [ \t]
number := [0-9]+
whitespace := [ \t]+
symbol_mark := [*_>#`%]
symbol_mark_noa := [_>#`%]
symbol_mark_nou := [*>#`%]
symbol_mark_nop := [*_>#`]
punctuation := [\(\)\,\.\!\?]
noaccent_code := -(newline / '`')+
accent_code := -(newline / '``')+
symbol := -(whitespace / newline)
text := -newline+
safe_text := -(newline / whitespace / [*_>#`] / '%%' / punctuation)+/whitespace
link := 'http' / 'ftp', 's'?, '://', (-[ \t\r\n<>`^'"*\,\.\!\?]/([,\.\?],?-[ \t\r\n<>`^'"*]))+
strikedout := -[ \t\r\n*_>#`^]+
ctrlw := '^W'+
ctrlh := '^H'+
strikeout := (strikedout, (whitespace, strikedout)*, ctrlw) / (strikedout, ctrlh)
strong := ('**', (inline_nostrong/symbol), (inline_safe_nostrong/symbol_mark_noa)* , '**') / ('__' , (inline_nostrong/symbol), (inline_safe_nostrong/symbol_mark_nou)*, '__')
emphasis := ('*',?-'*', (inline_noast/symbol), (inline_safe_noast/symbol_mark_noa)*, '*') / ('_',?-'_', (inline_nound/symbol), (inline_safe_nound/symbol_mark_nou)*, '_')
inline_code := ('`' , noaccent_code , '`') / ('``' , accent_code , '``')
inline_spoiler := ('%%', (inline_nospoiler/symbol), (inline_safe_nop/symbol_mark_nop)*, '%%')
inline := (inline_code / inline_spoiler / strikeout / strong / emphasis / link)
inline_nostrong := (?-('**'/'__'),(inline_code / reference / signature / inline_spoiler / strikeout / emphasis / link))
inline_nospoiler := (?-'%%',(inline_code / emphasis / strikeout / emphasis / link))
inline_noast := (?-'*',(inline_code / inline_spoiler / strikeout / strong / link))
inline_nound := (?-'_',(inline_code / inline_spoiler / strikeout / strong / link))
inline_safe := (inline_code / inline_spoiler / strikeout / strong / emphasis / link / safe_text / punctuation)+
inline_safe_nostrong := (?-('**'/'__'),(inline_code / inline_spoiler / strikeout / emphasis / link / safe_text / punctuation))+
inline_safe_noast := (?-'*',(inline_code / inline_spoiler / strikeout / strong / link / safe_text / punctuation))+
inline_safe_nound := (?-'_',(inline_code / inline_spoiler / strikeout / strong / link / safe_text / punctuation))+
inline_safe_nop := (?-'%%',(inline_code / emphasis / strikeout / strong / link / safe_text / punctuation))+
inline_full := (inline_code / inline_spoiler / strikeout / strong / emphasis / link / safe_text / punctuation / symbol_mark / text)+
line := newline, ?-[ \t], inline_full?
sub_cite := whitespace?, ?-reference, '>'
cite := newline, whitespace?, '>', sub_cite*, inline_full?
code := newline, [ \t], [ \t], [ \t], [ \t], text
block_cite := cite+
block_code := code+
all := (block_cite / block_code / line / code)+
El primer problema es que spoiler, fuerte y énfasis pueden incluirse entre sí en orden arbitrario. Y es posible que más tarde necesite más marcas en línea.
Mi solución actual implica simplemente crear un token separado para cada combinación (inline_noast, inline_nostrong, etc.), pero obviamente, el número de tales combinaciones crece demasiado rápido con el creciente número de elementos de marcado.
S, el problema económico es que estas miradas en fuerte / énfasis se comportan MUY mal en algunos casos de mal marcado como__._.__*__.__...___._.____.__**___***
(muchos símbolos de marcado colocados al azar). Se necesitan minutos para analizar algunos kb de dicho texto aleatorio.
¿Hay algún problema con mi gramática o debería usar algún otro tipo de analizador para esta tarea?