{-# LANGUAGE OverloadedStrings, CPP #-}

-- | The /LaTeX/ parser.
-- 
--   Use 'parseLaTeX' to parse a 'Text' containing /LaTeX/ code.
--   If the 'Text' is in a file, you may want to use 'parseLaTeXFile'.
--   Use this module together with "Text.LaTeX.Base.Syntax" to perform
--   analysis and transformations of /LaTeX/ code. The parser ('parseLaTeX')
--   is related with the renderer ('render') by the following property:
--
--   /If @t :: Text@ is a syntactically valid LaTeX block, then:/
--
-- > fmap render (parseLaTeX t) == Right t
-- 
--   This property says two things:
--
-- * Given a valid LaTeX input, 'parseLaTeX' returns a 'LaTeX' value.
-- * If the parsed value is again rendered, you get the initial input.
--
--   In other words, 'parseLaTeX' is a partial function defined over the
--   set of valid LaTeX files, and 'render' is its /left/ inverse.
--
module Text.LaTeX.Base.Parser (
    -- * The parser
    parseLaTeX
  , parseLaTeXFile
    -- * Parsing errors
  , ParseError
  , errorPos
  , errorMessages
    -- ** Error messages
  , Message (..)
  , messageString
    -- ** Source positions
  , SourcePos
  , sourceLine
  , sourceColumn
  , sourceName
    -- * Configuring your parser
  , ParserConf (..)
  , defaultParserConf
  , parseLaTeXWith
  , parseLaTeXFileWith
    -- * Parser combinators
  , Parser
  , latexParser
  , latexBlockParser
    ) where

import           Text.Parsec hiding ((<|>),many)
import           Text.Parsec.Error
import           Data.Char (toLower,digitToInt)
import           Data.Functor(($>))
#if !MIN_VERSION_base(4,11,0)
import           Data.Monoid
#endif
import           Data.Maybe (fromMaybe)
import           Data.Set(Set, fromList, member)
import qualified Data.Text as T 

import           Control.Applicative
import           Control.Monad (unless)

import           Text.LaTeX.Base.Syntax
import           Text.LaTeX.Base.Render

------------------------------------------------------------------------
-- Parser configuration
------------------------------------------------------------------------

-- | Configuration for the LaTeX parser.
newtype ParserConf = ParserConf
  { -- | This is the list of names of the environments such that
    --   their content will be parsed verbatim.
    ParserConf -> [String]
verbatimEnvironments :: [String]
    }

-- | Default parser configuration, used by 'parseLaTeX' and 'parseLaTeXFile'.
--
--   Defaults:
--
-- > verbatimEnvironments = ["verbatim"]
--
defaultParserConf :: ParserConf
defaultParserConf :: ParserConf
defaultParserConf = ParserConf :: [String] -> ParserConf
ParserConf
  { verbatimEnvironments :: [String]
verbatimEnvironments = [String
"verbatim"]
    }

-- | Parser with 'Text' input and 'ParserConf' environment.
type Parser = Parsec Text ParserConf

------------------------------------------------------------------------
-- Parser
------------------------------------------------------------------------

-- | Parse a 'Text' sequence as a 'LaTeX' block. If it fails, it returns
--   an error string.
parseLaTeX :: Text -> Either ParseError LaTeX
parseLaTeX :: Text -> Either ParseError LaTeX
parseLaTeX = ParserConf -> Text -> Either ParseError LaTeX
parseLaTeXWith ParserConf
defaultParserConf

parseLaTeXWith :: ParserConf -> Text -> Either ParseError LaTeX
parseLaTeXWith :: ParserConf -> Text -> Either ParseError LaTeX
parseLaTeXWith ParserConf
conf Text
t
  | Text -> Bool
T.null Text
t  = LaTeX -> Either ParseError LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return LaTeX
TeXEmpty
  | Bool
otherwise = Parsec Text ParserConf LaTeX
-> ParserConf -> String -> Text -> Either ParseError LaTeX
forall s t u a.
Stream s Identity t =>
Parsec s u a -> u -> String -> s -> Either ParseError a
runParser Parsec Text ParserConf LaTeX
latexParser ParserConf
conf String
"parseLaTeX input" Text
t

-- | Read a file and parse it as 'LaTeX'.
parseLaTeXFile :: FilePath -> IO (Either ParseError LaTeX)
parseLaTeXFile :: String -> IO (Either ParseError LaTeX)
parseLaTeXFile = ParserConf -> String -> IO (Either ParseError LaTeX)
parseLaTeXFileWith ParserConf
defaultParserConf

parseLaTeXFileWith :: ParserConf -> FilePath -> IO (Either ParseError LaTeX)
parseLaTeXFileWith :: ParserConf -> String -> IO (Either ParseError LaTeX)
parseLaTeXFileWith ParserConf
conf String
fp = Parsec Text ParserConf LaTeX
-> ParserConf -> String -> Text -> Either ParseError LaTeX
forall s t u a.
Stream s Identity t =>
Parsec s u a -> u -> String -> s -> Either ParseError a
runParser Parsec Text ParserConf LaTeX
latexParser ParserConf
conf String
fp (Text -> Either ParseError LaTeX)
-> IO Text -> IO (Either ParseError LaTeX)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO Text
readFileTex String
fp

-- | The 'LaTeX' parser.
latexParser :: Parser LaTeX
latexParser :: Parsec Text ParserConf LaTeX
latexParser = [LaTeX] -> LaTeX
forall a. Monoid a => [a] -> a
mconcat ([LaTeX] -> LaTeX)
-> ParsecT Text ParserConf Identity [LaTeX]
-> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parsec Text ParserConf LaTeX
latexBlockParser Parsec Text ParserConf LaTeX
-> ParsecT Text ParserConf Identity ()
-> ParsecT Text ParserConf Identity [LaTeX]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
`manyTill` ParsecT Text ParserConf Identity ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
eof

-- | Parser of a single 'LaTeX' constructor, no appending blocks.
latexBlockParser :: Parser LaTeX
latexBlockParser :: Parsec Text ParserConf LaTeX
latexBlockParser = (Parsec Text ParserConf LaTeX
 -> Parsec Text ParserConf LaTeX -> Parsec Text ParserConf LaTeX)
-> [Parsec Text ParserConf LaTeX] -> Parsec Text ParserConf LaTeX
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 Parsec Text ParserConf LaTeX
-> Parsec Text ParserConf LaTeX -> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
(<|>)
  [ Parsec Text ParserConf LaTeX
text            Parsec Text ParserConf LaTeX
-> String -> Parsec Text ParserConf LaTeX
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"text"
  , Parsec Text ParserConf LaTeX
dolMath         Parsec Text ParserConf LaTeX
-> String -> Parsec Text ParserConf LaTeX
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"inline math ($)"
  , Parsec Text ParserConf LaTeX
comment         Parsec Text ParserConf LaTeX
-> String -> Parsec Text ParserConf LaTeX
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"comment"
  , Parsec Text ParserConf LaTeX
text2           Parsec Text ParserConf LaTeX
-> String -> Parsec Text ParserConf LaTeX
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"text2"
  , Parsec Text ParserConf LaTeX -> Parsec Text ParserConf LaTeX
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try Parsec Text ParserConf LaTeX
environment Parsec Text ParserConf LaTeX
-> String -> Parsec Text ParserConf LaTeX
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"environment"
  , Parsec Text ParserConf LaTeX
command         Parsec Text ParserConf LaTeX
-> String -> Parsec Text ParserConf LaTeX
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"command"
    ]
-- Note: text stops on ']'; if the other parsers fail on the rest
--       text2 handles it, starting with ']' 

------------------------------------------------------------------------
-- Text
------------------------------------------------------------------------
nottext :: Set Char
nottext :: Set Char
nottext = String -> Set Char
forall a. Ord a => [a] -> Set a
fromList String
"$%\\{]}"

text :: Parser LaTeX
text :: Parsec Text ParserConf LaTeX
text = do
  Maybe Char
mbC <- Parser (Maybe Char)
peekChar
  case Maybe Char
mbC of
    Maybe Char
Nothing -> String -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"text: Empty input."
    Just Char
c | Char
c Char -> Set Char -> Bool
forall a. Ord a => a -> Set a -> Bool
`member` Set Char
nottext -> String -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"not text"
           | Bool
otherwise          -> Text -> LaTeX
TeXRaw (Text -> LaTeX)
-> ParsecT Text ParserConf Identity Text
-> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> ParsecT Text ParserConf Identity Text
takeTill (Char -> Set Char -> Bool
forall a. Ord a => a -> Set a -> Bool
`member` Set Char
nottext)

------------------------------------------------------------------------
-- Text without stopping on ']'
------------------------------------------------------------------------
text2 :: Parser LaTeX
text2 :: Parsec Text ParserConf LaTeX
text2 = do
  Char
_ <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
']'
  LaTeX
t <- Parsec Text ParserConf LaTeX -> Parsec Text ParserConf LaTeX
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Parsec Text ParserConf LaTeX
text Parsec Text ParserConf LaTeX
-> Parsec Text ParserConf LaTeX -> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> LaTeX
TeXRaw Text
T.empty))
  LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (LaTeX -> Parsec Text ParserConf LaTeX)
