attoparsec 0.5.1 → 0.6
raw patch · 4 files changed
+76/−13 lines, 4 filesdep +bytestring-lexingdep ~base
Dependencies added: bytestring-lexing
Dependency ranges changed: base
Files
- attoparsec.cabal +6/−2
- src/Data/ParserCombinators/Attoparsec.hs +2/−0
- src/Data/ParserCombinators/Attoparsec/Char8.hs +30/−1
- src/Data/ParserCombinators/Attoparsec/Internal.hs +38/−10
attoparsec.cabal view
@@ -1,11 +1,13 @@ name: attoparsec-version: 0.5.1+version: 0.6 license: BSD3 license-file: LICENSE category: Text, Parsing author: Bryan O'Sullivan <bos@serpentine.com>+maintainer: Bryan O'Sullivan <bos@serpentine.com> stability: experimental-synopsis: Combinator parsing with Data.ByteString.Lazy+synopsis: Fast combinator parsing with Data.ByteString.Lazy+description: Fast combinator parsing with Data.ByteString.Lazy cabal-version: >= 1.2 build-type: Simple description: Fast, flexible text-oriented parsing of lazy ByteStrings.@@ -26,6 +28,8 @@ cpp-options: -DAPPLICATIVE_IN_BASE else build-depends: base < 2.0++ build-depends: bytestring-lexing >= 0.2 extensions: CPP exposed-modules: Data.ParserCombinators.Attoparsec
src/Data/ParserCombinators/Attoparsec.hs view
@@ -28,6 +28,8 @@ -- * Things vaguely like those in @Parsec.Combinator@ (and @Parsec.Prim@) , try+ , many+ , many1 , manyTill , eof , skipMany
src/Data/ParserCombinators/Attoparsec/Char8.hs view
@@ -28,6 +28,8 @@ -- * Things vaguely like those in @Parsec.Combinator@ (and @Parsec.Prim@) , try+ , many+ , many1 , manyTill , eof , skipMany@@ -52,6 +54,11 @@ -- * Parser converters. , eitherP + -- * Numeric parsers.+ , int+ , integer+ , double+ -- * Miscellaneous functions. , getInput , getConsumed@@ -59,6 +66,7 @@ , takeWhile1 , takeTill , takeAll+ , takeCount , skipWhile , skipSpace , notEmpty@@ -79,7 +87,9 @@ import Data.ParserCombinators.Attoparsec.Internal (Parser, ParseError, (<?>), parse, parseAt, parseTest, try, manyTill, eof, skipMany, skipMany1, count, lookAhead, peek, sepBy, sepBy1, string,- eitherP, getInput, getConsumed, takeAll, notEmpty, match, endOfLine)+ eitherP, getInput, getConsumed, takeAll, takeCount, notEmpty, match,+ endOfLine, setInput, many, many1)+import Data.ByteString.Lex.Lazy.Double (readDouble) import Prelude hiding (takeWhile) -- | Character parser.@@ -155,3 +165,22 @@ skipSpace :: Parser () skipSpace = takeWhile isSpace >> return () {-# INLINE skipSpace #-}++numeric :: String -> (LB.ByteString -> Maybe (a,LB.ByteString)) -> Parser a+numeric desc f = do+ s <- getInput+ case f s of+ Nothing -> fail desc+ Just (i,s') -> setInput s' >> return i+ +-- | Parse an integer. The position counter is not updated.+int :: Parser Int+int = numeric "Int" LB.readInt++-- | Parse an integer. The position counter is not updated.+integer :: Parser Integer+integer = numeric "Integer" LB.readInteger++-- | Parse a Double. The position counter is not updated.+double :: Parser Double+double = numeric "Double" readDouble
src/Data/ParserCombinators/Attoparsec/Internal.hs view
@@ -28,6 +28,8 @@ -- * Things vaguely like those in @Parsec.Combinator@ (and @Parsec.Prim@) , try+ , many+ , many1 , manyTill , eof , skipMany@@ -52,10 +54,12 @@ -- * Miscellaneous functions. , getInput , getConsumed+ , setInput , takeWhile , takeWhile1 , takeTill , takeAll+ , takeCount , skipWhile , notEmpty , match@@ -77,6 +81,9 @@ type ParseError = String +-- State invariants:+-- * If both strict and lazy bytestrings are empty, the entire input+-- is considered to be empty. data S = S {-# UNPACK #-} !SB.ByteString LB.ByteString {-# UNPACK #-} !Int64@@ -167,6 +174,10 @@ getInput :: Parser LB.ByteString getInput = Parser $ \s@(S sb lb _) -> Right (sb +: lb, s) +-- | Set the remaining input.+setInput :: LB.ByteString -> Parser ()+setInput bs = Parser $ \(S _ _ n) -> Right ((), mkState bs n)+ -- | Get number of bytes consumed so far. getConsumed :: Parser Int64 getConsumed = Parser $ \s@(S _ _ n) -> Right (n, s)@@ -176,7 +187,7 @@ satisfy p = Parser $ \s@(S sb lb n) -> case SB.uncons sb of- Just (c, sb') | p c -> Right (c, S sb' lb (n + 1))+ Just (c, sb') | p c -> Right (c, mkState (sb' +: lb) (n + 1)) | otherwise -> Left (sb +: lb, []) Nothing -> unParser (nextChunk >> satisfy p) s {-# INLINE satisfy #-}@@ -215,14 +226,16 @@ endOfLine :: Parser () endOfLine = Parser $ \(S sb lb n) -> let bs = sb +: lb- in case I.w2c (U.unsafeHead sb) of- '\n' -> Right ((), mkState (LB.tail bs) (n + 1))- '\r' -> let (h,t) = LB.splitAt 2 bs- rn = L8.pack "\r\n"- in if h == rn- then Right ((), mkState t (n + 2))- else Right ((), mkState (LB.tail bs) (n + 1))- _ -> Left (bs, ["EOL"])+ in if SB.null sb+ then Left (bs, ["EOL"])+ else case I.w2c (U.unsafeHead sb) of+ '\n' -> Right ((), mkState (LB.tail bs) (n + 1))+ '\r' -> let (h,t) = LB.splitAt 2 bs+ rn = L8.pack "\r\n"+ in if h == rn+ then Right ((), mkState t (n + 2))+ else Right ((), mkState (LB.tail bs) (n + 1))+ _ -> Left (bs, ["EOL"]) -- | Satisfy a literal string, after applying a transformation to both -- it and the matching text.@@ -260,6 +273,15 @@ let bs = sb +: lb in Right (bs, mkState LB.empty (n + LB.length bs)) +takeCount :: Int64 -> Parser LB.ByteString+takeCount k =+ Parser $ \(S sb lb n) ->+ let bs = sb +: lb+ (h,t) = LB.splitAt k bs+ in if LB.length h == k+ then Right (h, mkState t (n + k))+ else Left (bs, [show k ++ " bytes"])+ -- | Consume characters while the predicate is true. takeWhile :: (Word8 -> Bool) -> Parser LB.ByteString takeWhile p =@@ -293,6 +315,12 @@ manyTill p end = scan where scan = (end >> return []) <|> liftM2 (:) p scan +many :: Parser a -> Parser [a]+many p = ((:) <$> p <*> many p) <|> return []++many1 :: Parser a -> Parser [a]+many1 p = (:) <$> p <*> many p+ -- |'skipMany' - skip zero or many instances of the parser skipMany :: Parser a -> Parser () skipMany p = scan@@ -342,7 +370,7 @@ parseAt p bs n = case unParser p (mkState bs n) of Left (bs', msg) -> (bs', Left $ showError msg)- Right (a, S sb lb n') -> (sb +: lb, Right (a, n'))+ Right (a, ~(S sb lb n')) -> (sb +: lb, Right (a, n')) where showError [""] = "Parser error\n" showError [msg] = "Parser error, expected:\n" ++ msg ++ "\n"