parsers 0.12.4 → 0.12.5
raw patch · 13 files changed
+379/−105 lines, 13 filesdep +mtldep ~basesetup-changednew-uploaderPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: mtl
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Text.Parser.Token: instance Control.Monad.Reader.Class.MonadReader e m => Control.Monad.Reader.Class.MonadReader e (Text.Parser.Token.Unhighlighted m)
+ Text.Parser.Token: instance Control.Monad.Reader.Class.MonadReader e m => Control.Monad.Reader.Class.MonadReader e (Text.Parser.Token.Unlined m)
+ Text.Parser.Token: instance Control.Monad.Reader.Class.MonadReader e m => Control.Monad.Reader.Class.MonadReader e (Text.Parser.Token.Unspaced m)
+ Text.Parser.Token: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Text.Parser.Token.Unhighlighted m)
+ Text.Parser.Token: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Text.Parser.Token.Unlined m)
+ Text.Parser.Token: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Text.Parser.Token.Unspaced m)
+ Text.Parser.Token: instance Control.Monad.Writer.Class.MonadWriter e m => Control.Monad.Writer.Class.MonadWriter e (Text.Parser.Token.Unhighlighted m)
+ Text.Parser.Token: instance Control.Monad.Writer.Class.MonadWriter e m => Control.Monad.Writer.Class.MonadWriter e (Text.Parser.Token.Unlined m)
+ Text.Parser.Token: instance Control.Monad.Writer.Class.MonadWriter e m => Control.Monad.Writer.Class.MonadWriter e (Text.Parser.Token.Unspaced m)
- Text.Parser.Char: satisfy :: (CharParsing m, MonadTrans t, CharParsing n, Monad n, m ~ t n) => (Char -> Bool) -> t n Char
+ Text.Parser.Char: satisfy :: (CharParsing m, MonadTrans t, CharParsing n, Monad n, m ~ t n) => (Char -> Bool) -> m Char
- Text.Parser.Combinators: eof :: (Parsing m, MonadTrans t, Monad n, Parsing n, m ~ t n) => t n ()
+ Text.Parser.Combinators: eof :: (Parsing m, MonadTrans t, Monad n, Parsing n, m ~ t n) => m ()
- Text.Parser.Combinators: unexpected :: (Parsing m, MonadTrans t, Monad n, Parsing n, m ~ t n) => String -> t n a
+ Text.Parser.Combinators: unexpected :: (Parsing m, MonadTrans t, Monad n, Parsing n, m ~ t n) => String -> m a
- Text.Parser.Permutation: permute :: Alternative m => Permutation m a -> m a
+ Text.Parser.Permutation: permute :: forall m a. Alternative m => Permutation m a -> m a
- Text.Parser.Token: charLiteral :: TokenParsing m => m Char
+ Text.Parser.Token: charLiteral :: forall m. TokenParsing m => m Char
- Text.Parser.Token: integer :: TokenParsing m => m Integer
+ Text.Parser.Token: integer :: forall m. TokenParsing m => m Integer
- Text.Parser.Token: integerOrScientific :: TokenParsing m => m (Either Integer Scientific)
+ Text.Parser.Token: integerOrScientific :: forall m. TokenParsing m => m (Either Integer Scientific)
- Text.Parser.Token: stringLiteral :: (TokenParsing m, IsString s) => m s
+ Text.Parser.Token: stringLiteral :: forall m s. (TokenParsing m, IsString s) => m s
- Text.Parser.Token: stringLiteral' :: (TokenParsing m, IsString s) => m s
+ Text.Parser.Token: stringLiteral' :: forall m s. (TokenParsing m, IsString s) => m s
- Text.Parser.Token.Style: buildSomeSpaceParser :: CharParsing m => m () -> CommentStyle -> m ()
+ Text.Parser.Token.Style: buildSomeSpaceParser :: forall m. CharParsing m => m () -> CommentStyle -> m ()
Files
- .travis.yml +19/−16
- CHANGELOG.markdown +124/−0
- README.markdown +21/−0
- Setup.lhs +24/−38
- Warning.hs +5/−0
- parsers.cabal +14/−3
- src/Text/Parser/Char.hs +1/−1
- src/Text/Parser/Combinators.hs +3/−3
- src/Text/Parser/Expression.hs +12/−1
- src/Text/Parser/Permutation.hs +4/−2
- src/Text/Parser/Token.hs +126/−16
- src/Text/Parser/Token/Style.hs +7/−1
- tests/doctests.hs +19/−24
.travis.yml view
@@ -13,27 +13,30 @@ matrix: include:- - env: CABALVER=1.18 GHCVER=7.0.4+ - env: CABALVER=1.24 GHCVER=7.0.4 compiler: ": #GHC 7.0.4"- addons: {apt: {packages: [cabal-install-1.18,ghc-7.0.4,hlint], sources: [hvr-ghc]}}- - env: CABALVER=1.18 GHCVER=7.2.2+ addons: {apt: {packages: [cabal-install-1.24,ghc-7.0.4,hlint], sources: [hvr-ghc]}}+ - env: CABALVER=1.24 GHCVER=7.2.2 compiler: ": #GHC 7.2.2"- addons: {apt: {packages: [cabal-install-1.18,ghc-7.2.2,hlint], sources: [hvr-ghc]}}- - env: CABALVER=1.18 GHCVER=7.4.2+ addons: {apt: {packages: [cabal-install-1.24,ghc-7.2.2,hlint], sources: [hvr-ghc]}}+ - env: CABALVER=1.24 GHCVER=7.4.2 compiler: ": #GHC 7.4.2"- addons: {apt: {packages: [cabal-install-1.18,ghc-7.4.2,hlint], sources: [hvr-ghc]}}- - env: CABALVER=1.18 GHCVER=7.6.3+ addons: {apt: {packages: [cabal-install-1.24,ghc-7.4.2,hlint], sources: [hvr-ghc]}}+ - env: CABALVER=1.24 GHCVER=7.6.3 compiler: ": #GHC 7.6.3"- addons: {apt: {packages: [cabal-install-1.18,ghc-7.6.3,hlint], sources: [hvr-ghc]}}- - env: CABALVER=1.18 GHCVER=7.8.4+ addons: {apt: {packages: [cabal-install-1.24,ghc-7.6.3,hlint], sources: [hvr-ghc]}}+ - env: CABALVER=1.24 GHCVER=7.8.4 compiler: ": #GHC 7.8.4"- addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,hlint], sources: [hvr-ghc]}}- - env: CABALVER=1.22 GHCVER=7.10.3+ addons: {apt: {packages: [cabal-install-1.24,ghc-7.8.4,hlint], sources: [hvr-ghc]}}+ - env: CABALVER=1.24 GHCVER=7.10.3 compiler: ": #GHC 7.10.3"- addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,hlint], sources: [hvr-ghc]}}- - env: CABALVER=1.24 GHCVER=8.0.1- compiler: ": #GHC 8.0.1"- addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1,hlint], sources: [hvr-ghc]}}+ addons: {apt: {packages: [cabal-install-1.24,ghc-7.10.3,hlint], sources: [hvr-ghc]}}+ - env: CABALVER=1.24 GHCVER=8.0.2+ compiler: ": #GHC 8.0.2"+ addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2,hlint], sources: [hvr-ghc]}}+ - env: CABALVER=1.24 GHCVER=8.2.1+ compiler: ": #GHC 8.2.1"+ addons: {apt: {packages: [cabal-install-1.24,ghc-8.2.1,hlint], sources: [hvr-ghc]}} before_install: - unset CC@@ -63,7 +66,7 @@ echo "cabal build-cache MISS"; rm -rf $HOME/.cabsnap; mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;- cabal install --only-dependencies --enable-tests --enable-benchmarks;+ cabal install -j --only-dependencies --enable-tests --enable-benchmarks; fi # snapshot package-db on cache miss
+ CHANGELOG.markdown view
@@ -0,0 +1,124 @@+0.12.5+------+* Allow building with GHC 8.2+* Add `mtl` instances for `Unspaced`, `Unhighlighted`, and `Unlined`+* Revamp `Setup.hs` to use `cabal-doctest`. This makes it build+ with `Cabal-2.0`, and makes the `doctest`s work with `cabal new-build` and+ sandboxes.++0.12.4+------+* Allow `transformers` 0.5++0.12.3+------+* Build without warnings on GHC 7.10+* Add `LookAheadParsing` instance for `attoparsec`+* Documentation fixes+* Fix out-of-bounds error in numeric escapes+* Depend on `base-orphans` for `Applicative ReadP` on old `base`++0.12.2+------+* Added parsers for `scientific`, so we can parse decimal places without losing precision.++0.12.1+----+* Fixed the fixed behavior of `notFollowedBy`, which was showing internal state. This had led to unnecessary constraints on internal state that are now removed.++0.12+------+* Fixed the behavior of `notFollowedBy`. This necessitated removing the default implementation, and therefore required a major version bump.++0.11.0.2+--------+* Allow `attoparsec` 0.12++0.11+----+* Mikhail Vorozhtsov refactored `attoparsec` to permit `parsers` instances. Instances added.++0.10.3+------+* Compatibility with ghc 7.8 roles++0.10.2+------+* Documentation fixes++0.10.1.2+--------+* Updated to work with `text` 1.0++0.10.1.1+--------+* 0.10.1 accidentally prevented the orphan instances for ReadP from compiling. Fxed.++0.10.1+------+* Fixed an issue with the expression parser, where it didn't `try` hard enough.+* Added `satisfyRange`+* Fixed a longstanding issue with the char escapes that we inherited from parsec, where ^A and the like were returning 0 not 1.++0.10+----+* Added proper upper bounds for PVP compliance+* Switched to an applicative expression parser++0.9+---+* `instance MonadTrans Unlined`++0.8.3+-----+* Fixed a _major_ performance regression in Text.Parser.Expression++0.8.2+-----+* Added `scalaCommentStyle`.++0.8.1+-----+* Text.Parser.Token.* is now Trustworthy++0.8+---+* Removed the need for `textLiteral`, `textLiteral'` and `identText` by using `fromString`. Use `stringLiteral`, `stringLiteral'`, and `ident` instead respectively.++0.7.1+-----+* Added support for `Text`-based parsing.++0.7+---+* Added `Unlined` to support parsing solely within a line+* Simplified `TokenParsing` instances++0.6+---+* Disallowed nested comments in 'javaCommentStyle'+* More derived instances++0.5.2+-----+* Bugfix in `commaSep1`.++0.5.1+-----+* Taught zeroNumFloat about `0.`.+* Bugfix in `buildExpressionParser`.++0.5+---+* Split out `LookAheadParsing` since it wasn't used by other combinators here and isn't supported by `attoparsec`.++0.4.1+-----+* Added `token` to `TokenParsing`.++0.4+-----+* Updated build system+* Converted various style accessors to lenses and traversals+* More aggressive inlining+* Added CHANGELOG
+ README.markdown view
@@ -0,0 +1,21 @@+parsers+=======++[](https://hackage.haskell.org/package/parsers) [](http://travis-ci.org/ekmett/parsers)++Goals+-----++This library provides convenient combinators for working with and building parsing combinator libraries.++Given a few simple instances, you get access to a large number of canned definitions.++Contact Information+-------------------++Contributions and bug reports are welcome!++Please feel free to contact me through github or on the #haskell IRC channel on irc.freenode.net.++-Edward Kmett+
Setup.lhs view
@@ -1,48 +1,34 @@-#!/usr/bin/runhaskell \begin{code}+{-# LANGUAGE CPP #-} {-# OPTIONS_GHC -Wall #-} module Main (main) where -import Data.List ( nub )-import Data.Version ( showVersion )-import Distribution.Package ( PackageName(PackageName), PackageId, InstalledPackageId, packageVersion, packageName )-import Distribution.PackageDescription ( PackageDescription(), TestSuite(..) )-import Distribution.Simple ( defaultMainWithHooks, UserHooks(..), simpleUserHooks )-import Distribution.Simple.Utils ( rewriteFile, createDirectoryIfMissingVerbose )-import Distribution.Simple.BuildPaths ( autogenModulesDir )-import Distribution.Simple.Setup ( BuildFlags(buildVerbosity), fromFlag )-import Distribution.Simple.LocalBuildInfo ( withLibLBI, withTestLBI, LocalBuildInfo(), ComponentLocalBuildInfo(componentPackageDeps) )-import Distribution.Verbosity ( Verbosity )-import System.FilePath ( (</>) )+#ifndef MIN_VERSION_cabal_doctest+#define MIN_VERSION_cabal_doctest(x,y,z) 0+#endif +#if MIN_VERSION_cabal_doctest(1,0,0)++import Distribution.Extra.Doctest ( defaultMainWithDoctests ) main :: IO ()-main = defaultMainWithHooks simpleUserHooks- { buildHook = \pkg lbi hooks flags -> do- generateBuildModule (fromFlag (buildVerbosity flags)) pkg lbi- buildHook simpleUserHooks pkg lbi hooks flags- }+main = defaultMainWithDoctests "doctests" -generateBuildModule :: Verbosity -> PackageDescription -> LocalBuildInfo -> IO ()-generateBuildModule verbosity pkg lbi = do- let dir = autogenModulesDir lbi- createDirectoryIfMissingVerbose verbosity True dir- withLibLBI pkg lbi $ \_ libcfg -> do- withTestLBI pkg lbi $ \suite suitecfg -> do- rewriteFile (dir </> "Build_" ++ testName suite ++ ".hs") $ unlines- [ "module Build_" ++ testName suite ++ " where"- , ""- , "autogen_dir :: String"- , "autogen_dir = " ++ show dir- , ""- , "deps :: [String]"- , "deps = " ++ (show $ formatdeps (testDeps libcfg suitecfg))- ]- where- formatdeps = map (formatone . snd)- formatone p = case packageName p of- PackageName n -> n ++ "-" ++ showVersion (packageVersion p)+#else -testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo -> [(InstalledPackageId, PackageId)]-testDeps xs ys = nub $ componentPackageDeps xs ++ componentPackageDeps ys+#ifdef MIN_VERSION_Cabal+-- If the macro is defined, we have new cabal-install,+-- but for some reason we don't have cabal-doctest in package-db+--+-- Probably we are running cabal sdist, when otherwise using new-build+-- workflow+import Warning ()+#endif++import Distribution.Simple++main :: IO ()+main = defaultMain++#endif \end{code}
+ Warning.hs view
@@ -0,0 +1,5 @@+module Warning+ {-# WARNING ["You are configuring this package without cabal-doctest installed.",+ "The doctests test-suite will not work as a result.",+ "To fix this, install cabal-doctest before configuring."] #-}+ () where
parsers.cabal view
@@ -1,6 +1,6 @@ name: parsers category: Text, Parsing-version: 0.12.4+version: 0.12.5 license: BSD3 cabal-version: >= 1.10 license-file: LICENSE@@ -18,10 +18,20 @@ get access to a large number of canned definitions. Instances exist for the parsers provided by @parsec@, @attoparsec@ and base’s "Text.Read". build-type: Custom-tested-with: GHC==7.0.4, GHC==7.2.2, GHC==7.4.2, GHC==7.6.3, GHC==7.8.4, GHC==7.10.2, GHC==8.0.1+tested-with: GHC==7.0.4, GHC==7.2.2, GHC==7.4.2, GHC==7.6.3, GHC==7.8.4, GHC==7.10.3, GHC==8.0.2, GHC==8.2.1 -extra-source-files: .travis.yml+extra-source-files:+ .travis.yml+ CHANGELOG.markdown+ README.markdown+ Warning.hs +custom-setup+ setup-depends:+ base >= 4.3 && <5,+ Cabal >= 1.10,+ cabal-doctest >= 1 && <1.1+ source-repository head type: git location: git://github.com/ekmett/parsers.git@@ -53,6 +63,7 @@ attoparsec >= 0.12.1.4 && < 0.14, text >= 0.10 && < 1.3, transformers >= 0.2 && < 0.6,+ mtl >= 2.0.1 && < 2.3, scientific >= 0.3 && < 0.4, unordered-containers >= 0.2 && < 0.3
src/Text/Parser/Char.hs view
@@ -183,7 +183,7 @@ #ifdef USE_DEFAULT_SIGNATURES default satisfy :: (MonadTrans t, CharParsing n, Monad n, m ~ t n) => (Char -> Bool) ->- t n Char+ m Char satisfy = lift . satisfy #endif -- | @char c@ parses a single character @c@. Returns the parsed
src/Text/Parser/Combinators.hs view
@@ -129,7 +129,7 @@ -- separated and optionally ended by @sep@. Returns a list of values -- returned by @p@. sepEndBy1 :: Alternative m => m a -> m sep -> m [a]-sepEndBy1 p sep = p <**> ((flip (:) <$> (sep *> sepEndBy p sep)) <|> pure pure)+sepEndBy1 p sep = (:) <$> p <*> ((sep *> sepEndBy p sep) <|> pure []) -- | @sepEndBy p sep@ parses /zero/ or more occurrences of @p@, -- separated and optionally ended by @sep@, ie. haskell style@@ -252,7 +252,7 @@ unexpected :: String -> m a #ifdef USE_DEFAULT_SIGNATURES default unexpected :: (MonadTrans t, Monad n, Parsing n, m ~ t n) =>- String -> t n a+ String -> m a unexpected = lift . unexpected {-# INLINE unexpected #-} #endif@@ -263,7 +263,7 @@ -- > eof = notFollowedBy anyChar <?> "end of input" eof :: m () #ifdef USE_DEFAULT_SIGNATURES- default eof :: (MonadTrans t, Monad n, Parsing n, m ~ t n) => t n ()+ default eof :: (MonadTrans t, Monad n, Parsing n, m ~ t n) => m () eof = lift eof {-# INLINE eof #-} #endif
src/Text/Parser/Expression.hs view
@@ -110,23 +110,34 @@ = foldl makeParser simpleExpr operators where makeParser term ops- = let (rassoc,lassoc,nassoc,prefix,postfix) = foldr splitOp ([],[],[],[],[]) ops+ = let rassoc, lassoc, nassoc :: [m (a -> a -> a)]+ prefix, postfix :: [m (a -> a)]+ (rassoc,lassoc,nassoc,prefix,postfix) = foldr splitOp ([],[],[],[],[]) ops++ rassocOp, lassocOp, nassocOp :: m (a -> a -> a) rassocOp = choice rassoc lassocOp = choice lassoc nassocOp = choice nassoc++ prefixOp, postfixOp :: m (a -> a) prefixOp = choice prefix <?> "" postfixOp = choice postfix <?> "" + ambiguous :: String -> m x -> m y ambiguous assoc op = try $ op *> empty <?> ("ambiguous use of a " ++ assoc ++ "-associative operator") + ambiguousRight, ambiguousLeft, ambiguousNon :: m y ambiguousRight = ambiguous "right" rassocOp ambiguousLeft = ambiguous "left" lassocOp ambiguousNon = ambiguous "non" nassocOp + termP :: m a termP = (prefixP <*> term) <**> postfixP + postfixP :: m (a -> a) postfixP = postfixOp <|> pure id + prefixP :: m (a -> a) prefixP = prefixOp <|> pure id rassocP, rassocP1, lassocP, lassocP1, nassocP :: m (a -> a)
src/Text/Parser/Permutation.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Text.Parser.Permutation@@ -62,7 +63,7 @@ (<$$>) f p = newPermutation f <||> p {-# INLINE (<$$>) #-} --- | The expression @perm \<||> (x,p)@ adds parser @p@ to the+-- | The expression @perm \<|?> (x,p)@ adds parser @p@ to the -- permutation parser @perm@. The parser @p@ is optional - if it can -- not be applied, the default value @x@ will be used instead. Returns -- a new permutation parser that includes the optional parser @p@.@@ -116,10 +117,11 @@ -- > tuple a b c = (a,b,c) -- transform a permutation tree into a normal parser-permute :: Alternative m => Permutation m a -> m a+permute :: forall m a. Alternative m => Permutation m a -> m a permute (Permutation def xs) = asum (map branch xs ++ e) where+ e :: [m a] e = maybe [] (pure . pure) def branch (Branch perm p) = flip id <$> p <*> permute perm
src/Text/Parser/Token.hs view
@@ -2,6 +2,9 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UndecidableInstances #-} #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702 {-# LANGUAGE Trustworthy #-} #endif@@ -93,6 +96,9 @@ import Control.Monad.Trans.RWS.Strict as Strict import Control.Monad.Trans.Reader import Control.Monad.Trans.Identity+import Control.Monad.State.Class as Class+import Control.Monad.Reader.Class as Class+import Control.Monad.Writer.Class as Class import Data.Char import Data.Functor.Identity import qualified Data.HashSet as HashSet@@ -124,8 +130,9 @@ -- sequences. The literal character is parsed according to the grammar -- rules defined in the Haskell report (which matches most programming -- languages quite closely).-charLiteral :: TokenParsing m => m Char+charLiteral :: forall m. TokenParsing m => m Char charLiteral = token (highlight CharLiteral lit) where+ lit :: m Char lit = between (char '\'') (char '\'' <?> "end of character") characterChar <?> "character" {-# INLINE charLiteral #-}@@ -135,45 +142,63 @@ -- gaps. The literal string is parsed according to the grammar rules -- defined in the Haskell report (which matches most programming -- languages quite closely).-stringLiteral :: (TokenParsing m, IsString s) => m s+stringLiteral :: forall m s. (TokenParsing m, IsString s) => m s stringLiteral = fromString <$> token (highlight StringLiteral lit) where+ lit :: m [Char] lit = Prelude.foldr (maybe id (:)) "" <$> between (char '"') (char '"' <?> "end of string") (many stringChar) <?> "string"++ stringChar :: m (Maybe Char) stringChar = Just <$> stringLetter <|> stringEscape <?> "string character"- stringLetter = satisfy (\c -> (c /= '"') && (c /= '\\') && (c > '\026')) + stringLetter :: m Char+ stringLetter = satisfy (\c -> (c /= '"') && (c /= '\\') && (c > '\026'))++ stringEscape :: m (Maybe Char) stringEscape = highlight EscapeCode $ char '\\' *> esc where+ esc :: m (Maybe Char) esc = Nothing <$ escapeGap <|> Nothing <$ escapeEmpty <|> Just <$> escapeCode++ escapeEmpty, escapeGap :: m Char escapeEmpty = char '&' escapeGap = skipSome space *> (char '\\' <?> "end of string gap") {-# INLINE stringLiteral #-} -- | This token parser behaves as 'stringLiteral', but for single-quoted -- strings.-stringLiteral' :: (TokenParsing m, IsString s) => m s+stringLiteral' :: forall m s. (TokenParsing m, IsString s) => m s stringLiteral' = fromString <$> token (highlight StringLiteral lit) where+ lit :: m [Char] lit = Prelude.foldr (maybe id (:)) "" <$> between (char '\'') (char '\'' <?> "end of string") (many stringChar) <?> "string"++ stringChar :: m (Maybe Char) stringChar = Just <$> stringLetter <|> stringEscape <?> "string character"- stringLetter = satisfy (\c -> (c /= '\'') && (c /= '\\') && (c > '\026')) + stringLetter :: m Char+ stringLetter = satisfy (\c -> (c /= '\'') && (c /= '\\') && (c > '\026'))++ stringEscape :: m (Maybe Char) stringEscape = highlight EscapeCode $ char '\\' *> esc where+ esc :: m (Maybe Char) esc = Nothing <$ escapeGap <|> Nothing <$ escapeEmpty <|> Just <$> escapeCode++ escapeEmpty, escapeGap :: m Char escapeEmpty = char '&' escapeGap = skipSome space *> (char '\\' <?> "end of string gap") {-# INLINE stringLiteral' #-} --- | This token parser parses a natural number (a positive whole+-- | This token parser parses a natural number (a non-negative whole -- number). Returns the value of the number. The number can be -- specified in 'decimal', 'hexadecimal' or -- 'octal'. The number is parsed according to the grammar@@ -188,9 +213,10 @@ -- number can be specified in 'decimal', 'hexadecimal' -- or 'octal'. The number is parsed according -- to the grammar rules in the Haskell report.-integer :: TokenParsing m => m Integer+integer :: forall m. TokenParsing m => m Integer integer = token (token (highlight Operator sgn <*> natural')) <?> "integer" where+ sgn :: m (Integer -> Integer) sgn = negate <$ char '-' <|> id <$ char '+' <|> pure id@@ -234,9 +260,11 @@ -- | This token parser is like 'naturalOrScientific', but handles -- leading @-@ or @+@.-integerOrScientific :: TokenParsing m => m (Either Integer Scientific)+integerOrScientific :: forall m. TokenParsing m => m (Either Integer Scientific) integerOrScientific = token (highlight Number ios <?> "number")- where ios = mneg <$> optional (oneOf "+-") <*> natFloating+ where ios :: m (Either Integer Scientific)+ ios = mneg <$> optional (oneOf "+-") <*> natFloating+ mneg (Just '-') nd = either (Left . negate) (Right . negate) nd mneg _ nd = nd {-# INLINE integerOrScientific #-}@@ -578,27 +606,38 @@ -- -- This parser does NOT swallow trailing whitespace -escapeCode :: TokenParsing m => m Char+escapeCode :: forall m. TokenParsing m => m Char escapeCode = (charEsc <|> charNum <|> charAscii <|> charControl) <?> "escape code" where+ charControl, charNum :: m Char charControl = (\c -> toEnum (fromEnum c - fromEnum '@')) <$> (char '^' *> (upper <|> char '@')) charNum = toEnum <$> num where+ num :: m Int num = bounded 10 maxchar <|> (char 'o' *> bounded 8 maxchar) <|> (char 'x' *> bounded 16 maxchar) maxchar = fromEnum (maxBound :: Char) + bounded :: Int -> Int -> m Int bounded base bnd = foldl' (\x d -> base * x + digitToInt d) 0 <$> bounded' (take base thedigits) (map digitToInt $ showIntAtBase base intToDigit bnd "") where+ thedigits :: [m Char] thedigits = map char ['0'..'9'] ++ map oneOf (transpose [['A'..'F'],['a'..'f']])++ toomuch :: m a toomuch = unexpected "out-of-range numeric escape sequence"++ bounded', bounded'' :: [m Char] -> [Int] -> m [Char] bounded' dps@(zero:_) bds = skipSome zero *> ([] <$ notFollowedBy (choice dps) <|> bounded'' dps bds) <|> bounded'' dps bds bounded' [] _ = error "bounded called with base 0" bounded'' dps [] = [] <$ notFollowedBy (choice dps) <|> toomuch- bounded'' dps (bd : bds) = let anyd = choice dps+ bounded'' dps (bd : bds) = let anyd :: m Char+ anyd = choice dps++ nomore :: m () nomore = notFollowedBy anyd <|> toomuch (low, ex : high) = splitAt bd dps in ((:) <$> choice low <*> atMost (length bds) anyd) <* nomore@@ -608,10 +647,16 @@ else empty atMost n p | n <= 0 = pure [] | otherwise = ((:) <$> p <*> atMost (n - 1) p) <|> pure []++ charEsc :: m Char charEsc = choice $ parseEsc <$> escMap+ parseEsc (c,code) = code <$ char c escMap = zip "abfnrtv\\\"\'" "\a\b\f\n\r\t\v\\\"\'"++ charAscii :: m Char charAscii = choice $ parseAscii <$> asciiMap+ parseAscii (asc,code) = try $ code <$ string asc asciiMap = zip (ascii3codes ++ ascii2codes) (ascii3 ++ ascii2) ascii2codes, ascii3codes :: [String]@@ -624,7 +669,7 @@ ascii2 = "\BS\HT\LF\VT\FF\CR\SO\SI\EM\FS\GS\RS\US\SP" ascii3 = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK\BEL\DLE\DC1\DC2\DC3\DC4\NAK\SYN\ETB\CAN\SUB\ESC\DEL" --- | This parser parses a natural number (a positive whole+-- | This parser parses a natural number (a non-negative whole -- number). Returns the value of the number. The number can be -- specified in 'decimal', 'hexadecimal' or -- 'octal'. The number is parsed according to the grammar@@ -670,13 +715,18 @@ floating = decimal <**> fractExponent {-# INLINE floating #-} -fractExponent :: TokenParsing m => m (Integer -> Scientific)+fractExponent :: forall m. TokenParsing m => m (Integer -> Scientific) fractExponent = (\fract expo n -> (fromInteger n + fract) * expo) <$> fraction <*> option 1 exponent' <|> (\expo n -> fromInteger n * expo) <$> exponent' where+ fraction :: m Scientific fraction = foldl' op 0 <$> (char '.' *> (some digit <?> "fraction"))+ op f d = f + Sci.scientific (fromIntegral (digitToInt d)) (Sci.base10Exponent f - 1)++ exponent' :: m Scientific exponent' = ((\f e -> power (f e)) <$ oneOf "eE" <*> sign <*> (decimal <?> "exponent")) <?> "exponent"+ power = Sci.scientific 1 . fromInteger @@ -695,7 +745,7 @@ fractFloat = (Right .) <$> fractExponent {-# INLINE fractFloat #-} --- | Parses a positive whole number in the decimal system. Returns the+-- | Parses a non-negative whole number in the decimal system. Returns the -- value of the number. -- -- This parser does NOT swallow trailing whitespace@@ -703,7 +753,7 @@ decimal = number 10 digit {-# INLINE decimal #-} --- | Parses a positive whole number in the hexadecimal system. The number+-- | Parses a non-negative whole number in the hexadecimal system. The number -- should be prefixed with \"x\" or \"X\". Returns the value of the -- number. --@@ -712,7 +762,7 @@ hexadecimal = oneOf "xX" *> number 16 hexDigit {-# INLINE hexadecimal #-} --- | Parses a positive whole number in the octal system. The number+-- | Parses a non-negative whole number in the octal system. The number -- should be prefixed with \"o\" or \"O\". Returns the value of the -- number. --@@ -743,6 +793,26 @@ lift = Unhighlighted {-# INLINE lift #-} +instance MonadState s m => MonadState s (Unhighlighted m) where+ get = lift Class.get+ {-# INLINE get #-}+ put = lift . Class.put+ {-# INLINE put #-}++instance MonadReader e m => MonadReader e (Unhighlighted m) where+ ask = lift Class.ask+ {-# INLINE ask #-}+ local f = Unhighlighted . Class.local f . runUnhighlighted+ {-# INLINE local #-}++instance MonadWriter e m => MonadWriter e (Unhighlighted m) where+ tell = lift . Class.tell+ {-# INLINE tell #-}+ listen = Unhighlighted . Class.listen . runUnhighlighted+ {-# INLINE listen #-}+ pass = Unhighlighted . Class.pass . runUnhighlighted+ {-# INLINE pass #-}+ instance TokenParsing m => TokenParsing (Unhighlighted m) where nesting (Unhighlighted m) = Unhighlighted (nesting m) {-# INLINE nesting #-}@@ -774,6 +844,26 @@ lift = Unspaced {-# INLINE lift #-} +instance MonadState s m => MonadState s (Unspaced m) where+ get = lift Class.get+ {-# INLINE get #-}+ put = lift . Class.put+ {-# INLINE put #-}++instance MonadReader e m => MonadReader e (Unspaced m) where+ ask = lift Class.ask+ {-# INLINE ask #-}+ local f = Unspaced . Class.local f . runUnspaced+ {-# INLINE local #-}++instance MonadWriter e m => MonadWriter e (Unspaced m) where+ tell = lift . Class.tell+ {-# INLINE tell #-}+ listen = Unspaced . Class.listen . runUnspaced+ {-# INLINE listen #-}+ pass = Unspaced . Class.pass . runUnspaced+ {-# INLINE pass #-}+ instance TokenParsing m => TokenParsing (Unspaced m) where nesting (Unspaced m) = Unspaced (nesting m) {-# INLINE nesting #-}@@ -804,6 +894,26 @@ instance MonadTrans Unlined where lift = Unlined {-# INLINE lift #-}++instance MonadState s m => MonadState s (Unlined m) where+ get = lift Class.get+ {-# INLINE get #-}+ put = lift . Class.put+ {-# INLINE put #-}++instance MonadReader e m => MonadReader e (Unlined m) where+ ask = lift Class.ask+ {-# INLINE ask #-}+ local f = Unlined . Class.local f . runUnlined+ {-# INLINE local #-}++instance MonadWriter e m => MonadWriter e (Unlined m) where+ tell = lift . Class.tell+ {-# INLINE tell #-}+ listen = Unlined . Class.listen . runUnlined+ {-# INLINE listen #-}+ pass = Unlined . Class.pass . runUnlined+ {-# INLINE pass #-} instance TokenParsing m => TokenParsing (Unlined m) where nesting (Unlined m) = Unlined (nesting m)
src/Text/Parser/Token/Style.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE ScopedTypeVariables #-} #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702 {-# LANGUAGE Trustworthy #-} #endif@@ -106,7 +107,7 @@ -- | Use this to easily build the definition of whiteSpace for your MonadParser -- given a comment style and an underlying someWhiteSpace parser-buildSomeSpaceParser :: CharParsing m => m () -> CommentStyle -> m ()+buildSomeSpaceParser :: forall m. CharParsing m => m () -> CommentStyle -> m () buildSomeSpaceParser simpleSpace (CommentStyle startStyle endStyle lineStyle nestingStyle) | noLine && noMulti = skipSome (simpleSpace <?> "") | noLine = skipSome (simpleSpace <|> multiLineComment <?> "")@@ -115,6 +116,8 @@ where noLine = null lineStyle noMulti = null startStyle++ oneLineComment, multiLineComment, inComment, inCommentMulti :: m () oneLineComment = try (string lineStyle) *> skipMany (satisfy (/= '\n')) multiLineComment = try (string startStyle) *> inComment inComment = if nestingStyle then inCommentMulti else inCommentSingle@@ -124,7 +127,10 @@ <|> skipSome (noneOf startEnd) *> inCommentMulti <|> oneOf startEnd *> inCommentMulti <?> "end of comment"+ startEnd = nub (endStyle ++ startStyle)++ inCommentSingle :: m () inCommentSingle = () <$ try (string endStyle) <|> skipSome (noneOf startEnd) *> inCommentSingle
tests/doctests.hs view
@@ -1,30 +1,25 @@+-----------------------------------------------------------------------------+-- |+-- Module : Main (doctests)+-- Copyright : (C) 2012-14 Edward Kmett+-- License : BSD-style (see the file LICENSE)+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : provisional+-- Portability : portable+--+-- This module provides doctests for a project based on the actual versions+-- of the packages it was built with. It requires a corresponding Setup.lhs+-- to be added to the project+----------------------------------------------------------------------------- module Main where -import Build_doctests (autogen_dir, deps)-import Control.Applicative-import Control.Monad-import Data.List-import System.Directory-import System.FilePath+import Build_doctests (flags, pkgs, module_sources)+import Data.Foldable (traverse_) import Test.DocTest main :: IO ()-main = getSources >>= \sources -> doctest $- "-isrc"- : ("-i" ++ autogen_dir)- : "-optP-include"- : ("-optP" ++ autogen_dir ++ "/cabal_macros.h")- : "-hide-all-packages"- : map ("-package="++) deps ++ sources--getSources :: IO [FilePath]-getSources = filter (isSuffixOf ".hs") <$> go "src"+main = do+ traverse_ putStrLn args+ doctest args where- go dir = do- (dirs, files) <- getFilesAndDirectories dir- (files ++) . concat <$> mapM go dirs--getFilesAndDirectories :: FilePath -> IO ([FilePath], [FilePath])-getFilesAndDirectories dir = do- c <- map (dir </>) . filter (`notElem` ["..", "."]) <$> getDirectoryContents dir- (,) <$> filterM doesDirectoryExist c <*> filterM doesFileExist c+ args = flags ++ pkgs ++ module_sources