-> LaTeX -> Parsec Text ParserConf LaTeX
forall a b. (a -> b) -> a -> b
$ Text -> LaTeX
TeXRaw (String -> Text
T.pack String
"]") LaTeX -> LaTeX -> LaTeX
forall a. Semigroup a => a -> a -> a
<> LaTeX
t

------------------------------------------------------------------------
-- Environment
------------------------------------------------------------------------
environment :: Parser LaTeX
environment :: Parsec Text ParserConf LaTeX
environment = Parsec Text ParserConf LaTeX
anonym Parsec Text ParserConf LaTeX
-> Parsec Text ParserConf LaTeX -> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parsec Text ParserConf LaTeX
env

anonym :: Parser LaTeX
anonym :: Parsec Text ParserConf LaTeX
anonym = do
  Char
_ <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'{'
  LaTeX
l <- LaTeX -> LaTeX
TeXBraces (LaTeX -> LaTeX) -> ([LaTeX] -> LaTeX) -> [LaTeX] -> LaTeX
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [LaTeX] -> LaTeX
forall a. Monoid a => [a] -> a
mconcat ([LaTeX] -> LaTeX)
-> ParsecT Text ParserConf Identity [LaTeX]
-> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parsec Text ParserConf LaTeX
-> ParsecT Text ParserConf Identity [LaTeX]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parsec Text ParserConf LaTeX
latexBlockParser
  Char
