parsimony 1 → 1.0.1
raw patch · 5 files changed
+68/−30 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Parsimony: Error :: !ParseError -> Reply s a
- Parsimony: Ok :: !a -> !State s -> Reply s a
- Parsimony: data Reply s a
- Parsimony.Stream: instance (Stream a Word8) => Stream (ASCII a) Char
- Parsimony.Stream: instance (Token a) => Stream [a] a
- Parsimony.UserState: instance (Stream stream token) => Stream (UserState user stream) token
+ Parsimony.Stream: instance Stream a Word8 => Stream (ASCII a) Char
+ Parsimony.Stream: instance Token a => Stream [a] a
+ Parsimony.UserState: instance Stream stream token => Stream (UserState user stream) token
- Parsimony: (*>) :: (Applicative f) => forall a b. f a -> f b -> f b
+ Parsimony: (*>) :: Applicative f => forall a b. f a -> f b -> f b
- Parsimony: (<$) :: (Functor f) => forall a b. a -> f b -> f a
+ Parsimony: (<$) :: Functor f => forall a b. a -> f b -> f a
- Parsimony: (<$>) :: (Functor f) => (a -> b) -> f a -> f b
+ Parsimony: (<$>) :: Functor f => (a -> b) -> f a -> f b
- Parsimony: (<*) :: (Applicative f) => forall a b. f a -> f b -> f a
+ Parsimony: (<*) :: Applicative f => forall a b. f a -> f b -> f a
- Parsimony: (<*>) :: (Applicative f) => forall a b. f (a -> b) -> f a -> f b
+ Parsimony: (<*>) :: Applicative f => forall a b. f (a -> b) -> f a -> f b
- Parsimony: (<|>) :: (Alternative f) => forall a. f a -> f a -> f a
+ Parsimony: (<|>) :: Alternative f => forall a. f a -> f a -> f a
- Parsimony: anyToken :: (Stream s t) => Parser s t
+ Parsimony: anyToken :: Stream s t => Parser s t
- Parsimony: empty :: (Alternative f) => forall a. f a
+ Parsimony: empty :: Alternative f => forall a. f a
- Parsimony: eof :: (Stream s t) => Parser s ()
+ Parsimony: eof :: Stream s t => Parser s ()
- Parsimony: match :: (Eq a) => (a -> String) -> [a] -> Parser t a -> Parser t ()
+ Parsimony: match :: Eq a => (a -> String) -> [a] -> Parser t a -> Parser t ()
- Parsimony: notFollowedBy :: (Show a) => Parser t a -> Parser t ()
+ Parsimony: notFollowedBy :: Show a => Parser t a -> Parser t ()
- Parsimony: optional :: (Alternative f) => f a -> f (Maybe a)
+ Parsimony: optional :: Alternative f => f a -> f (Maybe a)
- Parsimony: pure :: (Applicative f) => forall a. a -> f a
+ Parsimony: pure :: Applicative f => forall a. a -> f a
- Parsimony.Char: alphaNum :: (Stream s Char) => Parser s Char
+ Parsimony.Char: alphaNum :: Stream s Char => Parser s Char
- Parsimony.Char: anyChar :: (Stream s Char) => Parser s Char
+ Parsimony.Char: anyChar :: Stream s Char => Parser s Char
- Parsimony.Char: char :: (Stream s Char) => Char -> Parser s Char
+ Parsimony.Char: char :: Stream s Char => Char -> Parser s Char
- Parsimony.Char: digit :: (Stream s Char) => Parser s Char
+ Parsimony.Char: digit :: Stream s Char => Parser s Char
- Parsimony.Char: hexDigit :: (Stream s Char) => Parser s Char
+ Parsimony.Char: hexDigit :: Stream s Char => Parser s Char
- Parsimony.Char: letter :: (Stream s Char) => Parser s Char
+ Parsimony.Char: letter :: Stream s Char => Parser s Char
- Parsimony.Char: lower :: (Stream s Char) => Parser s Char
+ Parsimony.Char: lower :: Stream s Char => Parser s Char
- Parsimony.Char: newline :: (Stream s Char) => Parser s Char
+ Parsimony.Char: newline :: Stream s Char => Parser s Char
- Parsimony.Char: noneOf :: (Stream s Char) => [Char] -> Parser s Char
+ Parsimony.Char: noneOf :: Stream s Char => [Char] -> Parser s Char
- Parsimony.Char: octDigit :: (Stream s Char) => Parser s Char
+ Parsimony.Char: octDigit :: Stream s Char => Parser s Char
- Parsimony.Char: oneOf :: (Stream s Char) => [Char] -> Parser s Char
+ Parsimony.Char: oneOf :: Stream s Char => [Char] -> Parser s Char
- Parsimony.Char: satisfy :: (Stream s Char) => (Char -> Bool) -> Parser s Char
+ Parsimony.Char: satisfy :: Stream s Char => (Char -> Bool) -> Parser s Char
- Parsimony.Char: space :: (Stream s Char) => Parser s Char
+ Parsimony.Char: space :: Stream s Char => Parser s Char
- Parsimony.Char: spaces :: (Stream s Char) => Parser s ()
+ Parsimony.Char: spaces :: Stream s Char => Parser s ()
- Parsimony.Char: string :: (Stream s Char) => String -> Parser s String
+ Parsimony.Char: string :: Stream s Char => String -> Parser s String
- Parsimony.Char: tab :: (Stream s Char) => Parser s Char
+ Parsimony.Char: tab :: Stream s Char => Parser s Char
- Parsimony.Char: upper :: (Stream s Char) => Parser s Char
+ Parsimony.Char: upper :: Stream s Char => Parser s Char
- Parsimony.Stream: class (Token token) => Stream stream token | stream -> token
+ Parsimony.Stream: class Token token => Stream stream token | stream -> token
- Parsimony.Stream: getToken :: (Stream stream token) => PrimParser stream token
+ Parsimony.Stream: getToken :: Stream stream token => PrimParser stream token
- Parsimony.Stream: showToken :: (Token token) => token -> String
+ Parsimony.Stream: showToken :: Token token => token -> String
- Parsimony.Stream: updatePos :: (Token token) => token -> SourcePos -> SourcePos
+ Parsimony.Stream: updatePos :: Token token => token -> SourcePos -> SourcePos
Files
- parsimony.cabal +2/−2
- src/Parsimony.hs +2/−3
- src/Parsimony/Combinator.hs +4/−1
- src/Parsimony/Prim.hs +59/−23
- src/Parsimony/Stream.hs +1/−1
parsimony.cabal view
@@ -1,5 +1,5 @@ name: parsimony-version: 1+version: 1.0.1 license: BSD3 license-file: LICENSE author: Daan Leijen <daan@cs.uu.nl>, Iavor S. Diatchki <iavor.diatchki@gmail.com>@@ -14,7 +14,7 @@ Like Parsec, it is simple, safe, well documented, convenient, with good error messages, and fast. In addition, Parsimony adds support for working with differet types of input such as- byte strings (for compact input representation) and+ byte strings (for compat input representation) and lazy byte strings (for parsing large amounts of data). It also supports working with text in different character encodings such as UTF8.
src/Parsimony.hs view
@@ -29,7 +29,7 @@ , manyTill , count , foldMany-+ -- * Optoinal content , option, optional @@ -41,7 +41,7 @@ , notFollowedBy, notFollowedBy' , lookAhead, anyToken - -- * Errors+ -- * Errors , (<?>), unexpected, empty, parseError, labels -- * Parser State@@ -53,7 +53,6 @@ -- * Primitive Parsers , PrimParser- , Reply(..) , primParser ) where
src/Parsimony/Combinator.hs view
@@ -65,7 +65,10 @@ sepEndBy p sep = option [] (sepEndBy1 p sep) sepEndBy1 :: Parser t a -> Parser t sep -> Parser t [a]-sepEndBy1 p sep = sepBy1 p sep <* optional sep+sepEndBy1 p sep = do x <- p+ reverse <$> foldManyWhile (flip (:)) [x] loopP+ where+ loopP = option Nothing (sep >> option Nothing (Just <$> p)) -- directly recursive count :: Int -> Parser t a -> Parser t [a]
src/Parsimony/Prim.hs view
@@ -16,7 +16,7 @@ ( Parser, PrimParser, Reply(..) , runParser, primParser , parseError, try, lookAhead, labels- , foldMany, skipMany, match+ , foldMany, foldManyWhile, skipMany, match , State(..), getState, updateState, mapState ) where @@ -154,22 +154,54 @@ {-# INLINE foldMany #-} foldMany :: (b -> a -> b) -> b -> Parser t a -> Parser t b-foldMany cons nil p = P (outer nil)+foldMany cons nil p = P $ \s ->+ case unP p s of+ R False (Ok {}) -> crash "Parsimony.foldMany"+ R False (Error _) -> R False $ Ok nil s+ R True (Ok x s1) -> R True $ (walk $! cons nil x) s1+ R True (Error err) -> R True $ Error err++ -- NOTE: this is written like this because after the first iteration+ -- we already know weather the parser will be consuming input. where- -- not consumed- outer xs s =+ walk xs s = case unP p s of- R False (Ok x s1) -> (outer $! cons xs x) s1- R False (Error _) -> R False $ Ok xs s- R True (Ok x s1) -> R True $ (inner $! cons xs x) s1- R True (Error err) -> R True $ Error err+ R False (Ok {}) -> crash "Parsimony.foldMany"+ R False (Error _) -> Ok xs s+ R True (Ok x s1) -> (walk $! cons xs x) s1+ R True (Error e) -> Error e - -- consumed- inner xs s =++-- | Apply a parser repeatedly, combining the results with the+-- given functions. This function is similar to the strict 'foldl'.+-- We stop on one of the following conditions:+-- * an application of the parser fails without consuming any input,+-- * the pearser returns 'Nothing' as a result.+-- If the parser fails after it has consumed some input, then+-- the repeated parser will also fail.++{-# INLINE foldManyWhile #-}+foldManyWhile :: (b -> a -> b) -> b -> Parser t (Maybe a) -> Parser t b+foldManyWhile cons nil p = P $ \s ->+ case unP p s of+ R False (Ok Nothing _) -> R False $ Ok nil s+ R False (Ok {}) -> crash "Parsimony.foldManyWhile"+ R False (Error _) -> R False $ Ok nil s+ R True (Ok Nothing s1) -> R True $ Ok nil s1+ R True (Ok (Just x) s1) -> R True $ (walk $! cons nil x) s1+ R True (Error err) -> R True $ Error err++ -- NOTE: this is written like this because after the first iteration+ -- we already know weather the parser will be consuming input.+ where+ walk xs s = case unP p s of- R _ (Ok x s1) -> (inner $! cons xs x) s1- R False (Error _) -> Ok xs s- R True (Error e) -> Error e+ R False (Ok Nothing _) -> Ok xs s+ R False (Ok {}) -> crash "Parsimony.foldManyWhile"+ R False (Error _) -> Ok xs s+ R True (Ok Nothing s1) -> Ok xs s1+ R True (Ok (Just x) s1) -> (walk $! cons xs x) s1+ R True (Error e) -> Error e -- | Apply a parser repeatedly, ignoring the results.@@ -179,23 +211,23 @@ {-# INLINE skipMany #-} skipMany :: Parser t a -> Parser t ()-skipMany p = P outer+skipMany p = P $ \s -> -- pFold specialized for a common case + case unP p s of+ R False (Ok {}) -> crash "Parsimony.skipMany"+ R False (Error _) -> R False $ Ok () s+ R True (Ok _ s1) -> R True $ walk s1+ R True (Error err) -> R True $ Error err+ -- NOTE: this is written like this because after the first iteration -- we already know weather the parser will be consuming input. where- outer s =- case unP p s of- R False (Ok _ s1) -> outer s1- R False (Error _) -> R False $ Ok () s- R True (Ok _ s1) -> R True $ inner s1- R True (Error err) -> R True $ Error err-- inner s =+ walk s = case unP p s of- R _ (Ok _ s1) -> inner s1+ R False (Ok {}) -> crash "Parsimony.skipMany" R False (Error _) -> Ok () s+ R True (Ok _ s1) -> walk s1 R True (Error e) -> Error e @@ -235,6 +267,10 @@ R _ (Error e) -> Error e ++-- | We use to let the user know that we have entered an infinity loop.+crash :: String -> a+crash f = error $ f ++ " applied to a parser that accepts the empty string." -- Instances -------------------------------------------------------------------
src/Parsimony/Stream.hs view
@@ -17,7 +17,7 @@ -module Parsimony.Stream +module Parsimony.Stream ( Token(..), Stream(..) , ASCII, UTF8, ascii, utf8 ) where