module Data.Textual
(
Printable(..)
, maybePrint
, toString
, toText
, toLazyText
, toAscii
, toLazyAscii
, toUtf8
, toLazyUtf8
, Textual(..)
, Parsed(..)
, isParsed
, isMalformed
, maybeParsed
, builtInParser
, parseString
, parseStringAs
, parseText
, parseTextAs
, parseLazyText
, parseLazyTextAs
, parseAscii
, parseAsciiAs
, parseLazyAscii
, parseLazyAsciiAs
, parseUtf8
, parseUtf8As
, parseLazyUtf8
, parseLazyUtf8As
, fromString
, fromStringAs
, fromText
, fromTextAs
, fromLazyText
, fromLazyTextAs
, fromAscii
, fromAsciiAs
, fromLazyAscii
, fromLazyAsciiAs
, fromUtf8
, fromUtf8As
, fromLazyUtf8
, fromLazyUtf8As
) where
import Prelude hiding (print)
import Data.Typeable (Typeable)
import Data.Foldable (Foldable)
import Data.Traversable (Traversable)
import Data.Monoid (mempty)
import Data.Int
import Data.Word
import Data.Ratio (Ratio)
import Data.Fixed (Fixed, HasResolution)
import Data.List (stripPrefix)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Lazy.Char8 as BL8
import qualified Data.Text as TS
import qualified Data.Text.Lazy as TL
import Data.Text.Lazy.Encoding (decodeUtf8)
import Data.Textual.Integral
import Data.Textual.Fractional
import Control.Applicative
import qualified Text.Printer as TP
import qualified Text.Printer.Integral as TP
import qualified Text.Printer.Fractional as TP
import Text.Parser.Combinators (Parsing, (<?>))
import qualified Text.Parser.Combinators as PC
import Text.Parser.Char (CharParsing)
import qualified Text.Parser.Char as PC
class Printable α where
print ∷ TP.Printer p ⇒ α → p
instance Printable Char where
print = TP.char
instance Printable String where
print = TP.string
instance Printable TS.Text where
print = TP.text
instance Printable TL.Text where
print = TP.lazyText
instance Printable Integer where
print = TP.decimal
instance Printable Int where
print = TP.decimal
instance Printable Int8 where
print = TP.decimal
instance Printable Int16 where
print = TP.decimal
instance Printable Int32 where
print = TP.decimal
instance Printable Int64 where
print = TP.decimal
instance Printable Word where
print = TP.nnDecimal
instance Printable Word8 where
print = TP.nnDecimal
instance Printable Word16 where
print = TP.nnDecimal
instance Printable Word32 where
print = TP.nnDecimal
instance Printable Word64 where
print = TP.nnDecimal
instance Integral α ⇒ Printable (Ratio α) where
print = TP.fraction
instance HasResolution α ⇒ Printable (Fixed α) where
print = TP.string7 . show
instance Printable Float where
print = TP.string7 . show
instance Printable Double where
print = TP.string7 . show
maybePrint ∷ (TP.Printer p, Printable α) ⇒ Maybe α → p
maybePrint = maybe mempty print
toString ∷ Printable α ⇒ α → String
toString = TP.buildString . print
toText ∷ Printable α ⇒ α → TS.Text
toText = TP.buildText . print
toLazyText ∷ Printable α ⇒ α → TL.Text
toLazyText = TP.buildLazyText . print
toAscii ∷ Printable α ⇒ α → BS.ByteString
toAscii = TP.buildAscii . print
toLazyAscii ∷ Printable α ⇒ α → BL.ByteString
toLazyAscii = TP.buildLazyAscii . print
toUtf8 ∷ Printable α ⇒ α → BS.ByteString
toUtf8 = TP.buildUtf8 . print
toLazyUtf8 ∷ Printable α ⇒ α → BL.ByteString
toLazyUtf8 = TP.buildLazyUtf8 . print
class Printable α ⇒ Textual α where
textual ∷ (Monad μ, CharParsing μ) ⇒ μ α
instance Textual Char where
textual = PC.anyChar
instance Textual Integer where
textual = number Decimal
instance Textual Int where
textual = bounded Decimal
instance Textual Int8 where
textual = bounded Decimal
instance Textual Int16 where
textual = bounded Decimal
instance Textual Int32 where
textual = bounded Decimal
instance Textual Int64 where
textual = bounded Decimal
instance Textual Word where
textual = nnBounded Decimal
instance Textual Word8 where
textual = nnBounded Decimal
instance Textual Word16 where
textual = nnBounded Decimal
instance Textual Word32 where
textual = nnBounded Decimal
instance Textual Word64 where
textual = nnBounded Decimal
instance Integral α ⇒ Textual (Ratio α) where
textual = fraction
instance HasResolution α ⇒ Textual (Fixed α) where
textual = fractional
data Parsed α = Parsed α
| Malformed [String] String
deriving (Typeable, Functor, Foldable, Traversable, Eq, Show)
instance Applicative Parsed where
pure = Parsed
Parsed f <*> Parsed a = Parsed (f a)
Malformed ls e <*> _ = Malformed ls e
_ <*> Malformed ls e = Malformed ls e
instance Alternative Parsed where
empty = Malformed [] "Alternative.empty"
p@(Parsed _) <|> _ = p
_ <|> p = p
isParsed ∷ Parsed α → Bool
isParsed (Parsed _) = True
isParsed _ = False
isMalformed ∷ Parsed α → Bool
isMalformed (Malformed _ _) = True
isMalformed _ = False
maybeParsed ∷ Parsed α → Maybe α
maybeParsed (Parsed a) = Just a
maybeParsed _ = Nothing
data Parser α =
Parser { runParser ∷ ∀ r
. [String] → Word → String
→ ([String] → Word → String → α → Parsed r)
→ ([String] → Word → String → String → Parsed r)
→ Parsed r }
instance Functor Parser where
fmap f p = Parser $ \ls n i c h →
runParser p ls n i (\ls' n' i' a → c ls' n' i' (f a)) h
instance Applicative Parser where
pure a = Parser $ \ls n i c _ → c ls n i a
p <*> p' = Parser $ \ls n i c h →
runParser p ls n i
(\ls' n' i' f →
runParser p' ls' n' i'
(\ls'' n'' i'' a → c ls'' n'' i'' (f a)) h)
h
p *> p' = Parser $ \ls n i c h →
runParser p ls n i (\ls' n' i' _ → runParser p' ls' n' i' c h) h
p <* p' = Parser $ \ls n i c h →
runParser p ls n i
(\ls' n' i' a →
runParser p' ls' n' i'
(\ls'' n'' i'' _ → c ls'' n'' i'' a) h)
h
instance Alternative Parser where
empty = PC.unexpected "Alternative.empty"
p <|> p' = Parser $ \ls n i c h →
runParser p ls n i c $ \ls' n' i' e →
if n' == n then runParser p' ls n' i' c h
else h ls' n' i' e
instance Parsing Parser where
try p = Parser $ \ls n i c h →
runParser p ls n i c (\ls' _ _ e → h ls' n i e)
p <?> l = Parser $ \ls n i c h →
runParser p (l : ls) n i (\_ n' i' a → c ls n' i' a) h
skipMany p = Parser $ \ls n i c h →
runParser p ls n i
(\ls' n' i' _ → runParser (PC.skipMany p) ls' n' i' c h)
(\ls' n' i' _ → c ls' n' i' ())
skipSome p = p *> PC.skipMany p
unexpected e = Parser $ \ls n i _ h → h ls n i e
eof = Parser $ \ls n i c h → case i of
[] → c ls n i ()
_ → h ls n i "Parsing.eof"
notFollowedBy p = Parser $ \ls n i c h →
runParser p ls n i
(\_ _ _ _ → h ls n i "Parsing.notFollowedBy")
(\_ _ _ _ → c ls n i ())
instance CharParsing Parser where
satisfy f = Parser $ \ls n i c h → case i of
x : xs | f x → c ls n' xs x
where !n' = n + 1
_ → h ls n i "CharParsing.satisfy"
string s = Parser $ \ls n i c h → case stripPrefix s i of
Just i' → c ls n' i' s
where !n' = n + fromIntegral (length s)
Nothing → h ls n i "CharParsing.string"
instance Monad Parser where
return = pure
p >>= f = Parser $ \ls n i c h →
runParser p ls n i
(\ls' n' i' a → runParser (f a) ls' n' i' c h) h
(>>) = (*>)
fail = PC.unexpected
parse ∷ Parser α → String → Parsed α
parse p i = runParser p [] 0 i (\_ _ _ a → Parsed a)
(\ls _ _ e → Malformed (reverse ls) e)
builtInParser ∷ (∀ μ . (Monad μ, CharParsing μ) ⇒ μ α) → String → Parsed α
builtInParser p = parse p
parseString ∷ Textual α ⇒ String → Parsed α
parseString = parse $ textual <* PC.eof
parseStringAs ∷ Textual α ⇒ p α → String → Parsed α
parseStringAs _ = parseString
parseText ∷ Textual α ⇒ TS.Text → Parsed α
parseText = parseString . TS.unpack
parseTextAs ∷ Textual α ⇒ p α → TS.Text → Parsed α
parseTextAs _ = parseText
parseLazyText ∷ Textual α ⇒ TL.Text → Parsed α
parseLazyText = parseString . TL.unpack
parseLazyTextAs ∷ Textual α ⇒ p α → TL.Text → Parsed α
parseLazyTextAs _ = parseLazyText
parseAscii ∷ Textual α ⇒ BS.ByteString → Parsed α
parseAscii = parseString . BS8.unpack
parseAsciiAs ∷ Textual α ⇒ p α → BS.ByteString → Parsed α
parseAsciiAs _ = parseAscii
parseLazyAscii ∷ Textual α ⇒ BL.ByteString → Parsed α
parseLazyAscii = parseString . BL8.unpack
parseLazyAsciiAs ∷ Textual α ⇒ BL.ByteString → Parsed α
parseLazyAsciiAs = parseString . BL8.unpack
parseUtf8 ∷ Textual α ⇒ BS.ByteString → Parsed α
parseUtf8 = parseLazyText . decodeUtf8 . BL.fromStrict
parseUtf8As ∷ Textual α ⇒ p α → BS.ByteString → Parsed α
parseUtf8As _ = parseUtf8
parseLazyUtf8 ∷ Textual α ⇒ BL.ByteString → Parsed α
parseLazyUtf8 = parseLazyText . decodeUtf8
parseLazyUtf8As ∷ Textual α ⇒ p α → BL.ByteString → Parsed α
parseLazyUtf8As _ = parseLazyUtf8
fromString ∷ Textual α ⇒ String → Maybe α
fromString = maybeParsed . parseString
fromStringAs ∷ Textual α ⇒ p α → String → Maybe α
fromStringAs _ = fromString
fromText ∷ Textual α ⇒ TS.Text → Maybe α
fromText = maybeParsed . parseText
fromTextAs ∷ Textual α ⇒ p α → TS.Text → Maybe α
fromTextAs _ = fromText
fromLazyText ∷ Textual α ⇒ TL.Text → Maybe α
fromLazyText = maybeParsed . parseLazyText
fromLazyTextAs ∷ Textual α ⇒ p α → TL.Text → Maybe α
fromLazyTextAs _ = fromLazyText
fromAscii ∷ Textual α ⇒ BS.ByteString → Maybe α
fromAscii = maybeParsed . parseAscii
fromAsciiAs ∷ Textual α ⇒ p α → BS.ByteString → Maybe α
fromAsciiAs _ = fromAscii
fromLazyAscii ∷ Textual α ⇒ BL.ByteString → Maybe α
fromLazyAscii = maybeParsed . parseLazyAscii
fromLazyAsciiAs ∷ Textual α ⇒ p α → BL.ByteString → Maybe α
fromLazyAsciiAs _ = fromLazyAscii
fromUtf8 ∷ Textual α ⇒ BS.ByteString → Maybe α
fromUtf8 = maybeParsed . parseUtf8
fromUtf8As ∷ Textual α ⇒ p α → BS.ByteString → Maybe α
fromUtf8As _ = fromUtf8
fromLazyUtf8 ∷ Textual α ⇒ BL.ByteString → Maybe α
fromLazyUtf8 = maybeParsed . parseLazyUtf8
fromLazyUtf8As ∷ Textual α ⇒ p α → BL.ByteString → Maybe α
fromLazyUtf8As _ = fromLazyUtf8