_ <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'}'
  LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return LaTeX
l

env :: Parser LaTeX
env :: Parsec Text ParserConf LaTeX
env = do
  String
n  <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\\' ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> String -> ParsecT Text ParserConf Identity String
envName String
"begin"
  String
sps <- ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (ParsecT Text ParserConf Identity Char
 -> ParsecT Text ParserConf Identity String)
-> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity String
forall a b. (a -> b) -> a -> b
$ Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
' '
  let lsps :: LaTeX
lsps = if String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
sps then LaTeX
forall a. Monoid a => a
mempty else Text -> LaTeX
TeXRaw (Text -> LaTeX) -> Text -> LaTeX
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack String
sps
  Maybe [TeXArg]
as <- Parser (Maybe [TeXArg])
cmdArgs
  [String]
verbatims <- ParserConf -> [String]
verbatimEnvironments (ParserConf -> [String])
-> ParsecT Text ParserConf Identity ParserConf
-> ParsecT Text ParserConf Identity [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Text ParserConf Identity ParserConf
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
  if String
n String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
verbatims
     then let endenv :: ParsecT Text ParserConf Identity String
endenv = ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (ParsecT Text ParserConf Identity String
 -> ParsecT Text ParserConf Identity String)
-> ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity String
forall a b. (a -> b) -> a -> b
$ String -> ParsecT Text ParserConf Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"\\end" ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity ()
-> ParsecT Text ParserConf Identity ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT Text ParserConf Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces ParsecT Text ParserConf Identity ()
-> ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ParsecT Text ParserConf Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string (String
"{" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
n String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"}")
          in  String -> [TeXArg] -> LaTeX -> LaTeX
TeXEnv String
n ([TeXArg] -> Maybe [TeXArg] -> [TeXArg]
forall a. a -> Maybe a -> a
fromMaybe [] Maybe [TeXArg]
as) (LaTeX -> LaTeX) -> (String -> LaTeX) -> String -> LaTeX
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> LaTeX
TeXRaw (Text -> LaTeX) -> (String -> Text) -> String -> LaTeX
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> LaTeX)
-> ParsecT Text ParserConf Identity String
-> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity String
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar ParsecT Text ParserConf Identity String
endenv
     else do LaTeX
b <- String -> Parsec Text ParserConf LaTeX
envBody String
n 
             LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (LaTeX -> Parsec Text ParserConf LaTeX)
-> LaTeX -> Parsec Text ParserConf LaTeX
forall a b. (a -> b) -> a -> b
$ String -> [TeXArg] -> LaTeX -> LaTeX
TeXEnv String
n ([TeXArg] -> Maybe [TeXArg] -> [TeXArg]
forall a. a -> Maybe a -> a
fromMaybe [] Maybe [TeXArg]
as) (LaTeX -> LaTeX) -> LaTeX -> LaTeX
forall a b. (a -> b) -> a -> b
$
               case Maybe [TeXArg]
as of
                Just [] -> LaTeX
lsps LaTeX -> LaTeX -> LaTeX
forall a. Semigroup a => a -> a -> a
<> LaTeX -> LaTeX
TeXBraces LaTeX
forall a. Monoid a => a
mempty LaTeX -> LaTeX -> LaTeX
forall a. Semigroup a => a -> a -> a
<> LaTeX
b
                Maybe [TeXArg]
Nothing -> LaTeX
lsps LaTeX -> LaTeX -> LaTeX
forall a. Semigroup a => a -> a -> a
<> LaTeX
b
                Maybe [TeXArg]
_ -> LaTeX
b

envName :: String -> Parser String
envName :: String -> ParsecT Text ParserConf Identity String
envName String
k = do
  String
_ <- String -> ParsecT Text ParserConf Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
k
  Char
_ <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'{'
  Text
n <- (Char -> Bool) -> ParsecT Text ParserConf Identity Text
takeTill (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'}')
  Char
_ <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'}'
  String -> ParsecT Text ParserConf Identity String
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> ParsecT Text ParserConf Identity String)
-> String -> ParsecT Text ParserConf Identity String
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
n

