packages feed

paripari 0.6.0.1 → 0.7.0.0

raw patch · 15 files changed

+1059/−1490 lines, 15 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Text.PariPari: ECombinator :: String -> Error
- Text.PariPari: [_posColumn] :: Pos -> !Int
- Text.PariPari: [_reportColumn] :: Report -> !Int
- Text.PariPari: class Chunk k => CharChunk k
- Text.PariPari: class (ChunkParser k p, IsString (p k), CharChunk k) => CharParser k p | p -> k
- Text.PariPari: class (MonadFail p, MonadPlus p, Chunk k) => ChunkParser k p | p -> k
- Text.PariPari: commit :: ChunkParser k p => p a -> p a
- Text.PariPari: data Tracer k a
- Text.PariPari: element :: ChunkParser k p => Element k -> p (Element k)
- Text.PariPari: elementScan :: ChunkParser k p => (Element k -> Maybe a) -> p a
- Text.PariPari: runCharParser :: CharChunk k => (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari: runCharParserWithOptions :: CharChunk k => ReportOptions -> (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari: runChunkParser :: CharChunk k => (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari: runChunkParserWithOptions :: Chunk k => ReportOptions -> (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari: runSeqCharParser :: CharChunk k => (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari: runSeqCharParserWithOptions :: CharChunk k => ReportOptions -> (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari: runSeqChunkParser :: Chunk k => (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari: runSeqChunkParserWithOptions :: Chunk k => ReportOptions -> (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari: runTracer :: Chunk k => Tracer k a -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari: showElement :: Chunk k => Element k -> String
- Text.PariPari: type family Element k;
- Text.PariPari: }
- Text.PariPari.Internal.Acceptor: State :: !Int -> !Int -> !Int -> State
- Text.PariPari.Internal.Acceptor: [_envEnd] :: Env k -> !Int
- Text.PariPari.Internal.Acceptor: [_envRefColumn] :: Env k -> !Int
- Text.PariPari.Internal.Acceptor: [_stColumn] :: State -> !Int
- Text.PariPari.Internal.Acceptor: [_stLine] :: State -> !Int
- Text.PariPari.Internal.Acceptor: [_stOff] :: State -> !Int
- Text.PariPari.Internal.Acceptor: data State
- Text.PariPari.Internal.Acceptor: instance Text.PariPari.Internal.Chunk.CharChunk k => Data.String.IsString (Text.PariPari.Internal.Acceptor.Acceptor k k)
- Text.PariPari.Internal.Acceptor: instance Text.PariPari.Internal.Chunk.CharChunk k => Text.PariPari.Internal.Class.CharParser k (Text.PariPari.Internal.Acceptor.Acceptor k)
- Text.PariPari.Internal.Acceptor: instance Text.PariPari.Internal.Chunk.Chunk k => Text.PariPari.Internal.Class.ChunkParser k (Text.PariPari.Internal.Acceptor.Acceptor k)
- Text.PariPari.Internal.CharCombinators: alphaNumChar :: CharP k Char
- Text.PariPari.Internal.CharCombinators: anyAsciiByte :: CharP k Word8
- Text.PariPari.Internal.CharCombinators: anyChar :: CharP k Char
- Text.PariPari.Internal.CharCombinators: asciiChar :: CharP k Char
- Text.PariPari.Internal.CharCombinators: asciiSatisfy :: CharParser k p => (Word8 -> Bool) -> p Word8
- Text.PariPari.Internal.CharCombinators: categoryChar :: CharParser k p => GeneralCategory -> p Char
- Text.PariPari.Internal.CharCombinators: char' :: CharParser k p => Char -> p Char
- Text.PariPari.Internal.CharCombinators: decimal :: Num a => CharP k a
- Text.PariPari.Internal.CharCombinators: digit :: CharParser k p => Int -> p Word
- Text.PariPari.Internal.CharCombinators: digitByte :: CharParser k p => Int -> p Word8
- Text.PariPari.Internal.CharCombinators: digitChar :: CharParser k p => Int -> p Char
- Text.PariPari.Internal.CharCombinators: fractionDec :: (Num a, CharParser k p) => p digitSep -> p (Either a (a, Int, a))
- Text.PariPari.Internal.CharCombinators: fractionHex :: (Num a, CharParser k p) => p digitSep -> p (Either a (a, Int, a))
- Text.PariPari.Internal.CharCombinators: hexadecimal :: Num a => CharP k a
- Text.PariPari.Internal.CharCombinators: integer :: (Num a, CharParser k p) => p sep -> Int -> p a
- Text.PariPari.Internal.CharCombinators: integer' :: (Num a, CharParser k p) => p sep -> Int -> p (a, Int)
- Text.PariPari.Internal.CharCombinators: letterChar :: CharP k Char
- Text.PariPari.Internal.CharCombinators: lowerChar :: CharP k Char
- Text.PariPari.Internal.CharCombinators: notChar :: CharParser k p => Char -> p Char
- Text.PariPari.Internal.CharCombinators: octal :: Num a => CharP k a
- Text.PariPari.Internal.CharCombinators: punctuationChar :: CharP k Char
- Text.PariPari.Internal.CharCombinators: satisfy :: CharParser k p => (Char -> Bool) -> p Char
- Text.PariPari.Internal.CharCombinators: scanChars :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s
- Text.PariPari.Internal.CharCombinators: scanChars1 :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s
- Text.PariPari.Internal.CharCombinators: sign :: (CharParser k f, Num a) => f (a -> a)
- Text.PariPari.Internal.CharCombinators: signed :: (Num a, CharParser k p) => p a -> p a
- Text.PariPari.Internal.CharCombinators: skipChars :: CharParser k p => Int -> p ()
- Text.PariPari.Internal.CharCombinators: skipCharsWhile :: CharParser k p => (Char -> Bool) -> p ()
- Text.PariPari.Internal.CharCombinators: skipCharsWhile1 :: CharParser k p => (Char -> Bool) -> p ()
- Text.PariPari.Internal.CharCombinators: spaceChar :: CharP k Char
- Text.PariPari.Internal.CharCombinators: string :: CharParser k p => String -> p k
- Text.PariPari.Internal.CharCombinators: symbolChar :: CharP k Char
- Text.PariPari.Internal.CharCombinators: takeChars :: CharParser k p => Int -> p k
- Text.PariPari.Internal.CharCombinators: takeCharsWhile :: CharParser k p => (Char -> Bool) -> p k
- Text.PariPari.Internal.CharCombinators: takeCharsWhile1 :: CharParser k p => (Char -> Bool) -> p k
- Text.PariPari.Internal.CharCombinators: upperChar :: CharP k Char
- Text.PariPari.Internal.Chunk: Pos :: !Int -> !Int -> Pos
- Text.PariPari.Internal.Chunk: [_posColumn] :: Pos -> !Int
- Text.PariPari.Internal.Chunk: [_posLine] :: Pos -> !Int
- Text.PariPari.Internal.Chunk: byteAt :: CharChunk k => Buffer k -> Int -> Word8
- Text.PariPari.Internal.Chunk: charAt :: CharChunk k => Buffer k -> Int -> (Char, Int)
- Text.PariPari.Internal.Chunk: charAtFixed :: CharChunk k => Int -> Buffer k -> Int -> Char
- Text.PariPari.Internal.Chunk: charWidth :: CharChunk k => Char -> Int
- Text.PariPari.Internal.Chunk: chunkEqual :: Chunk k => Buffer k -> Int -> k -> Bool
- Text.PariPari.Internal.Chunk: chunkWidth :: Chunk k => k -> Int
- Text.PariPari.Internal.Chunk: class Chunk k => CharChunk k
- Text.PariPari.Internal.Chunk: data Pos
- Text.PariPari.Internal.Chunk: elementAt :: Chunk k => Buffer k -> Int -> (Element k, Int)
- Text.PariPari.Internal.Chunk: elementPos :: Chunk k => Element k -> Pos -> Pos
- Text.PariPari.Internal.Chunk: instance GHC.Classes.Eq Text.PariPari.Internal.Chunk.Pos
- Text.PariPari.Internal.Chunk: instance GHC.Generics.Generic Text.PariPari.Internal.Chunk.Pos
- Text.PariPari.Internal.Chunk: instance GHC.Show.Show Text.PariPari.Internal.Chunk.Pos
- Text.PariPari.Internal.Chunk: instance Text.PariPari.Internal.Chunk.CharChunk Data.ByteString.Internal.ByteString
- Text.PariPari.Internal.Chunk: instance Text.PariPari.Internal.Chunk.CharChunk Data.Text.Internal.Text
- Text.PariPari.Internal.Chunk: showElement :: Chunk k => Element k -> String
- Text.PariPari.Internal.Class: ECombinator :: String -> Error
- Text.PariPari.Internal.Class: [_posColumn] :: Pos -> !Int
- Text.PariPari.Internal.Class: class (ChunkParser k p, IsString (p k), CharChunk k) => CharParser k p | p -> k
- Text.PariPari.Internal.Class: class (MonadFail p, MonadPlus p, Chunk k) => ChunkParser k p | p -> k
- Text.PariPari.Internal.Class: commit :: ChunkParser k p => p a -> p a
- Text.PariPari.Internal.Class: element :: ChunkParser k p => Element k -> p (Element k)
- Text.PariPari.Internal.Class: elementScan :: ChunkParser k p => (Element k -> Maybe a) -> p a
- Text.PariPari.Internal.ElementCombinators: (<?>) :: ChunkParser k p => p a -> String -> p a
- Text.PariPari.Internal.ElementCombinators: (<|>) :: Alternative f => f a -> f a -> f a
- Text.PariPari.Internal.ElementCombinators: align :: ChunkP k ()
- Text.PariPari.Internal.ElementCombinators: anyElement :: ChunkP k (Element k)
- Text.PariPari.Internal.ElementCombinators: between :: Applicative m => m open -> m close -> m a -> m a
- Text.PariPari.Internal.ElementCombinators: choice :: (Foldable f, Alternative m) => f (m a) -> m a
- Text.PariPari.Internal.ElementCombinators: count :: Monad m => Int -> m a -> m [a]
- Text.PariPari.Internal.ElementCombinators: count' :: MonadPlus m => Int -> Int -> m a -> m [a]
- Text.PariPari.Internal.ElementCombinators: eitherP :: Alternative m => m a -> m b -> m (Either a b)
- Text.PariPari.Internal.ElementCombinators: elementSatisfy :: ChunkParser k p => (Element k -> Bool) -> p (Element k)
- Text.PariPari.Internal.ElementCombinators: empty :: Alternative f => f a
- Text.PariPari.Internal.ElementCombinators: endBy :: MonadPlus m => m a -> m sep -> m [a]
- Text.PariPari.Internal.ElementCombinators: endBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)
- Text.PariPari.Internal.ElementCombinators: getColumn :: ChunkP k Int
- Text.PariPari.Internal.ElementCombinators: getLine :: ChunkP k Int
- Text.PariPari.Internal.ElementCombinators: getRefColumn :: ChunkP k Int
- Text.PariPari.Internal.ElementCombinators: getRefLine :: ChunkP k Int
- Text.PariPari.Internal.ElementCombinators: indented :: ChunkP k ()
- Text.PariPari.Internal.ElementCombinators: infix 0 <?>
- Text.PariPari.Internal.ElementCombinators: infixl 3 <|>
- Text.PariPari.Internal.ElementCombinators: line :: ChunkP k ()
- Text.PariPari.Internal.ElementCombinators: linefold :: ChunkP k ()
- Text.PariPari.Internal.ElementCombinators: many :: MonadPlus m => m a -> m [a]
- Text.PariPari.Internal.ElementCombinators: manyTill :: MonadPlus m => m a -> m end -> m [a]
- Text.PariPari.Internal.ElementCombinators: notElement :: forall k p. ChunkParser k p => Element k -> p (Element k)
- Text.PariPari.Internal.ElementCombinators: option :: Alternative m => a -> m a -> m a
- Text.PariPari.Internal.ElementCombinators: optional :: Alternative f => f a -> f (Maybe a)
- Text.PariPari.Internal.ElementCombinators: scanElements :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s
- Text.PariPari.Internal.ElementCombinators: scanElements1 :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s
- Text.PariPari.Internal.ElementCombinators: sepBy :: MonadPlus m => m a -> m sep -> m [a]
- Text.PariPari.Internal.ElementCombinators: sepBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)
- Text.PariPari.Internal.ElementCombinators: sepEndBy :: MonadPlus m => m a -> m sep -> m [a]
- Text.PariPari.Internal.ElementCombinators: sepEndBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)
- Text.PariPari.Internal.ElementCombinators: skipCount :: Monad m => Int -> m a -> m ()
- Text.PariPari.Internal.ElementCombinators: skipElements :: ChunkParser k p => Int -> p ()
- Text.PariPari.Internal.ElementCombinators: skipElementsWhile :: ChunkParser k p => (Element k -> Bool) -> p ()
- Text.PariPari.Internal.ElementCombinators: skipElementsWhile1 :: ChunkParser k p => (Element k -> Bool) -> p ()
- Text.PariPari.Internal.ElementCombinators: skipMany :: MonadPlus m => m a -> m ()
- Text.PariPari.Internal.ElementCombinators: skipManyTill :: MonadPlus m => m a -> m end -> m end
- Text.PariPari.Internal.ElementCombinators: skipSome :: MonadPlus m => m a -> m ()
- Text.PariPari.Internal.ElementCombinators: skipSomeTill :: MonadPlus m => m a -> m end -> m end
- Text.PariPari.Internal.ElementCombinators: some :: MonadPlus m => m a -> m (NonEmpty a)
- Text.PariPari.Internal.ElementCombinators: someTill :: MonadPlus m => m a -> m end -> m (NonEmpty a)
- Text.PariPari.Internal.ElementCombinators: takeElements :: ChunkParser k p => Int -> p k
- Text.PariPari.Internal.ElementCombinators: takeElementsWhile :: ChunkParser k p => (Element k -> Bool) -> p k
- Text.PariPari.Internal.ElementCombinators: takeElementsWhile1 :: ChunkParser k p => (Element k -> Bool) -> p k
- Text.PariPari.Internal.ElementCombinators: void :: Functor f => f a -> f ()
- Text.PariPari.Internal.ElementCombinators: withPos :: ChunkParser k p => p a -> p (Pos, a)
- Text.PariPari.Internal.ElementCombinators: withRefPos :: ChunkParser k p => p a -> p a
- Text.PariPari.Internal.ElementCombinators: withSpan :: ChunkParser k p => p a -> p (Span, a)
- Text.PariPari.Internal.Reporter: [_envCommit] :: Env k -> !Int
- Text.PariPari.Internal.Reporter: [_envEnd] :: Env k -> !Int
- Text.PariPari.Internal.Reporter: [_envRefColumn] :: Env k -> !Int
- Text.PariPari.Internal.Reporter: [_reportColumn] :: Report -> !Int
- Text.PariPari.Internal.Reporter: [_stColumn] :: State -> !Int
- Text.PariPari.Internal.Reporter: [_stErrColumn] :: State -> !Int
- Text.PariPari.Internal.Reporter: [_stErrCommit] :: State -> !Int
- Text.PariPari.Internal.Reporter: instance Text.PariPari.Internal.Chunk.CharChunk k => Data.String.IsString (Text.PariPari.Internal.Reporter.Reporter k k)
- Text.PariPari.Internal.Reporter: instance Text.PariPari.Internal.Chunk.CharChunk k => Text.PariPari.Internal.Class.CharParser k (Text.PariPari.Internal.Reporter.Reporter k)
- Text.PariPari.Internal.Reporter: instance Text.PariPari.Internal.Chunk.Chunk k => Text.PariPari.Internal.Class.ChunkParser k (Text.PariPari.Internal.Reporter.Reporter k)
- Text.PariPari.Internal.Run: runCharParser :: CharChunk k => (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari.Internal.Run: runCharParserWithOptions :: CharChunk k => ReportOptions -> (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari.Internal.Run: runChunkParser :: CharChunk k => (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari.Internal.Run: runChunkParserWithOptions :: Chunk k => ReportOptions -> (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari.Internal.Run: runSeqCharParser :: CharChunk k => (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari.Internal.Run: runSeqCharParserWithOptions :: CharChunk k => ReportOptions -> (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari.Internal.Run: runSeqChunkParser :: Chunk k => (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari.Internal.Run: runSeqChunkParserWithOptions :: Chunk k => ReportOptions -> (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari.Internal.Tracer: Tracer :: Reporter k a -> Tracer k a
- Text.PariPari.Internal.Tracer: [unTracer] :: Tracer k a -> Reporter k a
- Text.PariPari.Internal.Tracer: instance (Text.PariPari.Internal.Chunk.Chunk k, GHC.Base.Monoid a) => GHC.Base.Monoid (Text.PariPari.Internal.Tracer.Tracer k a)
- Text.PariPari.Internal.Tracer: instance (Text.PariPari.Internal.Chunk.Chunk k, GHC.Base.Semigroup a) => GHC.Base.Semigroup (Text.PariPari.Internal.Tracer.Tracer k a)
- Text.PariPari.Internal.Tracer: instance Text.PariPari.Internal.Chunk.CharChunk k => Data.String.IsString (Text.PariPari.Internal.Tracer.Tracer k k)
- Text.PariPari.Internal.Tracer: instance Text.PariPari.Internal.Chunk.CharChunk k => Text.PariPari.Internal.Class.CharParser k (Text.PariPari.Internal.Tracer.Tracer k)
- Text.PariPari.Internal.Tracer: instance Text.PariPari.Internal.Chunk.CharChunk k => Text.PariPari.Internal.Class.ChunkParser k (Text.PariPari.Internal.Tracer.Tracer k)
- Text.PariPari.Internal.Tracer: instance Text.PariPari.Internal.Chunk.Chunk k => Control.Monad.Fail.MonadFail (Text.PariPari.Internal.Tracer.Tracer k)
- Text.PariPari.Internal.Tracer: instance Text.PariPari.Internal.Chunk.Chunk k => GHC.Base.Alternative (Text.PariPari.Internal.Tracer.Tracer k)
- Text.PariPari.Internal.Tracer: instance Text.PariPari.Internal.Chunk.Chunk k => GHC.Base.Applicative (Text.PariPari.Internal.Tracer.Tracer k)
- Text.PariPari.Internal.Tracer: instance Text.PariPari.Internal.Chunk.Chunk k => GHC.Base.Functor (Text.PariPari.Internal.Tracer.Tracer k)
- Text.PariPari.Internal.Tracer: instance Text.PariPari.Internal.Chunk.Chunk k => GHC.Base.Monad (Text.PariPari.Internal.Tracer.Tracer k)
- Text.PariPari.Internal.Tracer: instance Text.PariPari.Internal.Chunk.Chunk k => GHC.Base.MonadPlus (Text.PariPari.Internal.Tracer.Tracer k)
- Text.PariPari.Internal.Tracer: newtype Tracer k a
- Text.PariPari.Internal.Tracer: runTracer :: Chunk k => Tracer k a -> FilePath -> k -> (Maybe a, [Report])
- Text.PariPari.Lens: posColumn :: Lens Pos Int
- Text.PariPari.Lens: reportColumn :: Lens Report Int
+ Text.PariPari: (<!>) :: Parser k p => p a -> p a -> p a
+ Text.PariPari: [_posCol] :: Pos -> {-# UNPACK #-} !Int
+ Text.PariPari: [_reportCol] :: Report -> {-# UNPACK #-} !Int
+ Text.PariPari: class (MonadFail p, MonadPlus p, Chunk k, IsString (p k)) => Parser k p | p -> k
+ Text.PariPari: infixl 3 <!>
+ Text.PariPari: runParser :: Chunk k => (forall p. Parser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
+ Text.PariPari: runParserWithOptions :: Chunk k => ReportOptions -> (forall p. Parser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
+ Text.PariPari: try :: Parser k p => p a -> p a
+ Text.PariPari.Internal.Acceptor: [_envRefCol] :: Env k -> Int#
+ Text.PariPari.Internal.Acceptor: instance Text.PariPari.Internal.Chunk.Chunk k => Data.String.IsString (Text.PariPari.Internal.Acceptor.Acceptor k k)
+ Text.PariPari.Internal.Acceptor: instance Text.PariPari.Internal.Chunk.Chunk k => Text.PariPari.Internal.Class.Parser k (Text.PariPari.Internal.Acceptor.Acceptor k)
+ Text.PariPari.Internal.Chunk: indexByte :: Chunk k => Buffer k -> Int# -> Word#
+ Text.PariPari.Internal.Chunk: indexChar :: Chunk k => Buffer k -> Int# -> (# Char#, Int# #)
+ Text.PariPari.Internal.Chunk: matchChar :: Chunk k => Buffer k -> Int# -> Char# -> Int#
+ Text.PariPari.Internal.Chunk: matchChunk :: Chunk k => Buffer k -> Int# -> k -> Int#
+ Text.PariPari.Internal.Class: (<!>) :: Parser k p => p a -> p a -> p a
+ Text.PariPari.Internal.Class: [_posCol] :: Pos -> {-# UNPACK #-} !Int
+ Text.PariPari.Internal.Class: class (MonadFail p, MonadPlus p, Chunk k, IsString (p k)) => Parser k p | p -> k
+ Text.PariPari.Internal.Class: instance GHC.Classes.Eq Text.PariPari.Internal.Class.Pos
+ Text.PariPari.Internal.Class: instance GHC.Generics.Generic Text.PariPari.Internal.Class.Pos
+ Text.PariPari.Internal.Class: instance GHC.Show.Show Text.PariPari.Internal.Class.Pos
+ Text.PariPari.Internal.Class: try :: Parser k p => p a -> p a
+ Text.PariPari.Internal.Combinators: (<?>) :: Parser k p => p a -> String -> p a
+ Text.PariPari.Internal.Combinators: (<|>) :: Alternative f => f a -> f a -> f a
+ Text.PariPari.Internal.Combinators: align :: P k ()
+ Text.PariPari.Internal.Combinators: alphaNumChar :: P k Char
+ Text.PariPari.Internal.Combinators: anyAsciiByte :: P k Word8
+ Text.PariPari.Internal.Combinators: anyChar :: P k Char
+ Text.PariPari.Internal.Combinators: asciiChar :: P k Char
+ Text.PariPari.Internal.Combinators: asciiSatisfy :: Parser k p => (Word8 -> Bool) -> p Word8
+ Text.PariPari.Internal.Combinators: between :: Applicative m => m open -> m close -> m a -> m a
+ Text.PariPari.Internal.Combinators: categoryChar :: Parser k p => GeneralCategory -> p Char
+ Text.PariPari.Internal.Combinators: char' :: Parser k p => Char -> p Char
+ Text.PariPari.Internal.Combinators: choice :: (Foldable f, Alternative m) => f (m a) -> m a
+ Text.PariPari.Internal.Combinators: count :: Monad m => Int -> m a -> m [a]
+ Text.PariPari.Internal.Combinators: count' :: MonadPlus m => Int -> Int -> m a -> m [a]
+ Text.PariPari.Internal.Combinators: decimal :: Num a => P k a
+ Text.PariPari.Internal.Combinators: digit :: Parser k p => Int -> p Word
+ Text.PariPari.Internal.Combinators: digitByte :: Parser k p => Int -> p Word8
+ Text.PariPari.Internal.Combinators: digitChar :: Parser k p => Int -> p Char
+ Text.PariPari.Internal.Combinators: eitherP :: Alternative m => m a -> m b -> m (Either a b)
+ Text.PariPari.Internal.Combinators: empty :: Alternative f => f a
+ Text.PariPari.Internal.Combinators: endBy :: MonadPlus m => m a -> m sep -> m [a]
+ Text.PariPari.Internal.Combinators: endBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)
+ Text.PariPari.Internal.Combinators: fractionDec :: (Num a, Parser k p) => p digitSep -> p (Either a (a, Int, a))
+ Text.PariPari.Internal.Combinators: fractionHex :: (Num a, Parser k p) => p digitSep -> p (Either a (a, Int, a))
+ Text.PariPari.Internal.Combinators: getCol :: P k Int
+ Text.PariPari.Internal.Combinators: getLine :: P k Int
+ Text.PariPari.Internal.Combinators: getRefCol :: P k Int
+ Text.PariPari.Internal.Combinators: getRefLine :: P k Int
+ Text.PariPari.Internal.Combinators: hexadecimal :: Num a => P k a
+ Text.PariPari.Internal.Combinators: indented :: P k ()
+ Text.PariPari.Internal.Combinators: infix 0 <?>
+ Text.PariPari.Internal.Combinators: infixl 3 <|>
+ Text.PariPari.Internal.Combinators: integer :: (Num a, Parser k p) => p sep -> Int -> p a
+ Text.PariPari.Internal.Combinators: integer' :: (Num a, Parser k p) => p sep -> Int -> p (a, Int)
+ Text.PariPari.Internal.Combinators: letterChar :: P k Char
+ Text.PariPari.Internal.Combinators: line :: P k ()
+ Text.PariPari.Internal.Combinators: linefold :: P k ()
+ Text.PariPari.Internal.Combinators: lowerChar :: P k Char
+ Text.PariPari.Internal.Combinators: many :: MonadPlus m => m a -> m [a]
+ Text.PariPari.Internal.Combinators: manyTill :: MonadPlus m => m a -> m end -> m [a]
+ Text.PariPari.Internal.Combinators: notChar :: Parser k p => Char -> p Char
+ Text.PariPari.Internal.Combinators: octal :: Num a => P k a
+ Text.PariPari.Internal.Combinators: option :: Alternative m => a -> m a -> m a
+ Text.PariPari.Internal.Combinators: optional :: Alternative f => f a -> f (Maybe a)
+ Text.PariPari.Internal.Combinators: punctuationChar :: P k Char
+ Text.PariPari.Internal.Combinators: satisfy :: Parser k p => (Char -> Bool) -> p Char
+ Text.PariPari.Internal.Combinators: scanChars :: Parser k p => (s -> Char -> Maybe s) -> s -> p s
+ Text.PariPari.Internal.Combinators: scanChars1 :: Parser k p => (s -> Char -> Maybe s) -> s -> p s
+ Text.PariPari.Internal.Combinators: sepBy :: MonadPlus m => m a -> m sep -> m [a]
+ Text.PariPari.Internal.Combinators: sepBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)
+ Text.PariPari.Internal.Combinators: sepEndBy :: MonadPlus m => m a -> m sep -> m [a]
+ Text.PariPari.Internal.Combinators: sepEndBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)
+ Text.PariPari.Internal.Combinators: sign :: (Parser k f, Num a) => f (a -> a)
+ Text.PariPari.Internal.Combinators: signed :: (Num a, Parser k p) => p a -> p a
+ Text.PariPari.Internal.Combinators: skipChars :: Parser k p => Int -> p ()
+ Text.PariPari.Internal.Combinators: skipCharsWhile :: Parser k p => (Char -> Bool) -> p ()
+ Text.PariPari.Internal.Combinators: skipCharsWhile1 :: Parser k p => (Char -> Bool) -> p ()
+ Text.PariPari.Internal.Combinators: skipCount :: Monad m => Int -> m a -> m ()
+ Text.PariPari.Internal.Combinators: skipMany :: MonadPlus m => m a -> m ()
+ Text.PariPari.Internal.Combinators: skipManyTill :: MonadPlus m => m a -> m end -> m end
+ Text.PariPari.Internal.Combinators: skipSome :: MonadPlus m => m a -> m ()
+ Text.PariPari.Internal.Combinators: skipSomeTill :: MonadPlus m => m a -> m end -> m end
+ Text.PariPari.Internal.Combinators: some :: MonadPlus m => m a -> m (NonEmpty a)
+ Text.PariPari.Internal.Combinators: someTill :: MonadPlus m => m a -> m end -> m (NonEmpty a)
+ Text.PariPari.Internal.Combinators: spaceChar :: P k Char
+ Text.PariPari.Internal.Combinators: string :: Parser k p => String -> p k
+ Text.PariPari.Internal.Combinators: symbolChar :: P k Char
+ Text.PariPari.Internal.Combinators: takeChars :: Parser k p => Int -> p k
+ Text.PariPari.Internal.Combinators: takeCharsWhile :: Parser k p => (Char -> Bool) -> p k
+ Text.PariPari.Internal.Combinators: takeCharsWhile1 :: Parser k p => (Char -> Bool) -> p k
+ Text.PariPari.Internal.Combinators: upperChar :: P k Char
+ Text.PariPari.Internal.Combinators: void :: Functor f => f a -> f ()
+ Text.PariPari.Internal.Combinators: withPos :: Parser k p => p a -> p (Pos, a)
+ Text.PariPari.Internal.Combinators: withRefPos :: Parser k p => p a -> p a
+ Text.PariPari.Internal.Combinators: withSpan :: Parser k p => p a -> p (Pos, Pos, a)
+ Text.PariPari.Internal.Reporter: [_envRefCol] :: Env k -> Int#
+ Text.PariPari.Internal.Reporter: [_reportCol] :: Report -> {-# UNPACK #-} !Int
+ Text.PariPari.Internal.Reporter: [_stCol] :: State -> Int#
+ Text.PariPari.Internal.Reporter: [_stErrCol] :: State -> Int#
+ Text.PariPari.Internal.Reporter: instance Text.PariPari.Internal.Chunk.Chunk k => Data.String.IsString (Text.PariPari.Internal.Reporter.Reporter k k)
+ Text.PariPari.Internal.Reporter: instance Text.PariPari.Internal.Chunk.Chunk k => Text.PariPari.Internal.Class.Parser k (Text.PariPari.Internal.Reporter.Reporter k)
+ Text.PariPari.Internal.Run: runParser :: Chunk k => (forall p. Parser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
+ Text.PariPari.Internal.Run: runParserWithOptions :: Chunk k => ReportOptions -> (forall p. Parser k p => p a) -> FilePath -> k -> (Maybe a, [Report])
+ Text.PariPari.Lens: posCol :: Lens Pos Int
+ Text.PariPari.Lens: reportCol :: Lens Report Int
- Text.PariPari: EIndentNotAligned :: !Int -> !Int -> Error
+ Text.PariPari: EIndentNotAligned :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Error
- Text.PariPari: EIndentOverLine :: !Int -> !Int -> Error
+ Text.PariPari: EIndentOverLine :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Error
- Text.PariPari: ENotEnoughIndent :: !Int -> !Int -> Error
+ Text.PariPari: ENotEnoughIndent :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Error
- Text.PariPari: ErrorContext :: [Error] -> [String] -> ErrorContext
+ Text.PariPari: ErrorContext :: ![Error] -> ![String] -> ErrorContext
- Text.PariPari: Pos :: !Int -> !Int -> Pos
+ Text.PariPari: Pos :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Pos
- Text.PariPari: Report :: !FilePath -> !Int -> !Int -> [ErrorContext] -> Report
+ Text.PariPari: Report :: !FilePath -> ![ErrorContext] -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Report
- Text.PariPari: ReportOptions :: !Int -> !Int -> !Int -> ReportOptions
+ Text.PariPari: ReportOptions :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> ReportOptions
- Text.PariPari: [_ecContext] :: ErrorContext -> [String]
+ Text.PariPari: [_ecContext] :: ErrorContext -> ![String]
- Text.PariPari: [_ecErrors] :: ErrorContext -> [Error]
+ Text.PariPari: [_ecErrors] :: ErrorContext -> ![Error]
- Text.PariPari: [_optMaxContexts] :: ReportOptions -> !Int
+ Text.PariPari: [_optMaxContexts] :: ReportOptions -> {-# UNPACK #-} !Int
- Text.PariPari: [_optMaxErrorsPerContext] :: ReportOptions -> !Int
+ Text.PariPari: [_optMaxErrorsPerContext] :: ReportOptions -> {-# UNPACK #-} !Int
- Text.PariPari: [_optMaxLabelsPerContext] :: ReportOptions -> !Int
+ Text.PariPari: [_optMaxLabelsPerContext] :: ReportOptions -> {-# UNPACK #-} !Int
- Text.PariPari: [_posLine] :: Pos -> !Int
+ Text.PariPari: [_posLine] :: Pos -> {-# UNPACK #-} !Int
- Text.PariPari: [_reportErrors] :: Report -> [ErrorContext]
+ Text.PariPari: [_reportErrors] :: Report -> ![ErrorContext]
- Text.PariPari: [_reportLine] :: Report -> !Int
+ Text.PariPari: [_reportLine] :: Report -> {-# UNPACK #-} !Int
- Text.PariPari: asChunk :: ChunkParser k p => p () -> p k
+ Text.PariPari: asChunk :: Parser k p => p () -> p k
- Text.PariPari: asciiByte :: CharParser k p => Word8 -> p Word8
+ Text.PariPari: asciiByte :: Parser k p => Word8 -> p Word8
- Text.PariPari: asciiScan :: CharParser k p => (Word8 -> Maybe a) -> p a
+ Text.PariPari: asciiScan :: Parser k p => (Word8 -> Maybe a) -> p a
- Text.PariPari: char :: CharParser k p => Char -> p Char
+ Text.PariPari: char :: Parser k p => Char -> p Char
- Text.PariPari: chunk :: ChunkParser k p => k -> p k
+ Text.PariPari: chunk :: Parser k p => k -> p k
- Text.PariPari: class (Ord (Element k), Ord k) => Chunk k where {
+ Text.PariPari: class Ord k => Chunk k
- Text.PariPari: eof :: ChunkParser k p => p ()
+ Text.PariPari: eof :: Parser k p => p ()
- Text.PariPari: failWith :: ChunkParser k p => Error -> p a
+ Text.PariPari: failWith :: Parser k p => Error -> p a
- Text.PariPari: getFile :: ChunkParser k p => p FilePath
+ Text.PariPari: getFile :: Parser k p => p FilePath
- Text.PariPari: getPos :: ChunkParser k p => p Pos
+ Text.PariPari: getPos :: Parser k p => p Pos
- Text.PariPari: getRefPos :: ChunkParser k p => p Pos
+ Text.PariPari: getRefPos :: Parser k p => p Pos
- Text.PariPari: hidden :: ChunkParser k p => p a -> p a
+ Text.PariPari: hidden :: Parser k p => p a -> p a
- Text.PariPari: label :: ChunkParser k p => String -> p a -> p a
+ Text.PariPari: label :: Parser k p => String -> p a -> p a
- Text.PariPari: lookAhead :: ChunkParser k p => p a -> p a
+ Text.PariPari: lookAhead :: Parser k p => p a -> p a
- Text.PariPari: notFollowedBy :: (ChunkParser k p, Show a) => p a -> p ()
+ Text.PariPari: notFollowedBy :: (Parser k p, Show a) => p a -> p ()
- Text.PariPari: recover :: ChunkParser k p => p a -> p a -> p a
+ Text.PariPari: recover :: Parser k p => p a -> p a -> p a
- Text.PariPari: runAcceptor :: Chunk k => Acceptor k a -> FilePath -> k -> Either Error a
+ Text.PariPari: runAcceptor :: Chunk k => Acceptor k a -> FilePath -> k -> Maybe a
- Text.PariPari: scan :: CharParser k p => (Char -> Maybe a) -> p a
+ Text.PariPari: scan :: Parser k p => (Char -> Maybe a) -> p a
- Text.PariPari: withRefPos :: ChunkParser k p => p a -> p a
+ Text.PariPari: withRefPos :: Parser k p => p a -> p a
- Text.PariPari.Internal.Acceptor: Acceptor :: (forall b. Env k -> State -> (a -> State -> b) -> (Error -> b) -> b) -> Acceptor k a
+ Text.PariPari.Internal.Acceptor: Acceptor :: (Env k -> State# -> Result# a) -> Acceptor k a
- Text.PariPari.Internal.Acceptor: Env :: !Buffer k -> !Int -> !FilePath -> !Int -> !Int -> Env k
+ Text.PariPari.Internal.Acceptor: Env :: !Buffer k -> !FilePath -> Int# -> Int# -> Env k
- Text.PariPari.Internal.Acceptor: [_envRefLine] :: Env k -> !Int
+ Text.PariPari.Internal.Acceptor: [_envRefLine] :: Env k -> Int#
- Text.PariPari.Internal.Acceptor: [unAcceptor] :: Acceptor k a -> forall b. Env k -> State -> (a -> State -> b) -> (Error -> b) -> b
+ Text.PariPari.Internal.Acceptor: [unAcceptor] :: Acceptor k a -> Env k -> State# -> Result# a
- Text.PariPari.Internal.Acceptor: get :: (Env k -> State -> a) -> Acceptor k a
+ Text.PariPari.Internal.Acceptor: get :: (Env k -> State# -> a) -> Acceptor k a
- Text.PariPari.Internal.Acceptor: local :: (State -> Env k -> Env k) -> Acceptor k a -> Acceptor k a
+ Text.PariPari.Internal.Acceptor: local :: (State# -> Env k -> Env k) -> Acceptor k a -> Acceptor k a
- Text.PariPari.Internal.Acceptor: runAcceptor :: Chunk k => Acceptor k a -> FilePath -> k -> Either Error a
+ Text.PariPari.Internal.Acceptor: runAcceptor :: Chunk k => Acceptor k a -> FilePath -> k -> Maybe a
- Text.PariPari.Internal.Chunk: class (Ord (Element k), Ord k) => Chunk k where {
+ Text.PariPari.Internal.Chunk: class Ord k => Chunk k where {
- Text.PariPari.Internal.Chunk: packChunk :: Chunk k => Buffer k -> Int -> Int -> k
+ Text.PariPari.Internal.Chunk: packChunk :: Chunk k => Buffer k -> Int# -> Int# -> k
- Text.PariPari.Internal.Chunk: stringToChunk :: CharChunk k => String -> k
+ Text.PariPari.Internal.Chunk: stringToChunk :: Chunk k => String -> k
- Text.PariPari.Internal.Chunk: unpackChunk :: Chunk k => k -> (Buffer k, Int, Int)
+ Text.PariPari.Internal.Chunk: unpackChunk :: Chunk k => k -> (# Buffer k, Int# #)
- Text.PariPari.Internal.Class: EIndentNotAligned :: !Int -> !Int -> Error
+ Text.PariPari.Internal.Class: EIndentNotAligned :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Error
- Text.PariPari.Internal.Class: EIndentOverLine :: !Int -> !Int -> Error
+ Text.PariPari.Internal.Class: EIndentOverLine :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Error
- Text.PariPari.Internal.Class: ENotEnoughIndent :: !Int -> !Int -> Error
+ Text.PariPari.Internal.Class: ENotEnoughIndent :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Error
- Text.PariPari.Internal.Class: Pos :: !Int -> !Int -> Pos
+ Text.PariPari.Internal.Class: Pos :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Pos
- Text.PariPari.Internal.Class: [_posLine] :: Pos -> !Int
+ Text.PariPari.Internal.Class: [_posLine] :: Pos -> {-# UNPACK #-} !Int
- Text.PariPari.Internal.Class: asChunk :: ChunkParser k p => p () -> p k
+ Text.PariPari.Internal.Class: asChunk :: Parser k p => p () -> p k
- Text.PariPari.Internal.Class: asciiByte :: CharParser k p => Word8 -> p Word8
+ Text.PariPari.Internal.Class: asciiByte :: Parser k p => Word8 -> p Word8
- Text.PariPari.Internal.Class: asciiScan :: CharParser k p => (Word8 -> Maybe a) -> p a
+ Text.PariPari.Internal.Class: asciiScan :: Parser k p => (Word8 -> Maybe a) -> p a
- Text.PariPari.Internal.Class: char :: CharParser k p => Char -> p Char
+ Text.PariPari.Internal.Class: char :: Parser k p => Char -> p Char
- Text.PariPari.Internal.Class: chunk :: ChunkParser k p => k -> p k
+ Text.PariPari.Internal.Class: chunk :: Parser k p => k -> p k
- Text.PariPari.Internal.Class: eof :: ChunkParser k p => p ()
+ Text.PariPari.Internal.Class: eof :: Parser k p => p ()
- Text.PariPari.Internal.Class: failWith :: ChunkParser k p => Error -> p a
+ Text.PariPari.Internal.Class: failWith :: Parser k p => Error -> p a
- Text.PariPari.Internal.Class: getFile :: ChunkParser k p => p FilePath
+ Text.PariPari.Internal.Class: getFile :: Parser k p => p FilePath
- Text.PariPari.Internal.Class: getPos :: ChunkParser k p => p Pos
+ Text.PariPari.Internal.Class: getPos :: Parser k p => p Pos
- Text.PariPari.Internal.Class: getRefPos :: ChunkParser k p => p Pos
+ Text.PariPari.Internal.Class: getRefPos :: Parser k p => p Pos
- Text.PariPari.Internal.Class: hidden :: ChunkParser k p => p a -> p a
+ Text.PariPari.Internal.Class: hidden :: Parser k p => p a -> p a
- Text.PariPari.Internal.Class: label :: ChunkParser k p => String -> p a -> p a
+ Text.PariPari.Internal.Class: label :: Parser k p => String -> p a -> p a
- Text.PariPari.Internal.Class: lookAhead :: ChunkParser k p => p a -> p a
+ Text.PariPari.Internal.Class: lookAhead :: Parser k p => p a -> p a
- Text.PariPari.Internal.Class: notFollowedBy :: (ChunkParser k p, Show a) => p a -> p ()
+ Text.PariPari.Internal.Class: notFollowedBy :: (Parser k p, Show a) => p a -> p ()
- Text.PariPari.Internal.Class: recover :: ChunkParser k p => p a -> p a -> p a
+ Text.PariPari.Internal.Class: recover :: Parser k p => p a -> p a -> p a
- Text.PariPari.Internal.Class: scan :: CharParser k p => (Char -> Maybe a) -> p a
+ Text.PariPari.Internal.Class: scan :: Parser k p => (Char -> Maybe a) -> p a
- Text.PariPari.Internal.Class: string :: CharParser k p => String -> p k
+ Text.PariPari.Internal.Class: string :: Parser k p => String -> p k
- Text.PariPari.Internal.Class: withRefPos :: ChunkParser k p => p a -> p a
+ Text.PariPari.Internal.Class: withRefPos :: Parser k p => p a -> p a
- Text.PariPari.Internal.Reporter: Env :: !Buffer k -> !Int -> !FilePath -> !ReportOptions -> !Bool -> !Int -> [String] -> !Int -> !Int -> Env k
+ Text.PariPari.Internal.Reporter: Env :: !Buffer k -> !FilePath -> !ReportOptions -> !Bool -> ![String] -> Int# -> Int# -> Env k
- Text.PariPari.Internal.Reporter: ErrorContext :: [Error] -> [String] -> ErrorContext
+ Text.PariPari.Internal.Reporter: ErrorContext :: ![Error] -> ![String] -> ErrorContext
- Text.PariPari.Internal.Reporter: Report :: !FilePath -> !Int -> !Int -> [ErrorContext] -> Report
+ Text.PariPari.Internal.Reporter: Report :: !FilePath -> ![ErrorContext] -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Report
- Text.PariPari.Internal.Reporter: ReportOptions :: !Int -> !Int -> !Int -> ReportOptions
+ Text.PariPari.Internal.Reporter: ReportOptions :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> ReportOptions
- Text.PariPari.Internal.Reporter: State :: !Int -> !Int -> !Int -> !Int -> !Int -> !Int -> !Int -> [ErrorContext] -> [Report] -> State
+ Text.PariPari.Internal.Reporter: State :: Int# -> Int# -> Int# -> Int# -> Int# -> Int# -> ![ErrorContext] -> ![Report] -> State
- Text.PariPari.Internal.Reporter: [_ecContext] :: ErrorContext -> [String]
+ Text.PariPari.Internal.Reporter: [_ecContext] :: ErrorContext -> ![String]
- Text.PariPari.Internal.Reporter: [_ecErrors] :: ErrorContext -> [Error]
+ Text.PariPari.Internal.Reporter: [_ecErrors] :: ErrorContext -> ![Error]
- Text.PariPari.Internal.Reporter: [_envContext] :: Env k -> [String]
+ Text.PariPari.Internal.Reporter: [_envContext] :: Env k -> ![String]
- Text.PariPari.Internal.Reporter: [_envRefLine] :: Env k -> !Int
+ Text.PariPari.Internal.Reporter: [_envRefLine] :: Env k -> Int#
- Text.PariPari.Internal.Reporter: [_optMaxContexts] :: ReportOptions -> !Int
+ Text.PariPari.Internal.Reporter: [_optMaxContexts] :: ReportOptions -> {-# UNPACK #-} !Int
- Text.PariPari.Internal.Reporter: [_optMaxErrorsPerContext] :: ReportOptions -> !Int
+ Text.PariPari.Internal.Reporter: [_optMaxErrorsPerContext] :: ReportOptions -> {-# UNPACK #-} !Int
- Text.PariPari.Internal.Reporter: [_optMaxLabelsPerContext] :: ReportOptions -> !Int
+ Text.PariPari.Internal.Reporter: [_optMaxLabelsPerContext] :: ReportOptions -> {-# UNPACK #-} !Int
- Text.PariPari.Internal.Reporter: [_reportErrors] :: Report -> [ErrorContext]
+ Text.PariPari.Internal.Reporter: [_reportErrors] :: Report -> ![ErrorContext]
- Text.PariPari.Internal.Reporter: [_reportLine] :: Report -> !Int
+ Text.PariPari.Internal.Reporter: [_reportLine] :: Report -> {-# UNPACK #-} !Int
- Text.PariPari.Internal.Reporter: [_stErrLine] :: State -> !Int
+ Text.PariPari.Internal.Reporter: [_stErrLine] :: State -> Int#
- Text.PariPari.Internal.Reporter: [_stErrOff] :: State -> !Int
+ Text.PariPari.Internal.Reporter: [_stErrOff] :: State -> Int#
- Text.PariPari.Internal.Reporter: [_stErrors] :: State -> [ErrorContext]
+ Text.PariPari.Internal.Reporter: [_stErrors] :: State -> ![ErrorContext]
- Text.PariPari.Internal.Reporter: [_stLine] :: State -> !Int
+ Text.PariPari.Internal.Reporter: [_stLine] :: State -> Int#
- Text.PariPari.Internal.Reporter: [_stOff] :: State -> !Int
+ Text.PariPari.Internal.Reporter: [_stOff] :: State -> Int#
- Text.PariPari.Internal.Reporter: [_stReports] :: State -> [Report]
+ Text.PariPari.Internal.Reporter: [_stReports] :: State -> ![Report]

Files

example.hs view
@@ -9,14 +9,14 @@ import Text.PariPari import qualified Data.ByteString as B -type StringType    = B.ByteString-type ParserMonad p = CharParser StringType p-type Parser a      = (forall p. ParserMonad p => p a)+type StringType = B.ByteString+type PMonad p = Parser StringType p+type P a = (forall p. PMonad p => p a) --- {-# SPECIALISE_ALL ParserMonad p = p ~ Acceptor StringType #-}--- {-# SPECIALISE_ALL ParserMonad p = p ~ Reporter StringType #-}--- {-# SPECIALISE_ALL Parser = Acceptor StringType #-}--- {-# SPECIALISE_ALL Parser = Reporter StringType #-}+-- {-# SPECIALISE_ALL PMonad p = p ~ Acceptor StringType #-}+-- {-# SPECIALISE_ALL PMonad p = p ~ Reporter StringType #-}+-- {-# SPECIALISE_ALL P = Acceptor StringType #-}+-- {-# SPECIALISE_ALL P = Reporter StringType #-}  data Value   = Object ![(StringType, Value)]@@ -27,19 +27,19 @@   | Null   deriving (Eq, Show) -json :: Parser Value+json :: P Value json = space *> (object <|> array) <?> "json" -object :: Parser Value+object :: P Value object = Object <$> (char '{' *> space *> sepBy pair (space *> char ',' *> space) <* space <* char '}') <?> "object" -pair :: Parser (StringType, Value)+pair :: P (StringType, Value) pair = (,) <$> (text <* space) <*> (char ':' *> space *> value) -array :: Parser Value+array :: P Value array = Array <$> (char '[' *> sepBy value (space *> char ',' *> space) <* space <* char ']') <?> "array" -value :: Parser Value+value :: P Value value =   (String <$> text)     <|> object@@ -49,10 +49,10 @@     <|> (Null       <$ string "null")     <|> number -text :: Parser StringType+text :: P StringType text = char '"' *> takeCharsWhile (/= '"') <* char '"' <?> "text" -number :: Parser Value+number :: P Value number = label "number" $ do   neg <- sign   frac <- fractionDec (pure ())@@ -60,7 +60,7 @@            Left n -> Number (neg n) 0            Right (c, _, e) -> Number (neg c) e -space :: Parser ()+space :: P () space = skipCharsWhile (\c -> c == ' ' || c == '\n' || c == '\t')  main :: IO ()@@ -69,9 +69,7 @@   case args of     [file] -> do       src <- B.readFile file-      let (result, reports) = runCharParser json file src+      let (result, reports) = runParser json file src       for_ reports $ putStrLn . showReport-      case result of-        Just val -> print val-        Nothing  -> print $ runTracer json file src+      print result     _ -> error "Usage: paripari-example test.json"
paripari.cabal view
@@ -1,15 +1,8 @@ cabal-version: 1.12---- This file has been generated from package.yaml by hpack version 0.31.2.------ see: https://github.com/sol/hpack------ hash: e2aa081115e4cfadf8c060813b3ede4ab8a817542bc9d7f33fa82a04ee85da38- name:           paripari-version:        0.6.0.1+version:        0.7.0.0 synopsis:       Parser combinators with fast-path and slower fallback for error reporting-description:    PariPari offers two parsing strategies. There is a fast Acceptor and a slower Reporter which are evaluated in parallel. If the Acceptor fails, the Reporter returns a report about the parsing errors. Like Attoparsec, the parser combinators backtrack by default.+description:    PariPari offers two parsing strategies. There is a fast Acceptor and a slower Reporter. If the Acceptor fails, the Reporter returns a report about the parsing errors. category:       Text stability:      experimental homepage:       https://github.com/minad/paripari#readme@@ -19,7 +12,7 @@ copyright:      2018 Daniel Mendler license:        MIT license-file:   LICENSE-tested-with:    GHC == 8.0.1, GHC == 8.2.1, GHC == 8.4.3, GHC == 8.6.1+tested-with:    GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.3, GHC == 8.10.1 build-type:     Simple  source-repository head@@ -30,19 +23,17 @@   exposed-modules:       Text.PariPari       Text.PariPari.Internal.Acceptor-      Text.PariPari.Internal.CharCombinators       Text.PariPari.Internal.Chunk       Text.PariPari.Internal.Class-      Text.PariPari.Internal.ElementCombinators+      Text.PariPari.Internal.Combinators       Text.PariPari.Internal.Reporter       Text.PariPari.Internal.Run-      Text.PariPari.Internal.Tracer       Text.PariPari.Lens   other-modules:       Paths_paripari   hs-source-dirs:       src-  ghc-options: -Wall -Wcompat -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances+  ghc-options: -O2 -Wall -Wcompat -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances   build-depends:       base >=4.8 && <5     , bytestring >=0.10 && <0.11@@ -83,7 +74,7 @@       Paths_paripari   hs-source-dirs:       test-  ghc-options: -Wall -Wcompat -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances+  ghc-options: -O0 -Wall -Wcompat -Widentities -Wmonomorphism-restriction -Wincomplete-uni-patterns -Wincomplete-record-updates -Wtabs -fprint-potential-instances   build-depends:       base >=4.8 && <5     , bytestring >=0.10 && <0.11
specialise-all.hs view
@@ -4,7 +4,6 @@ {-# LANGUAGE Rank2Types #-}  import Data.Foldable (for_)-import Data.Semigroup ((<>)) import System.Environment (getArgs) import Text.PariPari import qualified Data.Char as C@@ -12,9 +11,9 @@ import qualified Data.Text as T import qualified Data.Text.IO as T -type StringType    = T.Text-type ParserMonad p = CharParser StringType p-type Parser a      = (forall p. ParserMonad p => p a)+type StringType = T.Text+type PMonad p = Parser StringType p+type P a = (forall p. PMonad p => p a)  data Type   = TypeName   !StringType@@ -33,34 +32,34 @@   | OtherLine     !StringType   deriving (Show) -source :: Parser [SourceLine]+source :: P [SourceLine] source = sepBy sourceLine (char '\n') <* eof -sourceLine :: Parser SourceLine+sourceLine :: P SourceLine sourceLine = specialiseAll <|> typeDecl <|> otherLine -otherLine :: Parser SourceLine+otherLine :: P SourceLine otherLine = OtherLine <$> takeCharsWhile (/= '\n') -specialiseAll :: Parser SourceLine+specialiseAll :: P SourceLine specialiseAll = SpecialiseAll   <$> (symbol "{-#" *> symbol "SPECIALISE_ALL" *> type_)   <*> (symbol "=" *> type_ <* symbol "#-}") -identifierAtom :: ParserMonad p => (Char -> Bool) -> p ()+identifierAtom :: PMonad p => (Char -> Bool) -> p () identifierAtom f = satisfy f *> skipCharsWhile (\c -> C.isAlphaNum c || c == '_' || c == '\'') -name :: Parser StringType+name :: P StringType name = asChunk (sepEndBy (identifierAtom C.isUpper) (char '.') *>                 identifierAtom C.isLower) <* space -typeName :: Parser StringType+typeName :: P StringType typeName = asChunk (void $ sepBy1 (identifierAtom C.isUpper) (char '.')) <* space -symbol :: ParserMonad p => String -> p StringType+symbol :: PMonad p => String -> p StringType symbol s = string s <* space -typeTuple :: Parser Type+typeTuple :: P Type typeTuple = do   ts <- between (symbol "(") (symbol ")") (sepBy type_ (symbol ","))   pure $ case ts of@@ -68,19 +67,19 @@            [t] -> t            _   -> TypeTuple ts -typeAtom :: Parser Type+typeAtom :: P Type typeAtom =   TypeName <$> typeName   <|> TypeVar <$> name   <|> TypeList <$> between (symbol "[") (symbol "]") type_   <|> typeTuple -typeApp :: Parser Type+typeApp :: P Type typeApp = do   t <- typeAtom   option t $ TypeApp t <$> some typeAtom -type_ :: Parser Type+type_ :: P Type type_ = do   t <- typeApp   TypeEq t <$> (symbol "~" *> type_)@@ -88,10 +87,10 @@     <|> TypeConstr t <$> (symbol "=>" *> type_)     <|> pure t -typeDecl :: Parser SourceLine+typeDecl :: P SourceLine typeDecl = TypeDecl <$> sepBy1 name (symbol ",") <*> (symbol "::" *> type_) -space :: Parser ()+space :: P () space = skipCharsWhile (== ' ')  showType :: Type -> StringType@@ -192,7 +191,7 @@   case args of     [src, _, dst] -> do       code <- T.readFile src-      let (result, reports) = runCharParser source src code+      let (result, reports) = runParser source src code       for_ reports $ putStrLn . showReport       case result of         Nothing -> pure ()
src/Text/PariPari.hs view
@@ -1,21 +1,13 @@ module Text.PariPari (-  C.ChunkParser(..)-  , C.CharParser(..)+  C.Parser(..)+  , C.Pos(..)   , C.Error(..)   , C.showError -  , K.Chunk(Element, showElement, showChunk)-  , K.CharChunk-  , K.Pos(..)+  , K.Chunk(showChunk) -  , U.runCharParser-  , U.runSeqCharParser-  , U.runCharParserWithOptions-  , U.runSeqCharParserWithOptions-  , U.runChunkParser-  , U.runSeqChunkParser-  , U.runChunkParserWithOptions-  , U.runSeqChunkParserWithOptions+  , U.runParser+  , U.runParserWithOptions    , A.Acceptor   , A.runAcceptor@@ -30,18 +22,12 @@   , R.runReporterWithOptions   , R.defaultReportOptions -  , T.Tracer-  , T.runTracer--  , module Text.PariPari.Internal.ElementCombinators-  , module Text.PariPari.Internal.CharCombinators+  , module Text.PariPari.Internal.Combinators ) where -import Text.PariPari.Internal.CharCombinators-import Text.PariPari.Internal.ElementCombinators+import Text.PariPari.Internal.Combinators import qualified Text.PariPari.Internal.Acceptor as A import qualified Text.PariPari.Internal.Chunk as K import qualified Text.PariPari.Internal.Class as C import qualified Text.PariPari.Internal.Reporter as R import qualified Text.PariPari.Internal.Run as U-import qualified Text.PariPari.Internal.Tracer as T
src/Text/PariPari/Internal/Acceptor.hs view
@@ -1,15 +1,18 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MagicHash #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UnboxedTuples #-} module Text.PariPari.Internal.Acceptor (   Acceptor(..)   , Env(..)-  , State(..)   , get   , local   , runAcceptor@@ -18,32 +21,45 @@ import Control.Monad (void) import Data.Semigroup as Sem import Data.String (IsString(..))+import GHC.Base hiding (State#)+import GHC.Word import Text.PariPari.Internal.Chunk import Text.PariPari.Internal.Class import qualified Control.Monad.Fail as Fail  data Env k = Env-  { _envBuf       :: !(Buffer k)-  , _envEnd       :: !Int-  , _envFile      :: !FilePath-  , _envRefLine   :: !Int-  , _envRefColumn :: !Int+  { _envBuf     :: !(Buffer k)+  , _envFile    :: !FilePath+  , _envRefLine :: Int#+  , _envRefCol  :: Int#   } -data State = State-  { _stOff    :: !Int-  , _stLine   :: !Int-  , _stColumn :: !Int-  }+type State# = (# Int#, Int#, Int# #) +type Result# a = (# Int# | (# State#, a #) #)++pattern Ok# :: State# -> a -> Result# a+pattern Ok# s a = (# | (# s, a #) #)+pattern Err# :: Int# -> Result# a+pattern Err# o = (# o | #)+{-# COMPLETE Ok#, Err# #-}++_stLine :: State# -> Int#+_stLine (# _, x, _ #) = x+{-# INLINE _stLine #-}++_stCol :: State# -> Int#+_stCol (# _, _, x #) = x+{-# INLINE _stCol #-}++_stOff :: State# -> Int#+_stOff (# x, _, _ #) = x+{-# INLINE _stOff #-}+ -- | Parser which is optimised for fast parsing. Error reporting -- is minimal. newtype Acceptor k a = Acceptor-  { unAcceptor :: forall b. Env k -> State-               -> (a     -> State -> b)-               -> (Error -> b)-               -> b-  }+  { unAcceptor :: Env k -> State# -> Result# a }  instance (Chunk k, Semigroup a) => Sem.Semigroup (Acceptor k a) where   p1 <> p2 = (<>) <$> p1 <*> p2@@ -57,19 +73,20 @@   {-# INLINE mappend #-}  instance Functor (Acceptor k) where-  fmap f p = Acceptor $ \env st ok err ->-    unAcceptor p env st (ok . f) err+  fmap f p = Acceptor $ \env st -> case unAcceptor p env st of+    Err# o -> Err# o+    Ok# st' x -> Ok# st' (f x)   {-# INLINE fmap #-}  instance Chunk k => Applicative (Acceptor k) where-  pure x = Acceptor $ \_ st ok _ -> ok x st+  pure x = Acceptor $ \_ st -> Ok# st x   {-# INLINE pure #-} -  f <*> a = Acceptor $ \env st ok err ->-    let ok1 f' s =-          let ok2 a' s' = ok (f' a') s'-          in unAcceptor a env s ok2 err-    in unAcceptor f env st ok1 err+  f <*> a = Acceptor $ \env st -> case unAcceptor f env st of+    Err# o -> Err# o+    Ok# s f' -> case unAcceptor a env s of+      Err# o -> Err# o+      Ok# s' a' -> Ok# s' (f' a')   {-# INLINE (<*>) #-}    p1 *> p2 = do@@ -84,20 +101,22 @@   {-# INLINE (<*) #-}  instance Chunk k => Alternative (Acceptor k) where-  empty = Acceptor $ \_ _ _ err -> err $ ECombinator "empty"+  empty = Acceptor $ \_ st -> Err# (_stOff st)   {-# INLINE empty #-} -  p1 <|> p2 = Acceptor $ \env st ok err ->-    let err' _ = unAcceptor p2 env st ok err-    in unAcceptor p1 env st ok err'+  p1 <|> p2 = Acceptor $ \env st ->+    case unAcceptor p1 env st of+      Ok# st' x -> Ok# st' x+      Err# _ -> unAcceptor p2 env st   {-# INLINE (<|>) #-}  instance Chunk k => MonadPlus (Acceptor k)  instance Chunk k => Monad (Acceptor k) where-  p >>= f = Acceptor $ \env st ok err ->-    let ok' x s = unAcceptor (f x) env s ok err-    in unAcceptor p env st ok' err+  p >>= f = Acceptor $ \env st ->+    case unAcceptor p env st of+      Err# o -> Err# o+      Ok# s x -> unAcceptor (f x) env s   {-# INLINE (>>=) #-}  #if !MIN_VERSION_base(4,11,0)@@ -109,38 +128,38 @@   fail msg = failWith $ EFail msg   {-# INLINE fail #-} -instance Chunk k => ChunkParser k (Acceptor k) where-  getPos = get $ \_ st -> Pos (_stLine st) (_stColumn st)+instance Chunk k => Parser k (Acceptor k) where+  getPos = get $ \_ st -> Pos (I# (_stLine st)) (I# (_stCol st))   {-# INLINE getPos #-}    getFile = get $ \env _ -> _envFile env   {-# INLINE getFile #-} -  getRefPos = get $ \env _ -> Pos (_envRefLine env) (_envRefColumn env)+  getRefPos = get $ \env _ -> Pos (I# (_envRefLine env)) (I# (_envRefCol env))   {-# INLINE getRefPos #-} -  withRefPos p = local (\st env -> env { _envRefLine = _stLine st, _envRefColumn = _stColumn st }) p+  withRefPos p = local (\st env -> env { _envRefLine = _stLine st, _envRefCol = _stCol st }) p   {-# INLINE withRefPos #-} -  notFollowedBy p = Acceptor $ \env st ok err ->-    let ok' _ _ = err $ ECombinator "notFollowedBy"-        err' _ = ok () st-    in unAcceptor p env st ok' err'+  notFollowedBy p = Acceptor $ \env st ->+    case unAcceptor p env st of+      Err# _ -> Ok# st ()+      Ok# _ _ -> Err# (_stOff st)   {-# INLINE notFollowedBy #-} -  lookAhead p = Acceptor $ \env st ok err ->-    let ok' x _ = ok x st-    in unAcceptor p env st ok' err+  lookAhead p = Acceptor $ \env st -> do+    case unAcceptor p env st of+      Err# _ -> Err# (_stOff st)+      Ok# _ x -> Ok# st x   {-# INLINE lookAhead #-} -  failWith e = Acceptor $ \_ _ _ err -> err e+  failWith _ = Acceptor $ \_ st -> Err# (_stOff st)   {-# INLINE failWith #-} -  eof = Acceptor $ \env st ok err ->-    if _stOff st >= _envEnd env then-      ok () st-    else-      err expectedEnd+  eof = Acceptor $ \env st ->+    case indexByte @k (_envBuf env) (_stOff st) `eqWord#` int2Word# 0# of+      1# -> Ok# st ()+      _ -> Err# (_stOff st)   {-# INLINE eof #-}    label _ p = p@@ -149,141 +168,110 @@   hidden p = p   {-# INLINE hidden #-} -  commit p = p-  {-# INLINE commit #-}-   recover p _ = p   {-# INLINE recover #-} -  element e = Acceptor $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-    if | _stOff < _envEnd env,-         (e', w) <- elementAt @k (_envBuf env) _stOff,-         e == e',-         pos <- elementPos @k e (Pos _stLine _stColumn) ->-           ok e st { _stOff = _stOff + w, _stLine = _posLine pos, _stColumn = _posColumn pos }-       | otherwise ->-           err $ ECombinator "element"-  {-# INLINE element #-}+  try p = Acceptor $ \env st ->+    case unAcceptor p env st of+      Ok# st' x -> Ok# st' x+      Err# _ -> Err# (_stOff st)+  {-# INLINE try #-} -  elementScan f = Acceptor $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-    if | _stOff < _envEnd env,-         (e, w) <- elementAt @k (_envBuf env) _stOff,-         Just r <- f e,-         pos <- elementPos @k e (Pos _stLine _stColumn) ->-           ok r st { _stOff = _stOff + w, _stLine = _posLine pos, _stColumn = _posColumn pos }-       | otherwise ->-           err $ ECombinator "elementScan"-  {-# INLINE elementScan #-}+  p1 <!> p2 = Acceptor $ \env st ->+    case unAcceptor p1 env st of+      Ok# st' x -> Ok# st' x+      Err# o | 1# <- o ==# _stOff st -> unAcceptor p2 env st+             | otherwise -> Err# o+  {-# INLINE (<!>) #-} -  chunk k = Acceptor $ \env st@State{_stOff,_stColumn} ok err ->-    let n = chunkWidth @k k-    in if n + _stOff <= _envEnd env &&-          chunkEqual @k (_envBuf env) _stOff k then-         ok k st { _stOff = _stOff + n, _stColumn = _stColumn + n }-       else-         err $ ECombinator "chunk"+  chunk k = Acceptor $ \env (# stOff, stLine, stCol #) ->+    case matchChunk @k (_envBuf env) stOff k of+      -1# -> Err# stOff+      n -> Ok# (# stOff +# n, stLine, stCol +# n #) k   {-# INLINE chunk #-}    asChunk p = do-    begin <- get (const _stOff)+    I# begin' <- get (const (\s -> I# (_stOff s)))     p-    end <- get (const _stOff)+    I# end' <- get (const (\s -> I# (_stOff s)))     src <- get (\env _ -> _envBuf env)-    pure $ packChunk src begin (end - begin)+    pure $ packChunk src begin' (end' -# begin')   {-# INLINE asChunk #-} -instance CharChunk k => CharParser k (Acceptor k) where-  scan f = Acceptor $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-    if | (c, w) <- charAt @k (_envBuf env) _stOff,-         c /= '\0',-         Just r <- f c ->-           ok r st-           { _stOff = _stOff + w-           , _stLine = if c == '\n' then _stLine + 1 else _stLine-           , _stColumn = if c == '\n' then 1 else _stColumn + 1-           }-       | otherwise ->-           err $ ECombinator "scan"+  scan f = Acceptor $ \env (# stOff, stLine, stCol #) ->+    case indexChar @k (_envBuf env) stOff of+      (# c, w #)+        | 1# <- c `neChar#` '\0'#, Just r <- f (C# c) ->+          Ok# (# stOff +# w,+                case c `eqChar#` '\n'# of 1# -> stLine +# 1#; _ -> stLine,+                case c `eqChar#` '\n'# of 1# -> 1#; _ -> stCol +# 1# #) r+      _ -> Err# stOff   {-# INLINE scan #-}    -- By inling this combinator, GHC should figure out the `charWidth`   -- of the character resulting in an optimised decoder.   char '\0' = error "Character '\\0' cannot be parsed because it is used as sentinel"-  char c-    | w <- charWidth @k c =-        Acceptor $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-        if charAtFixed @k w (_envBuf env) _stOff == c then-          ok c st-          { _stOff = _stOff + w-          , _stLine = if c == '\n' then _stLine + 1 else _stLine-          , _stColumn = if c == '\n' then 1 else _stColumn + 1-          }-        else-          err $ ECombinator "char"+  char c@(C# c') =+    Acceptor $ \env (# stOff, stLine, stCol #) ->+    case matchChar @k (_envBuf env) stOff c' of+      -1# -> Err# stOff+      w -> Ok# (# stOff +# w,+                if c == '\n' then stLine +# 1# else stLine,+                if c == '\n' then 1# else stCol +# 1# #) c   {-# INLINE char #-} -  asciiScan f = Acceptor $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-    if | b <- byteAt @k (_envBuf env) _stOff,+  asciiScan f = Acceptor $ \env (# stOff, stLine, stCol #) ->+    if | b <- W8# (indexByte @k (_envBuf env) stOff),          b /= 0,          b < 128,          Just x <- f b ->-           ok x st-           { _stOff = _stOff + 1-           , _stLine = if b == asc_newline then _stLine + 1 else _stLine-           , _stColumn = if b == asc_newline then 1 else _stColumn + 1-           }+           Ok# (# stOff +# 1#+               , if b == asc_newline then stLine +# 1# else stLine+               , if b == asc_newline then 1# else stCol +# 1# #) x        | otherwise ->-           err $ ECombinator "asciiScan"+           Err# stOff   {-# INLINE asciiScan #-}    asciiByte 0 = error "Character '\\0' cannot be parsed because it is used as sentinel"   asciiByte b     | b >= 128 = error "Not an ASCII character"-    | otherwise = Acceptor $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-        if byteAt @k (_envBuf env) _stOff == b then-          ok b st-          { _stOff = _stOff + 1-          , _stLine = if b == asc_newline then _stLine + 1 else _stLine-          , _stColumn = if b == asc_newline then 1 else _stColumn + 1-          }+    | otherwise = Acceptor $ \env (# stOff, stLine, stCol #) ->+        if W8# (indexByte @k (_envBuf env) stOff) == b then+          Ok# (# stOff +# 1#+              , if b == asc_newline then stLine +# 1# else stLine+              , if b == asc_newline then 1# else stCol +# 1# #) b         else-          err $ ECombinator "asciiByte"+          Err# stOff   {-# INLINE asciiByte #-} -instance CharChunk k => IsString (Acceptor k k) where+instance Chunk k => IsString (Acceptor k k) where   fromString = string   {-# INLINE fromString #-}  -- | Reader monad, get something from the environment-get :: (Env k -> State -> a) -> Acceptor k a-get f = Acceptor $ \env st ok _ -> ok (f env st) st+get :: (Env k -> State# -> a) -> Acceptor k a+get f = Acceptor $ \env st -> Ok# st (f env st) {-# INLINE get #-}  -- | Reader monad, modify environment locally-local :: (State -> Env k -> Env k) -> Acceptor k a -> Acceptor k a-local f p = Acceptor $ \env st ok err ->-  unAcceptor p (f st env) st ok err+local :: (State# -> Env k -> Env k) -> Acceptor k a -> Acceptor k a+local f p = Acceptor $ \env st ->+  unAcceptor p (f st env) st {-# INLINE local #-}  -- | Run 'Acceptor' on the given chunk, returning either -- a simple 'Error' or, if successful, the result.-runAcceptor :: Chunk k => Acceptor k a -> FilePath -> k -> Either Error a+runAcceptor :: Chunk k => Acceptor k a -> FilePath -> k -> Maybe a runAcceptor p f k =-  let (b, off, len) = unpackChunk k-  in unAcceptor p (initialEnv f b (off + len)) (initialState off) (\x _ -> Right x) Left+  let !(# b, off #) = unpackChunk k+  in case unAcceptor p (initialEnv f b) (# off, 1#, 1# #) of+       Err# _ -> Nothing+       Ok# _ x -> Just x -initialEnv :: FilePath -> Buffer k -> Int -> Env k-initialEnv _envFile _envBuf _envEnd = Env+initialEnv :: FilePath -> Buffer k -> Env k+initialEnv _envFile _envBuf = Env   { _envBuf   , _envFile-  , _envEnd-  , _envRefLine = 1-  , _envRefColumn = 1-  }--initialState :: Int -> State-initialState _stOff = State-  { _stOff-  , _stLine = 1-  , _stColumn = 1+  , _envRefLine = 1#+  , _envRefCol = 1#   }
− src/Text/PariPari/Internal/CharCombinators.hs
@@ -1,320 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE Rank2Types #-}-module Text.PariPari.Internal.CharCombinators (-  digitByte-  , integer-  , integer'-  , decimal-  , octal-  , hexadecimal-  , digit-  , sign-  , signed-  , fractionHex-  , fractionDec-  , char'-  , notChar-  , anyChar-  , anyAsciiByte-  , alphaNumChar-  , digitChar-  , letterChar-  , lowerChar-  , upperChar-  , symbolChar-  , categoryChar-  , punctuationChar-  , spaceChar-  , asciiChar-  , satisfy-  , asciiSatisfy-  , skipChars-  , takeChars-  , skipCharsWhile-  , takeCharsWhile-  , skipCharsWhile1-  , takeCharsWhile1-  , scanChars-  , scanChars1-  , string-) where--import Control.Applicative ((<|>), optional)-import Control.Monad.Combinators (option, skipCount, skipMany)-import Data.Functor (void)-import Data.Maybe (fromMaybe)-import Data.Semigroup ((<>))-import Data.Word (Word8)-import Text.PariPari.Internal.Chunk-import Text.PariPari.Internal.Class-import Text.PariPari.Internal.ElementCombinators ((<?>))-import qualified Data.Char as C--type CharP k a  = (forall p. CharParser k p => p a)---- | Parse a digit byte for the given base.--- Bases 2 to 36 are supported.-digitByte :: CharParser k p => Int -> p Word8-digitByte base = asciiSatisfy (isDigit base)-{-# INLINE digitByte #-}--isDigit :: Int -> Word8 -> Bool-isDigit base b-  | base >= 2 && base <= 10 = b >= asc_0 && b <= asc_0 + fromIntegral base - 1-  | base <= 36 = (b >= asc_0 && b <= asc_9)-                 || ((fromIntegral b :: Word) - fromIntegral asc_A) < fromIntegral (base - 10)-                 || ((fromIntegral b :: Word) - fromIntegral asc_a) < fromIntegral (base - 10)-  |otherwise = error "Text.PariPari.Internal.Combinators.isDigit: Bases 2 to 36 are supported"-{-# INLINE isDigit #-}--digitToInt :: Int -> Word8 -> Word-digitToInt base b-  | n <- (fromIntegral b :: Word) - fromIntegral asc_0, base <= 10 || n <= 9  = n-  | n <- (fromIntegral b :: Word) - fromIntegral asc_A, n               <= 26 = n + 10-  | n <- (fromIntegral b :: Word) - fromIntegral asc_a                        = n + 10-{-# INLINE digitToInt #-}---- | Parse a single digit of the given base and return its value.--- Bases 2 to 36 are supported.-digit :: CharParser k p => Int -> p Word-digit base = digitToInt base <$> asciiSatisfy (isDigit base)-{-# INLINE digit #-}---- | Parse an integer of the given base.--- Returns the integer and the number of digits.--- Bases 2 to 36 are supported.--- Digits can be separated by separator, e.g. `optional (char '_')`.--- Signs are not parsed by this combinator.-integer' :: (Num a, CharParser k p) => p sep -> Int -> p (a, Int)-integer' sep base = label (integerLabel base) $ do-  d <- digit base-  accum 1 $ fromIntegral d-  where accum !i !n = next i n <|> pure (n, i)-        next !i !n = do-          void $ sep-          d <- digit base-          accum (i + 1) $ n * fromIntegral base + fromIntegral d-{-# INLINE integer' #-}---- | Parse an integer of the given base.--- Bases 2 to 36 are supported.--- Digits can be separated by separator, e.g. `optional (char '_')`.--- Signs are not parsed by this combinator.-integer :: (Num a, CharParser k p) => p sep -> Int -> p a-integer sep base = label (integerLabel base) $ do-  d <- digit base-  accum $ fromIntegral d-  where accum !n = next n <|> pure n-        next !n = do-          void $ sep-          d <- digit base-          accum $ n * fromIntegral base + fromIntegral d-{-# INLINE integer #-}--integerLabel :: Int -> String-integerLabel 2  = "binary integer"-integerLabel 8  = "octal integer"-integerLabel 10 = "decimal integer"-integerLabel 16 = "hexadecimal integer"-integerLabel b  = "integer of base " <> show b---- | Parses a decimal integer.--- Signs are not parsed by this combinator.-decimal :: Num a => CharP k a-decimal = integer (pure ()) 10-{-# INLINE decimal #-}---- | Parses an octal integer.--- Signs are not parsed by this combinator.-octal :: Num a => CharP k a-octal = integer (pure ()) 8-{-# INLINE octal #-}---- | Parses a hexadecimal integer.--- Signs are not parsed by this combinator.-hexadecimal :: Num a => CharP k a-hexadecimal = integer (pure ()) 16-{-# INLINE hexadecimal #-}---- | Parse plus or minus sign-sign :: (CharParser k f, Num a) => f (a -> a)-sign = (negate <$ asciiByte asc_minus) <|> (id <$ optional (asciiByte asc_plus))-{-# INLINE sign #-}---- | Parse a number with a plus or minus sign.-signed :: (Num a, CharParser k p) => p a -> p a-signed p = ($) <$> sign <*> p-{-# INLINE signed #-}--fractionExp :: (Num a, CharParser k p) => p expSep -> p digitSep -> p (Maybe a)-fractionExp expSep digitSep = do-  e <- optional expSep-  case e of-    Nothing{} -> pure Nothing-    Just{} -> Just <$> signed (integer digitSep 10)-{-# INLINE fractionExp #-}---- | Parse a fraction of arbitrary exponent base and mantissa base.--- 'fractionDec' and 'fractionHex' should be used instead probably.--- Returns either an integer in 'Left' or a fraction in 'Right'.--- Signs are not parsed by this combinator.-fraction :: (Num a, CharParser k p) => p expSep -> Int -> Int -> p digitSep -> p (Either a (a, Int, a))-fraction expSep expBase mantBasePow digitSep = do-  let mantBase = expBase ^ mantBasePow-  mant <- integer digitSep mantBase-  frac <- optional $ asciiByte asc_point *> option (0, 0) (integer' digitSep mantBase)-  expn <- fractionExp expSep digitSep-  let (fracVal, fracLen) = fromMaybe (0, 0) frac-      expVal = fromMaybe 0 expn-  pure $ case (frac, expn) of-           (Nothing, Nothing) -> Left mant-           _ -> Right ( mant * fromIntegral mantBase ^ fracLen + fracVal-                      , expBase-                      , expVal - fromIntegral (fracLen * mantBasePow))-{-# INLINE fraction #-}---- | Parse a decimal fraction, e.g., 123.456e-78, returning (mantissa, 10, exponent),--- corresponding to mantissa * 10^exponent.--- Digits can be separated by separator, e.g. `optional (char '_')`.--- Signs are not parsed by this combinator.-fractionDec :: (Num a, CharParser k p) => p digitSep -> p (Either a (a, Int, a))-fractionDec sep = fraction (asciiSatisfy (\b -> b == asc_E || b == asc_e)) 10 1 sep <?> "fraction"-{-# INLINE fractionDec #-}---- | Parse a hexadecimal fraction, e.g., co.ffeep123, returning (mantissa, 2, exponent),--- corresponding to mantissa * 2^exponent.--- Digits can be separated by separator, e.g. `optional (char '_')`.--- Signs are not parsed by this combinator.-fractionHex :: (Num a, CharParser k p) => p digitSep -> p (Either a (a, Int, a))-fractionHex sep = fraction (asciiSatisfy (\b -> b == asc_P || b == asc_p)) 2 4 sep <?> "hexadecimal fraction"-{-# INLINE fractionHex #-}---- | Parse a case-insensitive character-char' :: CharParser k p => Char -> p Char-char' x =-  let l = C.toLower x-      u = C.toUpper x-  in satisfy (\c -> c == l || c == u)-{-# INLINE char' #-}---- | Parse a character different from the given one.-notChar :: CharParser k p => Char -> p Char-notChar c = satisfy (/= c)-{-# INLINE notChar #-}---- | Parse an arbitrary character.-anyChar :: CharP k Char-anyChar = satisfy (const True)-{-# INLINE anyChar #-}---- | Parse an arbitrary ASCII byte.-anyAsciiByte :: CharP k Word8-anyAsciiByte = asciiSatisfy (const True)-{-# INLINE anyAsciiByte #-}---- | Parse an alphanumeric character, including Unicode.-alphaNumChar :: CharP k Char-alphaNumChar = satisfy C.isAlphaNum <?> "alphanumeric character"-{-# INLINE alphaNumChar #-}---- | Parse a letter character, including Unicode.-letterChar :: CharP k Char-letterChar = satisfy C.isLetter <?> "letter"-{-# INLINE letterChar #-}---- | Parse a lowercase letter, including Unicode.-lowerChar :: CharP k Char-lowerChar = satisfy C.isLower <?> "lowercase letter"-{-# INLINE lowerChar #-}---- | Parse a uppercase letter, including Unicode.-upperChar :: CharP k Char-upperChar = satisfy C.isUpper <?> "uppercase letter"-{-# INLINE upperChar #-}---- | Parse a space character, including Unicode.-spaceChar :: CharP k Char-spaceChar = satisfy C.isSpace <?> "space"-{-# INLINE spaceChar #-}---- | Parse a symbol character, including Unicode.-symbolChar :: CharP k Char-symbolChar = satisfy C.isSymbol <?> "symbol"-{-# INLINE symbolChar #-}---- | Parse a punctuation character, including Unicode.-punctuationChar :: CharP k Char-punctuationChar = satisfy C.isPunctuation <?> "punctuation"-{-# INLINE punctuationChar #-}---- | Parse a digit character of the given base.--- Bases 2 to 36 are supported.-digitChar :: CharParser k p => Int -> p Char-digitChar base = unsafeAsciiToChar <$> digitByte base-{-# INLINE digitChar #-}---- | Parse a character beloning to the ASCII charset (< 128)-asciiChar :: CharP k Char-asciiChar = unsafeAsciiToChar <$> anyAsciiByte-{-# INLINE asciiChar #-}---- | Parse a character belonging to the given Unicode category-categoryChar :: CharParser k p => C.GeneralCategory -> p Char-categoryChar cat = satisfy ((== cat) . C.generalCategory) <?> untitle (show cat)-{-# INLINE categoryChar #-}--untitle :: String -> String-untitle []     = []-untitle (x:xs) = C.toLower x : go xs-  where go [] = ""-        go (y:ys) | C.isUpper y = ' ' : C.toLower y : untitle ys-                  | otherwise   = y : ys---- | Skip the next n characters-skipChars :: CharParser k p => Int -> p ()-skipChars n = skipCount n anyChar-{-# INLINE skipChars #-}---- | Skip char while predicate is true-skipCharsWhile :: CharParser k p => (Char -> Bool) -> p ()-skipCharsWhile f = skipMany (satisfy f)-{-# INLINE skipCharsWhile #-}---- | Skip at least one char while predicate is true-skipCharsWhile1 :: CharParser k p => (Char -> Bool) -> p ()-skipCharsWhile1 f = satisfy f *> skipCharsWhile f-{-# INLINE skipCharsWhile1 #-}---- | Take the next n characters and advance the position by n characters-takeChars :: CharParser k p => Int -> p k-takeChars n = asChunk (skipChars n) <?> "string of length " <> show n-{-# INLINE takeChars #-}---- | Take chars while predicate is true-takeCharsWhile :: CharParser k p => (Char -> Bool) -> p k-takeCharsWhile f = asChunk (skipCharsWhile f)-{-# INLINE takeCharsWhile #-}---- | Take at least one byte while predicate is true-takeCharsWhile1 :: CharParser k p => (Char -> Bool) -> p k-takeCharsWhile1 f = asChunk (skipCharsWhile1 f)-{-# INLINE takeCharsWhile1 #-}---- | Parse a single character with the given predicate-satisfy :: CharParser k p => (Char -> Bool) -> p Char-satisfy f = scan $ \c -> if f c then Just c else Nothing-{-# INLINE satisfy #-}---- | Parse a single character within the ASCII charset with the given predicate-asciiSatisfy :: CharParser k p => (Word8 -> Bool) -> p Word8-asciiSatisfy f = asciiScan $ \b -> if f b then Just b else Nothing-{-# INLINE asciiSatisfy #-}--scanChars :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s-scanChars f = go-  where go s = (scan (f s) >>= go) <|> pure s-{-# INLINE scanChars #-}--scanChars1 :: CharParser k p => (s -> Char -> Maybe s) -> s -> p s-scanChars1 f s = scan (f s) >>= scanChars f-{-# INLINE scanChars1 #-}
src/Text/PariPari/Internal/Chunk.hs view
@@ -1,11 +1,15 @@ {-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UnboxedTuples #-} module Text.PariPari.Internal.Chunk (   Chunk(..)-  , CharChunk(..)-  , Pos(..)   , showByte   , showByteString   , unsafeAsciiToChar@@ -16,15 +20,11 @@ import Data.Bits (unsafeShiftL, (.|.), (.&.)) import Data.ByteString (ByteString) import Data.Foldable (foldl')-import Data.Semigroup ((<>)) import Data.String (fromString) import Data.Text (Text)-import Data.Word (Word8)-import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)-import Foreign.Ptr (plusPtr)-import Foreign.Storable (peekByteOff)-import GHC.Base (unsafeChr)-import GHC.Generics (Generic)+import GHC.Base+import GHC.Word+import GHC.ForeignPtr import GHC.Show (showLitChar) import Numeric (showHex) import qualified Data.ByteString as B@@ -33,219 +33,152 @@ import qualified Data.Text.Encoding as T import qualified Data.Text.Internal as T --- | Line and column position starting at (1,1)-data Pos = Pos-  { _posLine   :: !Int-  , _posColumn :: !Int-  } deriving (Eq, Show, Generic)--class (Ord (Element k), Ord k) => Chunk k where-  type Element  k-  type Buffer   k-  elementAt :: Buffer k -> Int -> (Element k, Int)-  elementPos :: Element k -> Pos -> Pos-  chunkWidth :: k -> Int-  chunkEqual :: Buffer k -> Int -> k -> Bool-  packChunk :: Buffer k -> Int -> Int -> k-  unpackChunk :: k -> (Buffer k, Int, Int)-  showElement :: Element k -> String+class Ord k => Chunk k where+  type Buffer k+  matchChunk :: Buffer k -> Int# -> k -> Int# -- Returns -1# if not matched+  packChunk :: Buffer k -> Int# -> Int# -> k+  unpackChunk :: k -> (# Buffer k, Int# #)   showChunk :: k -> String--class Chunk k => CharChunk k where-  byteAt :: Buffer k -> Int -> Word8-  charAt :: Buffer k -> Int -> (Char, Int)-  charAtFixed :: Int -> Buffer k -> Int -> Char-  charWidth :: Char -> Int+  matchChar :: Buffer k -> Int# -> Char# -> Int# -- Returns -1# if not matched+  indexChar :: Buffer k -> Int# -> (# Char#, Int# #)+  indexByte :: Buffer k -> Int# -> Word#   stringToChunk :: String -> k  instance Chunk ByteString where-  type Element  ByteString = Word8-  type Buffer   ByteString = ForeignPtr Word8--  elementAt b i = (ptrByteAt b i, 1)-  {-# INLINE elementAt #-}--  elementPos e (Pos l c) =-    Pos (if e == asc_newline then l + 1 else l)-        (if e == asc_newline then 1 else c + 1)-  {-# INLINE elementPos #-}--  chunkWidth (B.PS _ _ n) = n-  {-# INLINE chunkWidth #-}+  type Buffer ByteString = ForeignPtr Word8 -  chunkEqual b i (B.PS p j n) = ptrBytesEqual b i p j n-  {-# INLINE chunkEqual #-}+  matchChunk (ForeignPtr p _) i (B.PS (ForeignPtr p' _) (I# j) (I# n)) = go 0#+    where go :: Int# -> Int#+          go k | 1# <- k >=# n = n+               | w <- indexWord8OffAddr# p (i +# k),+                 w' <- indexWord8OffAddr# p' (j +# k),+                 1# <- w `neWord#` int2Word# 0#,+                 1# <- w `eqWord#` w' = go (k +# 1#)+               | otherwise = -1#+  {-# INLINE matchChunk #-} -  packChunk b i n = B.PS b i n+  packChunk b i n = B.PS b (I# i) (I# n)   {-# INLINE packChunk #-}    unpackChunk k =-    let (B.PS b i n) = k <> fromString "\0\0\0" -- sentinel-    in (b, i, n - 3)+    let !(B.PS b (I# i) _) = k <> fromString "\0\0\0" -- sentinel+    in (# b, i #)   {-# INLINE unpackChunk #-} -  showElement = showByte   showChunk = showByteString -instance CharChunk ByteString where-  byteAt = ptrByteAt-  {-# INLINE byteAt #-}--  charAt = ptrDecodeUtf8-  {-# INLINE charAt #-}+  indexByte (ForeignPtr p _) i = indexWord8OffAddr# p i+  {-# INLINE indexByte #-} -  charWidth = charWidthUtf8-  {-# INLINE charWidth #-}+  matchChar p i m+    | C# m <= '\x7F' =+        if | unsafeChr (at p i) == C# m -> 1#+           | otherwise -> -1#+    | C# m <= '\x7FF' =+        if | a1 <- at p i, a2 <- at p (i +# 1#),+             unsafeChr (((a1 .&. 31) `unsafeShiftL` 6)+                         .|. (a2 .&. 0x3F)) == C# m -> 2#+           | otherwise -> -1#+    | C# m <= '\xFFFF' =+        if | a1 <- at p i, a2 <- at p (i +# 1#), a3 <- at p (i +# 2#),+             unsafeChr (((a1 .&. 15) `unsafeShiftL` 12)+                         .|. ((a2 .&. 0x3F) `unsafeShiftL` 6)+                         .|. (a3 .&. 0x3F)) == C# m -> 3#+           | otherwise -> -1#+    | otherwise =+        if | a1 <- at p i, a2 <- at p (i +# 1#), a3 <- at p (i +# 2#), a4 <- at p (i +# 3#),+             unsafeChr (((a1 .&. 7) `unsafeShiftL` 18)+                         .|. ((a2 .&. 0x3F) `unsafeShiftL` 12)+                         .|. ((a3 .&. 0x3F) `unsafeShiftL` 6)+                         .|. (a4 .&. 0x3F)) == C# m -> 4#+           | otherwise -> -1#+  {-# INLINE matchChar #-} -  charAtFixed = ptrDecodeFixedUtf8-  {-# INLINE charAtFixed #-}+  -- TODO detect invalid utf-8?+  indexChar p i+    | a1 <- at p i,+      a1 <= 0x7F =+      (# unsafeChr# a1, 1# #)+    | a1 <- at p i, a2 <- at p (i +# 1#),+      (a1 .&. 0xE0) == 0xC0,+      (a2 .&. 0xC0) == 0x80 =+      (# unsafeChr# (((a1 .&. 31) `unsafeShiftL` 6)+                     .|. (a2 .&. 0x3F)), 2# #)+    | a1 <- at p i, a2 <- at p (i +# 1#), a3 <- at p (i +# 2#),+      (a1 .&. 0xF0) == 0xE0,+      (a2 .&. 0xC0) == 0x80,+      (a3 .&. 0xC0) == 0x80 =+      (# unsafeChr# (((a1 .&. 15) `unsafeShiftL` 12)+                     .|. ((a2 .&. 0x3F) `unsafeShiftL` 6)+                     .|. (a3 .&. 0x3F)), 3# #)+    | a1 <- at p i, a2 <- at p (i +# 1#), a3 <- at p (i +# 2#), a4 <- at p (i +# 3#),+      (a1 .&. 0xF8) == 0xF0,+      (a2 .&. 0xC0) == 0x80,+      (a3 .&. 0xC0) == 0x80,+      (a4 .&. 0xC0) == 0x80 =+      (# unsafeChr# (((a1 .&. 7) `unsafeShiftL` 18)+                     .|. ((a2 .&. 0x3F) `unsafeShiftL` 12)+                     .|. ((a3 .&. 0x3F) `unsafeShiftL` 6)+                     .|. (a4 .&. 0x3F)), 4# #)+    | otherwise = (# '\0'#, 0# #)+  {-# INLINE indexChar #-}    stringToChunk t = T.encodeUtf8 $ fromString t   {-# INLINE stringToChunk #-}  instance Chunk Text where-  type Element  Text = Char-  type Buffer   Text = T.Array--  elementAt b i = arrayCharAt 2 b i-  {-# INLINE elementAt #-}--  elementPos e (Pos l c) =-    Pos (if e == '\n' then l + 1 else l)-        (if e == '\n' then 1 else c + 1)-  {-# INLINE elementPos #-}--  chunkWidth (T.Text _ _ n) = n-  {-# INLINE chunkWidth #-}+  type Buffer Text = T.Array -  chunkEqual b i (T.Text a j n) = T.equal b i a j n-  {-# INLINE chunkEqual #-}+  matchChunk a i (T.Text a' (I# j) (I# n)) = go 0#+    where go :: Int# -> Int#+          go k | 1# <- k >=# n = n+               | w <- T.unsafeIndex a (I# (i +# k)),+                 w' <- T.unsafeIndex a' (I# (j +# k)),+                 w /= 0, w == w' = go (k +# 1#)+               | otherwise = -1#+  {-# INLINE matchChunk #-} -  packChunk b i n = T.Text b i n+  packChunk b i n = T.Text b (I# i) (I# n)   {-# INLINE packChunk #-}    unpackChunk k =-    let (T.Text b i n) = k <> fromString "\0" -- sentinel-    in (b, i, n - 1)+    let !(T.Text b (I# i) _) = k <> fromString "\0" -- sentinel+    in (# b, i #)   {-# INLINE unpackChunk #-} -  showElement = show   showChunk = show -instance CharChunk Text where-  byteAt = arrayByteAt-  {-# INLINE byteAt #-}--  charAt = arrayCharAt 2-  {-# INLINE charAt #-}+  indexByte a i+    | W16# c <- T.unsafeIndex a (I# i), 1# <- c `leWord#` (int2Word# 0xFF#) = c+    | otherwise = int2Word# 0#+  {-# INLINE indexByte #-} -  charWidth = charWidthUtf16-  {-# INLINE charWidth #-}+  indexChar a i+    | hi <- T.unsafeIndex a (I# i), lo <- T.unsafeIndex a (I# (i +# 1#)) =+        if hi < 0xD800 || hi > 0xDFFF then+          (# unsafeChr# (fromIntegral hi), 1# #)+        else+          (# unsafeChr# (0x10000 + ((fromIntegral $ hi - 0xD800) `unsafeShiftL` 10) + (fromIntegral lo - 0xDC00)), 2# #)+  {-# INLINE indexChar #-} -  charAtFixed n b i = fst $ arrayCharAt n b i-  {-# INLINE charAtFixed #-}+  matchChar a i m+    | C# m <= '\xFFFF' =+        if | unsafeChr (fromIntegral (T.unsafeIndex a (I# i))) == C# m -> 1#+           | otherwise -> -1#+    | otherwise =+        if | hi <- T.unsafeIndex a (I# i), lo <- T.unsafeIndex a (I# (i +# 1#)),+             hi >= 0xD800, hi <= 0xDFFF,+             C# m == unsafeChr (0x10000 + ((fromIntegral $ hi - 0xD800) `unsafeShiftL` 10) ++                                (fromIntegral lo - 0xDC00)) -> 2#+           | otherwise -> -1#    stringToChunk t = fromString t   {-# INLINE stringToChunk #-} -arrayByteAt :: T.Array -> Int -> Word8-arrayByteAt a i-  | c <- T.unsafeIndex a i, c <= 0xFF = fromIntegral c-  | otherwise = 0-{-# INLINE arrayByteAt #-}--arrayCharAt :: Int -> T.Array -> Int -> (Char, Int)-arrayCharAt 1 a i-  | c <- T.unsafeIndex a i, c < 0xD800 || c > 0xDFFF = (unsafeChr $ fromIntegral c, 1)-  | otherwise = ('\0', 0)-arrayCharAt _ a i-  | hi <- T.unsafeIndex a i, lo <- T.unsafeIndex a (i + 1) =-      if hi < 0xD800 || hi > 0xDFFF then-        (unsafeChr $ fromIntegral hi, 1)-      else-        (unsafeChr $ 0x10000 + ((fromIntegral $ hi - 0xD800) `unsafeShiftL` 10) + (fromIntegral lo - 0xDC00), 2)-{-# INLINE arrayCharAt #-}--ptrBytesEqual :: ForeignPtr Word8 -> Int -> ForeignPtr Word8 -> Int -> Int -> Bool-ptrBytesEqual p1 i1 p2 i2 n =-  B.accursedUnutterablePerformIO $-  withForeignPtr p1 $ \q1 ->-  withForeignPtr p2 $ \q2 ->-  (== 0) <$> B.memcmp (q1 `plusPtr` i1) (q2 `plusPtr` i2) n-{-# INLINE ptrBytesEqual #-}--ptrByteAt :: ForeignPtr Word8 -> Int -> Word8-ptrByteAt p i = B.accursedUnutterablePerformIO $-  withForeignPtr p $ \q -> peekByteOff q i-{-# INLINE ptrByteAt #-}--at :: ForeignPtr Word8 -> Int -> Int-at p i = fromIntegral $ ptrByteAt p i+at :: ForeignPtr Word8 -> Int# -> Int+at p i = fromIntegral $ W8# (indexByte @ByteString p i) {-# INLINE at #-} --- | Decode UTF-8 character at the given offset relative to the pointer-ptrDecodeUtf8 :: ForeignPtr Word8 -> Int -> (Char, Int)-ptrDecodeUtf8 p i-  | a1 <- at p i,-    a1 <= 0x7F =-    (unsafeChr a1, 1)-  | a1 <- at p i, a2 <- at p (i + 1),-    (a1 .&. 0xE0) == 0xC0,-    (a2 .&. 0xC0) == 0x80 =-    (unsafeChr (((a1 .&. 31) `unsafeShiftL` 6)-                .|. (a2 .&. 0x3F)), 2)-  | a1 <- at p i, a2 <- at p (i + 1), a3 <- at p (i + 2),-    (a1 .&. 0xF0) == 0xE0,-    (a2 .&. 0xC0) == 0x80,-    (a3 .&. 0xC0) == 0x80 =-    (unsafeChr (((a1 .&. 15) `unsafeShiftL` 12)-                 .|. ((a2 .&. 0x3F) `unsafeShiftL` 6)-                 .|. (a3 .&. 0x3F)), 3)-  | a1 <- at p i, a2 <- at p (i + 1), a3 <- at p (i + 2), a4 <- at p (i + 3),-    (a1 .&. 0xF8) == 0xF0,-    (a2 .&. 0xC0) == 0x80,-    (a3 .&. 0xC0) == 0x80,-    (a4 .&. 0xC0) == 0x80 =-    (unsafeChr (((a1 .&. 7) `unsafeShiftL` 18)-                 .|. ((a2 .&. 0x3F) `unsafeShiftL` 12)-                 .|. ((a3 .&. 0x3F) `unsafeShiftL` 6)-                 .|. (a4 .&. 0x3F)), 4)-  | otherwise = ('\0', 0)-{-# INLINE ptrDecodeUtf8 #-}---- | Decode UTF-8 character with fixed width at the given offset relative to the pointer-ptrDecodeFixedUtf8 :: Int -> ForeignPtr Word8 -> Int -> Char-ptrDecodeFixedUtf8 w p i = unsafeChr $-  case w of-    1 -> at p i-    2 | a1 <- at p i, a2 <- at p (i + 1) ->-        ((a1 .&. 31) `unsafeShiftL` 6)-        .|. (a2 .&. 0x3F)-    3 | a1 <- at p i, a2 <- at p (i + 1), a3 <- at p (i + 2) ->-        ((a1 .&. 15) `unsafeShiftL` 12)-        .|. ((a2 .&. 0x3F) `unsafeShiftL` 6)-        .|. (a3 .&. 0x3F)-    4 | a1 <- at p i, a2 <- at p (i + 1), a3 <- at p (i + 2), a4 <- at p (i + 3) ->-        ((a1 .&. 7) `unsafeShiftL` 18)-        .|. ((a2 .&. 0x3F) `unsafeShiftL` 12)-        .|. ((a3 .&. 0x3F) `unsafeShiftL` 6)-        .|. (a4 .&. 0x3F)-    _ -> 0-{-# INLINE ptrDecodeFixedUtf8 #-}--charWidthUtf16 :: Char -> Int-charWidthUtf16 c | c <= unsafeChr 0xFFFF = 1-                 | otherwise = 2-{-# INLINE charWidthUtf16 #-}---- | Bytes width of an UTF-8 character-charWidthUtf8 :: Char -> Int-charWidthUtf8 c | c <= unsafeChr 0x7F = 1-                | c <= unsafeChr 0x7FF = 2-                | c <= unsafeChr 0xFFFF = 3-                | otherwise = 4-{-# INLINE charWidthUtf8 #-}- asc_0, asc_9, asc_A, asc_E, asc_P, asc_a, asc_e, asc_p,   asc_minus, asc_plus, asc_point, asc_newline :: Word8 asc_0 = 48@@ -262,8 +195,12 @@ asc_newline = 10  unsafeAsciiToChar :: Word8 -> Char-unsafeAsciiToChar = unsafeChr . fromIntegral+unsafeAsciiToChar x = unsafeChr (fromIntegral x) {-# INLINE unsafeAsciiToChar #-}++unsafeChr# :: Int -> Char#+unsafeChr# (I# i) = chr# i+{-# INLINE unsafeChr# #-}  byteS :: Word8 -> ShowS byteS b
src/Text/PariPari/Internal/Class.hs view
@@ -1,8 +1,7 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FunctionalDependencies #-} module Text.PariPari.Internal.Class (-  ChunkParser(..)-  , CharParser(..)+  Parser(..)   , Alternative(..)   , MonadPlus   , Pos(..)@@ -15,13 +14,12 @@  import Control.Applicative (Alternative(empty, (<|>))) import Control.Monad (MonadPlus(..))-import Control.Monad.Fail (MonadFail(..)) import Data.List (intercalate)-import Data.Semigroup ((<>)) import Data.String (IsString) import Data.Word (Word8) import GHC.Generics (Generic) import Text.PariPari.Internal.Chunk+import qualified Control.Monad.Fail as Fail  -- | Parsing errors data Error@@ -29,16 +27,23 @@   | EExpected         [String]   | EUnexpected       String   | EFail             String-  | ECombinator       String-  | EIndentNotAligned !Int !Int-  | EIndentOverLine   !Int !Int-  | ENotEnoughIndent  !Int !Int+  | EIndentNotAligned {-#UNPACK#-}!Int {-#UNPACK#-}!Int+  | EIndentOverLine   {-#UNPACK#-}!Int {-#UNPACK#-}!Int+  | ENotEnoughIndent  {-#UNPACK#-}!Int {-#UNPACK#-}!Int   deriving (Eq, Ord, Show, Generic) +-- | Line and column position starting at (1,1)+data Pos = Pos+  { _posLine   :: {-#UNPACK#-}!Int+  , _posCol :: {-#UNPACK#-}!Int+  } deriving (Eq, Show, Generic)++infixl 3 <!>+ -- | Parser class, which specifies the necessary -- primitives for parsing. All other parser combinators -- rely on these primitives.-class (MonadFail p, MonadPlus p, Chunk k) => ChunkParser k p | p -> k where+class (Fail.MonadFail p, MonadPlus p, Chunk k, IsString (p k)) => Parser k p | p -> k where   -- | Get file name associated with current parser   getFile :: p FilePath @@ -80,24 +85,12 @@   -- down the fast path of your parser.   hidden :: p a -> p a -  -- | Commit to the given branch, increasing-  -- the priority of the errors within this branch-  -- in contrast to other branches.-  ---  -- This is basically the opposite of the `try`-  -- combinator provided by other parser combinator-  -- libraries, which decreases the error priority-  -- within the given branch (and usually also influences backtracking).-  ---  -- `commit` only applies to the reported-  -- errors, it has no effect on the backtracking behavior-  -- of the parser.-  ---  -- __Note__: This function has zero cost in the 'Acceptor'. You can-  -- use it to improve the error reports without slowing-  -- down the fast path of your parser.-  commit :: p a -> p a+  -- | Reset position if parser fails+  try :: p a -> p a +  -- | Alternative which does not backtrack.+  (<!>) :: p a -> p a -> p a+   -- | Parse with error recovery.   -- If the parser p fails in `recover p r`   -- the parser r continues at the position where p failed.@@ -112,12 +105,6 @@   -- down the fast path of your parser.   recover :: p a -> p a -> p a -  -- | Parse a single element-  element :: Element k -> p (Element k)--  -- | Scan a single element-  elementScan :: (Element k -> Maybe a) -> p a-   -- | Parse a chunk of elements. The chunk must not   -- contain multiple lines, otherwise the position information   -- will be invalid.@@ -127,7 +114,6 @@   -- result as buffer   asChunk :: p () -> p k -class (ChunkParser k p, IsString (p k), CharChunk k) => CharParser k p | p -> k where   -- | Parse a single character   --   -- __Note__: The character '\0' cannot be parsed using this combinator@@ -158,7 +144,6 @@ showError (EExpected tokens)       = "Expected " <> intercalate ", " tokens showError (EUnexpected token)      = "Unexpected " <> token showError (EFail msg)              = msg-showError (ECombinator name)       = "Combinator " <> name <> " failed" showError (EIndentNotAligned rc c) = "Invalid alignment, expected column " <> show rc <> " expected, got " <> show c showError (EIndentOverLine   rl l) = "Indentation over line, expected line " <> show rl <> ", got " <> show l showError (ENotEnoughIndent  rc c) = "Must be indented deeper than column " <> show rc <> ", got column " <> show c@@ -170,6 +155,6 @@ unexpectedEnd = EUnexpected "end of file"  -- | Parse a string-string :: CharParser k p => String -> p k+string :: Parser k p => String -> p k string t = chunk (stringToChunk t) {-# INLINE string #-}
+ src/Text/PariPari/Internal/Combinators.hs view
@@ -0,0 +1,445 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE Rank2Types #-}+module Text.PariPari.Internal.Combinators (+  -- * Basic combinators+  void+  , (<|>)+  , empty++  -- * Control.Monad.Combinators.NonEmpty+  , ON.some+  , ON.endBy1+  , ON.someTill+  , ON.sepBy1+  , ON.sepEndBy1++  -- * Control.Monad.Combinators+  , O.optional -- dont use Applicative version for efficiency+  , O.many -- dont use Applicative version for efficiency+  , O.between+  , O.choice+  , O.count+  , O.count'+  , O.eitherP+  , O.endBy+  , O.manyTill+  , O.option+  , O.sepBy+  , O.sepEndBy+  , O.skipMany+  , O.skipSome+  , O.skipCount+  , O.skipManyTill+  , O.skipSomeTill++  -- * Labels+  , (<?>)++  -- * Position+  , getLine+  , getCol+  , withPos+  , withSpan++  -- * Indentation+  , getRefCol+  , getRefLine+  , withRefPos+  , align+  , indented+  , line+  , linefold++  -- * Char combinators+  , digitByte+  , integer+  , integer'+  , decimal+  , octal+  , hexadecimal+  , digit+  , sign+  , signed+  , fractionHex+  , fractionDec+  , char'+  , notChar+  , anyChar+  , anyAsciiByte+  , alphaNumChar+  , digitChar+  , letterChar+  , lowerChar+  , upperChar+  , symbolChar+  , categoryChar+  , punctuationChar+  , spaceChar+  , asciiChar+  , satisfy+  , asciiSatisfy+  , skipChars+  , takeChars+  , skipCharsWhile+  , takeCharsWhile+  , skipCharsWhile1+  , takeCharsWhile1+  , scanChars+  , scanChars1+  , string+) where++import Control.Applicative (optional)+import Control.Monad (when)+import Control.Monad.Combinators (option, skipCount, skipMany)+import Data.Functor (void)+import Data.Maybe (fromMaybe)+import Data.Word (Word8)+import Prelude hiding (getLine)+import Text.PariPari.Internal.Chunk+import Text.PariPari.Internal.Class+import qualified Control.Monad.Combinators as O+import qualified Control.Monad.Combinators.NonEmpty as ON+import qualified Data.Char as C++type P k a  = (forall p. Parser k p => p a)++-- | Infix alias for 'label'+(<?>) :: Parser k p => p a -> String -> p a+(<?>) = flip label+{-# INLINE (<?>) #-}+infix 0 <?>++-- | Get line number of the reference position+getRefLine :: P k Int+getRefLine = _posLine <$> getRefPos+{-# INLINE getRefLine #-}++-- | Get column number of the reference position+getRefCol :: P k Int+getRefCol = _posCol <$> getRefPos+{-# INLINE getRefCol #-}++-- | Get current line number+getLine :: P k Int+getLine = _posLine <$> getPos+{-# INLINE getLine #-}++-- | Get current column+getCol :: P k Int+getCol = _posCol <$> getPos+{-# INLINE getCol #-}++-- | Decorate the parser result with the current position+withPos :: Parser k p => p a -> p (Pos, a)+withPos p = do+  pos <- getPos+  ret <- p+  pure (pos, ret)+{-# INLINE withPos #-}++-- | Decorate the parser result with the position span+withSpan :: Parser k p => p a -> p (Pos, Pos, a)+withSpan p = do+  begin <- getPos+  ret <- p+  end <- getPos+  pure (begin, end, ret)+{-# INLINE withSpan #-}++-- | Parser succeeds on the same line as the reference line+line :: P k ()+line = do+  l <- getLine+  rl <- getRefLine+  when (l /= rl) $ failWith $ EIndentOverLine rl l+{-# INLINE line #-}++-- | Parser succeeds on the same column as the reference column+align :: P k ()+align = do+  c <- getCol+  rc <- getRefCol+  when (c /= rc) $ failWith $ EIndentNotAligned rc c+{-# INLINE align #-}++-- | Parser succeeds for columns greater than the current reference column+indented :: P k ()+indented = do+  c <- getCol+  rc <- getRefCol+  when (c <= rc) $ failWith $ ENotEnoughIndent rc c+{-# INLINE indented #-}++-- | Parser succeeds either on the reference line or+-- for columns greater than the current reference column+linefold :: P k ()+linefold = line <|> indented+{-# INLINE linefold #-}++-- | Parse a digit byte for the given base.+-- Bases 2 to 36 are supported.+digitByte :: Parser k p => Int -> p Word8+digitByte base = asciiSatisfy (isDigit base)+{-# INLINE digitByte #-}++isDigit :: Int -> Word8 -> Bool+isDigit base b+  | base >= 2 && base <= 10 = b >= asc_0 && b <= asc_0 + fromIntegral base - 1+  | base <= 36 = (b >= asc_0 && b <= asc_9)+                 || ((fromIntegral b :: Word) - fromIntegral asc_A) < fromIntegral (base - 10)+                 || ((fromIntegral b :: Word) - fromIntegral asc_a) < fromIntegral (base - 10)+  |otherwise = error "Text.PariPari.Internal.Combinators.isDigit: Bases 2 to 36 are supported"+{-# INLINE isDigit #-}++digitToInt :: Int -> Word8 -> Word+digitToInt base b+  | n <- (fromIntegral b :: Word) - fromIntegral asc_0, base <= 10 || n <= 9  = n+  | n <- (fromIntegral b :: Word) - fromIntegral asc_A, n               <= 26 = n + 10+  | n <- (fromIntegral b :: Word) - fromIntegral asc_a                        = n + 10+{-# INLINE digitToInt #-}++-- | Parse a single digit of the given base and return its value.+-- Bases 2 to 36 are supported.+digit :: Parser k p => Int -> p Word+digit base = digitToInt base <$> asciiSatisfy (isDigit base)+{-# INLINE digit #-}++-- | Parse an integer of the given base.+-- Returns the integer and the number of digits.+-- Bases 2 to 36 are supported.+-- Digits can be separated by separator, e.g. `optional (char '_')`.+-- Signs are not parsed by this combinator.+integer' :: (Num a, Parser k p) => p sep -> Int -> p (a, Int)+integer' sep base = label (integerLabel base) $ do+  d <- digit base+  accum 1 $ fromIntegral d+  where accum !i !n = next i n <|> pure (n, i)+        next !i !n = do+          void $ sep+          d <- digit base+          accum (i + 1) $ n * fromIntegral base + fromIntegral d+{-# INLINE integer' #-}++-- | Parse an integer of the given base.+-- Bases 2 to 36 are supported.+-- Digits can be separated by separator, e.g. `optional (char '_')`.+-- Signs are not parsed by this combinator.+integer :: (Num a, Parser k p) => p sep -> Int -> p a+integer sep base = label (integerLabel base) $ do+  d <- digit base+  accum $ fromIntegral d+  where accum !n = next n <|> pure n+        next !n = do+          void $ sep+          d <- digit base+          accum $ n * fromIntegral base + fromIntegral d+{-# INLINE integer #-}++integerLabel :: Int -> String+integerLabel 2  = "binary integer"+integerLabel 8  = "octal integer"+integerLabel 10 = "decimal integer"+integerLabel 16 = "hexadecimal integer"+integerLabel b  = "integer of base " <> show b++-- | Parses a decimal integer.+-- Signs are not parsed by this combinator.+decimal :: Num a => P k a+decimal = integer (pure ()) 10+{-# INLINE decimal #-}++-- | Parses an octal integer.+-- Signs are not parsed by this combinator.+octal :: Num a => P k a+octal = integer (pure ()) 8+{-# INLINE octal #-}++-- | Parses a hexadecimal integer.+-- Signs are not parsed by this combinator.+hexadecimal :: Num a => P k a+hexadecimal = integer (pure ()) 16+{-# INLINE hexadecimal #-}++-- | Parse plus or minus sign+sign :: (Parser k f, Num a) => f (a -> a)+sign = (negate <$ asciiByte asc_minus) <|> (id <$ optional (asciiByte asc_plus))+{-# INLINE sign #-}++-- | Parse a number with a plus or minus sign.+signed :: (Num a, Parser k p) => p a -> p a+signed p = ($) <$> sign <*> p+{-# INLINE signed #-}++fractionExp :: (Num a, Parser k p) => p expSep -> p digitSep -> p (Maybe a)+fractionExp expSep digitSep = do+  e <- optional expSep+  case e of+    Nothing{} -> pure Nothing+    Just{} -> Just <$> signed (integer digitSep 10)+{-# INLINE fractionExp #-}++-- | Parse a fraction of arbitrary exponent base and mantissa base.+-- 'fractionDec' and 'fractionHex' should be used instead probably.+-- Returns either an integer in 'Left' or a fraction in 'Right'.+-- Signs are not parsed by this combinator.+fraction :: (Num a, Parser k p) => p expSep -> Int -> Int -> p digitSep -> p (Either a (a, Int, a))+fraction expSep expBase mantBasePow digitSep = do+  let mantBase = expBase ^ mantBasePow+  mant <- integer digitSep mantBase+  frac <- optional $ asciiByte asc_point *> option (0, 0) (integer' digitSep mantBase)+  expn <- fractionExp expSep digitSep+  let (fracVal, fracLen) = fromMaybe (0, 0) frac+      expVal = fromMaybe 0 expn+  pure $ case (frac, expn) of+           (Nothing, Nothing) -> Left mant+           _ -> Right ( mant * fromIntegral mantBase ^ fracLen + fracVal+                      , expBase+                      , expVal - fromIntegral (fracLen * mantBasePow))+{-# INLINE fraction #-}++-- | Parse a decimal fraction, e.g., 123.456e-78, returning (mantissa, 10, exponent),+-- corresponding to mantissa * 10^exponent.+-- Digits can be separated by separator, e.g. `optional (char '_')`.+-- Signs are not parsed by this combinator.+fractionDec :: (Num a, Parser k p) => p digitSep -> p (Either a (a, Int, a))+fractionDec sep = fraction (asciiSatisfy (\b -> b == asc_E || b == asc_e)) 10 1 sep <?> "fraction"+{-# INLINE fractionDec #-}++-- | Parse a hexadecimal fraction, e.g., co.ffeep123, returning (mantissa, 2, exponent),+-- corresponding to mantissa * 2^exponent.+-- Digits can be separated by separator, e.g. `optional (char '_')`.+-- Signs are not parsed by this combinator.+fractionHex :: (Num a, Parser k p) => p digitSep -> p (Either a (a, Int, a))+fractionHex sep = fraction (asciiSatisfy (\b -> b == asc_P || b == asc_p)) 2 4 sep <?> "hexadecimal fraction"+{-# INLINE fractionHex #-}++-- | Parse a case-insensitive character+char' :: Parser k p => Char -> p Char+char' x =+  let l = C.toLower x+      u = C.toUpper x+  in satisfy (\c -> c == l || c == u)+{-# INLINE char' #-}++-- | Parse a character different from the given one.+notChar :: Parser k p => Char -> p Char+notChar c = satisfy (/= c)+{-# INLINE notChar #-}++-- | Parse an arbitrary character.+anyChar :: P k Char+anyChar = satisfy (const True)+{-# INLINE anyChar #-}++-- | Parse an arbitrary ASCII byte.+anyAsciiByte :: P k Word8+anyAsciiByte = asciiSatisfy (const True)+{-# INLINE anyAsciiByte #-}++-- | Parse an alphanumeric character, including Unicode.+alphaNumChar :: P k Char+alphaNumChar = satisfy C.isAlphaNum <?> "alphanumeric character"+{-# INLINE alphaNumChar #-}++-- | Parse a letter character, including Unicode.+letterChar :: P k Char+letterChar = satisfy C.isLetter <?> "letter"+{-# INLINE letterChar #-}++-- | Parse a lowercase letter, including Unicode.+lowerChar :: P k Char+lowerChar = satisfy C.isLower <?> "lowercase letter"+{-# INLINE lowerChar #-}++-- | Parse a uppercase letter, including Unicode.+upperChar :: P k Char+upperChar = satisfy C.isUpper <?> "uppercase letter"+{-# INLINE upperChar #-}++-- | Parse a space character, including Unicode.+spaceChar :: P k Char+spaceChar = satisfy C.isSpace <?> "space"+{-# INLINE spaceChar #-}++-- | Parse a symbol character, including Unicode.+symbolChar :: P k Char+symbolChar = satisfy C.isSymbol <?> "symbol"+{-# INLINE symbolChar #-}++-- | Parse a punctuation character, including Unicode.+punctuationChar :: P k Char+punctuationChar = satisfy C.isPunctuation <?> "punctuation"+{-# INLINE punctuationChar #-}++-- | Parse a digit character of the given base.+-- Bases 2 to 36 are supported.+digitChar :: Parser k p => Int -> p Char+digitChar base = unsafeAsciiToChar <$> digitByte base+{-# INLINE digitChar #-}++-- | Parse a character beloning to the ASCII charset (< 128)+asciiChar :: P k Char+asciiChar = unsafeAsciiToChar <$> anyAsciiByte+{-# INLINE asciiChar #-}++-- | Parse a character belonging to the given Unicode category+categoryChar :: Parser k p => C.GeneralCategory -> p Char+categoryChar cat = satisfy ((== cat) . C.generalCategory) <?> untitle (show cat)+{-# INLINE categoryChar #-}++untitle :: String -> String+untitle []     = []+untitle (x:xs) = C.toLower x : go xs+  where go [] = ""+        go (y:ys) | C.isUpper y = ' ' : C.toLower y : untitle ys+                  | otherwise   = y : ys++-- | Skip the next n characters+skipChars :: Parser k p => Int -> p ()+skipChars n = skipCount n anyChar+{-# INLINE skipChars #-}++-- | Skip char while predicate is true+skipCharsWhile :: Parser k p => (Char -> Bool) -> p ()+skipCharsWhile f = skipMany (satisfy f)+{-# INLINE skipCharsWhile #-}++-- | Skip at least one char while predicate is true+skipCharsWhile1 :: Parser k p => (Char -> Bool) -> p ()+skipCharsWhile1 f = satisfy f *> skipCharsWhile f+{-# INLINE skipCharsWhile1 #-}++-- | Take the next n characters and advance the position by n characters+takeChars :: Parser k p => Int -> p k+takeChars n = asChunk (skipChars n) <?> "string of length " <> show n+{-# INLINE takeChars #-}++-- | Take chars while predicate is true+takeCharsWhile :: Parser k p => (Char -> Bool) -> p k+takeCharsWhile f = asChunk (skipCharsWhile f)+{-# INLINE takeCharsWhile #-}++-- | Take at least one byte while predicate is true+takeCharsWhile1 :: Parser k p => (Char -> Bool) -> p k+takeCharsWhile1 f = asChunk (skipCharsWhile1 f)+{-# INLINE takeCharsWhile1 #-}++-- | Parse a single character with the given predicate+satisfy :: Parser k p => (Char -> Bool) -> p Char+satisfy f = scan $ \c -> if f c then Just c else Nothing+{-# INLINE satisfy #-}++-- | Parse a single character within the ASCII charset with the given predicate+asciiSatisfy :: Parser k p => (Word8 -> Bool) -> p Word8+asciiSatisfy f = asciiScan $ \b -> if f b then Just b else Nothing+{-# INLINE asciiSatisfy #-}++scanChars :: Parser k p => (s -> Char -> Maybe s) -> s -> p s+scanChars f = go+  where go s = (scan (f s) >>= go) <|> pure s+{-# INLINE scanChars #-}++scanChars1 :: Parser k p => (s -> Char -> Maybe s) -> s -> p s+scanChars1 f s = scan (f s) >>= scanChars f+{-# INLINE scanChars1 #-}
− src/Text/PariPari/Internal/ElementCombinators.hs
@@ -1,202 +0,0 @@-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-module Text.PariPari.Internal.ElementCombinators (-  -- * Basic combinators-  void-  , (<|>)-  , empty--  -- * Control.Monad.Combinators.NonEmpty-  , ON.some-  , ON.endBy1-  , ON.someTill-  , ON.sepBy1-  , ON.sepEndBy1--  -- * Control.Monad.Combinators-  , O.optional -- dont use Applicative version for efficiency-  , O.many -- dont use Applicative version for efficiency-  , O.between-  , O.choice-  , O.count-  , O.count'-  , O.eitherP-  , O.endBy-  , O.manyTill-  , O.option-  , O.sepBy-  , O.sepEndBy-  , O.skipMany-  , O.skipSome-  , O.skipCount-  , O.skipManyTill-  , O.skipSomeTill--  -- * PariPari-  , (<?>)-  , getLine-  , getColumn-  , withPos-  , withSpan-  , getRefColumn-  , getRefLine-  , withRefPos-  , align-  , indented-  , line-  , linefold-  , notElement-  , anyElement-  , elementSatisfy-  , takeElements-  , skipElements-  , skipElementsWhile-  , takeElementsWhile-  , skipElementsWhile1-  , takeElementsWhile1-  , scanElements-  , scanElements1-) where--import Control.Applicative ((<|>), empty)-import Control.Monad (when)-import Control.Monad.Combinators (skipCount, skipMany)-import Data.Functor (void)-import Data.Semigroup ((<>))-import Prelude hiding (getLine)-import Text.PariPari.Internal.Chunk-import Text.PariPari.Internal.Class-import qualified Control.Monad.Combinators as O-import qualified Control.Monad.Combinators.NonEmpty as ON--type ChunkP k a = (forall p. ChunkParser k p => p a)---- | Infix alias for 'label'-(<?>) :: ChunkParser k p => p a -> String -> p a-(<?>) = flip label-{-# INLINE (<?>) #-}-infix 0 <?>---- | Get line number of the reference position-getRefLine :: ChunkP k Int-getRefLine = _posLine <$> getRefPos-{-# INLINE getRefLine #-}---- | Get column number of the reference position-getRefColumn :: ChunkP k Int-getRefColumn = _posColumn <$> getRefPos-{-# INLINE getRefColumn #-}---- | Get current line number-getLine :: ChunkP k Int-getLine = _posLine <$> getPos-{-# INLINE getLine #-}---- | Get current column-getColumn :: ChunkP k Int-getColumn = _posColumn <$> getPos-{-# INLINE getColumn #-}---- | Decorate the parser result with the current position-withPos :: ChunkParser k p => p a -> p (Pos, a)-withPos p = do-  pos <- getPos-  ret <- p-  pure (pos, ret)-{-# INLINE withPos #-}--type Span = (Pos, Pos)---- | Decorate the parser result with the position span-withSpan :: ChunkParser k p => p a -> p (Span, a)-withSpan p = do-  begin <- getPos-  ret <- p-  end <- getPos-  pure ((begin, end), ret)-{-# INLINE withSpan #-}---- | Parser succeeds on the same line as the reference line-line :: ChunkP k ()-line = do-  l <- getLine-  rl <- getRefLine-  when (l /= rl) $ failWith $ EIndentOverLine rl l-{-# INLINE line #-}---- | Parser succeeds on the same column as the reference column-align :: ChunkP k ()-align = do-  c <- getColumn-  rc <- getRefColumn-  when (c /= rc) $ failWith $ EIndentNotAligned rc c-{-# INLINE align #-}---- | Parser succeeds for columns greater than the current reference column-indented :: ChunkP k ()-indented = do-  c <- getColumn-  rc <- getRefColumn-  when (c <= rc) $ failWith $ ENotEnoughIndent rc c-{-# INLINE indented #-}---- | Parser succeeds either on the reference line or--- for columns greater than the current reference column-linefold :: ChunkP k ()-linefold = line <|> indented-{-# INLINE linefold #-}---- | Parser a single element different from the given one-notElement :: forall k p. ChunkParser k p => Element k -> p (Element k)-notElement e = elementSatisfy @k (/= e) <?> "not " <> showElement @k e-{-# INLINE notElement #-}---- | Parse an arbitrary element-anyElement :: ChunkP k (Element k)-anyElement = elementSatisfy (const True)-{-# INLINE anyElement #-}---- | Skip the next n elements-skipElements :: ChunkParser k p => Int -> p ()-skipElements n = skipCount n anyElement-{-# INLINE skipElements #-}---- | Take the next n elements and advance the position by n-takeElements :: ChunkParser k p => Int -> p k-takeElements n = asChunk (skipElements n) <?> show n <> " elements"-{-# INLINE takeElements #-}---- | Skip elements while predicate is true-skipElementsWhile :: ChunkParser k p => (Element k -> Bool) -> p ()-skipElementsWhile f = skipMany (elementSatisfy f)-{-# INLINE skipElementsWhile #-}---- | Takes elements while predicate is true-takeElementsWhile :: ChunkParser k p => (Element k -> Bool) -> p k-takeElementsWhile f = asChunk (skipElementsWhile f)-{-# INLINE takeElementsWhile #-}---- | Skip at least one element while predicate is true-skipElementsWhile1 :: ChunkParser k p => (Element k -> Bool) -> p ()-skipElementsWhile1 f = elementSatisfy f *> skipElementsWhile f-{-# INLINE skipElementsWhile1 #-}---- | Take at least one element while predicate is true-takeElementsWhile1 :: ChunkParser k p => (Element k -> Bool) -> p k-takeElementsWhile1 f = asChunk (skipElementsWhile1 f)-{-# INLINE takeElementsWhile1 #-}---- | Parse a single element with the given predicate-elementSatisfy :: ChunkParser k p => (Element k -> Bool) -> p (Element k)-elementSatisfy f = elementScan $ \e -> if f e then Just e else Nothing-{-# INLINE elementSatisfy #-}--scanElements :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s-scanElements f = go-  where go s = (elementScan (f s) >>= go) <|> pure s-{-# INLINE scanElements #-}--scanElements1 :: ChunkParser k p => (s -> Element k -> Maybe s) -> s -> p s-scanElements1 f s = elementScan (f s) >>= scanElements f-{-# INLINE scanElements1 #-}
src/Text/PariPari/Internal/Reporter.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-}@@ -7,6 +8,8 @@ {-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE MagicHash #-} module Text.PariPari.Internal.Reporter (   Reporter(..)   , Env(..)@@ -28,9 +31,10 @@ import Control.Monad (void) import Data.Function (on) import Data.List (intercalate, sort, group, sortOn)-import Data.List.NonEmpty (NonEmpty(..)) import Data.Semigroup as Sem import Data.String (IsString(..))+import GHC.Base+import GHC.Word import GHC.Generics (Generic) import Text.PariPari.Internal.Chunk import Text.PariPari.Internal.Class@@ -38,45 +42,42 @@ import qualified Data.List.NonEmpty as NE  data ErrorContext = ErrorContext-  { _ecErrors  :: [Error]-  , _ecContext :: [String]+  { _ecErrors  :: ![Error]+  , _ecContext :: ![String]   } deriving (Eq, Show, Generic)  data ReportOptions = ReportOptions-  { _optMaxContexts         :: !Int-  , _optMaxErrorsPerContext :: !Int-  , _optMaxLabelsPerContext :: !Int+  { _optMaxContexts         :: {-#UNPACK#-}!Int+  , _optMaxErrorsPerContext :: {-#UNPACK#-}!Int+  , _optMaxLabelsPerContext :: {-#UNPACK#-}!Int   } deriving (Eq, Show, Generic)  data Report = Report   { _reportFile   :: !FilePath-  , _reportLine   :: !Int-  , _reportColumn :: !Int-  , _reportErrors :: [ErrorContext]+  , _reportErrors :: ![ErrorContext]+  , _reportLine   :: {-#UNPACK#-}!Int+  , _reportCol    :: {-#UNPACK#-}!Int   } deriving (Eq, Show, Generic)  data Env k = Env   { _envBuf       :: !(Buffer k)-  , _envEnd       :: !Int   , _envFile      :: !FilePath   , _envOptions   :: !ReportOptions   , _envHidden    :: !Bool-  , _envCommit    :: !Int-  , _envContext   :: [String]-  , _envRefLine   :: !Int-  , _envRefColumn :: !Int+  , _envContext   :: ![String]+  , _envRefLine   :: Int#+  , _envRefCol    :: Int#   }  data State = State-  { _stOff       :: !Int-  , _stLine      :: !Int-  , _stColumn    :: !Int-  , _stErrOff    :: !Int-  , _stErrLine   :: !Int-  , _stErrColumn :: !Int-  , _stErrCommit :: !Int-  , _stErrors    :: [ErrorContext]-  , _stReports   :: [Report]+  { _stOff       :: Int#+  , _stLine      :: Int#+  , _stCol       :: Int#+  , _stErrOff    :: Int#+  , _stErrLine   :: Int#+  , _stErrCol    :: Int#+  , _stErrors    :: ![ErrorContext]+  , _stReports   :: ![Report]   }  -- | Parser which is optimised for good error reports.@@ -153,17 +154,17 @@   fail msg = failWith $ EFail msg   {-# INLINE fail #-} -instance Chunk k => ChunkParser k (Reporter k) where-  getPos = get $ \_ st -> Pos (_stLine st) (_stColumn st)+instance Chunk k => Parser k (Reporter k) where+  getPos = get $ \_ st -> Pos (I# (_stLine st)) (I# (_stCol st))   {-# INLINE getPos #-}    getFile = get $ \env _ -> _envFile env   {-# INLINE getFile #-} -  getRefPos = get $ \env _ -> Pos (_envRefLine env) (_envRefColumn env)+  getRefPos = get $ \env _ -> Pos (I# (_envRefLine env)) (I# (_envRefCol env))   {-# INLINE getRefPos #-} -  withRefPos p = local (\st env -> env { _envRefLine = _stLine st, _envRefColumn = _stColumn st }) p+  withRefPos p = local (\st env -> env { _envRefLine = _stLine st, _envRefCol = _stCol st }) p   {-# INLINE withRefPos #-}    label l p = local (const $ addLabel l) p@@ -172,9 +173,18 @@   hidden p = local (const $ \env -> env { _envHidden = True }) p   {-# INLINE hidden #-} -  commit p = local (const $ \env -> env { _envCommit = _envCommit env + 1 }) p-  {-# INLINE commit #-}+  try p = Reporter $ \env st ok err ->+    let err' _ = err st+    in unReporter p env st ok err'+  {-# INLINE try #-} +  p1 <!> p2 = Reporter $ \env st ok err ->+    let err' s+          | 1# <- _stOff s ==# _stOff st = unReporter p2 env (mergeErrorState env st s) ok err+          | otherwise = err s+    in unReporter p1 env st ok err'+  {-# INLINE (<!>) #-}+   notFollowedBy p = Reporter $ \env st ok err ->     let ok' x _ = raiseError env st err $ EUnexpected $ show x         err' _ = ok () st@@ -190,10 +200,9 @@   {-# INLINE failWith #-}    eof = Reporter $ \env st ok err ->-    if _stOff st >= _envEnd env then-      ok () st-    else-      raiseError env st err expectedEnd+    case indexByte @k (_envBuf env) (_stOff st) `eqWord#` int2Word# 0# of+      1# -> ok () st+      _ -> raiseError env st err expectedEnd   {-# INLINE eof #-}    recover p r = Reporter $ \env st ok err ->@@ -203,92 +212,57 @@     in unReporter p env st ok err1   {-# INLINE recover #-} -  element e = Reporter $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-    if | _stOff < _envEnd env,-         (e', w) <- elementAt @k (_envBuf env) _stOff,-         e == e',-         pos <- elementPos @k e (Pos _stLine _stColumn) ->-           ok e st { _stOff =_stOff + w, _stLine = _posLine pos, _stColumn = _posColumn pos }-       | otherwise ->-           raiseError env st err $ EExpected [showElement @k e]-  {-# INLINE element #-}--  elementScan f = Reporter $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-    let (e, w) = elementAt @k (_envBuf env) _stOff-    in if | _stOff >= _envEnd env ->-              raiseError env st err unexpectedEnd-          | _stOff < _envEnd env,-            Just r <- f e,-            pos <- elementPos @k e (Pos _stLine _stColumn) ->-              ok r st { _stOff =_stOff + w, _stLine = _posLine pos, _stColumn = _posColumn pos }-          | otherwise ->-              raiseError env st err $ EUnexpected $ showElement @k e-  {-# INLINE elementScan #-}--  chunk k = Reporter $ \env st@State{_stOff,_stColumn} ok err ->-    let n = chunkWidth @k k-    in if n + _stOff <= _envEnd env &&-          chunkEqual @k (_envBuf env) _stOff k then-         ok k st { _stOff = _stOff + n, _stColumn = _stColumn + n }-       else-         raiseError env st err $ EExpected [showChunk @k k]+  chunk k = Reporter $ \env st@State{_stOff,_stCol} ok err ->+    case matchChunk @k (_envBuf env) _stOff k of+      -1# -> raiseError env st err $ EExpected [showChunk @k k]+      n -> ok k st { _stOff = _stOff +# n, _stCol = _stCol +# n }   {-# INLINE chunk #-}    asChunk p = do-    begin <- get (const _stOff)+    I# begin' <- get (const (\s -> I# (_stOff s)))     p-    end <- get (const _stOff)+    I# end' <- get (const (\s -> I# (_stOff s)))     src <- get (\env _ -> _envBuf env)-    pure $ packChunk src begin (end - begin)+    pure $ packChunk src begin' (end' -# begin')   {-# INLINE asChunk #-} -instance CharChunk k => CharParser k (Reporter k) where-  scan f = Reporter $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-    if | (c, w) <- charAt @k (_envBuf env) _stOff,-         c /= '\0' ->-           case f c of-             Just r ->-               ok r st-               { _stOff = _stOff + w-               , _stLine = if c == '\n' then _stLine + 1 else _stLine-               , _stColumn = if c == '\n' then 1 else _stColumn + 1-               }-             Nothing ->-               raiseError env st err $ EUnexpected $ show c-       | _stOff >= _envEnd env ->-           raiseError env st err unexpectedEnd-       | otherwise ->-           raiseError env st err EInvalidUtf8+  scan f = Reporter $ \env st@State{_stOff, _stLine, _stCol} ok err ->+    case indexChar @k (_envBuf env) _stOff of+      (# '\0'#, _ #) -> raiseError env st err unexpectedEnd+      (# c, w #) ->+        case f (C# c) of+          Just r ->+            ok r st { _stOff = _stOff +# w+                    , _stLine = case c `eqChar#` '\n'# of 1# -> _stLine +# 1#; _ -> _stLine+                    , _stCol = case c `eqChar#` '\n'# of 1# -> 1#; _ -> _stCol +# 1#+                    }+          Nothing -> raiseError env st err $ EUnexpected $ show (C# c)   {-# INLINE scan #-}    -- By inling this combinator, GHC should figure out the `charWidth`   -- of the character resulting in an optimised decoder.   char '\0' = error "Character '\\0' cannot be parsed because it is used as sentinel"-  char c-    | w <- charWidth @k c =-        Reporter $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-        if charAtFixed @k w (_envBuf env) _stOff == c then-          ok c st-          { _stOff = _stOff + w-          , _stLine = if c == '\n' then _stLine + 1 else _stLine-          , _stColumn = if c == '\n' then 1 else _stColumn + 1-          }-        else-          raiseError env st err $ EExpected [show c]+  char c@(C# c') =+    Reporter $ \env st@State{_stOff, _stLine, _stCol} ok err ->+        case matchChar @k (_envBuf env) _stOff c' of+          -1# -> raiseError env st err $ EExpected [show c]+          w -> ok c st+            { _stOff = _stOff +# w+            , _stLine = if c == '\n' then _stLine +# 1# else _stLine+            , _stCol = if c == '\n' then 1# else _stCol +# 1#+            }   {-# INLINE char #-} -  asciiScan f = Reporter $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-    let b = byteAt @k (_envBuf env) _stOff+  asciiScan f = Reporter $ \env st@State{_stOff, _stLine, _stCol} ok err ->+    let b = W8# (indexByte @k (_envBuf env) _stOff)     in if | b /= 0,             b < 128,             Just x <- f b ->               ok x st-              { _stOff = _stOff + 1-              , _stLine = if b == asc_newline then _stLine + 1 else _stLine-              , _stColumn = if b == asc_newline then 1 else _stColumn + 1+              { _stOff = _stOff +# 1#+              , _stLine = if b == asc_newline then _stLine +# 1# else _stLine+              , _stCol = if b == asc_newline then 1# else _stCol +# 1#               }-          | _stOff >= _envEnd env ->-              raiseError env st err unexpectedEnd           | otherwise ->               raiseError env st err $ EUnexpected $ showByte b   {-# INLINE asciiScan #-}@@ -296,18 +270,18 @@   asciiByte 0 = error "Character '\\0' cannot be parsed because it is used as sentinel"   asciiByte b     | b >= 128 = error "Not an ASCII character"-    | otherwise = Reporter $ \env st@State{_stOff, _stLine, _stColumn} ok err ->-        if byteAt @k (_envBuf env) _stOff == b then+    | otherwise = Reporter $ \env st@State{_stOff, _stLine, _stCol} ok err ->+        if W8# (indexByte @k (_envBuf env) _stOff) == b then           ok b st-          { _stOff = _stOff + 1-          , _stLine = if b == asc_newline then _stLine + 1 else _stLine-          , _stColumn = if b == asc_newline then 1 else _stColumn + 1+          { _stOff = _stOff +# 1#+          , _stLine = if b == asc_newline then _stLine +# 1# else _stLine+          , _stCol = if b == asc_newline then 1# else _stCol +# 1#           }         else           raiseError env st err $ EExpected [showByte b]   {-# INLINE asciiByte #-} -instance CharChunk k => IsString (Reporter k k) where+instance Chunk k => IsString (Reporter k k) where   fromString = string   {-# INLINE fromString #-} @@ -338,17 +312,13 @@ -- Furthermore the error is merged with existing errors if possible. addError :: Env k -> State -> Error -> State addError env st e-  | _stOff st > _stErrOff st || _envCommit env > _stErrCommit st,+  | 1# <- _stOff st ># _stErrOff st,     Just e' <- mkError env e =       st { _stErrors    = [e']          , _stErrOff    = _stOff st          , _stErrLine   = _stLine st-         , _stErrColumn = _stColumn st-         , _stErrCommit = _envCommit env+         , _stErrCol = _stCol st          }-  | _stOff st == _stErrOff st && _envCommit env == _stErrCommit st,-    Just e' <- mkError env e =-      st { _stErrors = shrinkErrors env $ e' : _stErrors st }   | otherwise = st {-# INLINE addError #-} @@ -362,23 +332,19 @@ -- | Merge errors of two states, used when backtracking mergeErrorState :: Env k -> State -> State -> State mergeErrorState env s s'-  | _stErrOff s' > _stErrOff s || _stErrCommit s' > _stErrCommit s =+  | 1# <- _stErrOff s' ># _stErrOff s =       s { _stErrors    = _stErrors s'         , _stErrOff    = _stErrOff s'         , _stErrLine   = _stErrLine s'-        , _stErrColumn = _stErrColumn s'-        , _stErrCommit = _stErrCommit s'+        , _stErrCol    = _stErrCol s'         }-  | _stErrOff s' == _stErrOff s && _stErrCommit s' == _stErrCommit s =+  | 1# <- _stErrOff s' ==# _stErrOff s =       s { _stErrors = shrinkErrors env $ _stErrors s' <> _stErrors s }   | otherwise = s {-# INLINE mergeErrorState #-} -groupOn :: Eq e => (a -> e) -> [a] -> [NonEmpty a]-groupOn f = NE.groupBy ((==) `on` f)- shrinkErrors :: Env k -> [ErrorContext] -> [ErrorContext]-shrinkErrors env = take (_optMaxContexts._envOptions $ env) . map (mergeErrorContexts env) . groupOn _ecContext . sortOn _ecContext+shrinkErrors env = take (_optMaxContexts._envOptions $ env) . map (mergeErrorContexts env) . NE.groupBy ((==) `on` _ecContext) . sortOn _ecContext  -- | Shrink error context by deleting duplicates -- and merging errors if possible.@@ -409,8 +375,8 @@ -- | Run 'Reporter' with additional 'ReportOptions'. runReporterWithOptions :: Chunk k => ReportOptions -> Reporter k a -> FilePath -> k -> (Maybe a, [Report]) runReporterWithOptions o p f k =-  let (b, off, len) = unpackChunk k-      env = initialEnv o f b (off + len)+  let !(# b, off #) = unpackChunk k+      env = initialEnv o f b       ok x s = (Just x, reverse $ _stReports s)       err s = (Nothing, reverse $ _stReports $ addReport env s)   in unReporter p env (initialState off) ok err@@ -423,30 +389,30 @@ runReporter = runReporterWithOptions defaultReportOptions  addReport :: Env k -> State -> State-addReport e s = s { _stReports = Report (_envFile e) (_stErrLine s) (_stErrColumn s) (_stErrors s) : _stReports s }+addReport e s = s { _stReports = Report { _reportFile = _envFile e+                                        , _reportErrors = _stErrors s+                                        , _reportLine = I# (_stErrLine s)+                                        , _reportCol = I# (_stErrCol s) } : _stReports s } -initialEnv :: ReportOptions -> FilePath -> Buffer k -> Int -> Env k-initialEnv _envOptions _envFile _envBuf _envEnd = Env+initialEnv :: ReportOptions -> FilePath -> Buffer k -> Env k+initialEnv _envOptions _envFile _envBuf = Env   { _envFile   , _envBuf   , _envOptions-  , _envEnd   , _envContext   = []   , _envHidden    = False-  , _envCommit    = 0-  , _envRefLine   = 1-  , _envRefColumn = 1+  , _envRefLine   = 1#+  , _envRefCol    = 1#   } -initialState :: Int -> State+initialState :: Int# -> State initialState _stOff = State   { _stOff-  , _stLine      = 1-  , _stColumn    = 1-  , _stErrOff    = 0-  , _stErrLine   = 0-  , _stErrColumn = 0-  , _stErrCommit = 0+  , _stLine      = 1#+  , _stCol       = 1#+  , _stErrOff    = 0#+  , _stErrLine   = 0#+  , _stErrCol    = 0#   , _stErrors    = []   , _stReports   = []   }@@ -456,7 +422,7 @@ showReport r =   "Parser errors at " <> _reportFile r   <> ", line " <> show (_reportLine r)-  <> ", column " <> show (_reportColumn r)+  <> ", column " <> show (_reportCol r)   <> "\n\n" <> showErrors (_reportErrors r)  -- | Pretty string representation of '[ErrorContext]'.
src/Text/PariPari/Internal/Run.hs view
@@ -1,89 +1,28 @@ {-# LANGUAGE Rank2Types #-} module Text.PariPari.Internal.Run (-  runCharParser-  , runSeqCharParser-  , runCharParserWithOptions-  , runSeqCharParserWithOptions-  , runChunkParser-  , runSeqChunkParser-  , runChunkParserWithOptions-  , runSeqChunkParserWithOptions+  runParser+  , runParserWithOptions ) where  import Text.PariPari.Internal.Acceptor import Text.PariPari.Internal.Class import Text.PariPari.Internal.Chunk import Text.PariPari.Internal.Reporter-import GHC.Conc (par) --- | Run fast 'Acceptor' and slower 'Reporter' on the given chunk **in parallel**.--- The 'FilePath' is used for error reporting.--- When the acceptor does not return successfully, the result from the reporter--- is awaited.-runCharParser :: CharChunk k => (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])-runCharParser = runCharParserWithOptions defaultReportOptions-{-# INLINE runCharParser #-}---- | Run fast 'Acceptor' and slower 'Reporter' on the given chunk **sequentially**.--- The 'FilePath' is used for error reporting.--- When the acceptor does not return successfully, the result from the reporter--- is awaited.-runSeqCharParser :: CharChunk k => (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])-runSeqCharParser = runSeqCharParserWithOptions defaultReportOptions-{-# INLINE runSeqCharParser #-}---- | Run parsers **in parallel** with additional 'ReportOptions'.-runCharParserWithOptions :: CharChunk k => ReportOptions -> (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])-runCharParserWithOptions o p f b =-  let a = runAcceptor p f b-      r = runReporterWithOptions o p f b-  in case r `par` a of-       Left _  -> r-       Right x -> (Just x, [])-{-# INLINE runCharParserWithOptions #-}---- | Run parsers **sequentially** with additional 'ReportOptions'.-runSeqCharParserWithOptions :: CharChunk k => ReportOptions -> (forall p. CharParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])-runSeqCharParserWithOptions o p f b =-  let a = runAcceptor p f b-      r = runReporterWithOptions o p f b-  in case a of-       Left _  -> r-       Right x -> (Just x, [])-{-# INLINE runSeqCharParserWithOptions #-}---- | Run fast 'Acceptor' and slower 'Reporter' on the given chunk **in parallel**.--- The 'FilePath' is used for error reporting.--- When the acceptor does not return successfully, the result from the reporter--- is awaited.-runChunkParser :: CharChunk k => (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])-runChunkParser = runCharParserWithOptions defaultReportOptions-{-# INLINE runChunkParser #-}---- | Run fast 'Acceptor' and slower 'Reporter' on the given chunk **sequentially**.+-- | Rsun fast 'Acceptor' and slower 'Reporter' on the given  sequentially. -- The 'FilePath' is used for error reporting. -- When the acceptor does not return successfully, the result from the reporter -- is awaited.-runSeqChunkParser :: Chunk k => (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])-runSeqChunkParser = runSeqChunkParserWithOptions defaultReportOptions-{-# INLINE runSeqChunkParser #-}---- | Run parsers **in parallel** with additional 'ReportOptions'.-runChunkParserWithOptions :: Chunk k => ReportOptions -> (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])-runChunkParserWithOptions o p f b =-  let a = runAcceptor p f b-      r = runReporterWithOptions o p f b-  in case r `par` a of-       Left _  -> r-       Right x -> (Just x, [])-{-# INLINE runChunkParserWithOptions #-}+runParser :: Chunk k => (forall p. Parser k p => p a) -> FilePath -> k -> (Maybe a, [Report])+runParser = runParserWithOptions defaultReportOptions+{-# INLINE runParser #-}  -- | Run parsers **sequentially** with additional 'ReportOptions'.-runSeqChunkParserWithOptions :: Chunk k => ReportOptions -> (forall p. ChunkParser k p => p a) -> FilePath -> k -> (Maybe a, [Report])-runSeqChunkParserWithOptions o p f b =+runParserWithOptions :: Chunk k => ReportOptions -> (forall p. Parser k p => p a) -> FilePath -> k -> (Maybe a, [Report])+runParserWithOptions o p f b =   let a = runAcceptor p f b       r = runReporterWithOptions o p f b   in case a of-       Left _  -> r-       Right x -> (Just x, [])-{-# INLINE runSeqChunkParserWithOptions #-}+       Nothing  -> r+       Just x -> (Just x, [])+{-# INLINE runParserWithOptions #-}
− src/Text/PariPari/Internal/Tracer.hs
@@ -1,48 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeApplications #-}-module Text.PariPari.Internal.Tracer (-  Tracer(..)-  , runTracer-) where--import Data.Semigroup as Sem-import Data.String (IsString)-import Debug.Trace (trace)-import Text.PariPari.Internal.Chunk-import Text.PariPari.Internal.Class-import Text.PariPari.Internal.Reporter-import qualified Control.Monad.Fail as Fail---- | Parser which prints trace messages, when backtracking occurs.-newtype Tracer k a = Tracer { unTracer :: Reporter k a }-  deriving (Sem.Semigroup, Monoid, Functor, Applicative, MonadPlus, Monad, Fail.MonadFail)--deriving instance CharChunk k => ChunkParser k (Tracer k)-deriving instance CharChunk k => CharParser k (Tracer k)-deriving instance CharChunk k => IsString (Tracer k k)--instance Chunk k => Alternative (Tracer k) where-  empty = Tracer empty--  p1 <|> p2 = Tracer $ Reporter $ \env st ok err ->-    let err' s =-          let width = _stOff s -_stOff st-              next  = unReporter (unTracer p2) env (mergeErrorState env st s) ok err-          in if width > 1 then-               trace ("Backtracking " <> show width <> " bytes at line " <> show (_stLine s)-                       <> ", column " <> show (_stColumn s) <> ", context " <> show (_envContext env) <> ": "-                       <> showChunk (packChunk @k (_envBuf env) (_stOff st) width)) next-             else-               next-    in unReporter (unTracer p1) env st ok err'---- | Run 'Tracer' on the given chunk, returning the result--- if successful and reports from error recoveries.--- In the case of an error, 'Nothing' is returned and the 'Report' list--- is non-empty.-runTracer :: Chunk k => Tracer k a -> FilePath -> k -> (Maybe a, [Report])-runTracer = runReporter . unTracer
src/Text/PariPari/Lens.hs view
@@ -1,9 +1,9 @@ {-# LANGUAGE Rank2Types #-} module Text.PariPari.Lens (   posLine-  , posColumn+  , posCol   , reportLine-  , reportColumn+  , reportCol   , reportFile   , reportErrors   , ecErrors@@ -13,7 +13,6 @@   , optMaxLabelsPerContext ) where -import Text.PariPari.Internal.Chunk import Text.PariPari.Internal.Class import Text.PariPari.Internal.Reporter @@ -23,17 +22,17 @@ posLine k p = fmap (\x -> p { _posLine = x }) (k (_posLine p)) {-# INLINE posLine #-} -posColumn :: Lens Pos Int-posColumn k p = fmap (\x -> p { _posColumn = x }) (k (_posColumn p))-{-# INLINE posColumn #-}+posCol :: Lens Pos Int+posCol k p = fmap (\x -> p { _posCol = x }) (k (_posCol p))+{-# INLINE posCol #-}  reportLine :: Lens Report Int reportLine k r = fmap (\x -> r { _reportLine = x }) (k (_reportLine r)) {-# INLINE reportLine #-} -reportColumn :: Lens Report Int-reportColumn k r = fmap (\x -> r { _reportColumn = x }) (k (_reportColumn r))-{-# INLINE reportColumn #-}+reportCol :: Lens Report Int+reportCol k r = fmap (\x -> r { _reportCol = x }) (k (_reportCol r))+{-# INLINE reportCol #-}  reportFile :: Lens Report FilePath reportFile k r = fmap (\x -> r { _reportFile = x }) (k (_reportFile r))
test/test.hs view
@@ -9,7 +9,6 @@ import Data.ByteString (ByteString) import Data.Either (isLeft) import Data.Text (Text)-import GHC.Stack (HasCallStack) import Prelude hiding (getLine) import System.Random import Test.Tasty@@ -18,7 +17,11 @@ import Text.PariPari.Internal.Chunk (stringToChunk, asc_a, asc_0, asc_9) import qualified Data.Char as C import qualified Data.List.NonEmpty as NE+import Data.String (IsString(..)) +runAcceptor' :: Chunk k => Acceptor k a -> FilePath -> k -> Either Error a+runAcceptor' a f k = maybe (Left $ EFail "Nothing") Right $ runAcceptor a f k+ main :: IO () main = defaultMain tests @@ -55,31 +58,102 @@  tests :: TestTree tests = testGroup "Tests"-  [ testGroup "Chunk"-    [ testGroup "Acceptor" $ chunkTests runAcceptor-    , testGroup "Reporter" $ chunkTests runReporterEither+  [ testGroup "Acceptor"+    [ testGroup "Text"       $ parserTests @Text       runAcceptor'+    , testGroup "ByteString" $ parserTests @ByteString runAcceptor'     ] -  , testGroup "Char"-    [ testGroup "Acceptor"-      [ testGroup "Text"       $ charTests @Text       runAcceptor-      , testGroup "ByteString" $ charTests @ByteString runAcceptor-      ]--    , testGroup "Reporter"-      [ testGroup "Text"       $ charTests @Text       runReporterEither-      , testGroup "ByteString" $ charTests @ByteString runReporterEither-      ]+  , testGroup "Reporter"+    [ testGroup "Text"       $ parserTests @Text       runReporterEither+    , testGroup "ByteString" $ parserTests @ByteString runReporterEither     ]    , testGroup "Reporter specific" reporterTests   ] -charTests :: forall k p e. (CharParser k p, CharChunk k, Eq e, Show e, Show k)+parserTests :: forall k p e. (Parser k p, Chunk k, IsString k, Eq e, Show e, Show k)           => (forall a. p a -> FilePath -> k -> Either e a) -> [TestTree]-charTests run =-  [ testGroup "CharParser" $-    [ testCase "char" $ do+parserTests run =+  [ testGroup "ChunkParser"+    [ testCase "getFile" $ do+        ok getFile "" "filename"++    , testCase "getPos" $ do+        ok getPos "" (Pos 1 1)+        ok (char 'a' *> getPos) "abc" (Pos 1 2)+        ok (char 'a' *> char '\n' *> getPos) "a\nb" (Pos 2 1)+        ok (chunk "a\n" *> getPos) "a\nb" (Pos 1 3) -- chunk must not contain newlines!+        ok (char 'a' *> char '\n' *> char 'b' *> getPos) "a\nb" (Pos 2 2)++    , testCase "getRefPos" $ do+        ok getRefPos "" (Pos 1 1)+        ok (char 'a' *> getRefPos) "abc" (Pos 1 1)+        ok (char 'a' *> char '\n' *> withRefPos getRefPos) "a\nb" (Pos 2 1)+        ok (char 'a' *> char '\n' *> char 'b' *> withRefPos getRefPos) "a\nb" (Pos 2 2)+        ok (char 'a' *> char '\n' *> withRefPos (char 'b' *> getRefPos)) "a\nb" (Pos 2 1)++    , testCase "notFollowedBy" $ do+        ok (char 'a' <* notFollowedBy (char 'c')) "abc" 'a'+        err (char 'a' <* notFollowedBy (char 'b')) "abc"+        ok (char 'a' *> notFollowedBy (chunk "bd") *> char 'b') "abc" 'b'+        err (char 'a' *> notFollowedBy (chunk "bc")) "abc"+        ok (char 'a' *> notFollowedBy (char 'c') *> getPos) "abc" (Pos 1 2)++    , testCase "lookAhead" $ do+        ok (lookAhead (char 'a')) "abc" 'a'+        ok (lookAhead (char 'a') *> getPos) "abc" (Pos 1 1)+        ok (lookAhead (chunk "ab") *> getPos) "abc" (Pos 1 1)+        err (lookAhead (char 'b')) "abc"+        err (lookAhead (chunk "bd")) "abc"+        err (lookAhead (char 'a')) ""++    , testCase "failWith" $+        err (failWith (EFail "empty") :: p ()) "abc"++    , testCase "eof" $ do+        ok eof "" ()+        ok eof "\0" ()+        ok eof "\0\0" ()+        ok (chunk "abc" *> eof) "abc" ()+        ok (chunk "abc" *> eof) "abc\0" ()+        err eof "abc"+        err (chunk "ab" *> eof) "abc"++    , testCase "label" $ do+        ok (label "blub" $ char 'a') "abc" 'a'+        err (label "blub" $ char 'b') "abc"+        ok (char 'a' <?> "blub") "abc" 'a'++    , testCase "hidden" $ do+        ok (hidden $ char 'a') "abc" 'a'+        err (hidden $ char 'b') "abc"++    , testCase "try" $ do+        ok (try $ char 'a') "abc" 'a'+        err (try $ char 'b') "abc"++    , testCase "(<!>)" $ do+        ok (char 'b' <!> char 'a' <!> char 'c') "abc" 'a'+        ok (chunk "abd" <!> chunk "abc" <!> chunk "abe") "abcdef" "abc"++    , testCase "recover" $ do+        ok (recover (char 'a' <* eof) (char 'b')) "a" 'a'+        err (recover (char 'a') (char 'b')) "c"+        err (recover (char 'a' <* eof) (char 'b')) "c"++    , testCase "chunk" $ do+        ok (chunk "ab") "abc" "ab"+        err (chunk "bc") "abc"+        err (chunk "ab") ""++    , testCase "asChunk" $ do+        ok (asChunk (void $ chunk "ab")) "abc" "ab"+        ok (asChunk (void $ anyChar *> anyChar)) "abc" "ab"+        ok (asChunk (skipCount 2 anyChar)) "abc" "ab"+        err (asChunk (void $ chunk "bc")) "abc"+        err (asChunk (void $ chunk "ab")) ""++    , testCase "char" $ do         ok (char 'a') "abc" 'a'         ok (char 'a' <* eof) "a" 'a'         err (char 'b') "abc"@@ -121,6 +195,78 @@         ok (traverse (asciiByte . fromIntegral . C.ord) s *> eof) s ()     ] +  , testGroup "Alternative"+    [ testCase "(<|>)" $ do+        ok (char 'b' <|> char 'a' <|> char 'c') "abc" 'a'+        ok (chunk "abd" <|> chunk "abc" <|> chunk "abe") "abcdef" "abc"++    , testCase "empty" $ do+        err (empty :: p ()) "abc"+        err (empty :: p ()) ""+    ]++  , testGroup "MonadFail"+    [ testCase "fail" $ do+        err (failWith (EFail "empty") :: p ()) "abc"+    ]++  , testGroup "Basic Combinators"+    [ testCase "optional" $ do+        ok (optional (char 'a')) "abc" (Just 'a')+        ok (optional (char 'b')) "abc" Nothing+        ok (optional (char 'a')) "" Nothing++    , testCase "some" $ do+        ok (some (char 'a')) "abc" (NE.fromList "a")+        ok (some (char 'a')) "aabc" (NE.fromList "aa")+        err (some (char 'b')) "abc"+        err (some (char 'a')) ""++    , testCase "many" $ do+        ok (many (char 'a')) "abc" "a"+        ok (many (char 'a')) "aabc" "aa"+        ok (many (char 'b')) "abc" ""+        ok (many (char 'a')) "" ""+    ]++  , testGroup "Position Combinators"+    [ testCase "getLine" $ do+        ok getLine "" 1+        ok (char 'a' *> getLine) "abc" 1+        ok (char 'a' *> char '\n' *> getLine) "a\nb" 2+        ok (char 'a' *> char '\n' *> char 'b' *> getLine) "a\nb" 2++    , testCase "getRefLine" $ do+        ok getRefLine "" 1+        ok (char 'a' *> getRefLine) "abc" 1+        ok (char 'a' *> char '\n' *> withRefPos getRefLine) "a\nb" 2+        ok (char 'a' *> char '\n' *> char 'b' *> withRefPos getRefLine) "a\nb" 2+        ok (char 'a' *> char '\n' *> withRefPos (char 'b' *> getRefLine)) "a\nb" 2++    , testCase "getCol" $ do+        ok getCol "" 1+        ok (char 'a' *> getCol) "abc" 2+        ok (char 'a' *> char '\n' *> getCol) "a\nb" 1+        ok (char 'a' *> char '\n' *> char 'b' *> getCol) "a\nb" 2++    , testCase "getRefCol" $ do+        ok getRefCol "" 1+        ok (char 'a' *> getRefCol) "abc" 1+        ok (char 'a' *> char '\n' *> withRefPos getRefCol) "a\nb" 1+        ok (char 'a' *> char '\n' *> char 'b' *> withRefPos getRefCol) "a\nb" 2+        ok (char 'a' *> char '\n' *> withRefPos (char 'b' *> getRefCol)) "a\nb" 1++    , testCase "withPos" $ do+        ok (withPos $ char 'a') "abc" (Pos 1 1, 'a')+        ok (char 'a' *> withPos (char 'b')) "abc" (Pos 1 2, 'b')+        ok (char 'a' *> char '\n' *> withPos (char 'b')) "a\nb" (Pos 2 1, 'b')++    , testCase "withSpan" $ do+        ok (withSpan $ chunk "ab") "abc" (Pos 1 1, Pos 1 3, "ab")+        ok (char 'a' *> withSpan (chunk "bcd")) "abcde" (Pos 1 2, Pos 1 5, "bcd")+        ok (char 'a' *> char '\n' *> withSpan (chunk "bcd")) "a\nbcde" (Pos 2 1, Pos 2 4, "bcd")+    ]+   , testGroup "Char Combinators"     [ testCase "satisfy" $ do         ok (satisfy (== 'a')) "abc" 'a'@@ -415,256 +561,20 @@   okFraction :: HasCallStack => p (Either Integer (Integer, Int, Integer)) -> String -> Either Integer (Integer, Int, Integer) -> Assertion   okFraction = ok -chunkTests :: forall p e. (ChunkParser Text p, Eq e, Show e)-          => (forall a. p a -> FilePath -> Text -> Either e a) -> [TestTree]-chunkTests run =-  [ testGroup "ChunkParser"-    [ testCase "getFile" $ do-        ok getFile "" "filename"--    , testCase "getPos" $ do-        ok getPos "" (Pos 1 1)-        ok (element 'a' *> getPos) "abc" (Pos 1 2)-        ok (element 'a' *> element '\n' *> getPos) "a\nb" (Pos 2 1)-        ok (chunk "a\n" *> getPos) "a\nb" (Pos 1 3) -- chunk must not contain newlines!-        ok (element 'a' *> element '\n' *> element 'b' *> getPos) "a\nb" (Pos 2 2)--    , testCase "getRefPos" $ do-        ok getRefPos "" (Pos 1 1)-        ok (element 'a' *> getRefPos) "abc" (Pos 1 1)-        ok (element 'a' *> element '\n' *> withRefPos getRefPos) "a\nb" (Pos 2 1)-        ok (element 'a' *> element '\n' *> element 'b' *> withRefPos getRefPos) "a\nb" (Pos 2 2)-        ok (element 'a' *> element '\n' *> withRefPos (element 'b' *> getRefPos)) "a\nb" (Pos 2 1)--    , testCase "notFollowedBy" $ do-        ok (element 'a' <* notFollowedBy (element 'c')) "abc" 'a'-        err (element 'a' <* notFollowedBy (element 'b')) "abc"-        ok (element 'a' *> notFollowedBy (chunk "bd") *> element 'b') "abc" 'b'-        err (element 'a' *> notFollowedBy (chunk "bc")) "abc"-        ok (element 'a' *> notFollowedBy (element 'c') *> getPos) "abc" (Pos 1 2)--    , testCase "lookAhead" $ do-        ok (lookAhead (element 'a')) "abc" 'a'-        ok (lookAhead (element 'a') *> getPos) "abc" (Pos 1 1)-        ok (lookAhead (chunk "ab") *> getPos) "abc" (Pos 1 1)-        err (lookAhead (element 'b')) "abc"-        err (lookAhead (chunk "bd")) "abc"-        err (lookAhead (element 'a')) ""--    , testCase "failWith" $-        err (failWith (ECombinator "empty") :: p ()) "abc"--    , testCase "eof" $ do-        ok eof "" ()-        ok (chunk "abc" *> eof) "abc" ()-        err eof "abc"-        err eof "\0"-        err (chunk "ab" *> eof) "abc"--    , testCase "label" $ do-        ok (label "blub" $ element 'a') "abc" 'a'-        err (label "blub" $ element 'b') "abc"-        ok (element 'a' <?> "blub") "abc" 'a'--    , testCase "hidden" $ do-        ok (hidden $ element 'a') "abc" 'a'-        err (hidden $ element 'b') "abc"--    , testCase "commit" $ do-        ok (commit $ element 'a') "abc" 'a'-        err (commit $ element 'b') "abc"--    , testCase "recover" $ do-        ok (recover (element 'a' <* eof) (element 'b')) "a" 'a'-        err (recover (element 'a') (element 'b')) "c"-        err (recover (element 'a' <* eof) (element 'b')) "c"--    , testCase "element" $ do-        ok (element 'a') "abc" 'a'-        ok (element 'a' <* eof) "a" 'a'-        err (element 'b') "abc"-        err (element 'a') ""--        -- sentinel-        ok (element '\0') "\0" '\0'-        ok (element '\0' <* eof) "\0" '\0'-        err (element '\0') ""--    , testCase "elementScan" $ do-        ok (elementScan (\c -> if c == 'a' then Just c else Nothing)) "abc" 'a'-        ok (elementScan (\c -> if c == 'a' then Just c else Nothing) <* eof) "a" 'a'-        err (elementScan (\c -> if c == 'b' then Just c else Nothing)) "abc"-        err (elementScan Just) ""--        -- sentinel-        ok (elementScan (\c -> if c == '\0' then Just c else Nothing)) "\0" '\0'-        ok (elementScan (\c -> if c == '\0' then Just c else Nothing) <* eof) "\0" '\0'--    , testCase "chunk" $ do-        ok (chunk "ab") "abc" "ab"-        err (chunk "bc") "abc"-        err (chunk "ab") ""--    , testCase "asChunk" $ do-        ok (asChunk (void $ chunk "ab")) "abc" "ab"-        ok (asChunk (void $ anyElement *> anyElement)) "abc" "ab"-        ok (asChunk (skipCount 2 anyElement)) "abc" "ab"-        err (asChunk (void $ chunk "bc")) "abc"-        err (asChunk (void $ chunk "ab")) ""-    ]--  , testGroup "Position Combinators"-    [ testCase "getLine" $ do-        ok getLine "" 1-        ok (element 'a' *> getLine) "abc" 1-        ok (element 'a' *> element '\n' *> getLine) "a\nb" 2-        ok (element 'a' *> element '\n' *> element 'b' *> getLine) "a\nb" 2--    , testCase "getRefLine" $ do-        ok getRefLine "" 1-        ok (element 'a' *> getRefLine) "abc" 1-        ok (element 'a' *> element '\n' *> withRefPos getRefLine) "a\nb" 2-        ok (element 'a' *> element '\n' *> element 'b' *> withRefPos getRefLine) "a\nb" 2-        ok (element 'a' *> element '\n' *> withRefPos (element 'b' *> getRefLine)) "a\nb" 2--    , testCase "getColumn" $ do-        ok getColumn "" 1-        ok (element 'a' *> getColumn) "abc" 2-        ok (element 'a' *> element '\n' *> getColumn) "a\nb" 1-        ok (element 'a' *> element '\n' *> element 'b' *> getColumn) "a\nb" 2--    , testCase "getRefColumn" $ do-        ok getRefColumn "" 1-        ok (element 'a' *> getRefColumn) "abc" 1-        ok (element 'a' *> element '\n' *> withRefPos getRefColumn) "a\nb" 1-        ok (element 'a' *> element '\n' *> element 'b' *> withRefPos getRefColumn) "a\nb" 2-        ok (element 'a' *> element '\n' *> withRefPos (element 'b' *> getRefColumn)) "a\nb" 1--    , testCase "withPos" $ do-        ok (withPos $ element 'a') "abc" (Pos 1 1, 'a')-        ok (element 'a' *> withPos (element 'b')) "abc" (Pos 1 2, 'b')-        ok (element 'a' *> element '\n' *> withPos (element 'b')) "a\nb" (Pos 2 1, 'b')--    , testCase "withSpan" $ do-        ok (withSpan $ chunk "ab") "abc" ((Pos 1 1, Pos 1 3), "ab")-        ok (element 'a' *> withSpan (chunk "bcd")) "abcde" ((Pos 1 2, Pos 1 5), "bcd")-        ok (element 'a' *> element '\n' *> withSpan (chunk "bcd")) "a\nbcde" ((Pos 2 1, Pos 2 4), "bcd")-    ]--  , testGroup "Element Combinators"-    [ testCase "elementSatisfy" $ do-        ok (elementSatisfy (== 'a')) "abc" 'a'-        ok (elementSatisfy (== 'a') <* eof) "a" 'a'-        err (elementSatisfy (== 'b')) "abc"-        err (elementSatisfy (== 'a')) ""--        -- sentinel-        ok (elementSatisfy (== '\0')) "\0" '\0'-        ok (elementSatisfy (== '\0') <* eof) "\0" '\0'-        err (elementSatisfy (== '\0')) ""--    , testCase "anyElement" $ do-        ok anyElement "abc" 'a'-        err anyElement ""--    , testCase "notElement" $ do-        ok (notElement 'b') "abc" 'a'-        err (notElement 'a') "a"-        err (notElement 'a') ""--    , testCase "takeElementsWhile" $ do-        ok (takeElementsWhile (== 'a')) "" ""-        ok (takeElementsWhile (== 'a')) "b" ""-        ok (takeElementsWhile (== 'a') <* eof) "aaa" "aaa"-        ok (takeElementsWhile (== 'a') <* element 'b') "aaab" "aaa"--    , testCase "skipElements" $ do-        ok (skipElements 0) "" ()-        ok (skipElements 3 <* eof) "abc" ()-        ok (skipElements 3 <* element 'b') "aaab" ()-        err (skipElements 1) ""-        err (skipElements 2) "a"--    , testCase "takeElements" $ do-        ok (takeElements 0) "" ""-        ok (takeElements 3 <* eof) "abc" "abc"-        ok (takeElements 3 <* element 'b') "aaab" "aaa"-        err (takeElements 1) ""-        err (takeElements 2) "a"--    , testCase "skipElementsWhile" $ do-        ok (skipElementsWhile (== 'a')) "" ()-        ok (skipElementsWhile (== 'a')) "b" ()-        ok (skipElementsWhile (== 'a') *> eof) "aaa" ()-        ok (skipElementsWhile (== 'a') *> element 'b') "aaab" 'b'--    , testCase "skipElementsWhile1" $ do-        err (skipElementsWhile1 (== 'a')) ""-        err (skipElementsWhile1 (== 'a')) "b"-        ok (skipElementsWhile1 (== 'a') *> eof) "aaa" ()-        ok (skipElementsWhile1 (== 'a') *> element 'b') "aaab" 'b'--    , testCase "takeElementsWhile1" $ do-        err (takeElementsWhile1 (== 'a')) ""-        err (takeElementsWhile1 (== 'a')) "b"-        ok (takeElementsWhile1 (== 'a') <* eof) "aaa" "aaa"-        ok (takeElementsWhile1 (== 'a') <* element 'b') "aaab" "aaa"-    ]--  , testGroup "MonadFail"-    [ testCase "fail" $ do-        err (failWith (ECombinator "empty") :: p ()) "abc"-    ]--  , testGroup "Alternative"-    [ testCase "(<|>)" $ do-        ok (element 'b' <|> element 'a' <|> element 'c') "abc" 'a'-        ok (chunk "abd" <|> chunk "abc" <|> chunk "abe") "abcdef" "abc"--    , testCase "empty" $ do-        err (empty :: p ()) "abc"-        err (empty :: p ()) ""-    ]--  , testGroup "Basic Combinators"-    [ testCase "optional" $ do-        ok (optional (element 'a')) "abc" (Just 'a')-        ok (optional (element 'b')) "abc" Nothing-        ok (optional (element 'a')) "" Nothing--    , testCase "some" $ do-        ok (some (element 'a')) "abc" (NE.fromList "a")-        ok (some (element 'a')) "aabc" (NE.fromList "aa")-        err (some (element 'b')) "abc"-        err (some (element 'a')) ""--    , testCase "many" $ do-        ok (many (element 'a')) "abc" "a"-        ok (many (element 'a')) "aabc" "aa"-        ok (many (element 'b')) "abc" ""-        ok (many (element 'a')) "" ""-    ]-  ]-  where-  ok :: (Eq a, Show a, HasCallStack) => p a -> Text -> a -> Assertion-  ok p i o = run p "filename" i @?= Right o-  err :: (Eq a, Show a, HasCallStack) => p a -> Text -> Assertion-  err p i = assertBool "err" $ isLeft $ run p "filename" i- reporterTests :: [TestTree] reporterTests =   [ testCase "recover" $ do-      run (element 'a' <* eof) "a" (Just 'a', 0)-      run (element 'a') "b" (Nothing, 1)-      run (recover (element 'a' <* eof) (element 'b')) "a" (Just 'a', 0)-      run (recover (element 'a') (element 'b')) "b" (Just 'b', 1)+      run (char 'a' <* eof) "a" (Just 'a', 0)+      run (char 'a') "b" (Nothing, 1)+      run (recover (char 'a' <* eof) (char 'b')) "a" (Just 'a', 0)+      run (recover (char 'a') (char 'b')) "b" (Just 'b', 1)       run ((,)-            <$> recover (element 'a') (element 'b')-            <*> recover (element 'a') (element 'c')) "bc" (Just ('b', 'c'), 2)-      run (recover (element 'a') (element 'b') *>-           recover (element 'a') (element 'c') *>-           element 'a') "bcd" (Nothing, 3)-      run (recover (element 'a' <* eof) (element 'b')) "c" (Nothing, 1)+            <$> recover (char 'a') (char 'b')+            <*> recover (char 'a') (char 'c')) "bc" (Just ('b', 'c'), 2)+      run (recover (char 'a') (char 'b') *>+           recover (char 'a') (char 'c') *>+           char 'a') "bcd" (Nothing, 3)+      run (recover (char 'a' <* eof) (char 'b')) "c" (Nothing, 1)   ]   where   run :: (Eq a, Show a, HasCallStack) => Reporter Text a -> Text -> (Maybe a, Int) -> Assertion@@ -716,10 +626,6 @@ Fraction: fraction fractionHex--Element Combinators:-scanElements-scanElements1  Char Combinators: scanChars