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