-- | This is the 'LaTeX' parser module. module Text.LaTeX.Base.Parser ( parseLaTeX , ParseError (..) ) where import Text.LaTeX.Base.Syntax -- import Text.Parsec import Text.Parsec.Text -- import Control.Applicative hiding ((<|>),many) import Data.Monoid import Data.String import Data.Text p_Comm :: Parser LaTeX p_Comm = do char '\\' str <- many1 alphaNum args <- try (string "{}" >> return []) <|> (many1 p_Arg) return $ TeXComm str args p_CommS :: Parser LaTeX p_CommS = do char '\\' TeXCommS <$> many1 alphaNum p_Env :: Parser LaTeX p_Env = do string "\\begin{" str <- many1 alphaNum char '}' args <- many p_Arg ls <- manyTill p_TeXU $ try $ string $ "\\end{" ++ str ++ "}" return $ TeXEnv str args $ mconcat ls p_Math :: Parser LaTeX p_Math = do char '$' TeXMath . mconcat <$> manyTill p_TeXU (char '$') p_NewLine :: Parser LaTeX p_NewLine = do string "\\\\" fmap TeXNewLine $ (char '*' >> return True) <|> return False p_RawG :: [Char] -> Parser LaTeX p_RawG xs = TeXRaw . fromString <$> manyTill anyChar (lookAhead $ (oneOf xs >> return mempty) <|> p_TeXURaw) p_Raw :: Parser LaTeX p_Raw = p_RawG [] p_RawNC :: Parser LaTeX p_RawNC = p_RawG "," p_TeXU :: Parser LaTeX p_TeXU = choice $ try <$> [p_NewLine , p_Math , p_Env , p_Comm , p_CommS , p_Raw] p_TeXURaw :: Parser LaTeX p_TeXURaw = choice $ try <$> [p_NewLine , p_Math , p_Env , p_Comm , p_CommS] p_TeX :: Parser LaTeX p_TeX = mconcat <$> many p_TeXU p_TeXUNC :: Parser LaTeX p_TeXUNC = choice $ try <$> [p_NewLine , p_Math , p_Env , p_Comm , p_CommS , p_RawNC] p_TeXNC :: Parser LaTeX p_TeXNC = mconcat <$> many p_TeXUNC p_SimpleArg :: (Char,Char) -> (LaTeX -> TeXArg) -> Parser TeXArg p_SimpleArg (c1,c2) f = do char c1 fmap (f . mconcat) $ manyTill (p_TeXURaw <|> p_RawG [c2]) $ char c2 p_MultiArg :: (Char,Char) -> ([LaTeX] -> TeXArg) -> Parser TeXArg p_MultiArg (c1,c2) f = do char c1 fmap f $ sepBy1 (mconcat <$> manyTill p_TeXUNC (char c2)) $ char ',' p_Opt :: Parser TeXArg p_Opt = p_SimpleArg ('[',']') OptArg p_MOpt :: Parser TeXArg p_MOpt = p_MultiArg ('[',']') MOptArg p_Fix :: Parser TeXArg p_Fix = p_SimpleArg ('{','}') FixArg p_Sym :: Parser TeXArg p_Sym = p_SimpleArg ('<','>') SymArg p_MSym :: Parser TeXArg p_MSym = p_MultiArg ('<','>') MSymArg p_Arg :: Parser TeXArg p_Arg = choice $ try <$> [ p_MOpt , p_MSym , p_Opt , p_Fix , p_Sym ] -- | Parse a LaTeX expression written in 'Text', to a 'LaTeX' AST. -- It returns a 'ParseError' in case of parsing error. parseLaTeX :: Text -> Either ParseError LaTeX parseLaTeX = parse (p_TeX >>= \l -> eof >> return l) "LaTeX input"