• Haskell parsers Мысли вслух:
    1. На практике не бывает строго top-down или bottom-up парсеров: что-то идет «вверх», а что-то — «вниз». Особенно, если на входе дерево. Особенно, если это квази-парсер а-ля aeson или binary.
    2. У континюейшена парсера должно быть две ветки. Как результат, фейлить можно двумя способами: возвращая состояние Fail через ветку «успех», или вызывая ветку «фейл». Разница, в работе комбинатора <|>.
    3. Фейл ­­­­­­­­­­— частный случай преждевременного исчерпания входного потока. Т.о. можно подрихтовать входной поток, и перезапустить парсер. Это крайне важно в квази-парсерах а-ля aeson.

    И да, аттрибутивные грамматики — рулят!

Replies (5)

  • @Macil, Как ты себе представляешь второе? И может быть исчерпание входного потока частный случай фиала, а не наоборот?
  • @ndtimofeev, Есть континюейшен, что-то типа
    newtype P ak= C {runC :: forall r. Input -> Failure -> Success a r -> Result r}, где Failure и Success — функциональные типы forall r. Input -> ... -> Result r
    Можно вызывать как ветку Failure, так и Success. Но ветке Success мы можем передать Fail в качестве результата. Получается два типа фейлов: «жесткий» или «внешний», который моментально выходит из runC, и «мягкий» или «внутренний», который может подавляться комбинатором <|> для типа P. При необходимости, «жесткий фейл» можно подавить комбинатором <|> для типа Result.
    Исчерпание входного потока — суровая правда жизни. И фейлом она быть не может. Ладно, шучу. На самом деле, без разницы как мне кажется, просто это я к тому, что не нужно делать отдельные ветки Partial и Fail для дататипа Result.
  • @Macil, 1. Может у меня какая-то неправильная практика, но бывает и даже почти всегда. На входе парсера всегда строка токенов, по определению. С деревом это какие-то дебри дикие.
    2,3. На практике, опять же, обычно используют три ветки — "успех", "еще ввода" и "фейл", вне зависимости от механизма реализации.
  • @rkit, Значит грамматики правильные. ;) Представь что у тебя на входе Map String String и спецификация как парсить данное value данного key, а на выходе — Result Foo.
    Cписок, это то же дерево, кстати.
    Или тип данных Bar = Section Bar | Subsection Bar | Block (Map String String)
  • @Macil, Ну вот то, что будет разбирать конкретное value и будет парсером. А все вместе — нет.
    список ⊂ дерево. Недопустимо тут такое обобщение.