envBody :: String -> Parser LaTeX
envBody :: String -> Parsec Text ParserConf LaTeX
envBody String
n = [LaTeX] -> LaTeX
forall a. Monoid a => [a] -> a
mconcat ([LaTeX] -> LaTeX)
-> ParsecT Text ParserConf Identity [LaTeX]
-> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Parsec Text ParserConf LaTeX
bodyBlock String
n Parsec Text ParserConf LaTeX
-> ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity [LaTeX]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
`manyTill` ParsecT Text ParserConf Identity String
endenv
  where endenv :: ParsecT Text ParserConf Identity String
endenv = ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (ParsecT Text ParserConf Identity String
 -> ParsecT Text ParserConf Identity String)
-> ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity String
forall a b. (a -> b) -> a -> b
$ String -> ParsecT Text ParserConf Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"\\end" ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity ()
-> ParsecT Text ParserConf Identity ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT Text ParserConf Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces ParsecT Text ParserConf Identity ()
-> ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ParsecT Text ParserConf Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string (String
"{" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
n String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"}")

bodyBlock :: String -> Parser LaTeX
bodyBlock :: String -> Parsec Text ParserConf LaTeX
bodyBlock String
n = do
  Maybe Char
c <- Parser (Maybe Char)
peekChar
  case Maybe Char
c of 
     Just Char
_ -> Parsec Text ParserConf LaTeX
latexBlockParser
     Maybe Char
_ -> String -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parsec Text ParserConf LaTeX)
-> String -> Parsec Text ParserConf LaTeX
forall a b. (a -> b) -> a -> b
$ String
"Environment '" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
n String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"' not finalized."

------------------------------------------------------------------------
-- Command
------------------------------------------------------------------------
command :: Parser LaTeX
command :: Parsec Text ParserConf LaTeX
command = do
  Char
_    <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\\'
  Maybe Char
mbX  <- Parser (Maybe Char)
peekChar
  case Maybe Char
mbX of
    Maybe Char
Nothing -> LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return LaTeX
TeXEmpty
    Just Char
x  -> if Char -> Bool
isSpecial Char
x
                  then Parsec Text ParserConf LaTeX
special
                  else do
                    Text
c  <- (Char -> Bool) -> ParsecT Text ParserConf Identity Text
takeTill Char -> Bool
endCmd
                    LaTeX -> ([TeXArg] -> LaTeX) -> Maybe [TeXArg] -> LaTeX
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> LaTeX
TeXCommS (String -> LaTeX) -> String -> LaTeX
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
c) (String -> [TeXArg] -> LaTeX
TeXComm (String -> [TeXArg] -> LaTeX) -> String -> [TeXArg] -> LaTeX
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
c) (Maybe [TeXArg] -> LaTeX)
-> Parser (Maybe [TeXArg]) -> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser (Maybe [TeXArg])
cmdArgs

------------------------------------------------------------------------
-- Command Arguments
------------------------------------------------------------------------
cmdArgs :: Parser (Maybe [TeXArg])
cmdArgs :: Parser (Maybe [TeXArg])
cmdArgs = Parser (Maybe [TeXArg]) -> Parser (Maybe [TeXArg])
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String -> ParsecT Text ParserConf Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"{}" ParsecT Text ParserConf Identity String
-> Parser (Maybe [TeXArg]) -> Parser (Maybe [TeXArg])
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe [TeXArg] -> Parser (Maybe [TeXArg])
forall (m :: * -> *) a. Monad m => a -> m a
return ([TeXArg] -> Maybe [TeXArg]
forall a. a -> Maybe a
Just []))
            Parser (Maybe [TeXArg])
-> Parser (Maybe [TeXArg]) -> Parser (Maybe [TeXArg])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ([TeXArg] -> Maybe [TeXArg])
-> ParsecT Text ParserConf Identity [TeXArg]
-> Parser (Maybe [TeXArg])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [TeXArg] -> Maybe [TeXArg]
forall a. a -> Maybe a
Just (ParsecT Text ParserConf Identity [TeXArg]
-> ParsecT Text ParserConf Identity [TeXArg]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (ParsecT Text ParserConf Identity [TeXArg]
 -> ParsecT Text ParserConf Identity [TeXArg])
-> ParsecT Text ParserConf Identity [TeXArg]
-> ParsecT Text ParserConf Identity [TeXArg]
forall a b. (a -> b) -> a -> b
$ ParsecT Text ParserConf Identity TeXArg
-> ParsecT Text ParserConf Identity [TeXArg]
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 ParsecT Text ParserConf Identity TeXArg
cmdArg)
            Parser (Maybe [TeXArg])
-> Parser (Maybe [TeXArg]) -> Parser (Maybe [TeXArg])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe [TeXArg] -> Parser (Maybe [TeXArg])
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe [TeXArg]
forall a. Maybe a
Nothing

cmdArg :: Parser TeXArg
cmdArg :: ParsecT Text ParserConf Identity TeXArg
cmdArg = do
  Char
c <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'[' ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'{'
  let e :: String
e = case Char
c of
            Char
