module Text.PariPari.Class ( MonadParser(..) , Parser , Alternative(..) , MonadPlus , Pos(..) , Error(..) , ByteString , Word8 , showError ) where import Control.Applicative (Alternative(empty, (<|>))) import Control.Monad (MonadPlus(..)) import Control.Monad.Fail (MonadFail(..)) import Data.ByteString (ByteString) import Data.List (intercalate) import Data.Word (Word8) import GHC.Generics (Generic) -- | Line and column position starting at (1,1) data Pos = Pos { _posLine :: !Int , _posColumn :: !Int } deriving (Eq, Show, Generic) -- | Parsing errors data Error = EEmpty | EInvalidUtf8 | EExpectedEnd | EExpected [String] | EUnexpected String | EFail String | ECombinator String | EIndentNotAligned !Int !Int | EIndentOverLine !Int !Int | ENotEnoughIndent !Int !Int deriving (Eq, Ord, Show, Generic) -- | Parser shortcut type Parser a = (forall p. MonadParser p => p a) -- | Parser class, which specifies the necessary -- primitives for parsing. All other parser combinators -- rely on these primitives. class (MonadFail p, MonadPlus p) => MonadParser p where -- | Get file name associated with current parser getFile :: p FilePath -- | Get current position of the parser getPos :: p Pos -- | Get reference position used for indentation-sensitive parsing getRefPos :: p Pos -- | Update reference position with current position withRefPos :: p a -> p a -- | Parser which succeeds when the given parser fails notFollowedBy :: Show a => p a -> p () -- | Look ahead and return result of the given parser -- The current position stays the same. lookAhead :: p a -> p a -- | Parser failure with detailled 'Error' failWith :: Error -> p a -- | Parser which succeeds at the end of file eof :: p () -- | Annotate the given parser with a label -- used for error reporting label :: String -> p a -> p a -- | Hide errors occurring within the given parser -- from the error report. Based on the given -- labels an 'Error' is constructed instead. 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). -- -- __Note__: `commit` only applies to the reported -- errors, it has no effect on the backtracking behavior -- of the parser. commit :: p a -> p a -- | Parse a single byte byte :: Word8 -> p Word8 -- | Parse a single UTF-8 character char :: Char -> p Char -- | Parse a single character with the given predicate satisfy :: (Char -> Bool) -> p Char -- | Parse a single byte with the given predicate byteSatisfy :: (Word8 -> Bool) -> p Word8 -- | Parse a string of bytes bytes :: ByteString -> p ByteString -- | Run the given parser and return the -- result as bytes asBytes :: p () -> p ByteString -- | Pretty string representation of 'Error' showError :: Error -> String showError EEmpty = "No error" showError EInvalidUtf8 = "Invalid UTF-8 character found" showError EExpectedEnd = "Expected end of file" 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) = "Not enough indentation, expected column " <> show rc <> ", got " <> show c