module Text.SmallCaps.TeXParser where
import Data.Attoparsec.Text ( Parser, satisfy, char, takeWhile1, takeTill, endOfLine, isEndOfLine )
import Data.Attoparsec.Combinator ( many', manyTill', option )
import Data.Text ( Text, singleton, cons, snoc )
import Control.Monad ( msum, mplus )
import Text.SmallCaps.TeX ( TeX, TeXElement (..), isMacroLetter, isMacroSign )
tex :: Parser TeX
tex = many' texElement
texElement :: Parser TeXElement
texElement = msum
[ printable
, comment
, macro
, block
, bblock
, math
]
printable :: Parser TeXElement
printable = fmap Printable $ takeWhile1 printableChar
where printableChar = not . flip elem "\\{}[]%$"
comment :: Parser TeXElement
comment = fmap Comment $ do
b <- commentChar
c <- takeTill isEndOfLine
option () endOfLine
return (cons b (snoc c '\n'))
commentChar :: Parser Char
commentChar = char '%'
macro :: Parser TeXElement
macro = fmap Macro $ do
b <- macroBegin
n <- macroName
return (cons b n)
macroBegin :: Parser Char
macroBegin = char '\\'
macroName :: Parser Text
macroName = macroLabel `mplus` tt macroSign
macroLabel :: Parser Text
macroLabel = takeWhile1 isMacroLetter
macroSign :: Parser Char
macroSign = satisfy isMacroSign
block :: Parser TeXElement
block = fmap Block $ do
_ <- blockBegin
c <- tex
_ <- blockEnd
return c
blockBegin :: Parser Char
blockBegin = char '{'
blockEnd :: Parser Char
blockEnd = char '}'
bblock :: Parser TeXElement
bblock = fmap BBlock $ do
_ <- bblockBegin
c <- tex
_ <- bblockEnd
return c
bblockBegin :: Parser Char
bblockBegin = char '['
bblockEnd :: Parser Char
bblockEnd = char ']'
math :: Parser TeXElement
math = fmap Math $ do
_ <- char '$'
manyTill' texElement (char '$')
tt :: Parser Char -> Parser Text
tt = fmap singleton