Haskell Language
Attoparsec
Поиск…
Вступление
Attoparsec - это библиотека комбинаторного анализатора, которая «нацелена, в частности, на эффективную работу с сетевыми протоколами и сложными форматами текстовых / двоичных файлов».
Attoparsec предлагает не только скорость и эффективность, но и обратную трассировку и инкрементный вход.
Его API тесно связан с API-интерфейсом другой библиотеки парсеров-парсеров Parsec.
Существуют подмодули для совместимости с ByteString , Text и Char8 . Рекомендуется использовать расширение языка OverloadedStrings .
параметры
| Тип | подробность |
|---|---|
Parser ia | Основной тип представления синтаксического анализатора. i - тип строки, например ByteString . |
IResult ir | Результат анализа, с Fail i [String] String , Partial (i -> IResult ir) и Done ir как конструкторы. |
Комбинаторы
Разбор ввода лучше всего достигается за счет более крупных функций парсера, состоящих из меньших одноцелевых.
Предположим, мы хотели разобрать следующий текст, который представляет собой рабочее время:
Понедельник: 0800 1600.
Мы могли бы разделить их на два «токена»: название дня - «понедельник» - и часть времени «0800» - «1600».
Чтобы проанализировать имя дня, мы могли бы написать следующее:
data Day = Day String day :: Parser Day day = do name <- takeWhile1 (/= ':') skipMany1 (char ':') skipSpace return $ Day name
Чтобы проанализировать временную часть, мы могли бы написать:
data TimePortion = TimePortion String String
time = do
start <- takeWhile1 isDigit
skipSpace
end <- takeWhile1 isDigit
return $ TimePortion start end
Теперь у нас есть два парсера для наших отдельных частей текста, мы можем объединить их в «большом» синтаксическом анализаторе для чтения рабочего дня всего дня:
data WorkPeriod = WorkPeriod Day TimePortion
work = do
d <- day
t <- time
return $ WorkPeriod d t
а затем запустите синтаксический анализатор:
parseOnly work "Monday: 0800 1600"
Bitmap - Разбор двоичных данных
Attoparsec делает синтаксический анализ двоичных данных тривиальным. Предполагая эти определения:
import Data.Attoparsec.ByteString (Parser, eitherResult, parse, take)
import Data.Binary.Get (getWord32le, runGet)
import Data.ByteString (ByteString, readFile)
import Data.ByteString.Char8 (unpack)
import Data.ByteString.Lazy (fromStrict)
import Prelude hiding (readFile, take)
-- The DIB section from a bitmap header
data DIB = BM | BA | CI | CP | IC | PT
deriving (Show, Read)
type Reserved = ByteString
-- The entire bitmap header
data Header = Header DIB Int Reserved Reserved Int
deriving (Show)
Мы можем легко разобрать заголовок из растрового файла. Здесь у нас есть 4 функции парсера, которые представляют секцию заголовка из файла растрового изображения:
Во-первых, раздел DIB можно прочитать, взяв первые 2 байта
dibP :: Parser DIB
dibP = read . unpack <$> take 2
Аналогично, размер растрового изображения, зарезервированные разделы и смещение пикселей можно легко прочитать:
sizeP :: Parser Int sizeP = fromIntegral . runGet getWord32le . fromStrict <$> take 4 reservedP :: Parser Reserved reservedP = take 2 addressP :: Parser Int addressP = fromIntegral . runGet getWord32le . fromStrict <$> take 4
которые затем могут быть объединены в большую функцию синтаксического анализа для всего заголовка:
bitmapHeader :: Parser Header
bitmapHeader = do
dib <- dibP
sz <- sizeP
reservedP
reservedP
offset <- addressP
return $ Header dib sz "" "" offset