'[' -> String
"]"
            Char
'{' -> String
"}"
            Char
_   -> String -> String
forall a. HasCallStack => String -> a
error String
"this cannot happen!"
  LaTeX
b <- [LaTeX] -> LaTeX
forall a. Monoid a => [a] -> a
mconcat ([LaTeX] -> LaTeX)
-> ParsecT Text ParserConf Identity [LaTeX]
-> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parsec Text ParserConf LaTeX
-> ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity [LaTeX]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill Parsec Text ParserConf LaTeX
latexBlockParser (String -> ParsecT Text ParserConf Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
e)
  case Char
c of  
    Char
'[' -> TeXArg -> ParsecT Text ParserConf Identity TeXArg
forall (m :: * -> *) a. Monad m => a -> m a
return (TeXArg -> ParsecT Text ParserConf Identity TeXArg)
-> TeXArg -> ParsecT Text ParserConf Identity TeXArg
forall a b. (a -> b) -> a -> b
$ LaTeX -> TeXArg
OptArg LaTeX
b
    Char
'{' -> TeXArg -> ParsecT Text ParserConf Identity TeXArg
forall (m :: * -> *) a. Monad m => a -> m a
return (TeXArg -> ParsecT Text ParserConf Identity TeXArg)
-> TeXArg -> ParsecT Text ParserConf Identity TeXArg
forall a b. (a -> b) -> a -> b
$ LaTeX -> TeXArg
FixArg LaTeX
b
    Char
_   -> String -> ParsecT Text ParserConf Identity TeXArg
forall a. HasCallStack => String -> a
error String
"this cannot happen!"

------------------------------------------------------------------------
-- Special commands (consisting of one char)
------------------------------------------------------------------------
special :: Parser LaTeX
special :: Parsec Text ParserConf LaTeX
special = do
  Char
x <- ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar
  case Char
x of
    Char
'('  -> MathType -> String -> Parsec Text ParserConf LaTeX
math MathType
Parentheses String
"\\)"
    Char
'['  -> MathType -> String -> Parsec Text ParserConf LaTeX
math MathType
Square      String
"\\]"
    Char
'{'  -> Parsec Text ParserConf LaTeX
lbrace
    Char
'}'  -> Parsec Text ParserConf LaTeX
rbrace
    Char
'|'  -> Parsec Text ParserConf LaTeX
vert
    Char
'\\' -> Parsec Text ParserConf LaTeX
lbreak
    Char
_    -> String -> Parsec Text ParserConf LaTeX
commS [Char
x]

isSpecial :: Char -> Bool
isSpecial :: Char -> Bool
isSpecial = (Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
specials)

------------------------------------------------------------------------
-- Line break
------------------------------------------------------------------------

lbreak :: Parser LaTeX
lbreak :: Parsec Text ParserConf LaTeX
lbreak = do
  Char
y <- ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'[' ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'*' ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> ParsecT Text ParserConf Identity Char
forall (m :: * -> *) a. Monad m => a -> m a
return Char
' ')  
  case Char
y of
    Char
'[' -> Bool -> Parsec Text ParserConf LaTeX
linebreak Bool
False
    Char
'*' -> do Char
z <- ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'[' ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> ParsecT Text ParserConf Identity Char
forall (m :: * -> *) a. Monad m => a -> m a
return Char
' ')
              case Char
z of
               Char
'[' -> Bool -> Parsec Text ParserConf LaTeX
linebreak Bool
True
               Char
_   -> LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Measure -> Bool -> LaTeX
TeXLineBreak Maybe Measure
forall a. Maybe a
Nothing Bool
True)
    Char
_   -> LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Measure -> Bool -> LaTeX
TeXLineBreak Maybe Measure
forall a. Maybe a
Nothing Bool
False)

linebreak :: Bool -> Parser LaTeX
linebreak :: Bool -> Parsec Text ParserConf LaTeX
linebreak Bool
t = do Measure
m <- Parser Measure
measure Parser Measure -> String -> Parser Measure
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"measure"
                 Char
_ <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
']'
                 Char
s <- ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'*' ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> ParsecT Text ParserConf Identity Char
forall (m :: * -> *) a. Monad m => a -> m a
return Char
' ')
                 LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (LaTeX -> Parsec Text ParserConf LaTeX)
-> LaTeX -> Parsec Text ParserConf LaTeX
forall a b. (a -> b) -> a -> b
$ Maybe Measure -> Bool -> LaTeX
TeXLineBreak (Measure -> Maybe Measure
forall a. a -> Maybe a
Just Measure
m) (Bool
t Bool -> Bool -> Bool
|| Char
s Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'*')

