Haskell Language
Attoparsec
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