/ / Scala Parser Combinator Niestandardowe komunikaty o błędach - scala, parser-combinatory, obsługa niestandardowych błędów

Scala Parser Combinator Niestandardowe komunikaty o błędach - scala, parser-combinatory, obsługa niestandardowych błędów

Przeczytałem kilka postów na temat paralizatora Scala i lepszych błędów obsługi, ale wiele "rozwiązań" wydaje się mówić "po prostu użyj" ~! "" Lub "Przewiduj awarie z regułami gramatyki".

Próbowałem więc wdrożyć niektóre z tych porad, ale utknąłem w zrozumieniu, jak działają parsery niepowodzenia / err:

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

Moje pytanie jest w zasadzie: jeśli foo jest wielokrotnie próbowane w odniesieniu do ciągu wejściowego z powodu repsep, a następnie dlaczego - ponieważ jego definicja obejmuje | o braku próby wymuszenia err - jest komunikat o błędzie z lewego skrajnego terminala w foo produkcja jest wyświetlana?

Czy istnieje sposób wyświetlenia stosu komunikatów o błędach w wyniku analizy i zawsze znajduje się mój i wyświetla się użytkownikowi? Czy muszę wdrożyć własną wersję repsep lub coś? Sądzę, że brakuje mi czegoś o koncepcyjnym modelu tego, co się dzieje :(

Odpowiedzi:

0 dla odpowiedzi № 1

Nie, nie musisz ponownie pisać repsep lub śledź własne komunikaty o błędach. Parser-combinator zachowuje się tak, jak prosiłeś. Po raz pierwszy dopasował "foo", a następnie znalazł ",". Ale potem nie powiodło się na "pasku", ale ponieważ już połknął "foo" i ",", to nie może dać im z powrotem, a następnie spróbuj drugą alternatywę (twój komunikat o błędzie). Możesz spróbować użyć parsera packrat zamiast tego, jeśli tak naprawdę jest to zachowanie, które chcesz.


0 dla odpowiedzi nr 2

Na mój komentarz powyżej: W końcu rozwiązałem ten problem za pomocą FastParse (lihaoyi.com/fastparse). Istnieje metoda nieprzezroczysta, która owija parser i generuje niestandardowy komunikat o błędzie, który jest przydatny w przypadku niepowodzenia. Na przykład.:

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

Ogólnie rzecz biorąc, znajduję FastParse o wiele szybszy i łatwiejszy w użyciu niż Scala Parser Combinators.