measure :: Parser Measure
measure :: Parser Measure
measure = Parser Measure -> Parser Measure
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (Parser Double
floating Parser Double -> (Double -> Parser Measure) -> Parser Measure
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Double -> Parser Measure
unit) Parser Measure -> Parser Measure -> Parser Measure
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (LaTeX -> Measure
CustomMeasure (LaTeX -> Measure) -> ([LaTeX] -> LaTeX) -> [LaTeX] -> Measure
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [LaTeX] -> LaTeX
forall a. Monoid a => [a] -> a
mconcat) ([LaTeX] -> Measure)
-> ParsecT Text ParserConf Identity [LaTeX] -> Parser Measure
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parsec Text ParserConf LaTeX
-> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity [LaTeX]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill Parsec Text ParserConf LaTeX
latexBlockParser (ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m a
lookAhead (ParsecT Text ParserConf Identity Char
 -> ParsecT Text ParserConf Identity Char)
-> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall a b. (a -> b) -> a -> b
$ Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
']')

unit :: Double -> Parser Measure
unit :: Double -> Parser Measure
unit Double
f = do
  Char
u1 <- ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar
  Char
u2 <- ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar
  case (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char
u1, Char
u2] of
    String
"pt" -> Measure -> Parser Measure
forall (m :: * -> *) a. Monad m => a -> m a
return (Measure -> Parser Measure) -> Measure -> Parser Measure
forall a b. (a -> b) -> a -> b
$ Double -> Measure
Pt Double
f
    String
"mm" -> Measure -> Parser Measure
forall (m :: * -> *) a. Monad m => a -> m a
return (Measure -> Parser Measure) -> Measure -> Parser Measure
forall a b. (a -> b) -> a -> b
$ Double -> Measure
Mm Double
f
    String
"cm" -> Measure -> Parser Measure
forall (m :: * -> *) a. Monad m => a -> m a
return (Measure -> Parser Measure) -> Measure -> Parser Measure
forall a b. (a -> b) -> a -> b
$ Double -> Measure
Cm Double
f
    String
"in" -> Measure -> Parser Measure
forall (m :: * -> *) a. Monad m => a -> m a
return (Measure -> Parser Measure) -> Measure -> Parser Measure
forall a b. (a -> b) -> a -> b
$ Double -> Measure
In Double
f
    String
"ex" -> Measure -> Parser Measure
forall (m :: * -> *) a. Monad m => a -> m a
return (Measure -> Parser Measure) -> Measure -> Parser Measure
forall a b. (a -> b) -> a -> b
$ Double -> Measure
Ex Double
f
    String
"em" -> Measure -> Parser Measure
forall (m :: * -> *) a. Monad m => a -> m a
return (Measure -> Parser Measure) -> Measure -> Parser Measure
forall a b. (a -> b) -> a -> b
$ Double -> Measure
Em Double
f
    String
_    -> String -> Parser Measure
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"NaN"

------------------------------------------------------------------------
-- Right or left brace or vertical
------------------------------------------------------------------------
rbrace, lbrace,vert :: Parser LaTeX
lbrace :: Parsec Text ParserConf LaTeX
lbrace = String -> Parsec Text ParserConf LaTeX
brace String
"{"
rbrace :: Parsec Text ParserConf LaTeX
rbrace = String -> Parsec Text ParserConf LaTeX
brace String
"}"
vert :: Parsec Text ParserConf LaTeX
vert   = String -> Parsec Text ParserConf LaTeX
brace String
"|"

brace :: String -> Parser LaTeX
brace :: String -> Parsec Text ParserConf LaTeX
brace = LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (LaTeX -> Parsec Text ParserConf LaTeX)
-> (String -> LaTeX) -> String -> Parsec Text ParserConf LaTeX
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> LaTeX
TeXCommS -- The same as commS?

commS :: String -> Parser LaTeX
commS :: String -> Parsec Text ParserConf LaTeX
commS = LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (LaTeX -> Parsec Text ParserConf LaTeX)
-> (String -> LaTeX) -> String -> Parsec Text ParserConf LaTeX
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> LaTeX
TeXCommS

------------------------------------------------------------------------
-- Math
------------------------------------------------------------------------
dolMath :: Parser LaTeX
dolMath :: Parsec Text ParserConf LaTeX
dolMath = do
  Char
_ <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'$' 
  [Parsec Text ParserConf LaTeX] -> Parsec Text ParserConf LaTeX
forall s (m :: * -> *) t u a.
Stream s m t =>
[ParsecT s u m a] -> ParsecT s u m a
choice
    [ do Char
_ <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'$'
         LaTeX
b <- [LaTeX] -> LaTeX
forall a. Monoid a => [a] -> a
mconcat ([LaTeX] -> LaTeX)
-> ParsecT Text ParserConf Identity [LaTeX]
-> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parsec Text ParserConf LaTeX
latexBlockParser Parsec Text ParserConf LaTeX
-> ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity [LaTeX]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
`manyTill` ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String -> ParsecT Text ParserConf Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"$$")
         LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (LaTeX -> Parsec Text ParserConf LaTeX)
-> LaTeX -> Parsec Text ParserConf LaTeX
forall a b. (a -> b) -> a -> b
$ MathType -> LaTeX -> LaTeX
TeXMath MathType
DoubleDollar LaTeX
b
    , do LaTeX
