ANTLR è un generatore di parser molto popolare che aiuta a costruire parser per vari sintassi linguistici, in particolare lingue di question o lingue specifiche del dominio. Questo strumento fornisce una gestione degli errori predefiniti, che è utile in molte circostanze, ma per applicazioni più robuste e intuitive, è richiesta una gestione degli errori più graziosa.
In questo articolo, descriveremo questo requisito con un semplice esempio e ti guideremo attraverso il processo di implementazione Gestione degli errori personalizzati con antlr.
State of affairs 1: Aggiungi marcatori nel testo analizzato
In questo situation, definiremo prima la grammatica e mostreremo l’errore di sintassi che otteniamo per impostazione predefinita dal parser generato dal Generatore di parser antlr.
Antlr Grammar
Ecco uno snippet di codice della grammatica antlr che definisce la sintassi necessaria per il nostro esempio.
grammar ExampleDsl;
question
: selectExpr fromExpr whereExpr EOF
;
selectExpr
: 'SELECT' expression_list
;
fromExpr
: 'FROM' identifier
;
whereExpr
: 'WHERE' expression
;
....
....
Nella sottosezione successiva, mostreremo come appare un messaggio di errore per un testo di enter cattivo o errato con impostazione predefinita Gestione degli errori.
Gestione degli errori predefiniti
Ecco un enter di esempio in cui abbiamo perso la clausola dal testo di enter.
Enter:
SELECT c1 FROM desk WHERE column shouldn't be null
Per l’enter sopra, il messaggio di errore predefinito sarà simile a quanto segue:
End result:
line 1:10 mismatched enter 'WHERE' anticipating {'FROM', ','}
Il messaggio mostra il numero di riga e un valore di offset, che indica la posizione dell’errore. Poiché il testo di enter sopra è una riga singola molto semplice, il messaggio di errore predefinito sembra sufficiente per identificare il punto problematico nel testo di enter.
Ma se il testo di enter è multi-riga e un paragrafo molto complesso, il messaggio di errore predefinito non aiuta molto. L’utente avrà bisogno di un messaggio di errore migliore con segnali visivi per identificare rapidamente il problema della sintassi. Nella prossima sottosezione, mostreremo come possiamo raggiungere questo obiettivo.
Aggiunta di marcatori di posizione di errore utilizzando ascoltatore di errore personalizzato
Definiamo un ascoltatore di errori personalizzati che intercetterà l’eccezione predefinita dal parser generato da ANTLR e proverà a creare un messaggio di errore nuovo e facilmente leggibile.
case class CustomErrorListener(enter: String) extends BaseErrorListener {
val StartMarker = ">"
val EndMarker = "
Nell’ascoltatore sopra, stiamo usando il RecognitionException
obiettare per estrarre il token offensivo in cui si è verificato l’errore di parser. Il token offensivo contiene i valori del marcatore di posizione. Usando questi marcatori, possiamo modificare la stringa di enter inserendo caratteri visivi (come> e
Una volta definito l’ascoltatore, dobbiamo aggiornare il parser per utilizzare l’ascoltatore di errori personalizzati.
def parse(enter: String): String = {
val lexer = new ExampleDslLexer(CharStreams.fromString(enter))
val parser = new ExampleDslParser(new CommonTokenStream(lexer))
// Including customized listener to parser
parser.addErrorListener(CustomErrorListener(enter))
val customer = new ExampleParseVisitor()
customer.visitQuery(parser.question())
}
Con la modifica di cui sopra, avremo i caratteri del marcatore di posizione nei messaggi di errore per indicare le posizioni degli errori del parser.
Ecco alcuni esempi di messaggi di errore migliorati dall’ascoltatore di errori personalizzati:
Enter:
SELECT c1 WHERE column shouldn't be null
Error Message:
Syntax error ( mismatched enter 'WHERE' anticipating {'FROM', ','} ) for enter:
SELECT c1 > WHER WHER
Nella prossima sezione, mostreremo un altro caso d’uso in cui possiamo estendere questo concetto per fornire diversi messaggi di errore per lo stesso errore di parser a seconda del contesto.
State of affairs 2: mostra il messaggio di errore basato sul contesto
Facciamo un semplice esempio: vogliamo gestire un errore di parser in modo diverso durante la registrazione rispetto a propagarlo all’utente.
In caso di registrazione, non vogliamo registrare la question dell’utente in quanto ciò può contenere dati sensibili, ma registrare solo il messaggio mentre il cliente potrebbe aver bisogno di un intero messaggio di errore.
Per raggiungere questo obiettivo, possiamo utilizzare un ascoltatore di errore personalizzato per creare un’eccezione personalizzata che contenga entrambi i tipi di messaggi di errore. Il codice chiamante può utilizzare questi messaggi in modo appropriato in base al contesto.
case class ContextSensitiveErrorListener(enter: String) extends BaseErrorListener {
val StartMarker = ">"
val EndMarker = "
Conclusione
La gestione degli errori personalizzati è un aspetto molto importante della costruzione di processori linguistici robusti e user-friendly con ANTLR. Implementando il tuo ascoltatore di errori, è possibile migliorare significativamente la qualità del reporting degli errori, facilitare il debug e alla positive creare un’esperienza migliore per coloro che interagiscono con i tuoi strumenti linguistici.