Haskell Language
Attoparsec
Buscar..
Introducción
Attoparsec es una biblioteca combinadora de análisis que está "dirigida especialmente a tratar de manera eficiente los protocolos de red y los complicados formatos de archivo de texto / binario".
Attoparsec ofrece no solo velocidad y eficiencia, sino también retroceso e ingreso incremental.
Su API es muy similar a la de otra biblioteca combinadora de analizadores, Parsec.
Hay submódulos para la compatibilidad con ByteString , Text y Char8 . Se recomienda el uso de la extensión de lenguaje OverloadedStrings .
Parámetros
| Tipo | Detalle |
|---|---|
Parser ia | El tipo de núcleo para representar un analizador. i es el tipo de cadena, por ejemplo, ByteString . |
IResult ir | El resultado de un análisis, con Fail i [String] String , Partial (i -> IResult ir) y Done ir como constructores. |
Combinadores
La entrada de análisis se logra mejor a través de funciones de analizador más grandes que se componen de funciones más pequeñas y de un solo propósito.
Digamos que deseamos analizar el siguiente texto que representa las horas de trabajo:
Lunes: 0800 1600.
Podríamos dividirlos en dos "tokens": el nombre del día, "Monday", y una parte de tiempo "0800" a "1600".
Para analizar el nombre de un día, podríamos escribir lo siguiente:
data Day = Day String day :: Parser Day day = do name <- takeWhile1 (/= ':') skipMany1 (char ':') skipSpace return $ Day name
Para analizar la parte del tiempo podríamos escribir:
data TimePortion = TimePortion String String
time = do
start <- takeWhile1 isDigit
skipSpace
end <- takeWhile1 isDigit
return $ TimePortion start end
Ahora que tenemos dos analizadores para nuestras partes individuales del texto, podemos combinarlos en un analizador "más grande" para leer las horas de trabajo de un día entero:
data WorkPeriod = WorkPeriod Day TimePortion
work = do
d <- day
t <- time
return $ WorkPeriod d t
y luego ejecute el analizador
parseOnly work "Monday: 0800 1600"
Mapa de bits - Análisis de datos binarios
Attoparsec hace que el análisis de datos binarios sea trivial. Asumiendo estas definiciones:
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)
Podemos analizar el encabezado de un archivo de mapa de bits fácilmente. Aquí, tenemos 4 funciones de analizador que representan la sección del encabezado de un archivo de mapa de bits:
En primer lugar, la sección DIB se puede leer tomando los primeros 2 bytes
dibP :: Parser DIB
dibP = read . unpack <$> take 2
Del mismo modo, el tamaño del mapa de bits, las secciones reservadas y el desplazamiento de píxeles también se pueden leer fácilmente:
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
que luego se puede combinar en una función de analizador más grande para todo el encabezado:
bitmapHeader :: Parser Header
bitmapHeader = do
dib <- dibP
sz <- sizeP
reservedP
reservedP
offset <- addressP
return $ Header dib sz "" "" offset