uu-parsinglib 2.4.2 → 2.4.4
raw patch · 5 files changed
+85/−54 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Text.ParserCombinators.UU.Core: class (Applicative p, Alternative p) => IsParser p
- Text.ParserCombinators.UU.Core: class Symbol p symbol token | p symbol -> token
- Text.ParserCombinators.UU.Core: instance (Applicative p, Alternative p) => IsParser p
- Text.ParserCombinators.UU.Core: instance (Provides state symbol token) => Symbol (P state) symbol token
+ Text.ParserCombinators.UU.Examples: pManyTill :: P st a -> P st b -> P st [a]
+ Text.ParserCombinators.UU.Examples: string :: String -> Parser String
+ Text.ParserCombinators.UU.Examples: test15 :: IO ()
+ Text.ParserCombinators.UU.Examples: test16 :: IO ()
+ Text.ParserCombinators.UU.Examples: test6 :: IO ()
+ Text.ParserCombinators.UU.Examples: test7 :: IO ()
+ Text.ParserCombinators.UU.Examples: test8 :: IO ()
+ Text.ParserCombinators.UU.Examples: test9 :: IO ()
- Text.ParserCombinators.UU.BasicInstances: pMunch :: (Symbol p (Munch a) [a]) => (a -> Bool) -> p [a]
+ Text.ParserCombinators.UU.BasicInstances: pMunch :: (Provides st (Munch a) [a]) => (a -> Bool) -> P st [a]
- Text.ParserCombinators.UU.Core: pSym :: (Symbol p symbol token) => symbol -> p token
+ Text.ParserCombinators.UU.Core: pSym :: (Provides state symbol token) => symbol -> P state token
- Text.ParserCombinators.UU.Core: pSymExt :: (Symbol p symbol token) => Nat -> Maybe token -> symbol -> p token
+ Text.ParserCombinators.UU.Core: pSymExt :: (Provides state symbol token) => Nat -> Maybe token -> symbol -> P state token
Files
- src/Text/ParserCombinators/UU/BasicInstances.hs +1/−1
- src/Text/ParserCombinators/UU/CHANGELOG.hs +13/−0
- src/Text/ParserCombinators/UU/Core.hs +37/−45
- src/Text/ParserCombinators/UU/Examples.hs +31/−7
- uu-parsinglib.cabal +3/−1
src/Text/ParserCombinators/UU/BasicInstances.hs view
@@ -75,7 +75,7 @@ l = length munched in Step l (k munched (Str rest msgs (pos+l) (l>0 || del_ok))) -pMunch :: (Text.ParserCombinators.UU.Core.Symbol p (Munch a) [a]) => (a -> Bool) -> p [a]+pMunch :: (Provides st (Munch a) [a]) => (a -> Bool) -> P st [a] pMunch p = pSymExt Zero (Just []) (Munch p) data Token a = Token [a] Int -- the Int value represents the cost for inserting such a token
src/Text/ParserCombinators/UU/CHANGELOG.hs view
@@ -1,4 +1,17 @@ -- | This module just contains the CHANGELOG+-- Version 2.4.4+-- +-- * solved a mistake which had crept in in the greedy choice+-- +-- * added priority for @`<<|>`@ which had disappeared+-- +-- * added an example how to achieve the effect of manytill from parsec+-- +-- Version 2.4.3+--+-- * removed the classes IsParser and Symbol, which made the code shorter and more H98-alike+-- last version with dynamic error message computation+-- -- Version 2.4.2 -- -- * fixed dependency in cabal file to base >=4.2
src/Text/ParserCombinators/UU/Core.hs view
@@ -2,12 +2,7 @@ {-# LANGUAGE RankNTypes, GADTs, MultiParamTypeClasses,- FunctionalDependencies, - FlexibleInstances, - FlexibleContexts, - UndecidableInstances,- NoMonomorphismRestriction #-}-+ FunctionalDependencies #-} -- | The module `Core` contains the basic functionality of the parser library. -- It uses the breadth-first module to realise online generation of results, the error@@ -21,40 +16,14 @@ import Debug.Trace import Maybe --- * The Classes Defining the Interface--- ** `IsParser` --- | This class collects a number of classes which together defines what a `Parser` should provide. --- Since it is just a predicate we have prefixed the name by the phrase `Is'+infix 2 <?> -- should be the last element in a sequence of alternatives+infixl 3 <<|> -- intended use p <<|> q <<|> r <|> x <|> y <?> z -class (Applicative p, Alternative p) => IsParser p where-instance (Applicative p, Alternative p) => IsParser p where -infix 2 <?>---- ** `Symbol'--- | Many parsing libraries do not make a distinction between the terminal symbols of the language recognised and the --- tokens actually constructed from the input. This happens e.g. if we want to recognise an integer or an identifier: we are also interested in which integer occurred in the input, --- or which identifier. ---- ^ The function `pSym` takes as argument a value of some type `symbol', and returns a value of type `token'. The parser will in general depend on some --- state which is maintained holding the input. The functional dependency fixes the `token` type, based on the `symbol` type and the type of the parser `p`.--- Since `pSym' is overloaded both the type and the value of symbol determine how to decompose the input in a `token` and the remaining input.--- `pSymExt` is the actual function, which takes two extra parameters: one describing the minimal numer of tokens recognised, --- and the second whether the symbol can recognise the empty string and the value which is to be returned in that case--class Symbol p symbol token | p symbol -> token where- -- | The first parameter to `pSymExt` is a `Nat` which describes the minimal numer of tokens accepted by this parser. It is used in the abstract interpretation- -- which computes this property for each parser. It's main use is in choosinga non-recursive alternative in case a non-terminal has to be inserted.- -- The second parameter indicates whether this parser can also skip recognising anything and just return a value of type a, hence a `Maybe a`- - pSymExt :: Nat -> Maybe token -> symbol -> p token- pSym :: symbol -> p token- pSym s = pSymExt (Succ Zero) Nothing s - -- ** `Provides' --- | The function `splitStae` playes a crucial role in splitting up the state. The `symbol` parameter tells us what kind of thing, and even which value of that kind, is expected from the input.+-- | The function `splitState` playes a crucial role in splitting up the state. The `symbol` parameter tells us what kind of thing, and even which value of that kind, is expected from the input. -- The state and and the symbol type together determine what kind of token has to be returned. Since the function is overloaded we do not have to invent -- all kind of different names for our elementary parsers. class Provides state symbol token | state symbol -> token where@@ -73,7 +42,6 @@ -- %%%%%%%%%%%%% Parsers %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --- do not change into data, or be prepared to add ~ at subtle places !! data P st a = P (forall r . (a -> st -> Steps r) -> st -> Steps r ) -- history parser (forall r . ( st -> Steps r) -> st -> Steps (a, r) ) -- future parser (forall r . ( st -> Steps r) -> st -> Steps r ) -- recogniser@@ -127,13 +95,28 @@ Nothing -- ** Parsers can recognise single tokens: @`pSym`@ and @`pSymExt`@-instance ( Provides state symbol token) => Symbol (P state) symbol token where- pSymExt l e a = P ( \ k inp -> splitState a k inp)- ( \ k inp -> splitState a (\ t inp' -> push t (k inp')) inp)- ( \ k inp -> splitState a (\ _ inp' -> k inp') inp)- l- e+-- | Many parsing libraries do not make a distinction between the terminal symbols of the language recognised +-- and the tokens actually constructed from the input. +-- This happens e.g. if we want to recognise an integer or an identifier: +-- we are also interested in which integer occurred in the input, or which identifier. +-- The function `pSymExt` takes as argument a value of some type `symbol', and returns a value of type `token'. The parser will in general depend on some +-- state which is maintained holding the input. The functional dependency fixes the `token` type, based on the `symbol` type and the type of the parser `p`.+-- Since `pSymExt' is overloaded both the type and the value of symbol determine how to decompose the input in a `token` and the remaining input.+-- `pSymExt` takes two extra parameters: one describing the minimal numer of tokens recognised, +-- and the second whether the symbol can recognise the empty string and the value which is to be returned in that case+ +pSymExt :: (Provides state symbol token) => Nat -> Maybe token -> symbol -> P state token + +pSymExt l e a = P ( \ k inp -> splitState a k inp)+ ( \ k inp -> splitState a (\ t inp' -> push t (k inp')) inp)+ ( \ k inp -> splitState a (\ _ inp' -> k inp') inp)+ l+ e+-- | @`pSym`@ covers the most common case of recognsiing a symbol: a single token is removed form the input, and it cannot recognise the empty string+pSym :: (Provides state symbol token) => symbol -> P state token+pSym s = pSymExt (Succ Zero) Nothing s + -- ** Parsers are Monads: @`>>=`@ and @`return`@ unParser_h (P h _ _ _ _) = h@@ -176,9 +159,15 @@ P ph pf pr pl pe <<|> P qh qf qr ql qe = let (rl, b) = nat_min pl ql bestx = if b then flip best else best- in P ( \ k st -> norm (ph k st) `bestx` norm (qh k st))- ( \ k st -> norm (pf k st) `bestx` norm (qf k st))- ( \ k st -> norm (pr k st) `bestx` norm (qr k st))+ in P ( \ k st -> let left = norm (ph k st) + in if has_success left then left+ else left `bestx` norm (qh k st))+ ( \ k st -> let left = norm (pf k st) + in if has_success left then left+ else left `bestx` norm (qf k st))+ ( \ k st -> let left = norm (pr k st) + in if has_success left then left+ else left `bestx` norm (qr k st)) rl (case (pe, qe) of (Nothing, _ ) -> qe@@ -298,6 +287,9 @@ succeedAlways = let steps = Step 0 steps in steps failAlways = Fail [] [const (0, failAlways)] noAlts = Fail [] []++has_success (Step _ _) = True+has_success _ = False -- ! @`eval`@ removes the progress information from a sequence of steps, and constructs the value contained in it. eval :: Steps a -> a
src/Text/ParserCombinators/UU/Examples.hs view
@@ -104,7 +104,7 @@ -- > Inserted 'k' at position 1 expecting 'a'..'z' -- -+test6 :: IO () test6 = run paz' "1" paz' = pSym (\t -> 'a' <= t && t <= 'z', "'a'..'z'", 'k') @@ -116,9 +116,9 @@ -- > Result: 5 -- -pCount p = (+1) <$ p <*> pCount p <<|> pReturn 0-+test7 :: IO () test7 = run (pCount pa) "aaaaa"+pCount p = (+1) <$ p <*> pCount p <<|> pReturn 0 -- | The parsers are instance of the class Monad and hence we can use the -- result of a previous parser to construct a following one: @@ -131,18 +131,19 @@ -- > Inserted 'b' at position 8 expecting 'b' -- -+test8 :: IO () test8 = run (do {l <- pCount pa; pExact l pb}) "aaacabbb" pExact 0 p = pReturn [] pExact n p = (:) <$> p <*> pExact (n-1) p + -- | The function @`amb`@ converts an ambigous parser into one which returns all possible parses: -- -- > run (amb ( (++) <$> pa2 <*> pa3 <|> (++) <$> pa3 <*> pa2)) "aaaaa" -- -- > Result: ["aaaaa","aaaaa"] -- -+test9 :: IO () test9 = run (amb ( (++) <$> pa2 <*> pa3 <|> (++) <$> pa3 <*> pa2)) "aaaaa" -- | The applicative style makes it very easy to merge recognsition and computing a result. @@ -154,9 +155,9 @@ -- > Result: 3 -- -test10 = run wfp "((()))()(())" wfp :: Parser Int wfp = max <$> pParens ((+1) <$> wfp) <*> wfp `opt` 0+test10 = run wfp "((()))()(())" -- | It is very easy to recognise infix expressions with any number of priorities and operators: --@@ -236,6 +237,7 @@ -- > requires that it's argument cannot recognise the empty string +test16 :: IO () test16 = run (pList spaces) " " ident = ((:) <$> pSym ('a','z') <*> pMunch (\x -> 'a' <= x && x <= 'z') `micro` 2) <* spaces@@ -262,6 +264,7 @@ -- > Result: ("123","abd","ACDD") -- +test15 :: IO () test15 = run ((,,) `pMerged` (list_of pDigit <||> list_of pLower <||> list_of pUpper)) "1AabCD2D3d" -- | The function@@ -283,7 +286,27 @@ munch :: Parser String munch = pMunch ( `elem` "^=*") --- bracketing expressions+-- | The effect of the combinator `manytill` from Parsec can be achieved:+--+-- > run simpleComment "<!--123$$-->abc"+-- > Result: "123$$"+-- > Correcting steps: +-- > The token 'a' was not consumed by the parsing process.+-- > The token 'b' was not consumed by the parsing process.+-- > The token 'c' was not consumed by the parsing process.+-- ++pManyTill :: P st a -> P st b -> P st [a]+pManyTill p end = [] <$ end + <<|> + (:) <$> p <*> pManyTill p end+simpleComment = string "<!--" + *> + pManyTill pAscii (string "-->")+++string :: String -> Parser String+string = pToken-- bracketing expressions pParens p = pSym '(' *> p <* pSym ')' pBracks p = pSym '[' *> p <* pSym ']' pCurlys p = pSym '{' *> p <* pSym '}'@@ -295,6 +318,7 @@ digit2Int a = ord a - ord '0' -- parsing letters and identifiers+pAscii = pSym (chr 0, chr 255) pDigit = pSym ('0', '9') pLower = pSym ('a','z') pUpper = pSym ('A','Z')
uu-parsinglib.cabal view
@@ -1,5 +1,5 @@ Name: uu-parsinglib-Version: 2.4.2+Version: 2.4.4 Build-Type: Simple License: MIT Copyright: S Doaitse Swierstra @@ -26,6 +26,8 @@ . Version 2.4.2 fixes a dependency in the .cabal file and has made the class ExtApplicative obsolete since <$ is now in the class Functor+ .+ Version 2.4.3: removed the class Symbol, which enabled us to become more H98-ish Category: Parsing Library