Haskell Language
Attoparsec
Szukaj…
Wprowadzenie
Attoparsec to parsująca biblioteka kombinatora, która „ma na celu szczególnie efektywne radzenie sobie z protokołami sieciowymi i skomplikowanymi formatami plików tekstowych / binarnych”.
Attoparsec oferuje nie tylko szybkość i wydajność, ale także cofanie się i wprowadzanie przyrostowe.
Jego interfejs API ściśle odzwierciedla bibliotekę innej biblioteki kombinacji parserów, Parsec.
Istnieją podmoduły kompatybilności z ByteString , Text i Char8 . Zalecane jest użycie rozszerzenia języka OverloadedStrings .
Parametry
| Rodzaj | Szczegół |
|---|---|
Parser ia | Podstawowy typ reprezentujący analizator składni. i jest typem ciągu, np. ByteString . |
IResult ir | Wynik analizy składniowej z Fail i [String] String , Partial (i -> IResult ir) i Done ir jako konstruktorami. |
Kombinatory
Parsowanie danych wejściowych można najlepiej osiągnąć dzięki większym funkcjom parsera, które składają się z mniejszych, pojedynczych funkcji.
Załóżmy, że chcemy przeanalizować następujący tekst reprezentujący godziny pracy:
Poniedziałek: 0800 1600.
Możemy podzielić je na dwa „tokeny”: nazwę dnia - „poniedziałek” - i przedział czasu od „0800” do „1600”.
Aby przeanalizować nazwę dnia, możemy napisać:
data Day = Day String day :: Parser Day day = do name <- takeWhile1 (/= ':') skipMany1 (char ':') skipSpace return $ Day name
Aby przeanalizować część czasu, możemy napisać:
data TimePortion = TimePortion String String
time = do
start <- takeWhile1 isDigit
skipSpace
end <- takeWhile1 isDigit
return $ TimePortion start end
Teraz mamy dwa parsery dla poszczególnych części tekstu, możemy połączyć je w „większy” parser, aby odczytać godziny pracy całego dnia:
data WorkPeriod = WorkPeriod Day TimePortion
work = do
d <- day
t <- time
return $ WorkPeriod d t
a następnie uruchom parser:
parseOnly work "Monday: 0800 1600"
Mapa bitowa - analizowanie danych binarnych
Attoparsec sprawia, że parsowanie danych binarnych jest banalne. Zakładając następujące definicje:
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)
Możemy łatwo parsować nagłówek z pliku mapy bitowej. Tutaj mamy 4 funkcje analizatora składni, które reprezentują sekcję nagłówka z pliku bitmapy:
Po pierwsze, sekcję DIB można odczytać, biorąc pierwsze 2 bajty
dibP :: Parser DIB
dibP = read . unpack <$> take 2
Podobnie łatwo można odczytać rozmiar mapy bitowej, zarezerwowane sekcje i przesunięcie pikseli:
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
który można następnie połączyć w większą funkcję parsera dla całego nagłówka:
bitmapHeader :: Parser Header
bitmapHeader = do
dib <- dibP
sz <- sizeP
reservedP
reservedP
offset <- addressP
return $ Header dib sz "" "" offset