b <- [LaTeX] -> LaTeX
forall a. Monoid a => [a] -> a
mconcat ([LaTeX] -> LaTeX)
-> ParsecT Text ParserConf Identity [LaTeX]
-> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parsec Text ParserConf LaTeX
latexBlockParser Parsec Text ParserConf LaTeX
-> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity [LaTeX]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
`manyTill` Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'$'
         LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (LaTeX -> Parsec Text ParserConf LaTeX)
-> LaTeX -> Parsec Text ParserConf LaTeX
forall a b. (a -> b) -> a -> b
$ MathType -> LaTeX -> LaTeX
TeXMath MathType
Dollar LaTeX
b
      ]

math :: MathType -> String -> Parser LaTeX
math :: MathType -> String -> Parsec Text ParserConf LaTeX
math MathType
t String
eMath = do
   LaTeX
b <- [LaTeX] -> LaTeX
forall a. Monoid a => [a] -> a
mconcat ([LaTeX] -> LaTeX)
-> ParsecT Text ParserConf Identity [LaTeX]
-> Parsec Text ParserConf LaTeX
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parsec Text ParserConf LaTeX
latexBlockParser Parsec Text ParserConf LaTeX
-> ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity [LaTeX]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
`manyTill` ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String -> ParsecT Text ParserConf Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
eMath)
   LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (LaTeX -> Parsec Text ParserConf LaTeX)
-> LaTeX -> Parsec Text ParserConf LaTeX
forall a b. (a -> b) -> a -> b
$ MathType -> LaTeX -> LaTeX
TeXMath MathType
t LaTeX
b

------------------------------------------------------------------------
-- Comment 
------------------------------------------------------------------------
comment :: Parser LaTeX
comment :: Parsec Text ParserConf LaTeX
comment = do
  Char
_  <- Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'%'
  Text
c  <- (Char -> Bool) -> ParsecT Text ParserConf Identity Text
takeTill (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\n')
  Bool
e  <- Parser Bool
atEnd
  Bool
-> ParsecT Text ParserConf Identity ()
-> ParsecT Text ParserConf Identity ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
e (Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\n' ParsecT Text ParserConf Identity Char
-> (Char -> ParsecT Text ParserConf Identity ())
-> ParsecT Text ParserConf Identity ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Char
_ -> () -> ParsecT Text ParserConf Identity ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())
  LaTeX -> Parsec Text ParserConf LaTeX
forall (m :: * -> *) a. Monad m => a -> m a
return (LaTeX -> Parsec Text ParserConf LaTeX)
-> LaTeX -> Parsec Text ParserConf LaTeX
forall a b. (a -> b) -> a -> b
$ Text -> LaTeX
TeXComment Text
c

------------------------------------------------------------------------
-- Helpers
------------------------------------------------------------------------

endCmd :: Char -> Bool
endCmd :: Char -> Bool
endCmd Char
c = Bool
notLowercaseAlph Bool -> Bool -> Bool
&& Bool
notUppercaseAlph
 where c' :: Int
c' = Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
c
       notLowercaseAlph :: Bool
notLowercaseAlph = Int
c' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
'a' Bool -> Bool -> Bool
|| Int
c' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
'z'
       notUppercaseAlph :: Bool
notUppercaseAlph = Int
c' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
'A' Bool -> Bool -> Bool
|| Int
c' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
'Z'

specials :: String
specials :: String
specials = String
"'(),.-\"!^$&#{}%~|/:;=[]\\` "

peekChar :: Parser (Maybe Char)
peekChar :: Parser (Maybe Char)
peekChar = Char -> Maybe Char
forall a. a -> Maybe a
Just (Char -> Maybe Char)
-> ParsecT Text ParserConf Identity Char -> Parser (Maybe Char)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m a
lookAhead ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar) Parser (Maybe Char) -> Parser (Maybe Char) -> Parser (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe Char -> Parser (Maybe Char)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Char
forall a. Maybe a
Nothing

atEnd :: Parser Bool
atEnd :: Parser Bool
atEnd = (ParsecT Text ParserConf Identity ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
eof ParsecT Text ParserConf Identity () -> Bool -> Parser Bool
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Bool
True) Parser Bool -> Parser Bool -> Parser Bool
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Bool -> Parser Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False

takeTill :: (Char -> Bool) -> Parser Text
takeTill :: (Char -> Bool) -> ParsecT Text ParserConf Identity Text
takeTill Char -> Bool
p = String -> Text
T.pack (String -> Text)
-> ParsecT Text ParserConf Identity String
-> ParsecT Text ParserConf Identity Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many ((Char -> Bool) -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
satisfy (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
p))

-- Parsing doubles
--
-- Code for 'floating', 'fractExponent', and 'sign' comes from parsers package:
--
-- http://hackage.haskell.org/package/parsers
--

floating :: Parser Double
floating :: Parser Double
floating = Parser Integer
decimal Parser Integer
-> ParsecT Text ParserConf Identity (Integer -> Double)
-> Parser Double
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> ParsecT Text ParserConf Identity (Integer -> Double)
fractExponent

fractExponent :: Parser (Integer -> Double)
fractExponent :: ParsecT Text ParserConf Identity (Integer -> Double)
fractExponent = (\Double
fract Double
expo Integer
n -> (Integer -> Double
forall a. Num a => Integer -> a
fromInteger Integer
n Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
fract) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
expo) (Double -> Double -> Integer -> Double)
-> Parser Double
-> ParsecT Text ParserConf Identity (Double -> Integer -> Double)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Double
forall u. ParsecT Text u Identity Double
fraction ParsecT Text ParserConf Identity (Double -> Integer -> Double)
-> Parser Double
-> ParsecT Text ParserConf Identity (Integer -> Double)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Double -> Parser Double -> Parser Double
forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
option Double
1.0 Parser Double
exponent'
            ParsecT Text ParserConf Identity (Integer -> Double)
-> ParsecT Text ParserConf Identity (Integer -> Double)
-> ParsecT Text ParserConf Identity (Integer -> Double)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (\Double
expo Integer
n -> Integer -> Double
forall a. Num a => Integer -> a
fromInteger Integer
n Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
expo) (Double -> Integer -> Double)
-> Parser Double
-> ParsecT Text ParserConf Identity (Integer -> Double)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Double
exponent' where
  fraction :: ParsecT Text u Identity Double
fraction = (Char -> Double -> Double) -> Double -> String -> Double
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Char -> Double -> Double
forall a. Fractional a => Char -> a -> a
op Double
0.0 (String -> Double)
-> ParsecT Text u Identity String -> ParsecT Text u Identity Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> ParsecT Text u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'.' ParsecT Text u Identity Char
-> ParsecT Text u Identity String -> ParsecT Text u Identity String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (ParsecT Text u Identity Char -> ParsecT Text u Identity String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some ParsecT Text u Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
digit ParsecT Text u Identity String
-> String -> ParsecT Text u Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"fraction"))
  op :: Char -> a -> a
