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


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow