parsimony 1.1 → 1.3
raw patch · 6 files changed
+91/−138 lines, 6 filesdep +textdep −utf8-stringPVP ok
version bump matches the API change (PVP)
Dependencies added: text
Dependencies removed: utf8-string
API changes (from Hackage documentation)
- Parsimony.Char: space, tab, newline :: Stream s Char => Parser s Char
- Parsimony.IO: parseFileASCII :: FilePath -> Parser (ASCII ByteString) a -> IO (Either ParseError a)
- Parsimony.IO: parseFileUTF8 :: FilePath -> Parser (UTF8 ByteString) a -> IO (Either ParseError a)
- Parsimony.IO: parseLargeFileASCII :: FilePath -> Parser (ASCII ByteString) a -> IO (Either ParseError a)
- Parsimony.IO: parseLargeFileUTF8 :: FilePath -> Parser (UTF8 ByteString) a -> IO (Either ParseError a)
- Parsimony.IO: uparseFileASCII :: FilePath -> ParserU u (ASCII ByteString) a -> u -> IO (Either ParseError a)
- Parsimony.IO: uparseFileUTF8 :: FilePath -> ParserU u (UTF8 ByteString) a -> u -> IO (Either ParseError a)
- Parsimony.IO: uparseLargeFileASCII :: FilePath -> ParserU u (ASCII ByteString) a -> u -> IO (Either ParseError a)
- Parsimony.IO: uparseLargeFileUTF8 :: FilePath -> ParserU u (UTF8 ByteString) a -> u -> IO (Either ParseError a)
- Parsimony.Stream: ascii :: content -> ASCII content
- Parsimony.Stream: data ASCII content
- Parsimony.Stream: data UTF8 string :: * -> *
- Parsimony.Stream: instance Stream (UTF8 ByteString) Char
- Parsimony.Stream: instance Stream (UTF8 [Word8]) Char
- Parsimony.Stream: instance Stream a Word8 => Stream (ASCII a) Char
- Parsimony.Stream: utf8 :: content -> UTF8 content
+ Parsimony: data ParseError
+ Parsimony: data SourcePos
+ Parsimony: errorPos :: ParseError -> SourcePos
+ Parsimony: type Column = Int
+ Parsimony: type Line = Int
+ Parsimony: type SourceName = String
+ Parsimony.Char: newline, tab :: Stream s Char => Parser s ()
+ Parsimony.Char: space :: Stream s Char => Parser s Char
+ Parsimony.IO: parseBinaryFile :: FilePath -> Parser ByteString a -> IO (Either ParseError a)
+ Parsimony.IO: parseFile :: FilePath -> Parser Text a -> IO (Either ParseError a)
+ Parsimony.IO: parseLargeBinaryFile :: FilePath -> Parser ByteString a -> IO (Either ParseError a)
+ Parsimony.IO: parseLargeFile :: FilePath -> Parser Text a -> IO (Either ParseError a)
+ Parsimony.IO: uparseBinaryFile :: FilePath -> ParserU u ByteString a -> u -> IO (Either ParseError a)
+ Parsimony.IO: uparseFile :: FilePath -> ParserU u Text a -> u -> IO (Either ParseError a)
+ Parsimony.IO: uparseLargeBinaryFile :: FilePath -> ParserU u ByteString a -> u -> IO (Either ParseError a)
+ Parsimony.IO: uparseLargeFile :: FilePath -> ParserU u Text a -> u -> IO (Either ParseError a)
+ Parsimony.Stream: instance Stream Text Char
- Parsimony.Char: char :: Stream s Char => Char -> Parser s Char
+ Parsimony.Char: char :: Stream s Char => Char -> Parser s ()
- Parsimony.Char: string :: Stream s Char => String -> Parser s String
+ Parsimony.Char: string :: Stream s Char => String -> Parser s ()
Files
- parsimony.cabal +9/−4
- src/Parsimony.hs +4/−1
- src/Parsimony/Char.hs +11/−8
- src/Parsimony/IO.hs +52/−75
- src/Parsimony/Prim.hs +8/−4
- src/Parsimony/Stream.hs +7/−46
parsimony.cabal view
@@ -1,5 +1,5 @@ name: parsimony-version: 1.1+version: 1.3 license: BSD3 license-file: LICENSE author: Daan Leijen <daan@cs.uu.nl>, Iavor S. Diatchki <iavor.diatchki@gmail.com>@@ -11,7 +11,7 @@ description: Parsimony is a generalized and simplified version of the industrial-strength parser combinator library Parsec.- Like Parsec, it is simple, safe, well documented, convenient, + Like Parsec, it is simple, safe, well documented, convenient, with good error messages, and fast. In addition, Parsimony adds support for working with differet types of input such as byte strings (for compat input representation) and@@ -19,7 +19,7 @@ It also supports working with text in different character encodings such as UTF8. -cabal-version: >= 1.2+cabal-version: >= 1.6 build-type: Simple library@@ -39,7 +39,12 @@ build-depends: base >= 3 && < 5, bytestring,- utf8-string+ text GHC-options: -O2 -Wall++source-repository head+ type: git+ location: git://github.com/yav/parsimony.git+
src/Parsimony.hs view
@@ -42,12 +42,13 @@ , lookAhead, anyToken -- * Errors - , (<?>), unexpected, empty, parseError, labels + , ParseError, errorPos, (<?>), unexpected, empty, parseError, labels -- * Parser State , State(..) , setState, updateState, mapState , getInput, setInput, updateInput+ , SourcePos(..), SourceName, Line, Column , getPosition, setPosition, updatePosition @@ -59,4 +60,6 @@ import Control.Applicative hiding(many) import Parsimony.Prim import Parsimony.Combinator+import Parsimony.Error(ParseError, errorPos)+import Parsimony.Pos(SourcePos(..), SourceName, Line, Column)
src/Parsimony/Char.hs view
@@ -39,8 +39,10 @@ spaces :: Stream s Char => Parser s () spaces = skipMany space <?> "white space" -space, newline, tab :: Stream s Char => Parser s Char+space :: Stream s Char => Parser s Char space = satisfy (isSpace) <?> "space"++newline, tab :: Stream s Char => Parser s () newline = char '\n' <?> "new-line" tab = char '\t' <?> "tab" @@ -54,20 +56,21 @@ hexDigit = satisfy (isHexDigit) <?> "hexadecimal digit" octDigit = satisfy (isOctDigit) <?> "octal digit" -char :: Stream s Char => Char -> Parser s Char-char c = satisfy (==c) <?> show [c]+char :: Stream s Char => Char -> Parser s ()+char c = (satisfy (==c) >> return ()) <?> show [c] anyChar :: Stream s Char => Parser s Char anyChar = anyToken <?> "a character" satisfy :: Stream s Char => (Char -> Bool) -> Parser s Char-satisfy f = try $ anyChar >>= \c ->+satisfy f = (try $ anyChar >>= \c -> if f c then return c- else unexpected (show c)+ else unexpected (show c))+ <?> "" -string :: Stream s Char => String -> Parser s String-string [] = return []-string s@(c:cs) = try (char c) >> match show cs anyChar >> return s+string :: Stream s Char => String -> Parser s ()+string [] = return ()+string (c:cs) = try (char c) >> match show cs anyChar
src/Parsimony/IO.hs view
@@ -12,102 +12,79 @@ ----------------------------------------------------------------------------- module Parsimony.IO - ( parseFileASCII - , parseFileUTF8 - , parseLargeFileASCII - , parseLargeFileUTF8 + ( parseFile + , parseLargeFile + , parseBinaryFile + , parseLargeBinaryFile - , uparseFileASCII - , uparseFileUTF8 - , uparseLargeFileASCII - , uparseLargeFileUTF8 + , uparseFile + , uparseLargeFile + , uparseBinaryFile + , uparseLargeBinaryFile ) where import Parsimony.Prim import Parsimony.Error -import Parsimony.Stream import Parsimony.Combinator import Parsimony.UserState import qualified Data.ByteString as Strict import qualified Data.ByteString.Lazy as Lazy +import qualified Data.Text as T +import qualified Data.Text.IO as T +import qualified Data.Text.Lazy as LT +import qualified Data.Text.Lazy.IO as LT --- | Parse a file containing ASCII encoded characters. +-- | Parse a text file in one go. -- This functions loads the whole file in memory. -parseFileASCII :: FilePath - -> Parser (ASCII Strict.ByteString) a - -> IO (Either ParseError a) -parseFileASCII f p = - do bytes <- Strict.readFile f - return $ parseSource p f $ ascii bytes +parseFile :: FilePath -> Parser T.Text a -> IO (Either ParseError a) +parseFile f p = parseSource p f `fmap` T.readFile f --- | Parse a file containing UTF8 encoded characters. --- This functions loads the whole file in memory. -parseFileUTF8 :: FilePath - -> Parser (UTF8 Strict.ByteString) a - -> IO (Either ParseError a) -parseFileUTF8 f p = - do bytes <- Strict.readFile f - return $ parseSource p f $ utf8 bytes - --- | Parse a file containing ASCII encoded characters. +-- | Parse a text file in chunks. -- This functions loads the file in chunks. -parseLargeFileASCII :: FilePath - -> Parser (ASCII Lazy.ByteString) a - -> IO (Either ParseError a) -parseLargeFileASCII f p = - do bytes <- Lazy.readFile f - return $ parseSource p f $ ascii bytes +parseLargeFile :: FilePath -> Parser LT.Text a -> IO (Either ParseError a) +parseLargeFile f p = parseSource p f `fmap` LT.readFile f --- | Parse a file containing UTF8 encoded characters. +-- | Parse a binary file in one go. +-- This functions loads the whole file in memory. +parseBinaryFile :: FilePath -> Parser Strict.ByteString a -> + IO (Either ParseError a) +parseBinaryFile f p = parseSource p f `fmap` Strict.readFile f + +-- | Parse a text file in chunks. -- This functions loads the file in chunks. -parseLargeFileUTF8 :: FilePath - -> Parser (UTF8 Lazy.ByteString) a - -> IO (Either ParseError a) -parseLargeFileUTF8 f p = - do bytes <- Lazy.readFile f - return $ parseSource p f $ utf8 bytes +parseLargeBinaryFile :: FilePath -> Parser Lazy.ByteString a -> + IO (Either ParseError a) +parseLargeBinaryFile f p = parseSource p f `fmap` Lazy.readFile f + -- With user state ------------------------------------------------------------- --- | Parse a file containing ASCII encoded characters, --- using a parser with custom user state. --- This functions loads the whole file in memory. -uparseFileASCII :: FilePath - -> ParserU u (ASCII Strict.ByteString) a - -> u -> IO (Either ParseError a) -uparseFileASCII f p u = - do bytes <- Strict.readFile f - return $ uparseSource p u f $ ascii bytes --- | Parse a file containing UTF8 encoded characters, --- using a parser with custom user state. + +-- | Parse a text file in one go, using user state. -- This functions loads the whole file in memory. -uparseFileUTF8 :: FilePath - -> ParserU u (UTF8 Strict.ByteString) a - -> u -> IO (Either ParseError a) -uparseFileUTF8 f p u = - do bytes <- Strict.readFile f - return $ uparseSource p u f $ utf8 bytes - --- | Parse a file containing ASCII encoded characters, --- using a parser with custom user state. +uparseFile :: FilePath -> ParserU u T.Text a -> u -> IO (Either ParseError a) +uparseFile f p u = uparseSource p u f `fmap` T.readFile f + +-- | Parse a text file in chunks, using user state. -- This functions loads the file in chunks. -uparseLargeFileASCII :: FilePath - -> ParserU u (ASCII Lazy.ByteString) a - -> u -> IO (Either ParseError a) -uparseLargeFileASCII f p u = - do bytes <- Lazy.readFile f - return $ uparseSource p u f $ ascii bytes +uparseLargeFile :: FilePath -> ParserU u LT.Text a -> + u -> IO (Either ParseError a) +uparseLargeFile f p u = uparseSource p u f `fmap` LT.readFile f --- | Parse a file containing UTF8 encoded characters, --- using a parser with custom user state. +-- | Parse a binary file in one go, using user state. +-- This functions loads the whole file in memory. +uparseBinaryFile :: FilePath -> ParserU u Strict.ByteString a -> + u -> IO (Either ParseError a) +uparseBinaryFile f p u = uparseSource p u f `fmap` Strict.readFile f + +-- | Parse a text file in chunks, using user state. -- This functions loads the file in chunks. -uparseLargeFileUTF8 :: FilePath - -> ParserU u (UTF8 Lazy.ByteString) a - -> u -> IO (Either ParseError a) -uparseLargeFileUTF8 f p u = - do bytes <- Lazy.readFile f - return $ uparseSource p u f $ utf8 bytes - - +uparseLargeBinaryFile :: FilePath -> ParserU u Lazy.ByteString a -> + u -> IO (Either ParseError a) +uparseLargeBinaryFile f p u = uparseSource p u f `fmap` Lazy.readFile f + + + +
src/Parsimony/Prim.hs view
@@ -134,7 +134,8 @@ labels :: Parser t a -> [String] -> Parser t a labels p msgs0 = P $ \s -> case unP p s of- R c r -> R c (addErr r)+ R False r -> R False (addErr r)+ other -> other where setExpectErrors err [] = setErrorMessage (Expect "") err setExpectErrors err [msg] = setErrorMessage (Expect msg) err@@ -272,7 +273,7 @@ crash :: String -> a crash f = error $ f ++ " applied to a parser that accepts the empty string." --- Instances -------------------------------------------------------------------+-- Instances ----------------------------------------------------------------- instance Functor (Parser t) where fmap = liftM@@ -303,9 +304,12 @@ -- because then we can quickly move to the second branch, without -- having to perform any actual parsing. case unP p1 s of- R False (Error _) -> unP p2 s+ R False (Error e) ->+ case unP p2 s of+ R c r -> R c $ case r of+ Error e2 -> Error (mergeError e e2)+ _ -> r other -> other- instance MonadPlus (Parser t) where mzero = empty
src/Parsimony/Stream.hs view
@@ -17,10 +17,7 @@ -module Parsimony.Stream - ( Token(..), Stream(..) - , ASCII, UTF8, ascii, utf8 - ) where +module Parsimony.Stream (Token(..), Stream(..)) where import Parsimony.Prim import Parsimony.Pos @@ -28,8 +25,8 @@ import qualified Data.ByteString as Strict (ByteString,uncons) import qualified Data.ByteString.Lazy as Lazy (ByteString,uncons) -import Data.String.UTF8 (UTF8,UTF8Bytes,fromRep,replacement_char) -import qualified Data.String.UTF8 as UTF8 (uncons) +import qualified Data.Text as T +import qualified Data.Text.Lazy as LT import Data.Word (Word8) import Numeric (showHex) @@ -83,45 +80,9 @@ instance Stream Lazy.ByteString Word8 where getToken = genToken Lazy.uncons --- Character encodings --------------------------------------------------------- - - --- | The type of ASCII encoded content. -newtype ASCII content = ASCII content - --- | Specify ASCII encoding for some content. -ascii :: content -> ASCII content -ascii = ASCII - --- | Specify UTF8 encoding for some content. -utf8 :: content -> UTF8 content -utf8 = fromRep - -instance Stream a Word8 => Stream (ASCII a) Char where - getToken (State (ASCII buf) p) = - case getToken (State buf p) of - Error err -> Error err - Ok w (State b1 p1) -> Ok (toEnum (fromEnum w)) (State (ASCII b1) p1) - - -instance Stream (UTF8 [Word8]) Char where - getToken = genTokenChar - -instance Stream (UTF8 Strict.ByteString) Char where - getToken = genTokenChar - -instance Stream (UTF8 Lazy.ByteString) Char where - getToken = genTokenChar - - -{-# INLINE genTokenChar #-} -genTokenChar :: UTF8Bytes stream ix => PrimParser (UTF8 stream) Char -genTokenChar (State i p) = - case UTF8.uncons i of - Just (a,i1) - | a /= replacement_char -> Ok a (State i1 (updatePos a p)) - | otherwise -> Error $ newErrorMessage - (Message "invalid UTF8 character") p - Nothing -> eof_err p +instance Stream T.Text Char where + getToken = genToken T.uncons +instance Stream LT.Text Char where + getToken = genToken LT.uncons