Haskell Language
Attoparsec
Suche…
Einführung
Attoparsec ist eine Parsing-Combinator-Bibliothek, die "besonders auf den effizienten Umgang mit Netzwerkprotokollen und komplizierten Text- / Binärdateiformaten abzielt".
Attoparsec bietet nicht nur Geschwindigkeit und Effizienz, sondern auch Rückverfolgung und inkrementelle Eingabe.
Seine API spiegelt genau die einer anderen Parser-Combinator-Bibliothek, Parsec, wider.
Es gibt Submodule für die Kompatibilität mit ByteString , Text und Char8 . Die Verwendung der Spracherweiterung OverloadedStrings wird empfohlen.
Parameter
| Art | Detail |
|---|---|
Parser ia | Der Kerntyp für die Darstellung eines Parsers. i ist der String-Typ, zB ByteString . |
IResult ir | Das Ergebnis einer Analyse mit Fail i [String] String , Partial (i -> IResult ir) und Done ir als Konstruktoren. |
Kombinatoren
Die Parsing-Eingabe wird am besten durch größere Parser-Funktionen erreicht, die aus kleineren Einzelfunktionen bestehen.
Angenommen, wir wollten den folgenden Text analysieren, der die Arbeitszeit darstellt:
Montag: 0800 bis 1600 Uhr
Wir könnten diese in zwei "Token" aufteilen: den Tagesnamen "Montag" und einen Zeitabschnitt "0800" bis "1600".
Um einen Tagesnamen zu analysieren, könnten wir folgendes schreiben:
data Day = Day String day :: Parser Day day = do name <- takeWhile1 (/= ':') skipMany1 (char ':') skipSpace return $ Day name
Um den Zeitabschnitt zu analysieren, könnten wir schreiben:
data TimePortion = TimePortion String String
time = do
start <- takeWhile1 isDigit
skipSpace
end <- takeWhile1 isDigit
return $ TimePortion start end
Jetzt haben wir zwei Parser für unsere einzelnen Textteile. Wir können diese in einem "größeren" Parser kombinieren, um die Arbeitsstunden eines ganzen Tages zu lesen:
data WorkPeriod = WorkPeriod Day TimePortion
work = do
d <- day
t <- time
return $ WorkPeriod d t
und dann den Parser ausführen:
parseOnly work "Monday: 0800 1600"
Bitmap - Analyse binärer Daten
Attoparsec macht das Parsen von binären Daten trivial. Angenommen diese Definitionen:
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)
Wir können den Header leicht aus einer Bitmap-Datei analysieren. Hier haben wir 4 Parser-Funktionen, die den Header-Abschnitt aus einer Bitmap-Datei darstellen:
Erstens kann der DIB-Abschnitt gelesen werden, indem die ersten 2 Bytes genommen werden
dibP :: Parser DIB
dibP = read . unpack <$> take 2
Ebenso können die Größe der Bitmap, die reservierten Abschnitte und der Pixelversatz problemlos gelesen werden:
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 dann zu einer größeren Parser-Funktion für den gesamten Header zusammengefasst werden kann:
bitmapHeader :: Parser Header
bitmapHeader = do
dib <- dibP
sz <- sizeP
reservedP
reservedP
offset <- addressP
return $ Header dib sz "" "" offset