op Char
d a
f = (a
f a -> a -> a
forall a. Num a => a -> a -> a
+ Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
digitToInt Char
d))a -> a -> a
forall a. Fractional a => a -> a -> a
/a
10.0
  exponent' :: Parser Double
exponent' = ((\Integer -> Integer
f Integer
e -> Integer -> Double
forall b p. (Fractional p, Integral b) => b -> p
power (Integer -> Integer
f Integer
e)) ((Integer -> Integer) -> Integer -> Double)
-> ParsecT Text ParserConf Identity Char
-> ParsecT
     Text
     ParserConf
     Identity
     ((Integer -> Integer) -> Integer -> Double)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
"eE" ParsecT
  Text
  ParserConf
  Identity
  ((Integer -> Integer) -> Integer -> Double)
-> ParsecT Text ParserConf Identity (Integer -> Integer)
-> ParsecT Text ParserConf Identity (Integer -> Double)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT Text ParserConf Identity (Integer -> Integer)
sign ParsecT Text ParserConf Identity (Integer -> Double)
-> Parser Integer -> Parser Double
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Parser Integer
decimal Parser Integer -> String -> Parser Integer
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"exponent")) Parser Double -> String -> Parser Double
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"exponent"
  power :: b -> p
power b
e
    | b
e b -> b -> Bool
forall a. Ord a => a -> a -> Bool
< b
0     = p
1.0p -> p -> p
forall a. Fractional a => a -> a -> a
/b -> p
power(-b
e)
    | Bool
otherwise = Integer -> p
forall a. Num a => Integer -> a
fromInteger (Integer
10Integer -> b -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^b
e)

decimal :: Parser Integer
decimal :: Parser Integer
decimal = String -> Integer
forall a. Read a => String -> a
read (String -> Integer)
-> ParsecT Text ParserConf Identity String -> Parser Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
digit

sign :: Parser (Integer -> Integer)
sign :: ParsecT Text ParserConf Identity (Integer -> Integer)
sign = Integer -> Integer
forall a. Num a => a -> a
negate (Integer -> Integer)
-> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity (Integer -> Integer)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'-'
   ParsecT Text ParserConf Identity (Integer -> Integer)
-> ParsecT Text ParserConf Identity (Integer -> Integer)
-> ParsecT Text ParserConf Identity (Integer -> Integer)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Integer -> Integer
forall a. a -> a
id (Integer -> Integer)
-> ParsecT Text ParserConf Identity Char
-> ParsecT Text ParserConf Identity (Integer -> Integer)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Char -> ParsecT Text ParserConf Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'+'
   ParsecT Text ParserConf Identity (Integer -> Integer)
-> ParsecT Text ParserConf Identity (Integer -> Integer)
-> ParsecT Text ParserConf Identity (Integer -> Integer)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Integer -> Integer)
-> ParsecT Text ParserConf Identity (Integer -> Integer)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Integer -> Integer
forall a. a -> a
id