uu-parsinglib 2.7.4.3 → 2.8.1
raw patch · 9 files changed
+69/−299 lines, 9 filesdep +uu-interleaveddep ~basePVP ok
version bump matches the API change (PVP)
Dependencies added: uu-interleaved
Dependency ranges changed: base
API changes (from Hackage documentation)
- Text.ParserCombinators.UU.Core: doNotInterpret :: ExtAlternative p => p a -> p a
- Text.ParserCombinators.UU.Demo.MergeAndPermute: pA :: Grammar String
- Text.ParserCombinators.UU.Demo.MergeAndPermute: pABC :: Gram (P (Str Char String LineColPos)) Char
- Text.ParserCombinators.UU.Demo.MergeAndPermute: pABC' :: Grammar String
- Text.ParserCombinators.UU.Demo.MergeAndPermute: pB :: Grammar String
- Text.ParserCombinators.UU.Demo.MergeAndPermute: pC :: Grammar String
- Text.ParserCombinators.UU.Demo.MergeAndPermute: pDigit' :: (ListLike state Char, IsLocationUpdatedBy loc Char) => Gram (P (Str Char state loc)) Char
- Text.ParserCombinators.UU.Demo.MergeAndPermute: pNat :: Grammar Int
- Text.ParserCombinators.UU.Demo.MergeAndPermute: show_demos :: IO ()
- Text.ParserCombinators.UU.Demo.MergeAndPermute: three :: Applicative f => f a -> f (a, a, a)
- Text.ParserCombinators.UU.Demo.MergeAndPermute: two :: Applicative f => f [a] -> f [a]
- Text.ParserCombinators.UU.Demo.MergeAndPermute: type Grammar a = Gram (P (Str Char String LineColPos)) a
- Text.ParserCombinators.UU.MergeAndPermute: (<<||>) :: Functor f => Gram f (b -> a) -> Gram f b -> Gram f a
- Text.ParserCombinators.UU.MergeAndPermute: (<||>) :: Functor f => Gram f (b -> a) -> Gram f b -> Gram f a
- Text.ParserCombinators.UU.MergeAndPermute: Bind :: (f b) -> (b -> Gram f a) -> Alt f a
- Text.ParserCombinators.UU.MergeAndPermute: Gram :: [Alt f a] -> (Maybe a) -> Gram f a
- Text.ParserCombinators.UU.MergeAndPermute: Seq :: (f b) -> (Gram f (b -> a)) -> Alt f a
- Text.ParserCombinators.UU.MergeAndPermute: data Alt f a
- Text.ParserCombinators.UU.MergeAndPermute: data Gram f a
- Text.ParserCombinators.UU.MergeAndPermute: instance Functor f => Alternative (Gram f)
- Text.ParserCombinators.UU.MergeAndPermute: instance Functor f => Applicative (Gram f)
- Text.ParserCombinators.UU.MergeAndPermute: instance Functor f => ExtAlternative (Gram f)
- Text.ParserCombinators.UU.MergeAndPermute: instance Functor f => Functor (Alt f)
- Text.ParserCombinators.UU.MergeAndPermute: instance Functor f => Functor (Gram f)
- Text.ParserCombinators.UU.MergeAndPermute: instance Functor f => IsParser (Gram f)
- Text.ParserCombinators.UU.MergeAndPermute: instance Monad (Gram f)
- Text.ParserCombinators.UU.MergeAndPermute: instance Show a => Show (Gram f a)
- Text.ParserCombinators.UU.MergeAndPermute: mkGram :: P t a -> Gram (P t) a
- Text.ParserCombinators.UU.MergeAndPermute: mkParserM :: (Monad f, Applicative f, ExtAlternative f) => Gram f a -> f a
- Text.ParserCombinators.UU.MergeAndPermute: mkParserS :: (Monad f, Applicative f, ExtAlternative f) => f b -> Gram f a -> f a
- Text.ParserCombinators.UU.MergeAndPermute: pmMany :: Functor f => Gram f a -> Gram f [a]
+ Text.ParserCombinators.UU.BasicInstances: pMunchL :: (Show a, loc IsLocationUpdatedBy a, ListLike state a) => (a -> Bool) -> String -> P (Str a state loc) [a]
+ Text.ParserCombinators.UU.Core: P :: (T st a) -> (Maybe (T st a)) -> (Maybe a) -> Nat -> P st a
+ Text.ParserCombinators.UU.Interleaved: doNotInterpret :: P st a -> P st a
+ Text.ParserCombinators.UU.Interleaved: instance Functor f => ExtAlternative (Gram f)
+ Text.ParserCombinators.UU.Interleaved: instance IsParser (Gram (P st))
+ Text.ParserCombinators.UU.Interleaved: instance Splittable (P st)
+ Text.ParserCombinators.UU.Interleaved: mkP :: Gram (P st) a -> P st a
- Text.ParserCombinators.UU.Core: class Alternative p => ExtAlternative p where doNotInterpret = id opt p v = must_be_non_empty "opt" p (p <<|> pure v)
+ Text.ParserCombinators.UU.Core: class Alternative p => ExtAlternative p where opt p v = must_be_non_empty "opt" p (p <<|> pure v)
- Text.ParserCombinators.UU.Core: data Steps a
+ Text.ParserCombinators.UU.Core: data Steps :: * -> *
- Text.ParserCombinators.UU.Utils: execParser :: ListLike state Char => P (Str Char state LineColPos) a -> state -> (a, [Error LineColPos])
+ Text.ParserCombinators.UU.Utils: execParser :: Parser a -> String -> (a, [Error LineColPos])
- Text.ParserCombinators.UU.Utils: runParser :: String -> P (Str Char String LineColPos) a -> String -> a
+ Text.ParserCombinators.UU.Utils: runParser :: String -> Parser a -> String -> a
Files
- src/Text/ParserCombinators/UU.hs +0/−2
- src/Text/ParserCombinators/UU/BasicInstances.hs +2/−1
- src/Text/ParserCombinators/UU/CHANGELOG.hs +0/−8
- src/Text/ParserCombinators/UU/Core.hs +20/−18
- src/Text/ParserCombinators/UU/Demo/MergeAndPermute.hs +0/−139
- src/Text/ParserCombinators/UU/Interleaved.hs +39/−0
- src/Text/ParserCombinators/UU/MergeAndPermute.hs +0/−124
- src/Text/ParserCombinators/UU/Utils.hs +2/−2
- uu-parsinglib.cabal +6/−5
src/Text/ParserCombinators/UU.hs view
@@ -19,11 +19,9 @@ module Text.ParserCombinators.UU ( module Text.ParserCombinators.UU.Core , module Text.ParserCombinators.UU.Derived- , module Text.ParserCombinators.UU.MergeAndPermute ) where import Text.ParserCombinators.UU.Core import Text.ParserCombinators.UU.Derived-import Text.ParserCombinators.UU.MergeAndPermute
src/Text/ParserCombinators/UU/BasicInstances.hs view
@@ -39,6 +39,7 @@ pToken, pTokenCost, pMunch,+ pMunchL ) where import Text.ParserCombinators.UU.Core import Data.Maybe@@ -190,7 +191,7 @@ else show_munch ("Accepting munch: " ++ msg ++ " as emtty munch " ++ show pos ++ "\n") (k [] inp) ) --- | `pMunch` recognises the longest prefix of the input for which the passed predicate holds. The message parameer is used when tracing has been switched on. +-- | `pMunch` recognises the longest prefix of the input for which the passed predicate holds. pMunch :: forall loc state a .((Show a, loc `IsLocationUpdatedBy` a, LL.ListLike state a) => (a -> Bool) -> P (Str a state loc) [a]) pMunch p = pMunchL p ""
src/Text/ParserCombinators/UU/CHANGELOG.hs view
@@ -1,13 +1,5 @@ -- | This module just contains the CHANGELOG ----- Version 2.7.4.3--- --- Fixed bug with exact location of reporting errors in runParser (thanks Markus Klinik)------ Version 2.7.4.2------ Changed a types of execParser and runParser; thanks due to Benjamin Moseley--- -- Version 2.7.4.1 -- -- export of constructors of LineCol and LineColPos
src/Text/ParserCombinators/UU/Core.hs view
@@ -2,7 +2,8 @@ GADTs, MultiParamTypeClasses, FunctionalDependencies,- FlexibleInstances #-}+ FlexibleInstances, + KindSignatures #-} -- | The module `Core` contains the basic functionality of the parser library. -- It defines the types and implementations of the elementary parsers and recognisers involved. @@ -17,7 +18,7 @@ HasPosition (..), -- * Types -- ** The parser descriptor- P (),+ P (..), -- ** The progress information Steps (..), Cost,@@ -53,11 +54,17 @@ import Control.Monad import Data.Char import Debug.Trace+import Prelude hiding ((.)) import Data.Maybe +f . g = \x -> f ( g x)++{-# INLINE (.) #-}+ -- | In the class `IsParser` we assemble the basic properties we expect parsers to have. The class itself does not have any methods. -- Most properties come directly from the standard -- "Control.Applicative" module. The class `ExtAlternative` contains some extra methods we expect our parsers to have.+ class (Alternative p, Applicative p, ExtAlternative p) => IsParser p instance MonadPlus (P st) where@@ -75,10 +82,6 @@ -- Quite often it is more informative to get e.g. the name of the non-terminal . -- The `<?>` combinator replaces this list of symbols by the string argument. (<?>) :: p a -> String -> p a- -- | `doNotInterpret` makes a parser opaque for abstract interpretation; used when permuting parsers- -- where we do not want to compare lengths.- doNotInterpret :: p a -> p a- doNotInterpret = id -- | `must_be_non_empty` checks whether its second argument -- is a parser which can recognise the empty input. If so, an error message is -- given using the String parameter. If not, then the third argument is@@ -167,8 +170,8 @@ data P st a = P (T st a) -- actual parsers (Maybe (T st a)) -- non-empty parsers; Nothing if they are absent- (Maybe a) -- the possibly empty alternative with value - Nat -- minimal length of the non-empty part+ (Maybe a) -- the possibly empty alternative with its value + Nat -- minimal number of symbols accepted by the non-empty part instance Show (P st a) where@@ -250,8 +253,6 @@ ( \ k inp -> replaceExpected (norm ( pf k inp))) ( \ k inp -> replaceExpected (norm ( pr k inp)))) in mkParser nnp pe pl- -- | `doNotInterpret` forgets the computed minimal number of tokens recognised by this parser- doNotInterpret (P t nep e _) = P t nep e Unspecified must_be_non_empty msg p@(P _ _ _ (Zero _)) _ = error ("The combinator " ++ msg ++ " requires that it's argument cannot recognise the empty string\n") must_be_non_empty _ _ q = q@@ -326,7 +327,6 @@ pErrors = let nnp = Just (T ( \ k inp -> let (errs, inp') = getErrors inp in k errs inp' ) ( \ k inp -> let (errs, inp') = getErrors inp in push errs (k inp')) ( \ k inp -> let (errs, inp') = getErrors inp in k inp' ))- nep = (Just (error "pErrors cannot occur in lhs of bind")) -- the errors consumed cannot be determined statically! in mkParser nnp Nothing (Zero Infinite) -- | `pPos` returns the current input position.@@ -334,7 +334,6 @@ pPos = let nnp = Just ( T ( \ k inp -> let pos = getPos inp in k pos inp ) ( \ k inp -> let pos = getPos inp in push pos (k inp)) ( \ k inp -> k inp ))- nep = Just (error "pPos cannot occur in lhs of bind") -- the errors consumed cannot be determined statically! in mkParser nnp Nothing (Zero Infinite) -- | `pState` returns the current input state@@ -415,7 +414,7 @@ -data Steps a where+data Steps :: * -> * where Step :: Progress -> Steps a -> Steps a Apply :: forall a b. (b -> a) -> Steps b -> Steps a Fail :: Strings -> [Strings -> (Cost , Steps a)] -> Steps a@@ -434,7 +433,7 @@ push v = Apply (\ r -> (v, r)) apply2fst :: (b -> a) -> Steps (b, r) -> Steps (a, r)-apply2fst f = Apply (\ (b, r) -> (f b, r)) +apply2fst f = Apply (\ br -> let (b, r) = br in (f b, r)) {- succeedAlways :: Steps a@@ -451,9 +450,12 @@ has_success (Step _ _) = True has_success _ = False --- | @`eval`@ removes the progress information from a sequence of steps, and constructs the value embedded in it.--- If you are really desparate to see how your parsers are making progress (e.g. when you have written an ambiguous parser, and you cannot find the cause of--- the exponential blow-up of your parsing process), you may switch on the trace in the function @`eval`@ (you will need to edit the library source code).+-- | @`eval`@ removes the progress information from a sequence of steps, +-- and constructs the value embedded in it.+-- If you are really desparate to see how your parsers are making progress+-- (e.g. when you have written an ambiguous parser, and you cannot find +-- the cause of the exponential blow-up of your parsing process), +-- you may switch on the trace in the function @`eval`@ (you will need to edit the library source code). -- eval :: Steps a -> a eval (Step n l) = trace' ("Step " ++ show n ++ "\n") (eval l)@@ -463,7 +465,7 @@ eval (End_f _ _ ) = error "dangling End_f constructor" eval (End_h _ _ ) = error "dangling End_h constructor" --- | `norm` makes sure that the head of the seqeunce contains progress information. +-- | `norm` makes sure that the head of the sequence contains progress information. -- It does so by pushing information about the result (i.e. the `Apply` steps) backwards. -- norm :: Steps a -> Steps a
− src/Text/ParserCombinators/UU/Demo/MergeAndPermute.hs
@@ -1,139 +0,0 @@-{-# LANGUAGE NoMonomorphismRestriction,- RankNTypes,- FlexibleContexts,- CPP #-}-#define DEMO(p,i) demo "p" i p-#define DEMOG(p,i) demo "p" i (mkParserM (p))-module Text.ParserCombinators.UU.Demo.MergeAndPermute where--import Text.ParserCombinators.UU-import Text.ParserCombinators.UU.MergeAndPermute-import Text.ParserCombinators.UU.BasicInstances hiding (Parser)-import Text.ParserCombinators.UU.Utils-import Text.ParserCombinators.UU.Demo.Examples hiding (show_demos)-import qualified Data.ListLike as LL --type Grammar a = Gram (P (Str Char String LineColPos)) a---- | By running the function `show_demos` you will get a demonstration of the merging parsers.------ >>> run ((,,) <$> two pA <||> three pB <||> pBetween 2 4 pC ) "cababbcccc"--- Result: ("aa",("b","b","b"),["c","c","c","c"])--- Correcting steps: --- The token 'c' was not consumed by the parsing process.--- --- >>> run (amb (mkParserM ((,) <$> pmMany ((,) <$> pA <*> pC) <||> pmMany pB))) "aabbcaabbccc"--- Result: [([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"]),([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"]),--- ([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"]),([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"]),--- ([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"]),([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"]),--- ([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"]),([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"]),--- ([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"]),([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"]),--- ([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"]),([("a","c"),("a","c"),("a","c"),("a","c")],["b","b","b","b"])]--- --- >>> run (pmMany(pABC)) "a2a1b1b2c2a3b3c1c3"--- Result: ["2a","1a","3a"]--- --- >>> run ((,) <$> pBetween 2 3 pA <||> pBetween 1 2 pB) "abba"--- Result: (["a","a"],["b","b"])--- --- >>> run ((,) <$> pBetween 2 3 pA <||> pBetween 1 2 pB) "bba"--- Result: (["a","a"],["b","b"])--- Correcting steps: --- Inserted 'a' at position LineColPos 0 3 3 expecting 'a'--- --- >>> run (amb (mkParserM( ((,) <$> pBetween 2 3 pA <||> pBetween 1 2 pA)))) "aaa"--- Result: [(["a","a"],["a"]),(["a","a"],["a"]),(["a","a"],["a"])]--- --- The 'a' at the right hand side can b any of the three 'a'-s in the input:------ >>> run ((,) <$> pAtLeast 3 pA <||> pAtMost 3 pB) "ababbb"--- Result: (["a","a","a"],["b","b","b"])--- Correcting steps: --- Deleted 'b' at position LineColPos 0 5 5 expecting 'a'--- Inserted 'a' at position LineColPos 0 6 6 expecting 'a'--- --- >>> run ((,) <$> pSome pA <||> pMany pB) "abba"--- Result: (["a","a"],["b","b"])--- --- >>> run ((,) <$> pSome pA <||> pMany pB) "abba"--- Result: (["a","a"],["b","b"])--- --- >>> run ((,) <$> pSome pA <||> pMany pB) ""--- Result: (["a"],[])--- Correcting steps: --- Inserted 'a' at position LineColPos 0 0 0 expecting one of ['a', 'b']--- --- >>> run ((,) <$> pMany pB <||> pSome pC) "bcbc"--- Result: (["b","b"],["c","c"])--- --- >>> run ((,) <$> pSome pB <||> pMany pC) "bcbc"--- Result: (["b","b"],["c","c"])--- --- >>> run ((,,,) <$> pSome pA <||> pMany pB <||> pC <||> (pNat `opt` 5) ) "bcab45"--- Result: (["a"],["b","b"],"c",45)--- --- >>> run ((,) <$> pMany (pA <|> pB) <||> pSome pNat) "1ab12aab14"--- Result: (["a","b","a","a","b"],[1,12,14])--- --- >>> run ( (,) <$> ((++) <$> pMany pA <||> pMany pB) <||> pC) "abcaaab"--- Result: (["a","a","a","a","b","b"],"c")--- --- >>> run (pc `mkParserS` ((,) <$> pMany pA <||> pMany pB)) "acbcacb"--- Result: (["a","a"],["b","b"])--- --show_demos :: IO ()-show_demos = do DEMOG (((,,) <$> two pA <||> three pB <||> pBetween 2 4 pC ), "cababbcccc")- DEMO ((amb (mkParserM ((,) <$> pmMany ((,) <$> pA <*> pC) <||> pmMany pB))) , "aabbcaabbccc")- DEMOG ((pmMany(pABC)) , "a2a1b1b2c2a3b3c1c3")- DEMOG (((,) <$> pBetween 2 3 pA <||> pBetween 1 2 pB) , "abba") - DEMOG (((,) <$> pBetween 2 3 pA <||> pBetween 1 2 pB) , "bba")- DEMO ((amb (mkParserM( ((,) <$> pBetween 2 3 pA <||> pBetween 1 2 pA)))) , "aaa")- putStr "-- The 'a' at the right hand side can b any of the three 'a'-s in the input\n"- DEMOG (((,) <$> pAtLeast 3 pA <||> pAtMost 3 pB) , "ababbb") - DEMOG (((,) <$> pSome pA <||> pMany pB) , "abba") - DEMOG (((,) <$> pSome pA <||> pMany pB) , "abba") - DEMOG (((,) <$> pSome pA <||> pMany pB) , "") - DEMOG (((,) <$> pMany pB <||> pSome pC) , "bcbc") - DEMOG (((,) <$> pSome pB <||> pMany pC) , "bcbc")- DEMOG (((,,,) <$> pSome pA <||> pMany pB <||> pC <||> (pNat `opt` 5) ) , "bcab45" )- DEMOG (((,) <$> pMany (pA <|> pB) <||> pSome pNat) , "1ab12aab14")- DEMOG (( (,) <$> ((++) <$> pMany pA <||> pMany pB) <||> pC) , "abcaaab")- DEMO ((pc `mkParserS` ((,) <$> pMany pA <||> pMany pB)) , "acbcacb")--pA, pB, pC:: Grammar String-pA = mkGram pa-pB = mkGram pb-pC = mkGram (lift <$> pSym 'c')---pNat :: Grammar Int-pNat = mkGram pNatural---pDigit' = mkGram pDigit---- | `two` recognises two instance of p as part of the input sequence-two :: Applicative f => f [a] -> f [a]-two p = (++) <$> p <*> p--- | `three` recognises two instance of p as part of the input sequence and concatenates the results-three :: Applicative f => f a-> f (a,a,a)-three p = (,,) <$> p <*> p <*> p---- | `pABC` minimcs a series of events (here an @a@, a @b@ and a @c@), which belong to the same transaction. --- The transaction is identified by a digit: hence a full transaction is a string like \"a5b5c5\". --- The third element in the body of `show_demos` below shows how the different transactions can be recovered from --- a log-file which contains all events generated by a collection of concurrently running transactions.-{--pABC :: Grammar Char-pABC = mkGram (pa *> pDigit ) >>= (\ d -> mkGram (pb *> pSym d) *> mkGram (pc *> pSym d))--}-pABC = do d <- mkGram (pa *> pDigit ) - mkGram (pb *> pSym d) *> mkGram (pc *> pSym d)--pABC' :: Grammar String -pABC' = (\ a d -> d:a) <$> pA <*> (pDigit' >>= \d -> pB *> mkGram (pSym d) *> pC *> mkGram (pSym d))----
+ src/Text/ParserCombinators/UU/Interleaved.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE ExistentialQuantification,+ FlexibleInstances #-}++-- | This module contains the additional data types, instance definitions and functions to run parsers in an interleaved way.+-- If all the interleaved parsers recognise a single connected piece of the input text this incorporates the permutation parsers.+-- For some examples see the module "Text.ParserCombinators.UU.Demo.MergeAndPermute".++module Text.ParserCombinators.UU.Interleaved where+import Control.Applicative.Interleaved hiding (mkP)+import Text.ParserCombinators.UU.Core++mkP :: Gram (P st) a -> P st a+mkP (Gram ls le) = foldr (\ p pp -> doNotInterpret p <|> pp) (maybe empty pure le) (map mkParserAlt ls)+ where mkParserAlt (p `Seq` pp ) = p <*> mkP pp+ mkParserAlt (fc `Bind` c2fa) = fc >>= (mkP . c2fa)++instance Splittable (P st) where+ getPure = getZeroP+ getNonPure = getOneP++instance Functor f => ExtAlternative (Gram f) where+ p <<|> q = p <|> q+ p <?> s = error "No <?> defined for Grammars yet. If you need ask for it"+ must_be_non_empty msg (Gram _ (Just _)) _+ = error ("The combinator " ++ msg ++ " requires that it's argument cannot recognise the empty string\n")+ must_be_non_empty _ _ q = q+ must_be_non_empties msg (Gram _ (Just _)) (Gram _ (Just _)) _ + = error ("The combinator " ++ msg ++ " requires that not both arguments can recognise the empty string\n")+ must_be_non_empties msg _ _ q = q++-- | `doNotInterpret` forgets the computed minimal number of tokens recognised by this parser+-- which makes a parser opaque for abstract interpretation; used when interleaving parsers+-- where we do not want to compare lengths.++doNotInterpret :: P st a -> P st a+doNotInterpret (P t nep e _) = P t nep e Unspecified++instance IsParser (Gram (P st))+
− src/Text/ParserCombinators/UU/MergeAndPermute.hs
@@ -1,124 +0,0 @@-{-# LANGUAGE ExistentialQuantification #-}---- | This module contains the additional data types, instance definitions and functions to run parsers in an interleaved way.--- If all the interleaved parsers recognise a single connected piece of the input text this incorporates the permutation parsers.--- For some examples see the module "Text.ParserCombinators.UU.Demo.MergeAndPermute".--module Text.ParserCombinators.UU.MergeAndPermute where-import Text.ParserCombinators.UU.Core-import Debug.Trace--infixl 4 <||>, <<||> ------ * The data type `Gram`--- | Since we want to get access to the individual parsers which recognise a consecutive piece of the input text we--- define a new data type, which lifts the underlying parsers to the grammatical level, so they can be transformed, manipulated, and run in a piecewise way.--- `Gram` is defined in such a way that we can always access the first parsers to be ran from such a structure.--- We require that all the `Alt`s do not recognise the empty string. These should be covered by the `Maybe` in the `Gram` constructor.-data Gram f a = Gram [Alt f a] (Maybe a) -data Alt f a = forall b . Seq (f b) (Gram f (b -> a)) - | forall b. Bind (f b) (b -> Gram f a)--instance (Show a) => Show (Gram f a) where- show (Gram l ma) = "Gram " ++ show (length l) ++ " " ++ show ma ---- | The function `mkGram` splits a simple parser into the possibly empty part and the non-empty part.--- The non-empty part recognises a consecutive part of the input.--- Here we use the functions `getOneP` and `getZeroP` which are provided in the uu-parsinglib package,--- but they could easily be provided by other packages too.--mkGram :: P t a -> Gram (P t) a-mkGram p = case getOneP p of- Just q -> Gram [q `Seq` Gram [] (Just id)] (getZeroP p)- Nothing -> Gram [] (getZeroP p)---- * Class instances for Gram--- | We define instances for the data type `Gram` for `Functor`, `Applicative`, `Alternative` and `ExtAlternative`-instance Functor f => Functor (Gram f) where- fmap f (Gram alts e) = Gram (map (f <$>) alts) (f <$> e)--instance Functor f => Functor (Alt f) where- fmap a2c (fb `Seq` fb2a) = fb `Seq` ( (a2c .) <$> fb2a)- fmap a2c (fb `Bind` b2fa) = fb `Bind` (\b -> fmap a2c (b2fa b))---- | The left hand side operand is gradually transformed so we get access to its first component-instance Functor f => Applicative (Gram f) where- pure a = Gram [] (Just a)- Gram l le <*> ~rg@(Gram r re) - = Gram ((map (`fwdby` rg) l) ++ maybe [] (\e -> map (e <$>) r) le) (le <*> re)- where (fb `Seq` fb2c2a) `fwdby` fc = fb `Seq` (flip <$> fb2c2a <*> fc)- (fb `Bind` b2fc2a) `fwdby` fc = fb `Bind` ((<*> fc) . b2fc2a)--instance Functor f => Alternative (Gram f) where- empty = Gram [] Nothing- Gram ps pe <|> Gram qs qe = Gram (ps++qs) (pe <|> qe)--instance Functor f => ExtAlternative (Gram f) where- p <<|> q = p <|> q- p <?> s = error "No <?> defined for Grammars yet. If you need ask for it"- must_be_non_empty msg (Gram _ (Just _)) _- = error ("The combinator " ++ msg ++ " requires that it's argument cannot recognise the empty string\n")- must_be_non_empty _ _ q = q- must_be_non_empties msg (Gram _ (Just _)) (Gram _ (Just _)) _ - = error ("The combinator " ++ msg ++ " requires that not both arguments can recognise the empty string\n")- must_be_non_empties msg _ _ q = q----- * `Gram` is a `Monad`-instance Monad (Gram f) where- return a = Gram [] (Just a)- Gram ps pe >>= a2qs = - let bindto :: Alt f b -> (b -> Gram f a) -> Alt f a- (b `Seq` b2a) `bindto` a2c = b `Bind` (\b -> b2a >>= ((\b2a -> a2c (b2a b))))- (b `Bind` b2a) `bindto` a2c = b `Bind` (\b -> b2a b >>= a2c)- psa2qs = (map (`bindto` a2qs) ps)- in case pe of- Nothing -> Gram psa2qs Nothing- Just a -> let Gram qs qe = a2qs a- in Gram (psa2qs ++ qs) qe--instance Functor f => IsParser (Gram f)- --- | The function `<||>` is the merging equivalent of `<*>`. Instead of running its two arguments consecutively, --- the input is split into parts which serve as input for the left operand and parts which are served to the right operand. -(<||>):: Functor f => Gram f (b->a) -> Gram f b -> Gram f a-pg@(Gram pl pe) <||> qg@(Gram ql qe)- = Gram ( [ p `Seq` (flip <$> pp <||> qg) | p `Seq` pp <- pl ]- ++ [ q `Seq` ((.) <$> pg <||> qq) | q `Seq` qq <- ql ]- ++ [ fc `Bind` (\c -> c2fb2a c <||> qg) | fc `Bind` c2fb2a <- pl]- ++ [ fc `Bind` (\c -> pg <||> c2fb c) | fc `Bind` c2fb <- ql]- ) (pe <*> qe) ---- | The function `<<||>` is a special version of `<||>`, which only starts a new instance of its right operand when the left operand cannot proceed.--- This is used in the function 'pmMany', where we want to merge as many instances of its argument, but no more than that.-(<<||>):: Functor f => Gram f (b->a) -> Gram f b -> Gram f a-pg@(Gram pl pe) <<||> ~qg@(Gram ql qe)- = Gram ( [ p `Seq` (flip <$> pp <||> qg)| p `Seq` pp <- pl] ++ [p `Bind` (\ a -> pp a <||> qg)| p `Bind` pp <- pl]- ) (pe <*> qe)----- | 'mkParserM' converts a `Gram`mar back into a parser, which can subsequenly be run.-mkParserM :: (Monad f, Applicative f, ExtAlternative f) => Gram f a -> f a-mkParserM (Gram ls le) = foldr (\ p pp -> doNotInterpret p <|> pp) (maybe empty pure le) (map mkParserAlt ls)- where mkParserAlt (p `Seq` pp ) = p <**> mkParserM pp- mkParserAlt (fc `Bind` c2fa) = fc >>= (mkParserM . c2fa)- ---- | `mkParserS` is like `mkParserM`, with the additional feature that we allow separators between the components. Only useful in the permuting case.-mkParserS :: (Monad f, Applicative f, ExtAlternative f) => f b -> Gram f a -> f a-mkParserS sep (Gram ls le) = foldr (\ p pp -> doNotInterpret p <|> pp) (maybe empty pure le) (map mkParserAlt ls)- where mkParserAlt (p `Seq` pp) = p <**> mkParserP sep pp- mkParserAlt (fc `Bind` c2fa) = fc >>= (mkParserS sep . c2fa)- mkParserP :: (Monad f, Applicative f, ExtAlternative f) => f b -> Gram f a -> f a- mkParserP sep (Gram ls le) = foldr (\ p pp -> doNotInterpret p <|> pp) (maybe empty pure le) (map mkParserAlt ls)- where mkParserAlt (p `Seq` pp) = sep *> p <**> mkParserP sep pp- mkParserAlt (fc `Bind` c2fa) = fc >>= (mkParserP sep . c2fa)---- | Run a sufficient number of @p@'s in a merged fashion, but no more than necessary!!-pmMany :: Functor f => Gram f a -> Gram f [a]-pmMany p = let pm = ( (:) <$> p <<||> pm ) <|> pure [] in pm---
src/Text/ParserCombinators/UU/Utils.hs view
@@ -277,13 +277,13 @@ -- * Running parsers straightforwardly -- | The lower-level interface. Returns all errors. -execParser :: LL.ListLike state Char => P (Str Char state LineColPos) a -> state -> (a, [Error LineColPos])+execParser :: Parser a -> String -> (a, [Error LineColPos]) execParser p = parse_h ((,) <$> p <*> pEnd) . createStr (LineColPos 0 0 0) -- | The higher-level interface. (Calls 'error' with a simplified error). -- Runs the parser; if the complete input is accepted without problems return the -- result else fail with reporting unconsumed tokens-runParser ::String -> P (Str Char String LineColPos) a -> String -> a+runParser :: String -> Parser a -> String -> a runParser inputName p s | (a,b) <- execParser p s = if null b then a
uu-parsinglib.cabal view
@@ -1,5 +1,5 @@ Name: uu-parsinglib-Version: 2.7.4.3+Version: 2.8.1 Build-Type: Simple License: MIT Copyright: S Doaitse Swierstra @@ -20,7 +20,9 @@ . The modules "Text.ParserCombinators.UU.Demo.Examples", "Text.ParserCombinators.UU.Idioms" and "Text.ParserCombinators.UU.Demo.MergeAndpermute" contain a ready-made @show_examples@ function,- which can be called (e.g. from @ghci@) to see e.g. the error correction at work. It contains extensive haddock documentation, so why not just take a look to see the correction process at work, and to get a feeling for how the various combinators can be used? + which can be called (e.g. from @ghci@) to see e.g. the error correction at work. + It contains extensive haddock documentation, so why not just take a look + to see the correction process at work, and to get a feeling for how the various combinators can be used? . The file "Text.ParserCombinators.UU.CHANGELOG" contains a log of the most recent changes and additions. .@@ -38,16 +40,15 @@ Library hs-source-dirs: src - Build-Depends: base >= 4.2 && <5, time, ListLike >= 3.0.1+ Build-Depends: base >= 4.2 && <5, time, ListLike >= 3.0.1, uu-interleaved >= 0.1.0 && < 0.2 Exposed-modules: Text.ParserCombinators.UU Text.ParserCombinators.UU.CHANGELOG Text.ParserCombinators.UU.README Text.ParserCombinators.UU.Core Text.ParserCombinators.UU.BasicInstances+ Text.ParserCombinators.UU.Interleaved Text.ParserCombinators.UU.Derived- Text.ParserCombinators.UU.MergeAndPermute Text.ParserCombinators.UU.Utils Text.ParserCombinators.UU.Idioms Text.ParserCombinators.UU.Demo.Examples- Text.ParserCombinators.UU.Demo.MergeAndPermute