Zoeken…


Invoering

Attoparsec is een parsing-combinatorbibliotheek die "vooral gericht is op het efficiënt omgaan met netwerkprotocollen en gecompliceerde tekst / binaire bestandsformaten".

Attoparsec biedt niet alleen snelheid en efficiëntie, maar ook backtracking en incrementele invoer.

De API komt nauw overeen met die van een andere parser-combinatorbibliotheek, Parsec.

Er zijn submodules voor compatibiliteit met ByteString , Text en Char8 . Het gebruik van de OverloadedStrings wordt aanbevolen.

parameters

Type Detail
Parser ia Het kerntype voor het weergeven van een parser. i is het ByteString , bijvoorbeeld ByteString .
IResult ir Het resultaat van een analyse, met Fail i [String] String , Partial (i -> IResult ir) en Done ir als constructors.

combinators

Parsing-invoer kan het beste worden bereikt via grotere parser-functies die zijn samengesteld uit kleinere functies voor één doel.

Laten we zeggen dat we de volgende tekst die werktijden wenst te parseren:

Maandag: 0800 1600.

We kunnen deze opsplitsen in twee "tokens": de dagnaam - "Maandag" - en een tijdsdeel "0800" tot "1600".

Om een dagnaam te ontleden, kunnen we het volgende schrijven:

data Day = Day String

day :: Parser Day
day = do
  name <- takeWhile1 (/= ':')
  skipMany1 (char ':')
  skipSpace
  return $ Day name

Om het tijdsgedeelte te ontleden zouden we kunnen schrijven:

data TimePortion = TimePortion String String

time = do
    start <- takeWhile1 isDigit
    skipSpace
    end <- takeWhile1 isDigit
    return $ TimePortion start end

Nu hebben we twee parsers voor onze afzonderlijke delen van de tekst, we kunnen deze combineren in een "grotere" parser om de hele werkdag te lezen:

data WorkPeriod = WorkPeriod Day TimePortion

work = do
    d <- day
    t <- time
    return $ WorkPeriod d t
    

en voer vervolgens de parser uit:

parseOnly work "Monday: 0800 1600"

Bitmap - Binaire gegevens parseren

Attoparsec maakt parseren van binaire gegevens triviaal. Uitgaande van deze definities:

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)

We kunnen de header eenvoudig uit een bitmapbestand ontleden. Hier hebben we 4 parserfuncties die de koptekstsectie van een bitmapbestand vertegenwoordigen:

Ten eerste kan de DIB-sectie worden gelezen door de eerste 2 bytes te nemen

dibP :: Parser DIB
dibP = read . unpack <$> take 2

Evenzo kunnen de grootte van de bitmap, de gereserveerde secties en de pixeloffset ook gemakkelijk worden gelezen:

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

die vervolgens kan worden gecombineerd tot een grotere parser-functie voor de hele koptekst:

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow