Voglio analizzare lingue specifiche del dominio definite dall'utente. Queste lingue sono in genere vicine alle notazioni matematiche (non sto analizzando un linguaggio naturale). Gli utenti definiscono il loro DSL in una notazione BNF, in questo modo:
expr ::= LiteralInteger
| ( expr )
| expr + expr
| expr * expr
Input like 1 + ( 2 * 3 )
deve essere accettato, mentre input like 1 +
deve essere rifiutato come errato e input like 1 + 2 * 3
deve essere rifiutato come ambiguo.
Una difficoltà centrale qui è far fronte a grammatiche ambigue in modo facile da usare. Limitare la grammatica in modo non ambiguo non è un'opzione: è così che la lingua è: l'idea è che gli scrittori preferiscono omettere le parentesi quando non sono necessarie per evitare ambiguità. Finché un'espressione non è ambigua, devo analizzarla e, in caso contrario, devo rifiutarla.
Il mio parser deve funzionare su qualsiasi grammatica senza contesto, anche ambigua, e deve accettare tutti gli input inequivocabili. Ho bisogno dell'albero di analisi per tutti gli input accettati. Per un input non valido o ambiguo, idealmente voglio buoni messaggi di errore, ma per cominciare prenderò quello che posso ottenere.
In genere invoco il parser su input relativamente brevi, con input più lunghi occasionali. Quindi l'algoritmo asintoticamente più veloce potrebbe non essere la scelta migliore. Vorrei ottimizzare per una distribuzione di circa l'80% di input lunghi meno di 20 simboli, il 19% tra 20 e 50 simboli e l'1% di input più rari più lunghi. La velocità per input non validi non è una delle maggiori preoccupazioni. Inoltre, mi aspetto una modifica del DSL circa ogni 1000-100000 ingressi; Posso passare un paio di secondi a elaborare la mia grammatica, non un paio di minuti.
Quali algoritmi di analisi dovrei esaminare, date le mie dimensioni di input tipiche? La segnalazione degli errori dovrebbe essere un fattore nella mia selezione o dovrei concentrarmi sull'analisi di input non ambigui ed eventualmente eseguire un parser completamente separato e più lento per fornire un feedback sugli errori?
(Nel progetto in cui ne avevo bisogno (qualche tempo fa), ho usato CYK , che non era troppo difficile da implementare e ha funzionato adeguatamente per le mie dimensioni di input ma non ha prodotto errori molto belli.)
x+y+z
.
+
, quindi x+y+z
è davvero ambigua e quindi errata.