Поиск…


Вступление

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


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow