Haskell Language
Attoparsec
Ricerca…
introduzione
Attoparsec è una libreria combinatoria di analisi che è "mirata in particolare a gestire in modo efficiente i protocolli di rete e i complicati formati di file testo / binari".
Attoparsec offre non solo velocità ed efficienza, ma anche backtracking e input incrementale.
La sua API rispecchia da vicino quella di un'altra libreria di combinatori di parser, Parsec.
Ci sono sottomoduli per la compatibilità con ByteString , Text e Char8 . Si consiglia l'uso dell'estensione di lingua OverloadedStrings .
Parametri
| genere | Dettaglio |
|---|---|
Parser ia | Il tipo principale per rappresentare un parser. i è il tipo di stringa, ad esempio ByteString . |
IResult ir | Il risultato di un'analisi, con Fail i [String] String , Partial (i -> IResult ir) e Done ir come costruttori. |
combinatori
L'input di analisi è ottenuto al meglio mediante funzioni di parser più grandi composte da più piccole, a uso singolo.
Diciamo che abbiamo voluto analizzare il seguente testo che rappresenta l'orario di lavoro:
Lunedì: 0800 1600.
Potremmo dividerli in due "token": il nome del giorno - "Monday" - e una parte del tempo "0800" in "1600".
Per analizzare il nome del giorno, potremmo scrivere quanto segue:
data Day = Day String day :: Parser Day day = do name <- takeWhile1 (/= ':') skipMany1 (char ':') skipSpace return $ Day name
Per analizzare la parte del tempo potremmo scrivere:
data TimePortion = TimePortion String String
time = do
start <- takeWhile1 isDigit
skipSpace
end <- takeWhile1 isDigit
return $ TimePortion start end
Ora abbiamo due parser per le singole parti del testo, possiamo combinarli in un parser "più grande" per leggere l'orario di un'intera giornata:
data WorkPeriod = WorkPeriod Day TimePortion
work = do
d <- day
t <- time
return $ WorkPeriod d t
e quindi eseguire il parser:
parseOnly work "Monday: 0800 1600"
Bitmap: analisi dei dati binari
Attoparsec rende banale l'analisi dei dati binari. Supponendo queste definizioni:
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)
Possiamo analizzare facilmente l'intestazione da un file bitmap. Qui, abbiamo 4 funzioni parser che rappresentano la sezione di intestazione da un file bitmap:
In primo luogo, la sezione DIB può essere letta prendendo i primi 2 byte
dibP :: Parser DIB
dibP = read . unpack <$> take 2
Allo stesso modo, le dimensioni della bitmap, le sezioni riservate e l'offset dei pixel possono essere letti facilmente:
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
che può quindi essere combinato in una funzione parser più grande per l'intera intestazione:
bitmapHeader :: Parser Header
bitmapHeader = do
dib <- dibP
sz <- sizeP
reservedP
reservedP
offset <- addressP
return $ Header dib sz "" "" offset