parsec-class (empty) → 1.0.0.0
raw patch · 5 files changed
+150/−0 lines, 5 filesdep +basedep +parsecsetup-changed
Dependencies added: base, parsec
Files
- LICENSE +20/−0
- Setup.hs +2/−0
- parsec-class.cabal +29/−0
- src/Text/Parsec/Class.hs +91/−0
- src/Text/Parsec/Class/Orphans.hs +8/−0
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2018 Peter Simons++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ parsec-class.cabal view
@@ -0,0 +1,29 @@+name: parsec-class+version: 1.0.0.0+synopsis: Class of types that can be constructed from their text representation+description: This library provides the type class 'HasParser' as a dual to 'Pretty'.+ Instances of this class provide a parser than can be used to construct the+ type from its text representation.+license: MIT+license-file: LICENSE+author: Peter Simons+maintainer: simons@cryp.to+tested-with: GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3+category: Text+homepage: https://github.com/peti/parsec-class+bug-reports: https://github.com/peti/parsec-class/issues+build-type: Simple+cabal-version: >= 1.10++source-repository head+ type: git+ location: git://github.com/peti/parsec-class.git++library+ exposed-modules: Text.Parsec.Class+ Text.Parsec.Class.Orphans+ hs-source-dirs: src+ build-depends: base >= 4.9 && < 5, parsec >= 3+ default-language: Haskell2010+ other-extensions: RankNTypes+ FlexibleContexts
+ src/Text/Parsec/Class.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE FlexibleContexts, RankNTypes #-} -- for 'CharParser'++-- | 'HasParser' can be considered a dual to 'Pretty' like 'Read' is to 'Show'.+-- The class provides "Data.Parsec" parsers for its instances that construct+-- the type from its textual representation. Combined with the 'parseM' and+-- 'parse' convenience functions, this class makes parsing simple. Unlike+-- 'Read', Parsec parsers return reasonable error messages in case of failure.+-- Also, there is a rich set of combinators and additional libraries available+-- for re-use.++module Text.Parsec.Class+ ( CharParser, HasParser(parser), ErrorContext+ , parseM, parse+ , -- * Re-exports from Text.Parsec+ module Text.Parsec+ )+ where++import Prelude hiding ( fail )++import Text.Parsec.Class.Orphans ( ) -- TODO: This is unnecessary.++import Control.Exception ( throw )+import Control.Monad.Fail+import Data.Functor.Identity+import Numeric.Natural ( Natural )+import Text.Parsec hiding ( parse )++-- | A simplified 'ParsecT' parser that consumes some kind of character stream+-- without requiring any particular state state.++type CharParser st input m a = Stream st m Char => ParsecT st input m a++-- | Types that are instances of this class can be parsed and constructed from+-- some character based text representation.++class HasParser a where+ parser :: CharParser st input m a++-- | Parsers functions like 'parse' or 'parseM' use this type to provide a+-- helpful context in case the parser failes. Parsec uses the synonym+-- 'SourceName' for the same purpose, but in fact this type doesn't necessarily+-- have to be a file name. It can be any name or identifier. Oftentimes, it+-- it's useful to pass the name of the type that the parser attempted to parse.++type ErrorContext = String++-- | Convenience wrapper around 'runParserT' that uses the 'HasParser' class to+-- determine the desired parser for the given result type. The function reports+-- syntax errors via 'fail'.+--+-- >>> parseM "Natural" "987654321" :: IO Natural+-- 987654321+-- >>> parseM "Natural" "123456789" :: Maybe Natural+-- Just 123456789+--+-- Please note that parsers run this way do not ignore any white space:+--+-- >>> parseM "Natural" " 1" :: Maybe Natural+-- Nothing+-- >>> parseM "Natural" "1 " :: Maybe Natural+-- Nothing++parseM :: (MonadFail m, Stream input m Char, HasParser a) => ErrorContext -> input -> m a+parseM ctx x = runParserT (parser <* eof) () ctx x >>= either (fail . show) return++-- | Convenience wrapper around 'runParser' that uses the 'HasParser' class to+-- determine the desired parser for the given result type. The function reports+-- syntax errors by 'throw'ing 'ParseError'. This approach is inherently impure+-- and complicates error handling greatly. Use this function only on occasions+-- where parser errors are fatal errors that your code cannot recover from. In+-- almost all cases, 'parseM' is the better choice.+--+-- >>> parse "Natural" "12345" :: Natural+-- 12345+--+-- Like 'parseM', this function does not skip over any white space. Use+-- Parsec's primitive 'runParser' or 'runParserT' functions if you don't like+-- this behavior:+--+-- >>> runParser (spaces >> parser) () "Natural" " 1 " :: Either ParseError Natural+-- Right 1++parse :: (Stream input Identity Char, HasParser a) => ErrorContext -> input -> a+parse ctx = either throw id . runParser (parser <* eof) () ctx+++----- Useful HasParser instances ----------------------------------------------++instance HasParser Natural where+ parser = read <$> many1 digit
+ src/Text/Parsec/Class/Orphans.hs view
@@ -0,0 +1,8 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Text.Parsec.Class.Orphans where++import Control.Exception+import Text.Parsec.Error++instance Exception ParseError