Parserka - библиотека LL парсер-комбинаторов.
Прообазом и основным референсом послужила библиотека Parsec - Parsec paper.
Тип парсера представляет из себя обёртку над функцией, принимающей состояние State i и возвращающее значение типа Consumed = Consumed | Empty. Фактически Consumed позволяет сделать LL(1) парсер.
newtypeParseria=Parser{runParser::Statei->Consumedia}Комбинатор, связывающий последовательные парсеры в один (>>=) реализуется как метод класса монада.
Логика работы следующая: если парсер завершился удачно, то управление передаётся следующему парсерсу, иначе - возвращается ошибка первого парсера. При этом большую роль играет то, потребил ли первый парсер элементы входного потока (Consumed) или нет (Empty)
instanceMonad (Parseri) where
p >>= f =Parser
( \state ->case (runParser p state) ofEmpty r1 ->case (r1) ofOk x state1 _ -> (runParser (f x) state1)
Error msg ->Empty (Error msg)
Consumed r1 ->Consumed
( case (r1) ofOk x state1 _ ->case (runParser (f x) state1) ofConsumed r2 -> r2
Empty r2 -> r2
Error msg ->Error msg
)
)
Комбинатор, описывающий выбор из 2-х парсеров - левоцентричен, но приоритезирует Consumed результаты.
Логика работы следующая: если парсер завершился удачно и принял значение из потока, то его результат возвращается, иначе на том же стейте запускается второй парсер, если он успешен, то его результат выводится.
instanceAlternative (Parseri) where
p <|> q =Parser
( \state ->case (runParser p state) ofEmpty (Error msg1) ->case (runParser q state) ofEmpty (Error msg2) -> mergeError msg1 msg2
Empty (Ok x state' msg2) -> mergeOk x state' msg1 msg2
consumed -> consumed
Empty (Ok x state' msg1) ->case (runParser q state) ofEmpty (Error msg2) -> mergeOk x state' msg1 msg2
Empty (Ok _ _ msg2) -> mergeOk x state' msg1 msg2
consumed -> consumed
consumed -> consumed
)
...YAMLparserka - лексер и парсер подмножества языка YAML, написанный при помощи библиотеки parserka.
Поддерживает основные типы YAML, гетерогенные словари и массивы, идентацию.
Использование:
stack run YAMLparserka -- file.yaml$ cat test.yaml
---
# all markdown
MD013: false# Line length
MD007: # Unordered list indentation
indent: 4
MD051: false# Link fragments should be valid# slides
MD035: false# Horizontal rule style
MD033: - "br"
- "div"# need to be removed
MD045: false# Images should have alternate text (alt text)
MD025: false# Multiple top-level headings in the same document
MD011: false# Reversed link syntax conflix with maths.
MD041: false# Required for course note
---
B: 256
...
stack run YAMLparserka -- test.yaml
...
{
"MD007";{
"indent";4
}
"MD011";False
"MD013";False
"MD025";False
"MD033";[
"br",
"div",
]
"MD035";False
"MD041";False
"MD045";False
"MD051";False
}
{
"B";256
}