Haskell Language
Attoparsec
Sök…
Introduktion
Attoparsec är ett parsing combinator-bibliotek som "syftar särskilt till att hantera nätverksprotokoll och komplicerade text / binära filformat" effektivt.
Attoparsec erbjuder inte bara hastighet och effektivitet, utan backtracking och inkrementell ingång.
Dess API speglar nära det för ett annat parser-kombinatorbibliotek, Parsec.
Det finns undermoduler för kompatibilitet med ByteString , Text och Char8 . Användning av språkförlängningen OverloadedStrings rekommenderas.
parametrar
| Typ | Detalj |
|---|---|
Parser ia | Kärntypen för att representera en parser. i är ByteString , t.ex. ByteString . |
IResult ir | Resultatet av en parse med Fail i [String] String , Partial (i -> IResult ir) och Done ir som konstruktörer. |
kombinatorer
Parsingingång uppnås bäst genom större parserfunktioner som består av mindre, enda ändamål.
Låt oss säga att vi ville analysera följande text som representerar arbetstid:
Måndag: 0800 1600.
Vi kunde dela upp dessa i två "tokens": dagnamnet - "måndag" - och en tidsdel "0800" till "1600".
För att analysera ett dagnamn kan vi skriva följande:
data Day = Day String day :: Parser Day day = do name <- takeWhile1 (/= ':') skipMany1 (char ':') skipSpace return $ Day name
För att analysera tidsdelen kan vi skriva:
data TimePortion = TimePortion String String
time = do
start <- takeWhile1 isDigit
skipSpace
end <- takeWhile1 isDigit
return $ TimePortion start end
Nu har vi två parsers för våra enskilda delar av texten, vi kan kombinera dessa i en "större" parser för att läsa en hel dags arbetstid:
data WorkPeriod = WorkPeriod Day TimePortion
work = do
d <- day
t <- time
return $ WorkPeriod d t
och kör sedan parser:
parseOnly work "Monday: 0800 1600"
Bitmapp - analysera binära data
Attoparsec gör parsing av binära data triviala. Antagande av dessa definitioner:
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)
Vi kan enkelt para rubriken från en bitmappsfil. Här har vi fyra parserfunktioner som representerar rubrikavsnittet från en bitmappsfil:
För det första kan DIB-avsnittet läsas genom att ta de två första byte
dibP :: Parser DIB
dibP = read . unpack <$> take 2
På samma sätt kan storleken på bitmappen, de reserverade avsnitten och pixelförskjutningen lätt läsas också:
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
som sedan kan kombineras till en större parser-funktion för hela huvudet:
bitmapHeader :: Parser Header
bitmapHeader = do
dib <- dibP
sz <- sizeP
reservedP
reservedP
offset <- addressP
return $ Header dib sz "" "" offset