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


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow