packages feed

parcom-lib 0.1.0.0 → 0.2.0.0

raw patch · 4 files changed

+97/−74 lines, 4 filesdep +mtldep +transformers

Dependencies added: mtl, transformers

Files

Text/Parcom/Combinators.hs view
@@ -11,26 +11,26 @@ import Text.Parcom.Internal  -- | Walk a list of options, return the first one that succeeds.-choice :: (Stream s t) => [Parcom s t a] -> Parcom s t a+choice :: (Monad m, Stream s t) => [ParcomT s t m a] -> ParcomT s t m a choice xs = foldl (<|>) empty xs <?> "I tried to make a choice, but couldn't"  -- | Like @choice@, but each choice tagged with a human-readable name for -- better error reporting.-namedChoice :: (Stream s t) => [(String, Parcom s t a)] -> Parcom s t a+namedChoice :: (Monad m, Stream s t) => [(String, ParcomT s t m a)] -> ParcomT s t m a namedChoice xs = choice (map snd xs) <?> (formatOptionList . map fst) xs  -- | Match two consecutive parser, return the first parser's result iff both -- succeed.-before :: (Stream s t) => Parcom s t a -> Parcom s t b -> Parcom s t a+before :: (Monad m, Stream s t) => ParcomT s t m a -> ParcomT s t m b -> ParcomT s t m a before p q = do { v <- p; q; return v }  -- | Match three consecutive parsers, return the middle parser's result iff -- all three match. Parsers are given in the order inner, left, right.-between :: (Stream s t) => Parcom s t a -> Parcom s t l -> Parcom s t r -> Parcom s t a+between :: (Monad m, Stream s t) => ParcomT s t m a -> ParcomT s t m l -> ParcomT s t m r -> ParcomT s t m a between p l r = do { l; v <- p; r; return v }  -- | Match zero or more occurrences of a parser-many :: (Stream s t) => Parcom s t a -> Parcom s t [a]+many :: (Monad m, Stream s t) => ParcomT s t m a -> ParcomT s t m [a] many p =     handle p f m     where@@ -40,7 +40,7 @@             return (x:xs)  -- | Match one or more occurrences of a parser-many1 :: (Stream s t) => Parcom s t a -> Parcom s t [a]+many1 :: (Monad m, Stream s t) => ParcomT s t m a -> ParcomT s t m [a] many1 p = do     xs <- many p     if null xs@@ -49,7 +49,7 @@  -- | Given an item parser and a separator parser, keep parsing until the -- separator or the item fails.-manySepBy :: (Stream s t) => Parcom s t a -> Parcom s t b -> Parcom s t [a]+manySepBy :: (Monad m, Stream s t) => ParcomT s t m a -> ParcomT s t m b -> ParcomT s t m [a] manySepBy p s = go     where         go = do@@ -66,7 +66,7 @@                     (\_ -> go >>= \xs -> return (x:xs))  -- | Run the given parser n times, returning all the results as a list.-times :: (Stream s t) => Int -> Parcom s t a -> Parcom s t [a]+times :: (Monad m, Stream s t) => Int -> ParcomT s t m a -> ParcomT s t m [a] times 0 p = return [] times n p = do     x <- p@@ -74,5 +74,5 @@     return (x:xs)  -- | Ignore the result of a parser.-skip :: Parcom s t a -> Parcom s t ()+skip :: Monad m => ParcomT s t m a -> ParcomT s t m () skip p = p >> return ()
Text/Parcom/Core.hs view
@@ -2,8 +2,8 @@ module Text.Parcom.Core ( ParcomError (..) , SourcePosition (..)-, Parcom-, parse+, ParcomT, parseT+, Parcom, parse , peek, next, atEnd , try, handle , notFollowedBy@@ -16,6 +16,8 @@ import Text.Parcom.Stream (Stream, Token) import Control.Monad (liftM, ap) import Control.Applicative+import Control.Monad.Identity+import Control.Monad.Trans.Class  data SourcePosition =     SourcePosition@@ -38,92 +40,111 @@         , psStream :: s         } -newtype Parcom s t a = Parcom { runParcom :: ParcomState s -> (Either ParcomError a, ParcomState s) }+type Parcom s t a = ParcomT s t Identity a+newtype ParcomT s t m a = ParcomT { runParcomT :: ParcomState s -> m (Either ParcomError a, ParcomState s) } -instance Monad (Parcom s t) where-    return x = Parcom (\s -> (Right x, s))-    fail err = Parcom (\s -> (Left $ ParcomError err (psSourcePosition s), s))-    m >>= f = Parcom $ \s ->-        let (a, s') = runParcom m s-        in case a of-            Left e -> (Left e, s')-            Right x -> runParcom (f x) s'+instance (Monad m) => Monad (ParcomT s t m) where+    return x = ParcomT (\s -> return (Right x, s))+    fail err = ParcomT (\s -> return (Left $ ParcomError err (psSourcePosition s), s))+    m >>= f = ParcomT $ \s -> do -- in the m Monad+        (a, s') <- runParcomT m s+        case a of+            Left err -> return (Left err, s')+            Right ma -> do+                runParcomT (f ma) s' -instance Functor (Parcom s t) where+instance MonadTrans (ParcomT s t) where+    lift a = ParcomT $ \s -> do+        v <- a+        return (Right v, s)++instance (Monad m) => Functor (ParcomT s t m) where     fmap f xs = xs >>= return . f -instance Applicative (Parcom s t) where+instance (Monad m) => Applicative (ParcomT s t m) where     pure = return     (<*>) = ap -instance Alternative (Parcom s t) where+instance (Monad m) => Alternative (ParcomT s t m) where     (<|>) = alt     empty = fail "empty" -runParser :: (Stream s t, Token t) => Parcom s t a -> String -> s -> (Either ParcomError a, ParcomState s)-runParser p fn str =-    runParcom p state+runParserT :: (Stream s t, Token t) => ParcomT s t m a -> String -> s -> m (Either ParcomError a, ParcomState s)+runParserT p fn str =+    runParcomT p state     where         state =             ParcomState                 { psSourcePosition = SourcePosition fn 1 1                 , psStream = str } +parseT :: (Stream s t, Token t, Monad m) => ParcomT s t m a -> String -> s -> m (Either ParcomError a)+parseT p fn str = fst `liftM` runParserT p fn str+ parse :: (Stream s t, Token t) => Parcom s t a -> String -> s -> Either ParcomError a-parse p fn str = fst $ runParser p fn str+parse p fn str = runIdentity $ parseT p fn str -getState :: Parcom s t (ParcomState s)-getState = Parcom $ \s -> (Right s, s)+getState :: Monad m => ParcomT s t m (ParcomState s)+getState = ParcomT $ \s -> return (Right s, s) -useState :: (ParcomState s -> a) -> Parcom s t a-useState f = Parcom $ \s -> (Right $ f s, s)+useState :: Monad m => (ParcomState s -> a) -> ParcomT s t m a+useState f = ParcomT $ \s -> return (Right $ f s, s) -setState :: ParcomState s -> Parcom s t ()-setState s = Parcom $ \_ -> (Right (), s)+setState :: Monad m => ParcomState s -> ParcomT s t m ()+setState s = ParcomT $ \_ -> return (Right (), s) -modifyState :: (ParcomState s -> ParcomState s) -> Parcom s t ()-modifyState f = Parcom $ \s -> (Right (), f s)+modifyState :: Monad m => (ParcomState s -> ParcomState s) -> ParcomT s t m ()+modifyState f = ParcomT $ \s -> return (Right (), f s) -handle :: Parcom s t a -> (ParcomError -> Parcom s t b) -> (a -> Parcom s t b) -> Parcom s t b-handle p f t = Parcom $ \s ->-    let (r', s') = runParcom p s-    in case r' of-        -- parse failed: run the error handler-        Left e -> runParcom (f e) s'-        -- parse succeeded: run the success handler-        Right x -> runParcom (t x) s'+-- | Very general error / success handler+-- Each of the error / success branches takes both the old and the new state,+-- so that the branch handler itself can decide whether to backtrack or+-- continue with the new state.+handle' :: Monad m+    => ParcomT s t m a+    -> (ParcomError -> ParcomState s -> ParcomState s -> m (Either ParcomError b, ParcomState s))+    -> (a -> ParcomState s -> ParcomState s -> m (Either ParcomError b, ParcomState s))+    -> ParcomT s t m b+handle' p errorH successH = ParcomT $ \s -> do+    (r, s') <- runParcomT p s+    case r of+        -- parse failed: run error handler+        Left e -> errorH e s s'+        -- parse succeeded: run success handler+        Right x -> successH x s s' +handle :: Monad m+    => ParcomT s t m a+    -> (ParcomError -> ParcomT s t m b)+    -> (a -> ParcomT s t m b)+    -> ParcomT s t m b+handle p f t =+    handle' p (\e _ s' -> runParcomT (f e) s') (\x _ s' -> runParcomT (t x) s') +handleB :: Monad m+    => ParcomT s t m a+    -> (ParcomError -> ParcomT s t m b)+    -> (a -> ParcomT s t m b)+    -> ParcomT s t m b+handleB p f t =+    handle' p (\e s _ -> runParcomT (f e) s) (\x s _ -> runParcomT (t x) s)+ -- | Backtracking modifier; restores the parser state to the previous situation -- if the wrapped parser fails.-try :: Parcom s t a -> Parcom s t a-try p = Parcom $ \s ->-    let (r', s') = runParcom p s-    in case r' of-        -- parse failed: return the error and restore the old state-        Left e -> (Left e, s)-        -- parse succeeded: return the result and the new state-        Right x -> (Right x, s')+try :: Monad m => ParcomT s t m a -> ParcomT s t m a+try p = handle' p (\e s _ -> return (Left e, s)) (\x _ s' -> return (Right x, s'))  -- | Return the result of the first parser that succeeds.-alt :: Parcom s t a -> Parcom s t a -> Parcom s t a-alt a b = Parcom $ \s ->-            let (r', s') = runParcom a s-            in case r' of-                Left _ -> runParcom b s-                Right x -> (Right x, s')+alt :: Monad m => ParcomT s t m a -> ParcomT s t m a -> ParcomT s t m a+alt a b = handle' a (\e s _ -> runParcomT b s) (\x _ s' -> return (Right x, s'))  -- | Succeeds iff the given parser fails-notFollowedBy :: (Stream s t) => Parcom s t a -> Parcom s t ()-notFollowedBy p = Parcom $ \s ->-    let (r', s') = runParcom p s-    in case r' of-        Left _ -> (Right (), s)-        Right x -> runParcom (fail "something followed that shouldn't") s+notFollowedBy :: (Monad m, Stream s t) => ParcomT s t m a -> ParcomT s t m ()+notFollowedBy p = handle' p (\_ s _ -> return (Right (), s)) (\x s _ -> runParcomT (fail "something followed that shouldn't") s)      -- | Gets the next token from the stream without consuming it. -- Fails at end-of-input.-peek :: (Stream s t) => Parcom s t t+peek :: (Monad m, Stream s t) => ParcomT s t m t peek = do     str <- psStream `liftM` getState     if Stream.atEnd str@@ -131,7 +152,7 @@         else return (Stream.peek str)  -- | Checks whether end-of-input has been reached.-atEnd :: (Stream s t) => Parcom s t Bool+atEnd :: (Monad m, Stream s t) => ParcomT s t m Bool atEnd = useState (Stream.atEnd . psStream)  nextLine :: SourcePosition -> SourcePosition@@ -144,7 +165,7 @@  -- | Gets the next token from the stream and consumes it. -- Fails at end-of-input.-next :: (Stream s t, Token t) => Parcom s t t+next :: (Monad m, Stream s t, Token t) => ParcomT s t m t next = do     str <- psStream `liftM` getState     if Stream.atEnd str@@ -157,5 +178,5 @@                 else modifyState $ \s -> s { psSourcePosition = nextColumn (psSourcePosition s) }             return t -(<?>) :: (Stream s t) => Parcom s t a -> String -> Parcom s t a+(<?>) :: (Monad m, Stream s t) => ParcomT s t m a -> String -> ParcomT s t m a p <?> expected = p <|> fail ("Expected " ++ expected)
Text/Parcom/Prim.hs view
@@ -9,20 +9,20 @@ import Text.Parcom.Internal  -- | Gets the next token from the stream-anyToken :: (Stream s t, Token t) => Parcom s t t+anyToken :: (Monad m, Stream s t, Token t) => ParcomT s t m t anyToken = next  -- | Succeeds iff end-of-input has been reached-eof :: (Stream s t, Token t) => Parcom s t ()+eof :: (Monad m, Stream s t, Token t) => ParcomT s t m () eof = notFollowedBy anyToken <?> "end of input"  -- | Matches one token against a list of possible tokens; returns the -- matching token.-oneOf :: (Stream s t, Token t, Show t, Eq t) => [t] -> Parcom s t t+oneOf :: (Monad m, Stream s t, Token t, Show t, Eq t) => [t] -> ParcomT s t m t oneOf xs = satisfy (`elem` xs) <?> (formatOptionList . map show) xs  -- | Succeeds if the given predicate is met for the next token.-satisfy :: (Stream s t, Token t) => (t -> Bool) -> Parcom s t t+satisfy :: (Monad m, Stream s t, Token t) => (t -> Bool) -> ParcomT s t m t satisfy p = do     c <- peek     if p c@@ -30,11 +30,11 @@         else fail "Predicate not met"  -- | Exactly match one particular token-token :: (Stream s t, Token t, Show t, Eq t) => t -> Parcom s t t+token :: (Monad m, Stream s t, Token t, Show t, Eq t) => t -> ParcomT s t m t token t = satisfy (== t) <?> show t  -- | Match a series of tokens exactly-tokens :: (Stream s t, Token t, Eq t, Show t) => [t] -> Parcom s t [t]+tokens :: (Monad m, Stream s t, Token t, Eq t, Show t) => [t] -> ParcomT s t m [t] tokens [] = return [] tokens (x:xs) = do     c <- token x
parcom-lib.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                parcom-lib-version:             0.1.0.0+version:             0.2.0.0 synopsis:            A simple parser-combinator library, a bit like Parsec but without the frills description:         Parcom provides parser combinator functionality in a string-type-agnostic way;                      it supports strict ByteStrings (with Word8 tokens) and any list type (with@@ -26,3 +26,5 @@                , containers ==0.4.*                , bytestring ==0.9.*                , word8+               , mtl == 2.1.*+               , transformers == 0.3.*