packages feed

JustParse 2.0 → 2.1

raw patch · 7 files changed

+246/−52 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.JustParse.Combinator: manyTill :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+ Data.JustParse.Combinator: takeWhile1 :: Stream s t => (t -> Bool) -> Parser s [t]
+ Data.JustParse.Combinator: takeWhile1_ :: Stream s t => (t -> Bool) -> Parser s [t]
+ Data.JustParse.Combinator: try :: Stream s t => Parser s a -> Parser s a
+ Data.JustParse.Numeric: decDigit :: Stream s Char => Parser s Int
+ Data.JustParse.Numeric: hexDigit :: Stream s Char => Parser s Int
+ Data.JustParse.Numeric: unsignedDecInt :: Stream s Char => Parser s Int
+ Data.JustParse.Numeric: unsignedDecInt_ :: Stream s Char => Parser s Int
+ Data.JustParse.Numeric: unsignedHexInt :: Stream s Char => Parser s Int
+ Data.JustParse.Numeric: unsignedHexInt_ :: Stream s Char => Parser s Int

Files

JustParse.cabal view
@@ -1,5 +1,5 @@ name:                JustParse-version:             2.0+version:             2.1 synopsis:            A simple and comprehensive Haskell parsing library description:         A simple and comprehensive Haskell parsing library homepage:            https://github.com/grantslatton/JustParse@@ -25,4 +25,4 @@         base >= 4.2 && < 5     hs-source-dirs: src     extensions: MultiParamTypeClasses, Rank2Types, FlexibleInstances, FlexibleContexts, Safe, TupleSections, UndecidableInstances-    ghc-options: -O2 -Wall+    ghc-options: -O2 
src/Data/JustParse.hs view
@@ -8,7 +8,7 @@ Portability : portable -}  ---{-# LANGUAGE Safe #-}+{-# LANGUAGE Safe #-} module Data.JustParse (     -- * Overview     -- $overview
src/Data/JustParse/Char.hs view
@@ -10,7 +10,7 @@ Several useful parsers for dealing with 'String's. -} ---{-# LANGUAGE Safe #-}+{-# LANGUAGE Safe #-} module Data.JustParse.Char (     char,     anyChar,@@ -40,74 +40,92 @@ -- | Parse a specic char. char :: Stream s Char => Char -> Parser s Char char = token+{-# INLINE char #-}  -- | Parse any char. anyChar :: Stream s Char =>  Parser s Char anyChar = anyToken+{-# INLINE anyChar #-}  -- | Parse a specific char, ignoring case. caseInsensitiveChar :: Stream s Char => Char -> Parser s Char caseInsensitiveChar c = char (toUpper c) <|> char (toLower c)+{-# INLINE caseInsensitiveChar #-}  -- | Parse any char that is ASCII. ascii :: Stream s Char =>  Parser s Char ascii = satisfy isAscii+{-# INLINE ascii #-}  -- | Parse any char that is Latin-1. latin1 :: Stream s Char =>  Parser s Char latin1 = satisfy isLatin1+{-# INLINE latin1 #-}  -- | Parse a control character. control :: Stream s Char =>  Parser s Char control = satisfy isControl+{-# INLINE control #-}  -- | Parse a space. space :: Stream s Char =>  Parser s Char space = satisfy isSpace+{-# INLINE space #-}  -- | Parse a lowercase character. lower :: Stream s Char =>  Parser s Char lower = satisfy isLower+{-# INLINE lower #-}  -- | Parse an uppercase character. upper :: Stream s Char =>  Parser s Char upper = satisfy isUpper+{-# INLINE upper #-}  -- | Parse an alphabetic character. alpha :: Stream s Char =>  Parser s Char alpha = satisfy isAlpha+{-# INLINE alpha #-}  -- | Parse an alphanumeric character. alphaNum :: Stream s Char =>  Parser s Char alphaNum = satisfy isAlphaNum+{-# INLINE alphaNum #-}  -- | Parse a printable (non-control) character. print :: Stream s Char =>  Parser s Char print = satisfy isPrint+{-# INLINE print #-}  -- | Parse a digit. digit :: Stream s Char =>  Parser s Char digit = satisfy isDigit+{-# INLINE digit #-}  -- | Parse an octal digit. octDigit :: Stream s Char =>  Parser s Char octDigit = satisfy isOctDigit+{-# INLINE octDigit #-}  -- | Parse a hexadeciaml digit. hexDigit :: Stream s Char =>  Parser s Char hexDigit = satisfy isHexDigit+{-# INLINE hexDigit #-}  -- | Parse a specific string. string :: Stream s Char => String -> Parser s String string = mapM char +{-# INLINE string #-}  -- | Parse a specfic string, ignoring case. caseInsensitiveString :: Stream s Char => String -> Parser s String caseInsensitiveString = mapM caseInsensitiveChar +{-# INLINE caseInsensitiveString #-}  -- | Parses until a newline, carriage return + newline, or newline + carriage return. eol :: Stream s Char => Parser s String eol = choice [string "\r\n", string "\n\r", string "\n"]+{-# INLINE eol #-}  -- | Makes common types such as 'String's into a Stream. instance Eq t => Stream [t] t where
src/Data/JustParse/Combinator.hs view
@@ -10,8 +10,7 @@ The bread and butter of combinatory parsing. -} ---{-# LANGUAGE Safe #-}---{-# LANGUAGE TupleSections #-}+{-# LANGUAGE Safe #-} module Data.JustParse.Combinator (     -- * Utility Parsers     assert,@@ -24,6 +23,7 @@     option,     optional,     test,+    try,     (<|>),      -- * Token Parsers@@ -44,6 +44,7 @@     exactly,     many,     many1,+    manyTill,     mN,     sepBy,     sepBy1,@@ -52,6 +53,7 @@     sepEndBy,     sepEndBy1,     takeWhile,+    takeWhile1,      -- * Group Parsers     choice,@@ -82,7 +84,8 @@     sepEndBy1_,     skipMany_,     skipMany1_,-    takeWhile_+    takeWhile_,+    takeWhile1_ ) where  import Prelude hiding ( print, length, takeWhile )@@ -104,58 +107,82 @@         Just s' -> case uncons s' of             Nothing -> [Partial $ parse (satisfy f)]             Just (x, xs) -> [Done x (Just xs) | f x]+{-# INLINE satisfy #-}  -- | A parser that succeeds on 'True' and fails on 'False'.  guard :: Stream s t => Bool -> Parser s () guard = M.guard+{-# INLINE guard #-}  -- | Synonym of 'guard'. assert :: Stream s t => Bool -> Parser s () assert = guard+{-# INLINE assert #-}  -- | Only succeeds when supplied with 'Nothing'. eof :: Stream s t => Parser s () eof = notFollowedBy anyToken+{-# INLINE eof #-}  -- | Parse a token that is a member of the list of tokens. oneOf :: (Eq t, Stream s t) => [t] -> Parser s t oneOf ts = satisfy (`elem` ts)+{-# INLINE oneOf #-}  -- | Parse a token that is not a member of the list of tokens. noneOf :: (Eq t, Stream s t) => [t] -> Parser s t noneOf ts = satisfy (`notElem` ts)+{-# INLINE noneOf #-}  -- | Parse a specific token. token :: (Eq t, Stream s t) => t -> Parser s t token t = satisfy (==t)+{-# INLINE token #-}  -- | Parse any token. anyToken :: Stream s t => Parser s t anyToken = satisfy (const True)+{-# INLINE anyToken #-}  -- | Parse tokens while a predicate remains true. takeWhile :: Stream s t => (t -> Bool) -> Parser s [t] takeWhile = many . satisfy+{-# INLINE takeWhile #-} +-- | Parse one or more tokens while a predicate remains true.+takeWhile1 :: Stream s t => (t -> Bool) -> Parser s [t]+takeWhile1 = many1 . satisfy+{-# INLINE takeWhile1 #-}+ -- | Branches every iteration where one branch stops and one branch  -- continues. takeWhile_ :: Stream s t => (t -> Bool) -> Parser s [t] takeWhile_ = many_ . satisfy+{-# INLINE takeWhile_ #-} +-- | Branches every iteration where one branch stops and one branch +-- continues.+takeWhile1_ :: Stream s t => (t -> Bool) -> Parser s [t]+takeWhile1_ = many1_ . satisfy+{-# INLINE takeWhile1_ #-}+ -- | Splits the current parse branch between the two parsers. branch :: Parser s a -> Parser s a -> Parser s a branch a b = Parser $ \s -> parse a s ++ parse b s+{-# INLINE branch #-}  infixr 1 <||> -- | Infix version of 'branch'. (<||>) :: Parser s a -> Parser s a -> Parser s a (<||>) = branch+{-# INLINE (<||>) #-}  -- | @mN m n p@ parses between @m@ and @n@ occurences of @p@, inclusive. mN :: Stream s t => Int -> Int -> Parser s a -> Parser s [a] mN _ 0 _ = Parser $ \s -> [Done [] s] mN 0 n p = M.liftM2 (:) p (mN 0 (n-1) p) A.<|> return [] mN m n p = M.liftM2 (:) p (mN (m-1) (n-1) p)+{-# INLINE mN #-}  -- | Branches every iteration where one branch stops and one branch  -- continues.@@ -163,46 +190,56 @@ mN_ _ 0 _ = Parser $ \s -> [Done [] s] mN_ 0 n p = M.liftM2 (:) p (mN 0 (n-1) p) <||> return [] mN_ m n p = M.liftM2 (:) p (mN (m-1) (n-1) p)+{-# INLINE mN_ #-}  -- | Synonym of 'count'. exactly :: Stream s t => Int -> Parser s a -> Parser s [a] exactly n = mN n n+{-# INLINE exactly #-}  -- | Applies a parser at least @n@ times. atLeast :: Stream s t => Int -> Parser s a -> Parser s [a] atLeast n = mN n (-1)+{-# INLINE atLeast #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. atLeast_ :: Stream s t => Int -> Parser s a -> Parser s [a] atLeast_ n = mN_ n (-1)+{-# INLINE atLeast_ #-}  -- | Applies a parser at most @n@ times. atMost :: Stream s t => Int -> Parser s a -> Parser s [a] atMost  = mN 0+{-# INLINE atMost #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. atMost_ :: Stream s t => Int -> Parser s a -> Parser s [a] atMost_ = mN 0+{-# INLINE atMost_ #-}  -- | Applies a parser zero or more times. many :: Stream s t => Parser s a -> Parser s [a] many = A.many+{-# INLINE many #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. many_ :: Parser s a -> Parser s [a] many_ p = return [] <||> M.liftM2 (:) p (many_ p)+{-# INLINE many_ #-}  -- | Applies a parser one or more times. many1 :: Stream s t => Parser s a -> Parser s [a] many1 p = M.liftM2 (:) p (many p)+{-# INLINE many1 #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. many1_ :: Parser s a -> Parser s [a] many1_ p = M.liftM2 (:) p (many_ p)+{-# INLINE many1_ #-}  -- | Return 'True' if the parser would succeed if one were to apply it, -- otherwise, it returns 'False'. It does not consume input.@@ -213,31 +250,37 @@         case a of             Nothing -> return False             _ -> return True+{-# INLINE test #-}  infixr 1 <|> -- | @a \<|\> b@ is equivalent to @'choice' [a,b]@. That is, first @a@ is -- tried, and if it yields no results, @b@ is tried. (<|>) :: Stream s t => Parser s a -> Parser s a -> Parser s a (<|>) = (A.<|>)+{-# INLINE (<|>) #-}  -- | Attempt to apply each parser in the list in order until one succeeds. choice :: Stream s t => [Parser s a] -> Parser s a choice = foldl1' (A.<|>) +{-# INLINE choice #-}  -- | Given a list of parsers, split off a branch for each one. choice_ :: Stream s t => [Parser s a] -> Parser s a choice_ = foldl1' (<||>)+{-# INLINE choice_ #-}  -- | Like 'choice', but returns the index of the successful parser as well -- as the result. select :: Stream s t => [Parser s a] -> Parser s (Int, a) select [] = M.mzero select (p:ps) = M.liftM (0,) p <|> M.liftM (\(x,y) -> (x+1,y)) (select ps)+{-# INLINE select #-}  -- | Like 'choice_', but returns the index of the successful parser. select_ :: Stream s t => [Parser s a] -> Parser s (Int, a) select_ [] = M.mzero select_ (p:ps) = M.liftM (0,) p <||> M.liftM (\(x,y) -> (x+1,y)) (select_ ps)+{-# INLINE select_ #-}  -- | Modifies a parser so that it will ony return the most consumptive -- succesful results. @@ -250,6 +293,7 @@         g xs              | all isDone xs = [minimumBy (comparing (f . leftover)) xs]             | otherwise = [Partial $ \s -> g $ extend s xs] +{-# INLINE greedy #-}  -- | Attempts to apply a parser and returns a default value if it fails. option :: Stream s t => a -> Parser s a -> Parser s a@@ -259,39 +303,47 @@         case r of             Nothing -> return v             Just v' -> return v'+{-# INLINE option #-}  -- | Splits off two branches, one where the parse is attempted, and one  -- where it is not. option_ :: Stream s t => a -> Parser s a -> Parser s a option_ v p = option v p <||> return v+{-# INLINE option_ #-}  -- | Attempts to apply the parser, returning 'Nothing' upon failure, or -- the result wrapped in a 'Just'. optional :: Stream s t => Parser s a -> Parser s (Maybe a) optional = A.optional+{-# INLINE optional #-}  -- | Splits off two branches, one where the parse is attempted, and one  -- where it is not. optional_ :: Stream s t => Parser s a -> Parser s (Maybe a) optional_ p = M.liftM Just p <||> return Nothing+{-# INLINE optional_ #-}  -- | @sepBy1 p s@ parses many  occurences of @p@ separated by @s@. sepBy :: Stream s t => Parser s a -> Parser s b -> Parser s [a] sepBy p s = sepBy1 p s A.<|> return []+{-# INLINE sepBy #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. sepBy_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a] sepBy_ p s = sepBy1_ p s <||> return []+{-# INLINE sepBy_ #-}  -- | @sepBy1 p s@ parses one or more occurences of @p@ separated by @s@. sepBy1 :: Stream s t => Parser s a -> Parser s b -> Parser s [a] sepBy1 p s = M.liftM2 (:) p (many (s >> p))+{-# INLINE sepBy1 #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. sepBy1_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a] sepBy1_ p s = M.liftM2 (:) p (many_ (s >> p))+{-# INLINE sepBy1_ #-}  -- | Applies the parser and returns its result, but resets -- the 'Stream' as if it consumed nothing.@@ -305,79 +357,95 @@                 _ -> parse (lookAhead v) (streamAppend s s')     in         map g (p s)+{-# INLINE lookAhead #-}  -- | @count n p@ parses exactly @n@ occurences of @p@. count :: Stream s t => Int -> Parser s a -> Parser s [a] count = exactly+{-# INLINE count #-}  -- | Identical to 'many' except the result is discarded. skipMany :: Stream s t => Parser s a -> Parser s () skipMany = M.void . many+{-# INLINE skipMany #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. skipMany_ :: Stream s t => Parser s a -> Parser s () skipMany_ = M.void . many_+{-# INLINE skipMany_ #-}  -- | Identical to 'many1' except the result is discarded. skipMany1 :: Stream s t => Parser s a -> Parser s () skipMany1 = M.void . many1+{-# INLINE skipMany1 #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. skipMany1_ :: Stream s t => Parser s a -> Parser s () skipMany1_ = M.void . many1_+{-# INLINE skipMany1_ #-}  -- | @endBy p s@ parses multiple occurences of @p@ separated and ended by -- @s@. endBy :: Stream s t => Parser s a -> Parser s b -> Parser s [a] endBy p s = many (p A.<* s)+{-# INLINE endBy #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. endBy_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a] endBy_ p s = many_ (p A.<* s)+{-# INLINE endBy_ #-}  -- | @endBy1 p s@ parses one or more occurences of @p@ separated and ended  -- by @s@. endBy1 :: Stream s t => Parser s a -> Parser s b -> Parser s [a] endBy1 p s = many1 (p A.<* s)+{-# INLINE endBy1 #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. endBy1_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a] endBy1_ p s = many1_ (p A.<* s)+{-# INLINE endBy1_ #-}  -- | @sepEndBy p s@ parses multiple occurences of @p@ separated and  -- optionally ended by @s@. sepEndBy :: Stream s t => Parser s a -> Parser s b -> Parser s [a] sepEndBy p s = sepBy p s A.<* optional s+{-# INLINE sepEndBy #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. sepEndBy_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a] sepEndBy_ p s = sepBy_ p s A.<* optional s+{-# INLINE sepEndBy_ #-}  -- | @sepEndBy p s@ parses one or more occurences of @p@ separated and  -- optionally ended by @s@. sepEndBy1 :: Stream s t => Parser s a -> Parser s b -> Parser s [a] sepEndBy1 p s = sepBy1 p s A.<* optional s+{-# INLINE sepEndBy1 #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. sepEndBy1_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a] sepEndBy1_ p s = sepBy1_ p s A.<* optional s+{-# INLINE sepEndBy1_ #-}  -- | @chainr p o x@ parses zero or more occurences of @p@ separated by @o@.  -- The result is the left associative application of the functions to the -- values. If @p@ succeeds zero times, @x@ is returned. chainl :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a chainl p o x = chainl1 p o <|> return x+{-# INLINE chainl #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. chainl_ :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a chainl_ p o x = chainl1_ p o <||> return x+{-# INLINE chainl_ #-}  -- | Like 'chainl', but a minimum of one occurence of @p@ must be parsed. chainl1 :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> Parser s a@@ -389,6 +457,7 @@                 y <- p                 f (g x y)             <|> return x+{-# INLINE chainl1 #-}  -- | Branches every iteration where one branch stops and one branch  -- continues.@@ -401,15 +470,18 @@                 y <- p                 f (g x y)             <||> return x+{-# INLINE chainl1_ #-}  -- | Like 'chainl', but right associative. chainr :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a chainr p o x = chainr1 p o <|> return x+{-# INLINE chainr #-}  -- | Branches every iteration where one branch stops and one branch  -- continues. chainr_ :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a chainr_ p o x = chainr1_ p o <||> return x+{-# INLINE chainr_ #-}  -- | Like 'chainl1', but right associative. chainr1 :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> Parser s a@@ -421,6 +493,7 @@                 y <- chainr1 p o                 return (g x y)             <|> return x+{-# INLINE chainr1 #-}  -- | Branches every iteration where one branch stops and one branch  -- continues.@@ -433,10 +506,12 @@                 y <- chainr1_ p o                 return (g x y)             <||> return x+{-# INLINE chainr1_ #-}  -- | Only succeeds when the given parser fails. Consumes no input. notFollowedBy :: Stream s t => Parser s a -> Parser s () notFollowedBy p = test p >>= assert . not+{-# INLINE notFollowedBy #-}  -- | @manyTill a b@ parses multiple occurences of @a@ until @b@ would  -- succeed if tried.@@ -447,19 +522,23 @@         if b              then return []             else M.liftM2 (:) p (manyTill p e)+{-# INLINE manyTill #-}  -- | Does nothing -- only used for @Parsec@ compatability. try :: Stream s t => Parser s a -> Parser s a try = id+{-# INLINE try #-}  -- | @eitherP a b@ returns the result wrapped in a 'Left' if @a@ succeeds or -- a 'Right' if @b@ succeeds eitherP :: Stream s t => Parser s a -> Parser s b -> Parser s (Either a b) eitherP a b = M.liftM Left a <|> M.liftM Right b+{-# INLINE eitherP #-}  -- | Like 'eitherP', but tries both @a@ and @b@. eitherP_ :: Stream s t => Parser s a -> Parser s b -> Parser s (Either a b) eitherP_ a b = M.liftM Left a <||> M.liftM Right b+{-# INLINE eitherP_ #-}  -- | Parses a sequence of parsers in any order. perm :: Stream s t => [Parser s a] -> Parser s [a]@@ -468,6 +547,7 @@     do         (i, r) <- select ps         M.liftM (r:) (perm (let (a,b) = splitAt i ps in a ++ tail b)) +{-# INLINE perm #-}  -- | Parses a sequence of parsers in all possible orders. perm_ :: Stream s t => [Parser s a] -> Parser s [a]@@ -476,3 +556,4 @@     do         (i, r) <- select_ ps         M.liftM (r:) (perm_ (let (a,b) = splitAt i ps in a ++ tail b)) +{-# INLINE perm_ #-}
src/Data/JustParse/Internal.hs view
@@ -14,7 +14,7 @@ {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FunctionalDependencies #-}---{-# LANGUAGE Safe #-}+{-# LANGUAGE Safe #-}  module Data.JustParse.Internal (     Stream (..),@@ -59,28 +59,38 @@  instance Stream s t => Monoid (Parser s a) where     mempty = mzero+    {-# INLINE mempty #-}     mappend = mplus+    {-# INLINE mappend #-}  instance Functor (Parser s) where     fmap f (Parser p) = Parser $ map (fmap f) . p +    {-# INLINE fmap #-}  instance Applicative (Parser s) where     pure = return +    {-# INLINE pure #-}     (<*>) = ap+    {-# INLINE (<*>) #-}  instance Stream s t => Alternative (Parser s) where     empty = mzero+    {-# INLINE empty #-}     (<|>) = mplus+    {-# INLINE (<|>) #-}  instance Monad (Parser s) where     return v = Parser $ \s -> [Done v s] +    {-# INLINE return #-}     (Parser p) >>= f = Parser $ p >=> g         where             g (Done a s) = parse (f a) s              g (Partial p) = [Partial $ p >=> g] +    {-# INLINE (>>=) #-}  instance Stream s t => MonadPlus (Parser s) where     mzero = Parser $ const []+    {-# INLINE mzero #-}     mplus a b = Parser $ \s ->         let             g [] = parse b s@@ -101,6 +111,7 @@          in             g (parse a s) +    {-# INLINE mplus #-}  data Result s a      -- | A @Partial@ wraps the same function as a Parser. Supply it with @@ -121,28 +132,35 @@ isDone :: Result s a -> Bool isDone (Done _ _) = True isDone _ = False+{-# INLINE isDone #-}  isPartial :: Result s a -> Bool isPartial (Partial _) = True isPartial _ = False+{-# INLINE isPartial #-}  -- | Lifts a parser into the result space toPartial :: Parser s a -> [Result s a] toPartial (Parser p) = [Partial p]+{-# INLINE toPartial #-}  instance Functor (Result s) where     fmap f (Partial p) = Partial $ map (fmap f) . p     fmap f (Done a s) = Done (f a) s+    {-# INLINE fmap #-} + instance Show a => Show (Result s a) where     show (Partial _) = "Partial"     show (Done a _) = show a+    {-# INLINE show #-}  -- | @finalize@ takes a list of results (presumably returned from a  -- 'Parser' or 'Partial', and supplies 'Nothing' to any remaining 'Partial'  -- values, so that only 'Done' values remain. finalize :: (Eq s, Monoid s) => [Result s a] -> [Result s a] finalize = extend Nothing+{-# INLINE finalize #-}  -- | @extend@ takes a @'Maybe' s@ as input, and supplies the input to all  -- values  in the 'Result' list. For 'Done' values, it appends @@ -153,8 +171,10 @@     where         g (Partial p) = p s         g (Done a s') = [Done a (streamAppend s' s)]+{-# INLINE extend #-}  streamAppend :: (Eq s, Monoid s) => Maybe s -> Maybe s -> Maybe s streamAppend Nothing _ = Nothing  streamAppend (Just s) Nothing = if s == mempty then Nothing else Just s  streamAppend s s' = mappend s s'+{-# INLINE streamAppend #-}
src/Data/JustParse/Language.hs view
@@ -36,18 +36,22 @@ -- The returned parser is greedy. regex :: Stream s Char => String -> Parser s Match regex = greedy . fromMaybe mzero . parseOnly regular+{-# INLINE regex #-}  -- | Like 'regex', but returns a branching (non-greedy) parser. regex_ :: Stream s Char => String -> Parser s Match regex_ = fromMaybe mzero . parseOnly regular+{-# INLINE regex_ #-}  -- | The same as 'regex', but only returns the full matched text. regex' :: Stream s Char => String -> Parser s String regex' = liftM matched . regex +{-# INLINE regex' #-}  -- | The same as 'regex_', but only returns the full matched text. regex_' :: Stream s Char => String -> Parser s String regex_' = liftM matched . regex_+{-# INLINE regex_' #-}   -- | The result of a 'regex'@@ -76,6 +80,7 @@  regular :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) regular = liftM (liftM mconcat . sequence) (many parser)+{-# INLINE regular #-}  parser :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) parser = choice [@@ -90,6 +95,7 @@     negCharClass,     period     ]+{-# INLINE parser #-}  parserNP :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) parserNP = choice [@@ -103,6 +109,7 @@     negCharClass,     period     ]+{-# INLINE parserNP #-}   @@ -114,9 +121,11 @@     group,     period     ]+{-# INLINE restricted #-}  unreserved :: Stream s Char => Parser s Char  unreserved = (char '\\' >> anyChar ) <|> noneOf "()[]\\*+{}^?|."+{-# INLINE unreserved #-}  character :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) character = @@ -125,6 +134,7 @@         return $ do             c' <- char c             return $ Match [c] []+{-# INLINE character #-}  charClass :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) charClass = @@ -135,6 +145,7 @@         return $ do             c' <- oneOf c             return $ Match [c'] []+{-# INLINE charClass #-}  negCharClass :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) negCharClass = @@ -145,6 +156,7 @@         return $ do             c' <- noneOf c             return $ Match [c'] []+{-# INLINE negCharClass #-}  period :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) period = @@ -153,6 +165,7 @@         return $ do             c <- noneOf "\n\r"             return $ Match [c] []+{-# INLINE period #-}   question :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match)@@ -161,6 +174,7 @@         p <- restricted         char '?'         return $ liftM mconcat (mN_ 0 1 p)+{-# INLINE question #-}  group :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) group = @@ -171,6 +185,7 @@         return $ do             r <- p             return $ r { groups = [r] } +{-# INLINE group #-}  asterisk :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) asterisk = @@ -178,6 +193,7 @@         p <- restricted         char '*'         return $ liftM mconcat (many_ p)+{-# INLINE asterisk #-}  plus :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) plus = @@ -185,6 +201,7 @@         p <- restricted         char '+'         return $ liftM mconcat (many1_ p)+{-# INLINE plus #-}  mn :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) mn = @@ -196,6 +213,7 @@         r <- option (-1) decInt         char '}'         return $ liftM mconcat (mN_ l r p)+{-# INLINE mn #-}  pipe :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match) pipe = @@ -204,3 +222,4 @@         char '|'         p' <- parser         return $ p <||> p'+{-# INLINE pipe #-}
src/Data/JustParse/Numeric.hs view
@@ -11,91 +11,147 @@ -}  module Data.JustParse.Numeric (-    decFloat,-    decFloat_,+    decDigit,+    hexDigit,+    unsignedDecInt,+    unsignedDecInt_,+    unsignedHexInt,+    unsignedHexInt_,     decInt,     decInt_,     hexInt,-    hexInt_+    hexInt_,+    decFloat,+    decFloat_, ) where ---{-# LANGUAGE Safe #-}+{-# LANGUAGE Safe #-} import Data.JustParse.Combinator import Data.JustParse.Internal-import Data.JustParse.Char+import qualified Data.JustParse.Char as C import Control.Monad ( liftM, liftM2 ) import Data.Char ( ord, digitToInt, toUpper, isDigit, isHexDigit ) --- | Reads many decimal digits and returns them as an @Int@.+-- | Parse a single decimal digit into an 'Int'.+decDigit :: Stream s Char => Parser s Int+decDigit = liftM digitToInt C.digit+{-# INLINE decDigit #-}++-- | Parse a single hexadecimal digit into an 'Int'.+hexDigit :: Stream s Char => Parser s Int+hexDigit = liftM digitToInt C.hexDigit+{-# INLINE hexDigit #-}++-- | Parse a series of decimal digits into an 'Int'.+unsignedDecInt :: Stream s Char => Parser s Int+unsignedDecInt = decDigit >>= g+    where+        g x = +            do+                d <- decDigit+                g (x*10+d)+            <|> return x+{-# INLINE unsignedDecInt #-}++-- | Branching version of 'unsignedDecInt'.+unsignedDecInt_ :: Stream s Char => Parser s Int+unsignedDecInt_ = decDigit >>= g+    where+        g x = +            do+                d <- decDigit+                g (x*10+d)+            <||> return x+{-# INLINE unsignedDecInt_ #-}++-- | Parse a series of hexadecimal digits into an 'Int'.+unsignedHexInt :: Stream s Char => Parser s Int+unsignedHexInt = hexDigit >>= g+    where+        g x = +            do+                d <- hexDigit+                g (x*16+d)+            <|> return x+{-# INLINE unsignedHexInt #-}++-- | Branching version of 'unsignedHexInt'.+unsignedHexInt_ :: Stream s Char => Parser s Int+unsignedHexInt_ = hexDigit >>= g+    where+        g x = +            do+                d <- hexDigit+                g (x*16+d)+            <||> return x+{-# INLINE unsignedHexInt_ #-}++-- | Parse a series of decimal digits into an 'Int' with an optional sign. decInt :: Stream s Char => Parser s Int decInt =      do         sign <- optional (oneOf "-+")-        num <- liftM read (many1 digit)+        num <- unsignedDecInt         case sign of             Just '-' -> return (-num)             _ -> return num+{-# INLINE decInt #-} --- | Branching version of decInt.+-- | Branching version of 'decInt'. decInt_ :: Stream s Char => Parser s Int decInt_ =      do         sign <- optional (oneOf "-+")-        num <- liftM read (many1_ digit)+        num <- unsignedDecInt_         case sign of             Just '-' -> return (-num)             _ -> return num+{-# INLINE decInt_ #-} +-- | Parse a series of hexadecimal digits into an 'Int' with an optional +-- sign.+hexInt :: Stream s Char => Parser s Int+hexInt = +    do+        sign <- optional (oneOf "-+")+        num <- unsignedHexInt+        case sign of+            Just '-' -> return (-num)+            _ -> return num+{-# INLINE hexInt #-}++-- | Branching versino of 'hexInt'.+hexInt_ :: Stream s Char => Parser s Int+hexInt_ = +    do+        sign <- optional (oneOf "-+")+        num <- unsignedHexInt_+        case sign of+            Just '-' -> return (-num)+            _ -> return num+{-# INLINE hexInt_ #-}+ -- | Parse a float. If a decimal point is present, it must have at  -- least one digit before and after the decimal point. decFloat :: Stream s Char => Parser s Float decFloat =      do         sign <- optional (oneOf "-+")-        whole <- many1 digit-        fractional <- option ".0" (liftM2 (:) (char '.') (many1 digit))+        whole <- many1 C.digit+        fractional <- option ".0" (liftM2 (:) (C.char '.') (many1 C.digit))         case sign of             Just '-' -> return (-(read (whole ++ fractional)))             _ -> return (read (whole ++ fractional))+{-# INLINE decFloat #-}  -- | Branching version of decFloat. decFloat_ :: Stream s Char => Parser s Float decFloat_ =      do         sign <- optional (oneOf "-+")-        whole <- many1_ digit-        fractional <- option_ ".0" (liftM2 (:) (char '.') (many1_ digit))+        whole <- many1_ C.digit+        fractional <- option_ ".0" (liftM2 (:) (C.char '.') (many1_ C.digit))         case sign of             Just '-' -> return (-(read (whole ++ fractional)))             _ -> return (read (whole ++ fractional))----- | Reads many hexidecimal digits and returns them as an @Int@.-hexInt :: Stream s Char => Parser s Int-hexInt = -    do-        sign <- optional (oneOf "-+")-        num <- liftM (f . reverse) (many1 hexDigit)-        case sign of-            Just '-' -> return (-num)-            _ -> return num-    where-        f [] = 0-        f (x:xs) -            | isDigit x = digitToInt x + 16 * f xs -            | otherwise = ord (toUpper x) - ord 'A' + 16 * f xs---- | Branching versino of 'hexInt'.-hexInt_ :: Stream s Char => Parser s Int-hexInt_ = -    do-        sign <- optional (oneOf "-+")-        num <- liftM (f . reverse) (many1_ hexDigit)-        case sign of-            Just '-' -> return (-num)-            _ -> return num-    where-        f [] = 0-        f (x:xs) -            | isDigit x = digitToInt x + 16 * f xs -            | otherwise = ord (toUpper x) - ord 'A' + 16 * f xs+{-# INLINE decFloat_ #-}