/ / Scala Parser Combinator Messaggi di errore personalizzati - scala, parser-combinators, custom-error-handling

Scala Parser Combinator Messaggi di errore personalizzati - scala, parser-combinators, custom-error-handling

Ho letto alcuni post qui su parser-combinators di Scala e una migliore gestione degli errori, ma molte "soluzioni" sembrano dire "basta usare" ~! "", O "Anticipare i casi di errore con le regole grammaticali".

Così ho tentato di implementare alcuni di questi consigli, ma sono bloccato a capire come funzionano i parser di errori / errori:

val foo: Parser[String] = """foo""".r | err("Custom Message")
val test: Parser[List[String]] = repsep(foo, ",") | err("Custom Message Repsep")
val r = parseAll(foo, ""bar") //[1.1] error: Custom Message -- YAY
val r = parseAll(test, "foo, bar") //[1.2] failure: string matching regex `foo" expected but `b" found -- NOOOOOO

La mia domanda è fondamentalmente: se foo viene ripetutamente tentato contro la stringa di input a causa di repsep, allora perché - poiché la sua definizione include a | in caso di fallimento di provare e forzare un err - è il messaggio di errore dal terminale più a sinistra nel foo la produzione viene visualizzata?

C'è un modo per visualizzare una pila di messaggi di errore nel risultato di analisi e trovare sempre il mio e visualizzare all'utente? O devo implementare la mia versione di repsep o qualcosa? Credo che mi manchi qualcosa sul modello concettuale di ciò che sta succedendo :(

risposte:

0 per risposta № 1

No, non è necessario riscrivere repsep o tieni traccia dei tuoi messaggi di errore. Il parser-combinator sembra comportarsi proprio come te l'hai chiesto. Corrisponde a "pippo" una volta e poi trova ",". Ma poi ha fallito su "bar", ma dato che aveva già inghiottito "foo" e ",", non poteva restituirli e quindi provare la seconda alternativa (il tuo messaggio di errore). Potresti provare a usare un parser packrat invece se questo è davvero il comportamento che vuoi.


0 per risposta № 2

Per il mio commento sopra: Ho finito per risolvere questo problema usando FastParse (lihaoyi.com/fastparse). Esiste un metodo opaco che avvolge un parser e genera un messaggio di errore personalizzato utile in caso di errore. Per esempio.:

val test = foo.rep(1,",").opaque("Custom Message Repsep")

Complessivamente, trovo FastParse molto più veloce e più facile da usare rispetto a Scala Parser Combinators.