{-| Lower-level parsers, which avoid overriding the native Attoparsec names. -} module Attoparsec.Data.Parsers where import Attoparsec.Data.Prelude hiding (bool) import Data.Attoparsec.Text import qualified GHC.Show import qualified Data.Text as Text {-| Parse the output of the 'show' function applied to 'String' or 'Text' into what was used for its input. -} show :: Parser Text show = char '"' *> body <* char '"' where body = mconcat <$> many chunk where chunk = escaped <|> nonEscaped nonEscaped = takeWhile1 (\ a -> a /= '\\' && a /= '"') escaped = Text.singleton <$> escapedChar -- https://hackage.haskell.org/package/base-4.14.0.0/docs/src/GHC.Show.html#showLitChar escapedChar :: Parser Char escapedChar = char '\\' *> escapedCharBody escapedCharBody :: Parser Char escapedCharBody = char '\\' <|> char 'a' $> '\a' <|> char 'b' $> '\b' <|> char 'f' $> '\f' <|> char 'n' $> '\n' <|> char 'r' $> '\r' <|> char 't' $> '\t' <|> char 'v' $> '\v' <|> string "DEL" $> '\DEL' <|> ordEscapedCharBody <|> asciiTabEscapedCharBody asciiTabEscapedCharBody :: Parser Char asciiTabEscapedCharBody = zipWith asciiTabChar [0..] GHC.Show.asciiTab & asum where asciiTabChar index chars = string (fromString chars) $> chr index ordEscapedCharBody :: Parser Char ordEscapedCharBody = chr <$> decimal