{-
Copyright (C) 2012-2015 UAB VTeX, Lithuania

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-}

{- |
   Module      : Text.Tex2txt
   Copyright   : Copyright (C) 2012-2015 UAB VTeX, Lithuania
   License     : GNU GPL, version 2 or above
   Maintainer  : Vidas Daudaravicius <vidas.daudaravicius@vtex.lt>
   Stability   : alpha
   Portability : portable

Conversion of TeX/LaTeX to plain-text document.
-}



module Text.Tex2txt (tex2TXTFile,tex2TXT,sentences) where

import Text.Parsec hiding (spaces)
import qualified Data.List as L
import Data.Char
import System.IO
import Control.DeepSeq
import qualified Data.Map as Map
import Data.Maybe
import Numeric

switches = ["Huge","huge","LARGE","Large","large","normalsize","small","footnotesize","scriptsize","tiny","em","normalfont","rmfamily","sffamily","ttfamily","upshape","itshape","slshape","scshape","bfseries","mdseries","tt","noindent","indent","sl","unit","abbrev","Bbb","bf","it"]

isSwitch t = elem t switches

data Pos = Start Line Column | Stop Line Column 
           deriving (Show, Ord, Eq)
type Space = String

emptyStart = Start 0 0
emptyStop = Stop 0 0

data Tex = TexComment Pos Pos !String !Space
           | TexCommand Pos Pos !String ![Tex] !Space
           | TexNewCommand Pos Pos Tex !Int !(Maybe String) ![Tex] !Space
           | TexNewEnvironment Pos Pos !String !Int !(Maybe String) ![Tex] ![Tex] !Space
           | TexNewCommandArg Pos Pos !Int !String !Space
           | TexNewCommandArgExp Pos Pos !Int 
           | TexDef Pos Pos Tex ![Tex] ![Tex] !Space
           | TexDefArg Pos Pos !String
           | TexDefArgExp Pos Pos !Int 
           | TexToken Pos Pos !String !Space
           | TexDimention Pos Pos !String !Space
           | TexDigit Pos Pos !String !Space
           | TexSymbol Pos Pos !String !Space
           | TexVerbatim Pos Pos String !Space
           | TexVerbatimAllTT Pos Pos String !Space
           | TexVerbatimListing Pos Pos String !Space
           | Tex Pos Pos ![Tex] 
           | TexSpace Pos Pos !String !Space
           | TexPar Pos Pos !String !Space
           | TexBraces Pos Pos !String !String ![Tex] !Space
           | TexMath Pos Pos !String !String ![Tex] !Space
           | TexMathDisp Pos Pos !String !String ![Tex] !Space
           | TexGroup Pos Pos !String !String ![Tex] !Space
           | TexEmpty !String
           | TexRegistry Pos Pos !Tex !String !Tex !String  -- name type value spaceBefore. Types:  \newbox \newcount \newdimen \newmuskip \newskip \newtoks
           deriving (Show, Ord, Eq)

data TexState = TexState {
                          macroState::(Map.Map String Tex),
                          environmentState::(Map.Map String Tex)
                         }

instance NFData (Tex)
instance NFData (Pos)
instance NFData (TexState)


-----------------------Various helpers --------------------------------------

tex2TXTFile fileIn =
        do h <- openFile (fileIn) ReadMode
--           hSetEncoding h latin1
           txt <- hGetContents h
--           let r = readExpr $  U8.utf8Encode txt
           let r = readExpr fileIn txt
           seq r hClose h
           let rr = head $ removeComments ([r])
           return $!  ( unlines $ map (sentences) $ lines $ dropWhile (\x -> if x == ' ' || x == '\n' || x == '\r' then True else False) $ removeDSpaces $ replaceT $ showTexTXT $ rr)


tex2TXT context txt =
        do let r = readExpr context $ removeDSpaces2 $ replaceT txt
           let rr = head $ removeComments ([r])
           return $!  ( dropWhile (\x -> if x == ' ' || x == '\n' || x == '\r' then True else False) $ removeDSpaces $ replaceT $ showTexTXT $ rr)

-------------------- TEX parser---------------------------------------------

--sentencesT xs = init $ concat $ map (\ln -> "<par>" ++ ln ++ "</par><par>paredit.</par>\n") $ lines $ sentences xs

sentences [] = []
sentences ('.':' ':a@(x:xs))
      | isDigit x  = '.':' ':'\n':sentences a
      | isUpper x  = '.':' ':'\n':sentences a
      | length rN > 0 
        && (not $ null enumerate) 
        && head rN == ')'  = ('.' : ' ' : '\n' : enumerate) ++  (sentences rN)
      | length rN2 > 0 
        && x == '(' 
        && (not $ null enumerate2) 
        && head rN2 == ')'  = ('.' : ' ' : '\n' : '(' : enumerate2) ++  (sentences rN2)
      | otherwise  = '.' : ' ' : sentences a
      where 
           (enumerate,rN) = span (isAlpha) a
           (enumerate2,rN2) = span (isAlpha) xs
sentences xs 
      | titleLen > 0 = (take titleLen xs) ++ ((sentences (drop titleLen xs)))
      | abbrLen > 0 = if L.isPrefixOf " The" rmAbbr || L.isPrefixOf " A"  rmAbbr || L.isPrefixOf " It"  rmAbbr
                            then  abbr ++ ('\n':(sentences rmAbbr))
                            else  abbr ++ ((sentences rmAbbr))
      | numLen > 0 = if L.isPrefixOf " The" rmNum || L.isPrefixOf " A"  rmNum || L.isPrefixOf " It"  rmNum
                            then  num ++ ('\n':(sentences rmNum))
                            else  num ++ ((sentences rmNum))
      | L.isPrefixOf "MATH. " xs = (take 5 xs) ++ ('\n':(sentences (drop 6 xs)))
      | L.isPrefixOf "MATHDISP. " xs = (take 9 xs) ++ ('\n':(sentences (drop 10 xs)))
      | (isUpper $ head xs) 
        && last isProbablyTitle == '.' 
        && length isProbablyTitle < 7  =
                                         if L.isPrefixOf " The" rm || L.isPrefixOf " A"  rm || L.isPrefixOf " It"  rm
                                           then (isProbablyTitle) ++ ('\n':(sentences rm))
                                           else (take (length isProbablyTitle) xs) ++ ((sentences (drop (length isProbablyTitle) xs)))
      | otherwise = (head xs):(sentences $ tail xs)
         where  
              titleLen = isTitle xs titles
              abbrLen = isAbbr xs abbreviations
              (abbr,rmAbbr) = splitAt abbrLen xs
              numLen = isNum xs
              (num,rmNum) = splitAt numLen xs
              (isProbablyTitle,rm) = span (/=' ') xs
--sentences (x:xs)  = x: sentences xs

titles :: [String]
titles = [ "Mr.", "Mrs.", "Dr.", "St.", "Prof.","Ms.","Sr.","Phd." ]

isTitle x [] = 0
isTitle x (a:as) = if L.isPrefixOf a x then length a else isTitle x as

abbreviations :: [String]
abbreviations = [ "cf.", "eg.", "ie.", "i.e.", "e.g.", "vs.","etc.","no.","esp.","inc.","ltd.","co.","corp.","dept.","univ.","assn","bross","col.","gen.","lt.","adm.","viz.","et al."]

isAbbr x [] = 0
isAbbr x (a:as) = if (map (toLower) $ take (length a) x) == a then length a else isAbbr x as

isNum x
       | null nums = 0
       | length r > 0 && head r == '.' = (length nums) + (length $ takeWhile (=='.') r)
       | otherwise = 0
            where 
              (nums,r) = span (isDigit) x

replaceT [] = []
replaceT ('\t': xs) = ' ' : replaceT xs
replaceT ('~': xs) = ' ' : replaceT xs
replaceT ('\n': '\r': xs) = '\n' : replaceT xs
replaceT ('\r': '\n': xs) = '\n' : replaceT xs
replaceT ('\r': xs) = '\n' : replaceT xs   -- it is a must to handle MAC 
replaceT (x : xs) = x : replaceT xs

removeDSpaces2 (' ':' ':xs) = removeDSpaces2 (' ':xs)
removeDSpaces2 (' ':'\n':xs) = removeDSpaces2 ('\n':xs)
removeDSpaces2 ('\n':' ':xs) = removeDSpaces2 ('\n':xs)
removeDSpaces2 (x:xs) = x:removeDSpaces2 xs
removeDSpaces2 x = x

removeDSpaces (' ':' ':xs) = removeDSpaces (' ':xs)
removeDSpaces (' ':'\n':xs) = removeDSpaces ('\n':xs)
removeDSpaces ('\n':' ':xs) = removeDSpaces ('\n':xs)
removeDSpaces ('\n':'\n':xs) = removeDSpaces ('\n':xs)
removeDSpaces (x:xs) = x:removeDSpaces xs
removeDSpaces x = x

texAsTxt (TexComment _ _ txt sp) = sp ++ txt
texAsTxt (TexCommand _ _ txt texs sp) = sp ++ txt ++ (concat $ map (texAsTxt) texs)
texAsTxt (TexNewCommand _ _ cmd ars Nothing tex sp) = sp ++ "\\newcommand{" ++ (texAsTxt cmd) ++ "}[" ++ (show ars) ++ "]{" ++ (concat $ map (texAsTxt) tex) ++ "}" 
texAsTxt (TexNewCommand _ _ cmd ars (Just def) tex sp) = sp ++ "\\newcommand{" ++ (texAsTxt cmd) ++ "}[" ++ (show ars) ++ "][" ++ def ++ "]{" ++ (concat $ map (texAsTxt) tex) ++ "}" 
texAsTxt (TexNewCommandArgExp _ _ x) = show x
texAsTxt (TexNewCommandArg _ _ p txt sp) = sp ++ txt ++ (show p)
texAsTxt (TexDef _ _ cmd texargs texexp sp) = sp ++ "\\def" ++ (texAsTxt cmd) ++ (concat $ map (texAsTxt) texargs) ++ "{" ++ (concat $ map (texAsTxt) texexp) ++ "}" 
texAsTxt (TexToken _ _ txt sp) = sp ++ txt
texAsTxt (TexDimention _ _ txt sp) = sp ++ txt
texAsTxt (TexDigit _ _ txt sp) = sp ++ txt
texAsTxt (TexSymbol _ _ txt sp) = sp ++ txt
texAsTxt (TexVerbatim _ _ txt sp) = sp ++ txt
texAsTxt (Tex _ _ tex) = concat $ map (texAsTxt) tex
texAsTxt (TexSpace _ _ txt sp) = sp ++ txt
texAsTxt (TexPar _ _ txt sp) = sp ++ txt
texAsTxt (TexBraces _ _ b e tex sp) = sp ++ b ++ (concat $ map (texAsTxt) tex) ++ e
texAsTxt (TexMath _ _ b e tex sp) = sp ++ b ++ (concat $ map (texAsTxt) tex) ++ e
texAsTxt (TexMathDisp _ _ b e tex sp) = sp ++ b ++ (concat $ map (texAsTxt) tex) ++ e
texAsTxt (TexGroup _ _ b e tex sp) = sp ++ b ++ (concat $ map (texAsTxt) tex) ++ e
texAsTxt (TexEmpty sp) = sp
texAsTxt (TexRegistry _ _ n t v sp) = sp ++ (texAsTxt v) 

parseTexItem mode
          = do 
               ((try (verbatim mode))
--                <|> (try (texParToken mode))  
                <|> (try (comment mode))
                <|> (try (betweenBraces mode))
                <|> (try (math mode))  
                <|> (try (beginEnd mode))  
                <|> (try (texParToken mode))  
                <|> (try (texCommand mode))
                <|> (try (texToken mode))
                <|> (try (texDigit mode)) 
                <|> (try (texSymbol mode))) 

parseTexToken mode =  do 
                      (  
                       (try (betweenBracesTokens mode))
                       <|> (try (texParToken mode))  
                       <|> (try (texCommandToken mode))
                       <|> (try (texSymbol mode)) 
                       <|> (try $ texSpaceToken mode))

parseTexToken2 mode 
                 =  do 
                    (  (try (comment1 mode)) 
                       <|> (try (texNewCommandArg mode))
                       <|> (try (betweenBracesTokens2 mode))
                       <|> (try (texCommandToken mode))
                       <|> (try (texSymbol mode)) 
                       <|> (try $ texSpaceToken mode))


makeTexCmd v = TexCommand emptyStart emptyStop v [] ""

defaultDimentions
        = Map.fromList
           [("\\year"                    , TexRegistry emptyStart emptyStop (makeTexCmd "\\year"                     ) "token" (TexEmpty "") "")
           ,("\\day"                     , TexRegistry emptyStart emptyStop (makeTexCmd "\\day"                      ) "token" (TexEmpty "") "")
           ,("\\month"                   , TexRegistry emptyStart emptyStop (makeTexCmd "\\month"                    ) "token" (TexEmpty "") "")
           ,("\\defaulthyphenchar"       , TexRegistry emptyStart emptyStop (makeTexCmd "\\defaulthyphenchar"        ) "token" (TexEmpty "`\\-") "")
           ,("\\gnat"                    , TexRegistry emptyStart emptyStop (makeTexCmd "\\gnat"                     ) "token" (TexEmpty "") "")
           ,("\\jot"                     , TexRegistry emptyStart emptyStop (makeTexCmd "\\jot"                      ) "dimen" (TexEmpty "3pt") "")
           ,("\\labst"                   , TexRegistry emptyStart emptyStop (makeTexCmd "\\labst"                    ) "token" (TexEmpty "") "")
           ,("\\tracinglostchars"        , TexRegistry emptyStart emptyStop (makeTexCmd "\\tracinglostchars"         ) "token" (TexEmpty "1") "")
           ,("\\@beginparpenalty"        , TexRegistry emptyStart emptyStop (makeTexCmd "\\@beginparpenalty"         ) "count" (TexEmpty "") "")
           ,("\\@endparpenalty"          , TexRegistry emptyStart emptyStop (makeTexCmd "\\@endparpenalty"           ) "count" (TexEmpty "") "")
           ,("\\@itempenalty"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\@itempenalty"             ) "count" (TexEmpty "") "")
           ,("\\@listdepth"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\@listdepth"               ) "count" (TexEmpty "0") "")
           ,("\\adjdemerits"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\adjdemerits"              ) "count" (TexEmpty "10000") "")
           ,("\\arraystretch"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\arraystretch"             ) "count" (TexEmpty "1") "")
           ,("\\badness"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\badness"                  ) "count" (TexEmpty "1") "")
           ,("\\baselinestretch"         , TexRegistry emptyStart emptyStop (makeTexCmd "\\baselinestretch"          ) "count" (TexEmpty "1") "")
           ,("\\binoppenalty"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\binoppenalty"             ) "count" (TexEmpty "700") "")
           ,("\\brokenpenalty"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\brokenpenalty"            ) "count" (TexEmpty "100") "")
           ,("\\clubpenalty"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\clubpenalty"              ) "count" (TexEmpty "150") "")
           ,("\\defaultskewchar"         , TexRegistry emptyStart emptyStop (makeTexCmd "\\defaultskewchar"          ) "count" (TexEmpty "-1") "")
           ,("\\delimiterfactor"         , TexRegistry emptyStart emptyStop (makeTexCmd "\\delimiterfactor"          ) "count" (TexEmpty "901") "")
           ,("\\displaywidowpenalty"     , TexRegistry emptyStart emptyStop (makeTexCmd "\\displaywidowpenalty"      ) "count" (TexEmpty "50") "")
           ,("\\doublehyphendemerits"    , TexRegistry emptyStart emptyStop (makeTexCmd "\\doublehyphendemerits"     ) "count" (TexEmpty "10000") "")
           ,("\\emergencystretch"        , TexRegistry emptyStart emptyStop (makeTexCmd "\\emergencystretch"         ) "count" (TexEmpty "1") "")
           ,("\\errorcontextlines"       , TexRegistry emptyStart emptyStop (makeTexCmd "\\errorcontextlines"        ) "count" (TexEmpty "-1") "")
           ,("\\exhyphenpenalty"         , TexRegistry emptyStart emptyStop (makeTexCmd "\\exhyphenpenalty"          ) "count" (TexEmpty "50") "")
           ,("\\finalhyphendemerits"     , TexRegistry emptyStart emptyStop (makeTexCmd "\\finalhyphendemerits"      ) "count" (TexEmpty "5000") "")
           ,("\\hbadness"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\hbadness"                 ) "count" (TexEmpty "1000") "")
           ,("\\holdinginserts"          , TexRegistry emptyStart emptyStop (makeTexCmd "\\holdinginserts"           ) "count" (TexEmpty "1") "")
           ,("\\hyphenpenalty"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\hyphenpenalty"            ) "count" (TexEmpty "50") "")
           ,("\\inputlineno"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\inputlineno"              ) "count" (TexEmpty "-1") "")
           ,("\\interfootnotelinepenalty", TexRegistry emptyStart emptyStop (makeTexCmd "\\interfootnotelinepenalty" ) "count" (TexEmpty "100") "")
           ,("\\language"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\language"                 ) "count" (TexEmpty "1") "")
           ,("\\lefthyphenmin"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\lefthyphenmin"            ) "count" (TexEmpty "1") "")
           ,("\\linepenalty"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\linepenalty"              ) "count" (TexEmpty "10") "")
           ,("\\predisplaypenalty"       , TexRegistry emptyStart emptyStop (makeTexCmd "\\predisplaypenalty"        ) "count" (TexEmpty "10000") "")
           ,("\\pretolerance"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\pretolerance"             ) "count" (TexEmpty "100") "")
           ,("\\relpenalty"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\relpenalty"               ) "count" (TexEmpty "500") "")
           ,("\\righthyphenmin"          , TexRegistry emptyStart emptyStop (makeTexCmd "\\righthyphenmin"           ) "count" (TexEmpty "1") "")
           ,("\\setlanguage"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\setlanguage"              ) "count" (TexEmpty "1") "")
           ,("\\tolerance"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\tolerance"                ) "count" (TexEmpty "200") "")
           ,("\\uchyph"                  , TexRegistry emptyStart emptyStop (makeTexCmd "\\uchyph"                   ) "count" (TexEmpty "1") "")
           ,("\\vbadness"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\vbadness"                 ) "count" (TexEmpty "1000") "")
           ,("\\widowpenalty"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\widowpenalty"             ) "count" (TexEmpty "150") "")
           ,("\\@dblfpbot"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\@dblfpbot"                ) "skip" (TexEmpty "0\\p@ plus 1fil") "")
           ,("\\@dblfpsep"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\@dblfpsep"                ) "skip" (TexEmpty "8\\p@ plus 2fil") "")
           ,("\\@dblfptop"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\@dblfptop"                ) "skip" (TexEmpty "0\\p@ plus 1fil") "")
           ,("\\@fpbot"                  , TexRegistry emptyStart emptyStop (makeTexCmd "\\@fpbot"                   ) "skip" (TexEmpty "0\\p@ plus 1fil") "")
           ,("\\@fpsep"                  , TexRegistry emptyStart emptyStop (makeTexCmd "\\@fpsep"                   ) "skip" (TexEmpty "8\\p@ plus 2fil") "")
           ,("\\@fptop"                  , TexRegistry emptyStart emptyStop (makeTexCmd "\\@fptop"                   ) "skip" (TexEmpty "0\\p@ plus 1fil") "")
           ,("\\@outerparskip"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\@outerparskip"            ) "skip" (TexEmpty "1pt") "")
           ,("\\@topsep"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\@topsep"                  ) "skip" (TexEmpty "1pt") "")
           ,("\\abovecaptionskip"        , TexRegistry emptyStart emptyStop (makeTexCmd "\\abovecaptionskip"         ) "skip" (TexEmpty "1pt") "")
           ,("\\abovedisplayshortskip"   , TexRegistry emptyStart emptyStop (makeTexCmd "\\abovedisplayshortskip"    ) "skip" (TexEmpty "0pt plus 3pt") "")
           ,("\\abovedisplayskip"        , TexRegistry emptyStart emptyStop (makeTexCmd "\\abovedisplayskip"         ) "skip" (TexEmpty "12pt plus 3pt minus 9pt") "")
           ,("\\baselineskip"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\baselineskip"             ) "skip" (TexEmpty "1pt") "")
           ,("\\belowcaptionskip"        , TexRegistry emptyStart emptyStop (makeTexCmd "\\belowcaptionskip"         ) "skip" (TexEmpty "1pt") "")
           ,("\\belowdisplayshortskip"   , TexRegistry emptyStart emptyStop (makeTexCmd "\\belowdisplayshortskip"    ) "skip" (TexEmpty "7pt plus 3pt minus 4pt") "")
           ,("\\belowdisplayskip"        , TexRegistry emptyStart emptyStop (makeTexCmd "\\belowdisplayskip"         ) "skip" (TexEmpty "12pt plus 3pt minus 9pt") "")
           ,("\\bigskipamount"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\bigskipamount"            ) "skip" (TexEmpty "12pt plus 4pt minus 4pt") "")
           ,("\\dblfloatsep"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\dblfloatsep"              ) "skip" (TexEmpty "12\\p@ plus 2\\p@ minus 2\\p@") "")
           ,("\\dbltextfloatsep"         , TexRegistry emptyStart emptyStop (makeTexCmd "\\dbltextfloatsep"          ) "skip" (TexEmpty "20\\p@ plus 2\\p@ minus 4\\p@") "")
           ,("\\defbaselineskip"         , TexRegistry emptyStart emptyStop (makeTexCmd "\\defbaselineskip"          ) "skip" (TexEmpty "1pt") "")
           ,("\\earraycolsep"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\earraycolsep"             ) "skip" (TexEmpty "1pt") "")
           ,("\\figureskip"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\figureskip"               ) "skip" (TexEmpty "1pt") "")
           ,("\\floatsep"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\floatsep"                 ) "skip" (TexEmpty "12\\p@ plus 2\\p@ minus 2\\p@") "")
           ,("\\footnotesep"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\footnotesep"              ) "skip" (TexEmpty "1pt") "")
           ,("\\hangafter"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\hangafter"                ) "skip" (TexEmpty "1pt") "")
           ,("\\hangindent"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\hangindent"               ) "skip" (TexEmpty "1pt") "")
           ,("\\hideskip"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\hideskip"                 ) "skip" (TexEmpty "-1000pt") "")
           ,("\\intextsep"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\intextsep"                ) "skip" (TexEmpty "12\\p@ plus 2\\p@ minus 2\\p@") "")
           ,("\\itemsep"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\itemsep"                  ) "skip" (TexEmpty "1pt") "")
           ,("\\leftskip"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\leftskip"                 ) "skip" (TexEmpty "1pt") "")
           ,("\\lineskip"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\lineskip"                 ) "skip" (TexEmpty "1pt") "")
           ,("\\medskipamount"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\medskipamount"            ) "skip" (TexEmpty "6pt plus 2pt minus 2pt") "")
           ,("\\multicolsep"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\multicolsep"              ) "skip" (TexEmpty "1pt") "")
           ,("\\multlinegap"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\multlinegap"              ) "skip" (TexEmpty "1pt") "")
           ,("\\normalbaselineskip"      , TexRegistry emptyStart emptyStop (makeTexCmd "\\normalbaselineskip"       ) "skip" (TexEmpty "12pt") "")
           ,("\\normallineskip"          , TexRegistry emptyStart emptyStop (makeTexCmd "\\normallineskip"           ) "skip" (TexEmpty "1pt") "")
           ,("\\nulldelimiterspace"      , TexRegistry emptyStart emptyStop (makeTexCmd "\\nulldelimiterspace"       ) "skip" (TexEmpty "1.2pt") "")
           ,("\\parfillskip"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\parfillskip"              ) "skip" (TexEmpty "0pt plus 1fil") "")
           ,("\\parsep"                  , TexRegistry emptyStart emptyStop (makeTexCmd "\\parsep"                   ) "skip" (TexEmpty "1pt") "")
           ,("\\parskip"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\parskip"                  ) "skip" (TexEmpty "0pt plus 1pt") "")
           ,("\\partopsep"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\partopsep"                ) "skip" (TexEmpty "1pt") "")
           ,("\\rightskip"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\rightskip"                ) "skip" (TexEmpty "1pt") "")
           ,("\\scriptspace"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\scriptspace"              ) "skip" (TexEmpty "0.5pt") "")
           ,("\\smallskipamount"         , TexRegistry emptyStart emptyStop (makeTexCmd "\\smallskipamount"          ) "skip" (TexEmpty "3pt plus 1pt minus 1pt") "")
           ,("\\spacer"                  , TexRegistry emptyStart emptyStop (makeTexCmd "\\spacer"                   ) "skip" (TexEmpty "1pt") "")
           ,("\\splittopskip"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\splittopskip"             ) "skip" (TexEmpty "10pt") "")
           ,("\\textfloatsep"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\textfloatsep"             ) "skip" (TexEmpty "20\\p@ plus 2\\p@ minus 4\\p@") "")
           ,("\\theorempostskipamount"   , TexRegistry emptyStart emptyStop (makeTexCmd "\\theorempostskipamount"    ) "skip" (TexEmpty "1pt") "")
           ,("\\theorempreskipamount"    , TexRegistry emptyStart emptyStop (makeTexCmd "\\theorempreskipamount"     ) "skip" (TexEmpty "1pt") "")
           ,("\\topsep"                  , TexRegistry emptyStart emptyStop (makeTexCmd "\\topsep"                   ) "skip" (TexEmpty "1pt") "")
           ,("\\topskip"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\topskip"                  ) "skip" (TexEmpty "10pt") "")
           ,("\\z@skip"                  , TexRegistry emptyStart emptyStop (makeTexCmd "\\z@skip"                   ) "skip" (TexEmpty "0pt plus0pt minus0pt") "")
           ,("\\@topsepadd"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\@topsepadd"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\@totalleftmargin"        , TexRegistry emptyStart emptyStop (makeTexCmd "\\@totalleftmargin"         ) "dimen" (TexEmpty "\\z@") "")
           ,("\\algomargin"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\algomargin"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\arraycolsep"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\arraycolsep"              ) "dimen" (TexEmpty "1pt") "")
           ,("\\arrayrulewidth"          , TexRegistry emptyStart emptyStop (makeTexCmd "\\arrayrulewidth"           ) "dimen" (TexEmpty "1pt") "")
           ,("\\arrowwidth"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\arrowwidth"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\basicheight"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\basicheight"              ) "dimen" (TexEmpty "1pt") "")
           ,("\\basicwidth"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\basicwidth"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\bibhang"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\bibhang"                  ) "dimen" (TexEmpty "1pt") "")
           ,("\\bibsep"                  , TexRegistry emptyStart emptyStop (makeTexCmd "\\bibsep"                   ) "dimen" (TexEmpty "1pt") "")
           ,("\\boxmaxdepth"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\boxmaxdepth"              ) "dimen" (TexEmpty "\\maxdimen") "")
           ,("\\boxwidth"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\boxwidth"                 ) "dimen" (TexEmpty "1pt") "")
           ,("\\captionmargin"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\captionmargin"            ) "dimen" (TexEmpty "1pt") "")
           ,("\\columnsep"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\columnsep"                ) "dimen" (TexEmpty "1pt") "")
           ,("\\columnseprule"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\columnseprule"            ) "dimen" (TexEmpty "1pt") "")
           ,("\\columnwidth"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\columnwidth"              ) "dimen" (TexEmpty "1pt") "")
           ,("\\delimitershortfall"      , TexRegistry emptyStart emptyStop (makeTexCmd "\\delimitershortfall"       ) "dimen" (TexEmpty "5pt") "")
           ,("\\dinmargin"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\dinmargin"                ) "dimen" (TexEmpty "1pt") "")
           ,("\\dinwidth"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\dinwidth"                 ) "dimen" (TexEmpty "1pt") "")
           ,("\\doublerulesep"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\doublerulesep"            ) "dimen" (TexEmpty "1pt") "")
           ,("\\epsfxsize"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\epsfxsize"                ) "dimen" (TexEmpty "1pt") "")
           ,("\\evensidemargin"          , TexRegistry emptyStart emptyStop (makeTexCmd "\\evensidemargin"           ) "dimen" (TexEmpty "1pt") "")
           ,("\\extrarowheight"          , TexRegistry emptyStart emptyStop (makeTexCmd "\\extrarowheight"           ) "dimen" (TexEmpty "1pt") "")
           ,("\\fboxrule"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\fboxrule"                 ) "dimen" (TexEmpty "1pt") "")
           ,("\\fboxsep"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\fboxsep"                  ) "dimen" (TexEmpty "1pt") "")
           ,("\\figurewidth"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\figurewidth"              ) "dimen" (TexEmpty "1pt") "")
           ,("\\figwidth"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\figwidth"                 ) "dimen" (TexEmpty "1pt") "")
           ,("\\figwidthfull"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\figwidthfull"             ) "dimen" (TexEmpty "1pt") "")
           ,("\\figwidthhalf"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\figwidthhalf"             ) "dimen" (TexEmpty "1pt") "")
           ,("\\footheight"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\footheight"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\footskip"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\footskip"                 ) "dimen" (TexEmpty "1pt") "")
           ,("\\framewidth"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\framewidth"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\graphheight"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\graphheight"              ) "dimen" (TexEmpty "1pt") "")
           ,("\\graphwidth"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\graphwidth"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\headheight"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\headheight"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\headrulewidth"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\headrulewidth"            ) "dimen" (TexEmpty "1pt") "")
           ,("\\headsep"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\headsep"                  ) "dimen" (TexEmpty "1pt") "")
           ,("\\hfuzz"                   , TexRegistry emptyStart emptyStop (makeTexCmd "\\hfuzz"                    ) "dimen" (TexEmpty "0.1pt") "")
           ,("\\hoffset"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\hoffset"                  ) "dimen" (TexEmpty "1pt") "")
           ,("\\hsize"                   , TexRegistry emptyStart emptyStop (makeTexCmd "\\hsize"                    ) "dimen" (TexEmpty "1pt") "")
           ,("\\itemindent"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\itemindent"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\labelsep"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\labelsep"                 ) "dimen" (TexEmpty "1pt") "")
           ,("\\labelwidth"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\labelwidth"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\leftmargin"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\leftmargin"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\leftmargini"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\leftmargini"              ) "dimen" (TexEmpty "1pt") "")
           ,("\\leftmarginii"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\leftmarginii"             ) "dimen" (TexEmpty "1pt") "")
           ,("\\leftmarginiii"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\leftmarginiii"            ) "dimen" (TexEmpty "1pt") "")
           ,("\\leftmarginiv"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\leftmarginiv"             ) "dimen" (TexEmpty "1pt") "")
           ,("\\leftmarginv"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\leftmarginv"              ) "dimen" (TexEmpty "1pt") "")
           ,("\\leftmarginvi"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\leftmarginvi"             ) "dimen" (TexEmpty "1pt") "")
           ,("\\linewidth"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\linewidth"                ) "dimen" (TexEmpty "1pt") "")
           ,("\\listparindent"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\listparindent"            ) "dimen" (TexEmpty "1pt") "")
           ,("\\marginparpush"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\marginparpush"            ) "dimen" (TexEmpty "1pt") "")
           ,("\\marginparsep"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\marginparsep"             ) "dimen" (TexEmpty "1pt") "")
           ,("\\marginparwidth"          , TexRegistry emptyStart emptyStop (makeTexCmd "\\marginparwidth"           ) "dimen" (TexEmpty "1pt") "")
           ,("\\mathindent"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\mathindent"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\maxdepth"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\maxdepth"                 ) "dimen" (TexEmpty "4pt") "")
           ,("\\maxdimen"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\maxdimen"                 ) "dimen" (TexEmpty "16383.99999pt") "")
           ,("\\normallineskiplimit"     , TexRegistry emptyStart emptyStop (makeTexCmd "\\normallineskiplimit"      ) "dimen" (TexEmpty "0pt") "")
           ,("\\oddsidemargin"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\oddsidemargin"            ) "dimen" (TexEmpty "1pt") "")
           ,("\\overfullrule"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\overfullrule"             ) "dimen" (TexEmpty "5pt") "")
           ,("\\p@"                      , TexRegistry emptyStart emptyStop (makeTexCmd "\\p@"                       ) "dimen" (TexEmpty "1pt") "")
           ,("\\paperheight"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\paperheight"              ) "dimen" (TexEmpty "1pt") "")
           ,("\\paperwidth"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\paperwidth"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\parboxwidth"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\parboxwidth"              ) "dimen" (TexEmpty "1pt") "")
           ,("\\parindent"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\parindent"                ) "dimen" (TexEmpty "20pt") "")
           ,("\\rightmargin"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\rightmargin"              ) "dimen" (TexEmpty "1pt") "")
           ,("\\shortbasicwidth"         , TexRegistry emptyStart emptyStop (makeTexCmd "\\shortbasicwidth"          ) "dimen" (TexEmpty "1pt") "")
           ,("\\showboxbreadth"          , TexRegistry emptyStart emptyStop (makeTexCmd "\\showboxbreadth"           ) "dimen" (TexEmpty "-1") "")
           ,("\\showboxdepth"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\showboxdepth"             ) "dimen" (TexEmpty "-1") "")
           ,("\\splitmaxdepth"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\splitmaxdepth"            ) "dimen" (TexEmpty "\\maxdimen") "")
           ,("\\tabbingsep"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\tabbingsep"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\tabcolsep"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\tabcolsep"                ) "dimen" (TexEmpty "1pt") "")
           ,("\\textheight"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\textheight"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\textwidth"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\textwidth"                ) "dimen" (TexEmpty "1pt") "")
           ,("\\topmargin"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\topmargin"                ) "dimen" (TexEmpty "1pt") "")
           ,("\\unitlength"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\unitlength"               ) "dimen" (TexEmpty "1pt") "")
           ,("\\vfuzz"                   , TexRegistry emptyStart emptyStop (makeTexCmd "\\vfuzz"                    ) "dimen" (TexEmpty "0.1pt") "")
           ,("\\voffset"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\voffset"                  ) "dimen" (TexEmpty "1pt") "")
           ,("\\z@"                      , TexRegistry emptyStart emptyStop (makeTexCmd "\\z@"                       ) "dimen" (TexEmpty "0pt") "")
           ,("\\thepart"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\thepart"                  ) "count" (TexEmpty "0") "")
           ,("\\thechapter"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\thechapter"               ) "count" (TexEmpty "0") "")
           ,("\\thesection"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\thesection"               ) "count" (TexEmpty "0") "")
           ,("\\thesubsection"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\thesubsection"            ) "count" (TexEmpty "0") "")
           ,("\\thesubsubsection"        , TexRegistry emptyStart emptyStop (makeTexCmd "\\thesubsubsection"         ) "count" (TexEmpty "0") "")
           ,("\\theparagraph"            , TexRegistry emptyStart emptyStop (makeTexCmd "\\theparagraph"             ) "count" (TexEmpty "0") "")
           ,("\\thesubparagraph"         , TexRegistry emptyStart emptyStop (makeTexCmd "\\thesubparagraph"          ) "count" (TexEmpty "0") "")
           ,("\\thepage"                 , TexRegistry emptyStart emptyStop (makeTexCmd "\\thepage"                  ) "count" (TexEmpty "0") "")
           ,("\\theequation"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\theequation"              ) "count" (TexEmpty "0") "")
           ,("\\thefigure"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\thefigure"                ) "count" (TexEmpty "0") "")
           ,("\\thetable"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\thetable"                 ) "count" (TexEmpty "0") "")
           ,("\\thefootnote"             , TexRegistry emptyStart emptyStop (makeTexCmd "\\thefootnote"              ) "count" (TexEmpty "0") "")
           ,("\\thempfootnote"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\thempfootnote"            ) "count" (TexEmpty "0") "")
           ,("\\theenumi"                , TexRegistry emptyStart emptyStop (makeTexCmd "\\theenumi"                 ) "count" (TexEmpty "0") "")
           ,("\\theenumii"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\theenumii"                ) "count" (TexEmpty "0") "")
           ,("\\theenumiii"              , TexRegistry emptyStart emptyStop (makeTexCmd "\\theenumiii"               ) "count" (TexEmpty "0") "")
           ,("\\theenumiv"               , TexRegistry emptyStart emptyStop (makeTexCmd "\\theenumiv"                ) "count" (TexEmpty "0") "")
           ,("\\linethickness"           , TexRegistry emptyStart emptyStop (makeTexCmd "\\linethickness"            ) "dimen" (TexEmpty "1pt") "")
--                ,("\"              , TexRegistry emptyStart emptyStop (makeTexCmd "\"              ) "" (TexEmpty "") "")
                ]

readExpr :: String -> String -> Tex
readExpr context input
               = case runParser (tex "tex") (TexState defaultDimentions Map.empty) context input of
                      Left err -> error $ "No match: "  ++ (show err)
                      Right val -> val

tex mode = do   p <- getPosition
                x <- many1 (parseTexItem mode)
                p2 <- getPosition
                return $ Tex (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) x

texCmp tex1 tex2 = compare (texAsTxt tex1) (texAsTxt tex2)

beginEnd mode = do 
                 p <- getPosition
                 sp <- texSpace mode
                 string "\\begin"
                 texSpace mode
                 char '{'
                 tt <- manyTill anyChar (char '}')
                 st <- getState
                 case findMacro (tt) (environmentState st) of 
                     Just rs  -> try $ do
                                   (expText1,expText2) <- expandEnvironment mode rs
                                   inp <- getInput
                                   pT <-  getPosition
                                   t <- manyTill (try $ parseTexItem mode) (try $ lookAhead ((texSpace mode) >> string "\\end" >> (texSpace mode) >> char '{' >> string tt >> char '}'))
                                   inp2 <- getInput
                                   envT <- return $ 
                                                    take (length inp - length inp2) inp
                                   texSpace mode 
                                   string "\\end"
                                   texSpace mode
                                   char '{'
                                   string tt
                                   char '}'
                                   inp2 <- getInput
                                   setInput $ ( sp ++ expText1 ++ (concat $ map (texAsTxt) t) ++ expText2 ++ inp2)
                                   return $ TexEmpty ""
                     Nothing -> try $ do
                                        br <- optionMaybe ( try (betweenBrackets mode))
                                        x <- manyTill (try $ parseTexItem mode)
                                                      ((lookAhead (try $ do (texSpace mode)
                                                                            string "\\end" 
                                                                            (texSpace mode)
                                                                            char '{'
                                                                            string tt
                                                                            char '}')))
                                        esp <- texSpace mode
                                        string "\\end"
                                        texSpace mode
                                        char '{'
                                        string tt
                                        char '}'
                                        p2 <- getPosition
                                        r <- return $ TexGroup (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ("\\begin{" ++ tt ++ "}") (esp ++ "\\end{" ++ tt ++ "}") x sp
                                        if tt == "document" then do
                                                                 setInput ("\n")
                                                                 return r
                                                            else return r

math "math" = fail ""
math mode = do   p <- getPosition
                 sp <- texSpace mode
                 ((try (do string "$$"
                           x <- manyTill (try $ parseTexItem "math") (try (lookAhead ((texSpace mode) >> string "$$")))
                           esp <- texSpace mode
                           string "$$"
                           p2 <- getPosition
                           return $ TexMathDisp (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "$$" (esp ++ "$$") x sp))
                  <|> (try (do string "\\["
                               x <- manyTill (try $ parseTexItem "math") (try (lookAhead ((texSpace mode) >> string "\\]")))
                               esp <- texSpace mode
                               string "\\]"
                               p2 <- getPosition
                               return $ TexMathDisp (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "\\[" (esp ++ "\\]") x sp))
                  <|> (try (do string "\\begin"
                               texSpace mode
                               b <- ( do 
                                         char '{'
                                         texSpace mode
                                         bT <- (try (many1 (try ((try $ char '*') <|> (try $ char '@') <|> (try letter)))))
                                         texSpace mode  
                                         char '}'
                                         if elem bT  ["align",                 "math",           "math*",                     "displaymath", 
                                                      "displaymath*",          "optprog",        "equationarray",             "diagram",
                                                      "align*",                "gather",         "gather*",                   "array", 
                                                      "array*",                "gathered",       "equation",                  "equation*",
                                                      "subequations",          "subequations*",  "alignat",                   "alignat*",
                                                      "flalign",               "flalign*",       "aligned",                   "alignedat",
                                                      "subeqnarray",           "subeqnarray*",   "eqnarray",                  "eqnarray*", 
                                                      "Eqnarray",              "Eqnarray*",      "multline",                  "displaymath", 
                                                      "displaymath*",          "split",          "argue",                     "pmatrix",
                                                      "bmatrix",               "Bmatrix",        "vmatrix",                   "Vmatrix",
                                                      "matrix",                "multline*"]
                                           then return bT
                                           else fail ""
                                    )
                               x <- manyTill (try $ parseTexItem "math")
                                             (try (lookAhead (try $ do (texSpace mode)
                                                                       string "\\end"
                                                                       (texSpace mode)
                                                                       char '{'
                                                                       (texSpace mode)
                                                                       string b
                                                                       (texSpace mode)
                                                                       char '}' )))
                               esp <- texSpace mode
                               string "\\end"
                               texSpace mode
                               char '{'
                               texSpace mode
                               string b
                               texSpace mode
                               char '}'
                               p2 <- getPosition
                               return $ TexMathDisp (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ("\\begin" ++ "{" ++ b ++ "}") (esp ++ "\\end" ++ "{" ++ b ++ "}") x sp))
                  <|> (try (do string "\\ensuremath"
                               texSpace mode
                               string "{"
                               x <- manyTill (try $ parseTexItem "math") (try (lookAhead ((texSpace mode) >> string "}" >> (texSpace mode))))
                               esp <- texSpace mode
                               string "}"
                               texSpace mode
                               p2 <- getPosition
                               return $ TexMath (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ("\\ensuremath{") (esp ++ "}") x sp))
                  <|> (try (do string "\\("
                               x <- manyTill (try $ parseTexItem "math") (try (lookAhead ((texSpace mode) >> string "\\)")))
                               esp <- texSpace mode
                               string "\\)"
                               p2 <- getPosition
                               return $ TexMath (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "\\(" (esp ++ "\\)") x sp))
                  <|> (do string "$"
                          x <- manyTill (try $ parseTexItem "math") (try (lookAhead ((texSpace mode) >> string "$")))
                          esp <- texSpace mode
                          string "$"
                          p2 <- getPosition
                          return $ TexMath (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "$" (esp ++ "$") x sp
                      ))

verbatim mode = (try $
                 do p <- getPosition
                    sp <- texSpace mode
                    x <- (try ( do string "\\begin{verbatim}"
                                   x1 <- manyTill anyChar (try (string "\\end{verbatim}"))
                                   return $ x1))
                         <|>  ( do string "\\verb"
                                   notFollowedBy letter
                                   c <- anyChar
                                   x1 <- manyTill anyChar (char c)
                                   return $ x1)
                    p2 <- getPosition
                    return $ TexVerbatim (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) x sp)
                <|> (try ( do p <- getPosition
                              sp <- texSpace mode
                              string "\\begin{alltt}"
                              x <- manyTill anyChar (try (string "\\end{alltt}"))
                              p2 <- getPosition
                              return $ TexVerbatimAllTT (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) x sp
                    ))
                <|> (try ( do p <- getPosition
                              sp <- texSpace mode
                              string "\\begin{lstlisting}"
                              x <- manyTill anyChar (try (string "\\end{lstlisting}"))
                              p2 <- getPosition
                              return $ TexVerbatimListing (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) x sp
                    ))
                <|> (try ( do p <- getPosition
                              sp <- texSpace mode
                              string "\\end{algorithmic}"
                              x <- manyTill anyChar (try (string "\\end{algorithmic}"))
                              p2 <- getPosition
                              return $ TexVerbatimListing (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) x sp
                    ))
                <|> (try ( do p <- getPosition
                              sp <- texSpace mode
                              string "\\end{algorithm2e}"
                              x <- manyTill anyChar (try (string "\\end{algorithm2e}"))
                              p2 <- getPosition
                              return $ TexVerbatimListing (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) x sp
                    ))


betweenBrackets mode
                = do if mode == "tex"
                     then do p <- getPosition
                             sp <- texSpace mode
                             char '['
                             br1 <- texSpace mode
                             x <- manyTill (try $ parseTexItem mode) ( try (lookAhead ((texSpace mode) >> char ']')))
                             br <- texSpace mode
                             char ']'
                             p2 <- getPosition
                             return $ TexBraces (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ("[" ++ br1 ) (br ++ "]") x sp
                     else do p <- getPosition    
                             sp <- texSpace mode
                             char '['
                             p2 <- getPosition
                             return $ TexToken (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "[" sp

betweenBraces mode
              = (try $
                do p <- getPosition
                   sp <- texSpace mode
                   char '{'
                   sp1 <- texSpace mode
                   char '$'
                   sp2 <- texSpace mode
                   char '}'
                   p2 <- getPosition
                   let x = TexSymbol (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) (sp1 ++ "$" ++ sp2) ""
                   return $ TexBraces (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "{" "}" [x] sp
                )
                <|>
                (try $
                do p <- getPosition
                   sp <- texSpace mode
                   char '{'
                   sp1 <- texSpace mode
                   x <- string "$$"
                   sp2 <- texSpace mode
                   char '}'
                   p2 <- getPosition
                   let x = TexSymbol (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) (sp1 ++ "$$" ++ sp2) ""
                   return $ TexBraces (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "{" "}" [x] sp
                )
                <|>
                (try $
                do p <- getPosition
                   sp <- texSpace mode
                   (char '<' <|> char '>')
                   char '{'
                   sp1 <- texSpace mode
                   [x1] <- many1 ((try $ do t <- texCommandToken mode
                                            return $ texAsTxt t) <|> (string "$"))
                   sp2 <- texSpace mode
                   char '}'
                   p2 <- getPosition
                   let x = TexSymbol (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) (sp1 ++ x1 ++ sp2) ""
                   return $ TexBraces (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "{" "}" [x] sp
                )
                <|>
                (try $ do 
                   p <- getPosition
                   sp <- texSpace mode
                   char '{'
                   x <- manyTill (try $ parseTexItem mode) ( try (lookAhead ((texSpace mode) >> char '}')))
                   br <- texSpace mode
                   char '}'
                   p2 <- getPosition
                   return $ TexBraces (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "{" (br ++ "}") x sp)

betweenBracesTokens mode
              = (try $
                do p <- getPosition
                   sp <- texSpace mode
                   char '{'
                   sp1 <- texSpace mode
                   x <- char '$'
                   sp2 <- texSpace mode
                   char '}'
                   p2 <- getPosition
                   let x = TexSymbol (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) (sp1 ++ "$"++ sp2) ""
                   return $ TexBraces (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "{" "}" [x] sp
                )
                <|>
                (try $
                do p <- getPosition
                   sp <- texSpace mode
                   char '{'
                   sp1 <- texSpace mode
                   x <- string "$$"
                   sp2 <- texSpace mode
                   char '}'
                   p2 <- getPosition
                   let x = TexSymbol (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) (sp1 ++ "$$" ++ sp2) ""
                   return $ TexBraces (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "{" "}" [x] sp
                )
                <|>
                (try $ do p <- getPosition
                          sp <- texSpace mode
                          char '{'
                          x <- manyTill (try $ parseTexToken mode) ( try (lookAhead ((texSpace mode) >> char '}')))
                          br <- texSpace mode
                          char '}'
                          p2 <- getPosition
                          return $ TexBraces (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "{" (br ++ "}") x sp
                )

betweenBracesTokensText mode
                    = do p <- getPosition
                         sp <- texSpace mode
                         char '{'
                         x <- manyTill (try $ parseTexToken mode) ( try (lookAhead ((texSpace mode) >> char '}')))
                         br <- texSpace mode
                         char '}'
                         p2 <- getPosition
                         return $ TexBraces (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "" (br) x sp


betweenBracesTokens2 mode
                     = do p <- getPosition
                          sp <- texSpace mode
                          char '{'
                          x <- manyTill (try $ parseTexToken2 mode) ( try (lookAhead ((texSpace mode) >> char '}')))
                          br <- texSpace mode
                          char '}'
                          p2 <- getPosition
                          return $ TexBraces (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "{" (br ++ "}") x sp

texSpaces mode = (many1 (texSpace mode))

tabV = do char '\t' ; return ' '

texSpace mode =  do r <- (many ((try $ do s <- texSpaceT mode; return [s]) 
                                <|> (try $ do e <- eol mode
                                              notFollowedBy (try ((many (texSpaceT mode)) >> eol mode))
                                              return e)
                                <|> (try $ do comment mode
                                              return "")
                               ))
                    return $ concat r

texSpace2 mode =  do r <- (many ((try $ do s <- texSpaceT mode; return [s]) 
                                 <|> (do e <- eol mode
                                         notFollowedBy (try ((many (texSpaceT mode)) >> eol mode))
                                         return e)
                                         ))
                     return $ concat r


spaceT = do s <- space 
            if elem s "\n\r" then fail "" else return s

texSpaceT mode = (try spaceT 
                        <|> (char '~') 
                        <|> tabV)


texToken mode 
         = do p <- getPosition
              sp <- texSpace mode
              x <- letter
              p2 <- getPosition
              return $ TexToken (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) [x] sp

texDigit mode
         = do p <- getPosition
              sp <- (try (texSpace mode))
              x <- digit
              p2 <- getPosition
              return $ TexDigit (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) [x] sp

comment1 mode
         = do  p <- getPosition
               char '%'
               x <- manyTill anyChar (try (lookAhead (eol mode))) 
               sp2 <- ((try $ lookAhead (try $ texPar mode) >> return [])
                       <|> eol mode)
               p2 <- getPosition
               return $ TexComment (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2))  ("%" ++ x ++ (sp2)) ""

comment mode = try (comment1 mode)

updateEnvironmentList (n2@(TexNewEnvironment _ _ mmm _ _ _ _ _)) p list
                               = case Map.lookup mmm (environmentState list) of
                                 Just m -> if p then list {macroState = (Map.insert mmm n2 (environmentState list))}
                                                else (error $ "Redefining '" ++ mmm ++ "', which is defined already")
                                 Nothing -> list {environmentState = (Map.insert mmm n2 (environmentState list))}

updateMacroList (n2@(TexNewCommand _ _ (TexCommand _ _ mmm _ _) _ _ _ _)) p list
                           = if (elem mmm doNotRedefine)
                             then list
                             else
                                 case Map.lookup mmm (macroState list) of
                                 Just m -> if p then list {macroState = (Map.insert mmm n2 (macroState list))}
                                                else (error $ "Redefining '" ++ mmm ++ "', which is defined already")
                                 Nothing -> list {macroState = (Map.insert mmm n2 (macroState list))}

updateMacroList (n2@(TexDef _ _ (TexCommand _ _ mmm _ _) _ _ _)) p list 
                           = if (elem mmm doNotRedefine)
                             then list
                             else
                                 case  Map.lookup mmm (macroState list) of
                                 Just m -> if p then list {macroState = (Map.insert mmm n2 (macroState list))}
                                                else (error $ "Redefining '" ++ mmm ++ "', which is defined already")
                                 Nothing -> list {macroState = (Map.insert mmm n2 (macroState list))}


updateMacroList (n2@(TexRegistry _ _ (TexCommand _ _ mmm _ _) _ _ _)) p list 
                               = case  Map.lookup mmm (macroState list) of
                                 Just m -> if p then list {macroState = (Map.insert mmm n2 (macroState list))}
                                                else (error $ "Redefining '" ++ mmm ++ "', which is defined already")
                                 Nothing -> list {macroState = (Map.insert mmm n2 (macroState list))}

findMacro cmd st  = do
                    case Map.lookup cmd st of
                         Just m -> Just m
                         Nothing -> Nothing

expandEnvironment mode (TexNewEnvironment _ _ cmd ars defs expnd expnd2 sp)
                 = do
                     texSpace mode
                     rrs <- case defs of 
                            Nothing -> (try $ count ars (try $ parseTexToken mode))
                            Just df ->
                                  (do
                                   texSpace mode
                                   ccc3 <- option Nothing  (do   char '['
                                                                 m <- try (manyTill (try $ parseTexToken "def") ( try (texSpace mode >> char ']')))
                                                                 return $ Just $ concat $ map (texAsTxt) m
                                                           )
                                   p2 <- getPosition
                                   df <- case ccc3 of 
                                                     Nothing -> return df
                                                     Just xs -> return xs
                                   texSpace mode
                                   rrss <- count (ars-1) (try $ parseTexToken mode)
                                   return ((TexToken (Start (sourceLine p2) (sourceColumn p2)) (Stop (sourceLine p2) (sourceColumn p2))  df ""):rrss))
                     let r = concat (map (applyMacro1 rrs) expnd)
                     let r2 = case r of
                                   (h:rs) -> if isAlpha h then ' ':r
                                                          else r
                                   _ -> r
                     let rT = concat (map (applyMacro1 rrs) expnd2)
                     let rT2 = case r of
                                   (h:rs) -> if isAlpha h then ' ':rT
                                                          else rT
                                   _ -> rT
                     return $ (r2,rT2)

expandMacro mode (TexNewCommand _ _ cmd ars defs expnd sp)
                 = do
                     if ars == 0 && length expnd == 0
                      then (texSpace mode)
                      else if length expnd == 0
                              then return []
                              else if isTexCommand (last expnd)
                                   then return []
                                   else (texSpace mode)
                     rrs <- case defs of 
                            Nothing -> 
                                       countWithBreak (ars) (try $ parseTexToken mode) ((texSpace mode) >> (char '}'))
                            Just df ->
                             (try $ do
                                   texSpace mode
                                   ccc3 <- option Nothing  (do   char '['
                                                                 m <- try (manyTill (try $ parseTexToken mode) ( try (texSpace mode >> char ']')))
                                                                 return $ Just $ concat $ map (texAsTxt) m
                                                           )
                                   p2 <- getPosition
                                   df <- case ccc3 of 
                                                     Nothing -> return df
                                                     Just xs -> return xs
                                   texSpace mode
                                   rrss <- countWithBreak (ars-1) (try $ parseTexToken mode) ((texSpace mode) >> (char '}'))
                                   return ((TexToken (Start (sourceLine p2) (sourceColumn p2)) (Stop (sourceLine p2) (sourceColumn p2))  df ""):rrss))
                     let r = concat (map (applyMacro1 rrs) expnd)
                     let r2 = case r of
                                   (h:rs) -> if isAlpha h then r
                                                          else r
                                   _ -> r
                     return $ r2

expandMacro mode (TexDef _ _ cmd regex expnd sp)
                 = do
                     if numberOfArgs regex == 0 && length expnd == 0
                      then (texSpace mode)
                      else if length expnd == 0
                              then return []
                              else if isTexCommand (last expnd)
                                   then return []
                                   else (texSpace mode)
                     rrs <- scanDefArgs mode regex <?> "error in parsing arguments." 
                     let  r = concat (map (applyMacro rrs) expnd)
                     let r2 = case r of
                                   (h:rs) -> if isAlpha h then r
                                                          else r
                                   _ -> r
                     return $ r2

numberOfArgs ((TexDefArgExp {}):regex) = 1 + numberOfArgs regex
numberOfArgs (x:xs) = numberOfArgs xs
numberOfArgs [] = 0



countWithBreak 0 pr br = return $ []
countWithBreak n pr br = do x <- try $ optionMaybe $ lookAhead $ try br 
                            case x of
                                 Nothing -> do p <- pr
                                               ps <- countWithBreak (n-1) pr br
                                               return (p:ps)
                                 Just _ -> do return $ replicate n (TexEmpty "") 


texAsTxtMacroExpand (TexBraces _ _ b e tex sp) = (concat $ map (texAsTxt) tex)
texAsTxtMacroExpand xs = texAsTxt xs

applyMacro1 rrs (TexNewCommandArg _ _ p "#" sp) = if p <= length rrs then (sp ++ (texAsTxtMacroExpand (rrs!!(p-1)))) else error $ "Index too large. Probaly, an error in the deffinition of the macro!!!"
applyMacro1 rrs (TexNewCommandArg _ _ p (d:ds) _) = error $ "Sorry. Incremetal arguments are not implemented yet!!!"
applyMacro1 rrs (TexBraces p1 p2 bb be xs sp) =  sp ++ bb ++ (concat $ map (applyMacro1 rrs) xs)  ++ be   
applyMacro1 rrs x = texAsTxt x

applyMacro rrs (TexNewCommandArg _ _ p "#" sp) = if p <= length rrs then (sp ++ res) else error $ "Index too large. Probaly, an error in the deffinition of the macro!!!"
                                                 where 
                                                    res = concat $ map texAsTxtMacroExpand (rrs!!(p-1))
applyMacro rrs (TexNewCommandArg _ _ p (d:ds) _) = error $ "Sorry. Incremetal arguments are not implemented yet!!!"
applyMacro rrs (TexBraces p1 p2 bb be xs sp) =  sp ++ bb ++ (concat $ map (applyMacro rrs) xs) ++ be   
applyMacro rrs x = texAsTxt x

endGroup  mode = do texSpace mode
                    char '}'
beginGroup  mode = do texSpace mode
                      char '{'

scanDefArgs mode ((TexDefArgExp _ _ regPos1):(TexDefArg _ _ " "):(a@(TexDefArgExp _ _ 0)):rs)
                                  = do b <- optionMaybe $ try $ lookAhead $ try $ endGroup mode
                                       case b of
                                        Just _ -> return [[],[]]
                                        Nothing -> do
                                                   r <- (manyTill (try $ parseTexToken mode) (try (texSpaces mode) >> try (lookAhead (string "{")))) <?> "Error in scaning \\def argmuments!!!!\n"
                                                   return $ [r]

scanDefArgs mode ((TexDefArgExp _ _ regPos1):(TexDefArg _ _ str):(a@(TexDefArgExp _ _ 0)):rs)
                                  = do b <- optionMaybe $ try $ lookAhead $ try $ endGroup mode
                                       case b of
                                        Just _ -> return [[],[]]
                                        Nothing -> do
                                                   r <- (manyTill (try $ parseTexToken mode) (try (string str) >> try (lookAhead (string "{")))) <?> "Error in scaning \\def argmuments!!!!\n"
                                                   return $ [r]

scanDefArgs mode ((TexDefArgExp _ _ regPos1):(a@(TexDefArgExp _ _ 0)):rs)
                                  = do b <- optionMaybe $ try $ lookAhead $ try $ endGroup mode
                                       case b of
                                        Just _ -> return [[],[]]
                                        Nothing -> do
                                                   r <- (manyTill (try $ parseTexToken mode) (try $ lookAhead (char '{'))) <?> "Error in scaning \\def argmuments!!!!\n"
                                                   return $ [r]

scanDefArgs mode ((TexDefArgExp _ _ regPos1):(a@(TexDefArgExp _ _ pregPos2)):rs)
                                  = do b <- optionMaybe $ try $ lookAhead $ try $ endGroup mode
                                       case b of
                                        Just _ -> return $ replicate (2 + ( length  rs))  []
                                        Nothing -> do
                                                   r <- ((try $ parseTexToken mode) <?> "Error in scaning \\def argmuments!!!!\n")
                                                   rs <- (try $ scanDefArgs mode (a:rs))
                                                   return ([r]:rs)

scanDefArgs mode ((TexDefArgExp _ _ regPos1):(a@(TexDefArg _ _ " ")):rs)
                                  = do b <- optionMaybe $ try $ lookAhead $ try $ endGroup mode
                                       case b of
                                        Just _ -> return $ replicate (1 + ( length  rs))  []
                                        Nothing -> do
                                                   r <- (manyTill (try $ parseTexToken mode) (try (texSpaces mode))) <?> "Error in scaning \\def argmuments!!!!\n"
                                                   rs <- try $ scanDefArgs mode (rs)
                                                   return (r:rs)

scanDefArgs mode ((TexDefArgExp _ _ regPos1):(a@(TexDefArg _ _ str)):rs)
                                  = do b <- optionMaybe $ try $ lookAhead $ try $ endGroup mode
                                       case b of
                                        Just _ -> return $ replicate (1 + ( length  rs))  []
                                        Nothing -> do
                                                   r <- (manyTill (try $ parseTexToken mode) (try (string str))) <?> "Error in scaning \\def argmuments!!!!\n"
                                                   rs <- try $ scanDefArgs mode (rs)
                                                   return (r:rs)

scanDefArgs mode [(TexDefArgExp _ _ 0)]
                                  = do (try $ lookAhead (try $ texSpace mode >> char '{')) <?> "Error in scaning \\def argmuments!!!!\n"
                                       return []
scanDefArgs mode ((TexDefArgExp _ _ regPos1):rs)
                                  = do b <- optionMaybe $ try $ lookAhead $ try $ endGroup mode
                                       case b of
                                          Just _ -> return $ replicate (1 + ( length  rs))  []
                                          Nothing -> do
                                                     r <- (try $ parseTexToken mode) <?> "Error in scaning \\def argmuments!!!!\n"
                                                     rs <- (try $ scanDefArgs mode rs)
                                                     return ([r]:rs)
scanDefArgs mode ((TexDefArg _ _ " "):rs)
                                  = do (try $ texSpaces mode) <?> "Error in scaning \\def argmuments!!!!\n"
                                       scanDefArgs mode rs

scanDefArgs mode ((TexDefArg _ _ str):rs)
                                  = do (string str) <?> "Error in scaning \\def argmuments!!!!\n"
                                       scanDefArgs mode rs
scanDefArgs mode [] = return []
scanDefArgs mode xs = error $ "Error in scaning \\def argmuments!!!!\n" ++ (show xs)

isTexCommand (TexCommand {}) = True
isTexCommand _ = False

isTexDefArgExp (TexDefArgExp {}) = True
isTexDefArgExp _ = False

argsNumberedOK c ((TexDefArg _ _ _):rs) = argsNumberedOK c rs 
argsNumberedOK c [(TexDefArgExp _ _ 0)] = True
argsNumberedOK c ((TexDefArgExp _ _ p):rs) = if p==(c+1) then argsNumberedOK p rs else False
argsNumberedOK c x = True

texPar mode = do 
                many (texSpaceT mode)
                rs <- many1 ((try (do 
                                     string "\\par"
                                     notFollowedBy letter
                                     return "\n\n")) 
                             <|> (do 
                                     r1 <- eol mode
                                     r <-  many1 (eol mode)
                                     return (concat ((r1):r)))
                            )
                return $ concat rs

texParToken mode 
            = do  p <- getPosition
                  rs <- texPar mode
                  p2 <- getPosition
                  return $ TexPar (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "\\par" (rs)

texNewCommandArg mode
                 = do p <- getPosition
                      sp <- texSpace mode
                      cc <- many1 (char '#')
                      x <- digit
                      if length cc == 1
                      then do 
                            p2 <- getPosition
                            return $ TexNewCommandArg (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) (read [x]) cc sp
                      else do
                            p2 <- getPosition
                            return $ TexSymbol (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ((tail cc) ++ [x]) sp

texCommandToken mode
                = (try $ csname mode)
                  <|> 
                  (do p <- getPosition
                      sp <- texSpace mode
                      char '\\'
                      x <- ((try (many1 ((char '*') <|> (char '@') <|> (letter))))
                           <|> (count 1 anyChar))
                      p2 <- getPosition
                      st <- getState
                      case (findMacro ('\\':x) (macroState st)) of
                           Just (TexRegistry pp1 pp2 cmd t v spp)
                                    ->  return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':x) [] sp
                           Just rs -> (try $ do if mode == "def"
                                                 then (return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':x) [] sp)
                                                 else (try $ do
                                                               expText <- expandMacro "def" rs
                                                               inp <- getInput
                                                               setInput $ ( sp ++ expText ++ inp) 
                                                               texCommandToken mode
                                                      )
                                                      <|> 
                                                      (return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':x) [] sp)
                                      )
                           _        -> return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':x) [] sp
                  ) 

tryExpand mode  = ( do
                      xT <- lookAhead $ try $ texCommandToken "def"
                      Just (x,sp) <- return $ getCommandName xT
                      st <- getState
                      case (findMacro ('\\':x) (macroState st)) of
                           Just (TexRegistry pp1 pp2 cmd t v spp)
                                    -> return ""
                           Just rs -> try $ do texCommandToken "def"
                                               expText <- expandMacro "def" rs
                                               inp <- getInput
                                               setInput $ ( sp ++ expText ++ inp) 
                                               rt <- optionMaybe $ try $ tryExpand mode
                                               return ""
                           _        -> return ""
                  )<|>(return "")




texDefArgExpTokenEnd mode
                     = do  p <- getPosition
                           texSpace mode
                           cc <- char '#'
                           x <- lookAhead (try $ texSpace mode >> char '{')
                           p2 <- getPosition
                           return $ TexDefArgExp (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) 0

texDefArgExpToken mode
                  = do  p <- getPosition
                        texSpace mode
                        cc <- char '#'
                        x <- digit
                        p2 <- getPosition
                        return $ TexDefArgExp (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) (read [x])

texChar mode = do c <- (try anyChar)
                  return $ [c]

texDefSpace mode = do try (many1 spaceT)
                      return " "

texDefArgToken mode = do  p <- getPosition
                          cc <- ((try (texDefSpace mode)) <|> (try (texPar mode)) <|> (texChar mode))
                          p2 <- getPosition
                          return $ TexDefArg (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) cc 

texDefArg mode = do
               ((try (texDefArgExpToken mode)) <|> (try (texDefArgExpTokenEnd mode)) <|> (texDefArgToken mode))

nextItem mode = do 
                   x <- parseTexItem mode
                   case x of
                        (TexEmpty "") -> nextItem mode
                        x             -> return x 

texCommand mode
          = do p <- getPosition
               xT <- (try $ texCommandToken "def")
               Just (x,sp) <- return $ getCommandName xT
               st <- getState
               (
                (try $ case (findMacro ('\\':x) (macroState st)) of
                            Just (tr@(TexRegistry pp1 pp2 cmd t _ spp))
                                     -> do
                                          texMeasure (if t == "count" || t == "language" then "nostrech" else "dimen")
                                          return $ TexEmpty ""
                            Just rs  -> do
                                          expText <- expandMacro "def" rs
                                          inp <- getInput
                                          setInput $ ( sp ++ expText ++ inp)
                                          return $ TexEmpty ""
                            Nothing -> fail "" )
                <|> 
                ( if last x == '*'
                  then  try $ case (findMacro ('\\':(init x)) (macroState st)) of
                            Just rs  -> do
                                          inp <- getInput
                                          setInput $ ( "*" ++ inp) 
                                          expText <- expandMacro "def" rs
                                          inp <- getInput
                                          setInput $ ( sp ++ expText ++ inp) 
                                          return $ TexEmpty ""
                            Nothing -> fail ""
                  else fail "" 
                )
                <|> 
                ( try $ if x /= "catcode" then fail "" else error "\\catcode's are not supported!!!! Please remove them." 
                )
                <|> 
                (try $ if x /= "let" then fail "" else do
                                                      texSpace mode
                                                      ccc1 <- (( try
                                                                    (do char '{'
                                                                        cccc1 <- (try (texCommandToken "def"))
                                                                        texSpace mode
                                                                        char '}'
                                                                        return cccc1))
                                                               <|> (try $ texCommandToken "def"))
                                                      texSpace mode
                                                      optionMaybe (char '=')
                                                      texSpace mode
                                                      ccc2 <- ((try (do char '{'
                                                                        cccc1 <- (try (texCommandToken mode))
                                                                        texSpace mode 
                                                                        char '}'
                                                                        return cccc1))
                                                               <|> (try $ texCommandToken mode) 
                                                               <|> (try $ texSymbol "symbol"))
                                                      texSpace mode
                                                      rt <- case (findMacro ('\\':x) (macroState st)) of
                                                                 Just (TexNewCommand pp1 pp2 cmd ars defs expnd sp)
                                                                       -> do return (TexNewCommand pp1 pp2 ccc1 ars defs expnd sp)
                                                                 Just (TexDef pp1 pp2 cmd regex expnd sp)
                                                                       -> do return (TexDef pp1 pp2 ccc1 regex expnd sp)
                                                                 Nothing -> do
                                                                             p2 <- getPosition
                                                                             Just (x,sp) <- return $ getCommandName ccc2
                                                                             ccc2 <- return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ("\\LET" ++ x) [] sp
                                                                             return  (TexDef (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ccc1 [] [ccc2] sp)
                                                      updateState (updateMacroList rt True)
                                                      return $ TexEmpty sp
                 )
                <|> 
                (try $ if x /= "newcommand" && x /= "providecommand" && x /= "newcommand*" && x /= "providecommand*" && x/= "DeclareRobustCommand"
                       then fail "" else do
                                                      mode <- return "def"
                                                      texSpace mode
                                                      ccc1 <- (try $ do char '{'
                                                                        texSpace mode
                                                                        cccc1 <- (try (texCommandToken "def"))
                                                                        texSpace mode
                                                                        char '}'
                                                                        return cccc1)
                                                              <|> (try $ texCommandToken "def")
                                                      texSpace mode
                                                      ccc2 <- option "0" (try $ do   char '['
                                                                                     cccc2 <- (try (many1 digit))
                                                                                     texSpace mode
                                                                                     char ']'
                                                                                     return (cccc2))
                                                      texSpace mode
                                                      ccc3 <- option Nothing  ((try
                                                                                  $ do   char '['  
                                                                                         rr <- (try (manyTill (parseTexToken "def") (try $ texSpace mode >> char ']')))
                                                                                         return $ Just $ concat $ map (texAsTxt) rr)
                                                                               <|>(try
                                                                                   $ do   char '['  
                                                                                          texSpace mode
                                                                                          char ']'
                                                                                          return $ Just ([])))
                                                      texSpace mode
                                                      ccc4 <- option []  (try $ do   char '{'
                                                                                     manyTill ( (try (texNewCommandArg mode)) <|> (try $ parseTexToken2 mode)) (try ((try (texSpace mode)) >> char '}')))
                                                      p2 <- getPosition
                                                      rt <- return $! TexNewCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ccc1 (read ccc2) ccc3 ccc4 sp
                                                      updateState (updateMacroList rt True)
                                                      return $ TexEmpty sp
                 )
                 <|> (if x /= "renewcommand" && x /= "renewcommand*"
                      then fail ""
                      else try $ do
                                                      mode <- return "def"
                                                      texSpace mode
                                                      ccc1 <- (do char '{'
                                                                  texSpace mode
                                                                  cccc1 <- (try (texCommandToken "def"))
                                                                  texSpace mode
                                                                  char '}'
                                                                  return cccc1)
                                                              <|> (try $ texCommandToken "def")
                                                      texSpace mode
                                                      ccc2 <- option "0" (try $ do   char '['
                                                                                     cccc2 <- (try (many1 digit))
                                                                                     texSpace mode
                                                                                     char ']'
                                                                                     return (cccc2))
                                                      texSpace mode
                                                      ccc3 <- option Nothing  (try
                                                                                  $ do   char '['  
                                                                                         rr <- (try (manyTill (try $ parseTexToken "def") (try $ texSpace mode >>  char ']')))
                                                                                         return $ Just $ concat $ map (texAsTxt) rr
                                                                              )
                                                      texSpace mode
                                                      ccc4 <- option []  (try $ do   char '{'
                                                                                     manyTill ( (try (texNewCommandArg mode)) <|> (try $ parseTexToken2 mode)) (try ((try (texSpace mode)) >> char '}')))
                                                      p2 <- getPosition
                                                      rt <- return $! TexNewCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ccc1 (read ccc2) ccc3 ccc4 sp
                                                      updateState (updateMacroList rt True)
                                                      return $ TexEmpty sp
                 )
                 <|> (if x /= "newenvironment" && x /= "renewenvironment" &&  x /= "newenvironment*" && x /= "renewenvironment*"
                      then fail ""
                      else try $ do
                                                      mode <- return "def"
                                                      texSpace mode
                                                      ccc1 <- (do char '{'
                                                                  cccc1 <- (try (manyTill anyChar ( char '}')))
                                                                  return cccc1)
                                                      texSpace mode
                                                      ccc2 <- option "0" (try $ do   char '['
                                                                                     texSpace mode
                                                                                     cccc2 <- (try (many1 digit))
                                                                                     texSpace mode
                                                                                     char ']'
                                                                                     return (cccc2))
                                                      texSpace mode
                                                      ccc3 <- option Nothing  (try
                                                                                  $ do   char '['  
                                                                                         texSpace mode
                                                                                         rr <- (try (manyTill (try $ parseTexToken "def") (try $ texSpace mode >> char ']')))
                                                                                         return $ Just $ concat $ map (texAsTxt) rr
                                                                              )
                                                      texSpace mode
                                                      ccc4 <- option []  (try $ do   char '{'
                                                                                     manyTill ( (try (texNewCommandArg mode)) <|> (try $ parseTexToken2 mode)) (try ((texSpace mode) >> char '}')))
                                                      ccc5 <- option []  (try $ do   texSpace mode
                                                                                     char '{'
                                                                                     manyTill ( (try (texNewCommandArg mode)) <|> (try $ parseTexToken2 mode)) (try ( (texSpace mode) >> char '}'))
                                                                         )
                                                      p2 <- getPosition
                                                      rt <- return $! TexNewEnvironment (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ccc1 (read ccc2) ccc3 ccc4 ccc5 sp
                                                      updateState (updateEnvironmentList rt True)
                                                      return $ TexEmpty sp
                 )
                 <|> (if x /= "def" && x /= "edef" && x /= "gdef" && x /= "xdef"
                      then fail ""
                      else try $ do
                                                      mode <- return "def"
                                                      texSpace mode
                                                      ccc1 <- (try $ texCommandToken "def") <|> (try $ csname mode)
                                                      texSpace mode
                                                      ccc2 <- manyTill (try $ texDefArg mode) (try $ texSpace mode >> char '{')
                                                      if argsNumberedOK 0 ccc2 then return ()
                                                                            else error "\\def arguments should be numbered consequtively !!!!"
                                                      ccc3 <- manyTill ( (try (texNewCommandArg mode)) <|> (try $ parseTexToken2 mode)) (try ((try (texSpace mode)) >> char '}'))
                                                      p2 <- getPosition
                                                      rt <- return $! TexDef (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ccc1 ccc2 ccc3 sp
                                                      updateState (updateMacroList rt True)
                                                      return $ TexEmpty sp
                 )
                 <|> ( if x /= "par" 
                       then fail ""
                       else try $ do
                                                      texSpace mode
                                                      p2 <- getPosition
                                                      return $ TexPar (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "\n\n" (sp)
                 )
                 <|>(if x /= "count" && x /= "language"
                     then fail ""
                     else do texSpace mode
                             many1 digit
                             return $ TexEmpty ""
                             
                 )
                 <|>(if x /= "wd" && x /= "ht" && x /= "dp" && x /= "dimen" && x /= "skip" && x /= "muskip"
                     then fail ""
                     else do texMeasure mode
                             return $ TexEmpty ""
                 )
                 <|>(if x /= "global" && x /= "local" && x /= "obeylines"
                     then fail ""
                     else do texSpace mode
                             return $ TexEmpty sp
                 )
                 <|> (if x /= "advance"
                      then fail ""
                      else try $ do
                                                      texSpace mode
                                                      (arg1,tp) <- ((try $ do
                                                                            reg <- regDimention mode
                                                                            case (takeWhile (not.isDigit) $ tail reg) of
                                                                              "count" -> return (reg,"nostrech") 
                                                                              "language" -> return (reg,"nostrech") 
                                                                              "wd" -> return (reg,"strech") 
                                                                              "ht" -> return (reg,"strech") 
                                                                              "dp" -> return (reg,"strech") 
                                                                              "dimen" -> return (reg,"strech") 
                                                                              "skip" -> return (reg,"strech") 
                                                                              "muskip" -> return (reg,"strech") 
                                                                              "toks" -> return (reg,"nostrech") 
                                                                              "box" -> return (reg,"nostrech"))
                                                                    <|> 
                                                                    (try $ do
                                                                             cmd <- texCommandToken mode
                                                                             Just (xx,sp) <- return $ getCommandName cmd
                                                                             (try $ case (findMacro ('\\':xx) (macroState st)) of
                                                                                    Just (tr@(TexRegistry pp1 pp2 cmdT "count" _ spp))  -> return (xx,"nostrech")
                                                                                    Just (tr@(TexRegistry pp1 pp2 cmdT "language" _ spp))  -> return (xx,"nostrech")
                                                                                    Just (tr@(TexRegistry pp1 pp2 cmdT t _ spp))        -> return (xx,"strech")
                                                                                    Nothing -> return ("nerasta " ++ xx,"strech")
                                                                                    _ -> return ("nezinoma " ++ xx,""))))
                                                      texSpace mode
                                                      option "" $ string "by"
                                                      texSpace mode
                                                      m <- texMeasure tp 
                                                      return $ TexEmpty sp
                 )
                 <|> (if x /= "multiply" && x /= "divide"
                      then fail ""
                      else try $ do
                                                      texSpace mode
                                                      arg1 <- ((try ((regDimention mode) >> return (TexEmpty ""))) <|> (try $ texCommandToken mode))
                                                      texSpace mode
                                                      option "" $ string "by"
                                                      texSpace mode
                                                      m <- texMeasure "nostrech"
                                                      return $ TexEmpty sp
                 )
                 <|> (if x /= "definecolor"
                      then fail ""
                      else try $ (do       texSpace mode
                                           betweenBraces mode
                                           texSpace mode
                                           betweenBraces mode
                                           texSpace mode
                                           betweenBraces mode
                                           return $ TexEmpty "")
                 )
                 <|> (if x /= "color" && x /= "pagecolor"
                      then fail ""
                      else try $ (do       texSpace mode
                                           optionMaybe $ do string "["
                                                            manyTill anyChar (string "]")
                                           texSpace mode
                                           betweenBraces mode
                                           return $ TexEmpty "")
                 )
                 <|> (if x /= "textcolor" &&  x /= "colorbox"
                      then fail ""
                      else try $ (do       texSpace mode
                                           optionMaybe $ do string "["
                                                            manyTill anyChar (string "]")
                                           texSpace mode
                                           betweenBraces mode
                                           texSpace mode
                                           rs <- betweenBraces mode
                                           p2 <- getPosition
                                           return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':x) [rs] sp 
                                 )
                 )
                 <|> (if x /= "fcolorbox"
                      then fail ""
                      else try $ (do       texSpace mode
                                           betweenBraces mode
                                           texSpace mode
                                           betweenBraces mode
                                           texSpace mode
                                           rs <- betweenBraces mode
                                           p2 <- getPosition
                                           return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ("\\colorbox") [rs] sp 
                                 )
                 )
                 <|> (if x /= "setlength" && x /= "addtolength"
                      then fail ""
                      else try $ do
                                                      br <- option "" ((texSpace mode) >> string "{")
                                                      texSpace mode
                                                      cmd <- texCommandToken mode
                                                      texSpace mode
                                                      if br == "{" 
                                                         then string "}" 
                                                         else return $ ""
                                                      texSpace mode
                                                      option "" (string "=")
                                                      texSpace mode
                                                      br <- option "" ((texSpace mode) >> string "{")
                                                      texMeasure mode
                                                      texSpace mode
                                                      if br == "{" 
                                                         then string "}" 
                                                         else return $ ""
                                                      return $ TexEmpty sp
                 )
                 <|> (if x /= "newcount"
                      then fail ""
                     else try $ do
                                                      texSpace mode
                                                      cmd <- texCommandToken mode
                                                      texSpace mode
                                                      v <- option ("") ((try $ (option "" (string "="))) >> (try $ texMeasure mode))
                                                      p2 <- getPosition
                                                      rt <- return $! TexRegistry (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) cmd "count" (TexEmpty v) sp
                                                      updateState (updateMacroList rt True)
                                                      return $ TexEmpty sp
                 )
                 <|> (if x /= "newdimen" && x /= "newlength"
                      then fail ""
                     else try $ do
                                                      texSpace mode
                                                      cmd <- texCommandToken mode
                                                      texSpace mode
                                                      v <- option ("") ((try $ (option "" (string "="))) >> (try $ texMeasure mode))
                                                      p2 <- getPosition
                                                      rt <- return $! TexRegistry (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) cmd "dimen" (TexEmpty v) sp
                                                      updateState (updateMacroList rt True)
                                                      return $ TexEmpty sp
                 )
                 <|> (if x /= "newmuskip"  && x /= "newskip"
                      then fail ""
                     else try $ do
                                                      texSpace mode
                                                      cmd <- texCommandToken mode
                                                      texSpace mode
                                                      v <- option ("") ((try $ (option "" (string "="))) >> (try $ texMeasure mode))
                                                      p2 <- getPosition
                                                      rt <- return $! TexRegistry (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) cmd "skip" (TexEmpty v) sp
                                                      updateState (updateMacroList rt True)
                                                      return $ TexEmpty sp
                 )
                 <|> (if x /= "newtoks"
                      then fail ""
                     else try $ do
                                                      texSpace mode
                                                      cmd <- texCommandToken mode
                                                      texSpace mode
                                                      v <- option ("") ((try $ (option "" (string "="))) >> (try $ texDimention mode))
                                                      p2 <- getPosition
                                                      rt <- return $! TexRegistry (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) cmd "token" (TexEmpty v) sp
                                                      updateState (updateMacroList rt True)
                                                      return $ TexEmpty sp
                 )
                 <|> (if x /= "urldef"
                      then fail ""
                      else try $ do
                                                      esp <- try $ texSpace mode
                                                      ccc1 <- ((try $ texCommandToken mode)
                                                                <|> (do char '{' 
                                                                        cmd <- texCommandToken mode
                                                                        texSpace mode 
                                                                        char '}'
                                                                        return cmd))
                                                      c <- ((try $ texCommandToken mode)
                                                                <|> (do char '{' 
                                                                        cmd <- texCommandToken mode
                                                                        texSpace mode
                                                                        char '}'
                                                                        return cmd))
                                                      ccc4 <- ((try $ do   char '{'
                                                                           manyTill ( (parseTexToken mode)) (try ((try (texSpace mode)) >> char '}')))
                                                               <|>
                                                               (do   char '|'
                                                                     manyTill ( (parseTexToken mode)) (try ((try (texSpace mode)) >> char '|'))))
                                                      Just (xxx,sps) <- return $ getCommandName c
                                                      p2 <- getPosition
                                                      br <- return $ TexBraces (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) "{" "}" ccc4 sp
                                                      ccc5 <- return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':xxx) [br] sps
                                                      rt <- return $! TexNewCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ccc1 0 Nothing [ccc5] sp
                                                      updateState (updateMacroList rt True)
                                                      return $ TexEmpty sp
                 )
                 <|> (if x /= "\\"
                      then fail ""
                      else try $ do
                                                      ar <- optionMaybe (try $ do
                                                                                 texSpace mode
                                                                                 optionMaybe $ char '*'
                                                                                 texSpace mode
                                                                                 char '['
                                                                                 measure <- texMeasure mode
                                                                                 try $ texSpace mode
                                                                                 char ']'
                                                                                 p2 <- getPosition
                                                                                 return $ TexDimention (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ("[" ++ measure ++ "]") ""
                                                                        )
                                                      p2 <- getPosition
                                                      case ar of
                                                           Nothing -> return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ("\\\\") [] sp
                                                           Just m  -> return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ("\\\\") [m] sp
                 )
                 <|> (if x  /= "rule"
                      then fail ""
                      else try $ do
                                                       optionMaybe (do texSpace mode
                                                                       string "["
                                                                       texMeasure mode
                                                                       texSpace mode
                                                                       string "]"
                                                                   )
                                                       texMeasure mode
                                                       texMeasure mode
                                                       return $ TexEmpty ""
                 )
                 <|> (if x /= "vrule" && x /= "hrule"
                      then fail ""
                      else try $ do
                                                       ms <- many (try $ texRule mode)
                                                       p2 <- getPosition
                                                       return $ TexEmpty ""
                 )
                 <|> (if x /= "ensuremath"
                      then fail ""
                      else try $ do
                                                      texSpace mode
                                                      string "{"
                                                      x <- manyTill (parseTexItem "math") (try (lookAhead ((texSpace mode) >> string "}" >> (texSpace mode))))
                                                      esp <- texSpace mode
                                                      string "}"
                                                      texSpace mode
                                                      p2 <- getPosition
                                                      return $ TexMath (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ("\\ensuremath{") (esp ++ "}") x sp
                 )
                 <|> (if x /= "ifthenelse"
                      then fail ""
                      else try $ do
                                                      sp <- texSpace mode
                                                      betweenBracesTokens mode
                                                      betweenBracesTokens mode
                                                      t <- betweenBracesTokensText mode 
                                                      inp <- getInput
                                                      setInput $ ( sp ++  (texAsTxt t) ++ inp) 
                                                      return $ TexEmpty ""
                 )
                 <|> (if x /= "ifcase"
                      then fail ""
                      else try $ do
                                                      t2 <- manyTill (try $ parseTexItem mode)  (try ( do texSpace mode 
                                                                                                          string "\\fi"
                                                                                                          notFollowedBy letter))
                                                      return $ TexEmpty ""
                 )
                 <|> (if x /= "iffalse"
                      then fail ""
                      else try $ do
                                                      t2 <- manyTill (try $ parseTexItem mode)  (try ( do texSpace mode 
                                                                                                          string "\\fi"
                                                                                                          notFollowedBy letter))
                                                      (true,false) <- return $ span (\tT-> not $ L.isSuffixOf "\\else" (texAsTxt tT)) t2 
                                                      case false of
                                                           [] ->  return ()
                                                           rrr -> do
                                                                               inp <- getInput
                                                                               setInput $ ( (concat $ map (texAsTxt) rrr) ++ inp) 
                                                      return $ TexEmpty ""
                 )
                 <|> (if x /= "@ifnextchar"
                      then fail ""
                      else try $ do
                                                      c <- anyChar
                                                      true <- betweenBracesTokensText mode
                                                      false <- betweenBracesTokensText mode
                                                      inp <- getInput
                                                      star <- optionMaybe $ char c
                                                      case star of 
                                                           Just _ -> do 
                                                                               setInput $  ( sp ++ (texAsTxt true) ++ " " ++ inp) 
                                                           Nothing -> do 
                                                                               setInput $  (sp ++  (texAsTxt false) ++ " " ++ inp) 
                                                      return $ TexEmpty ""
                 )
                 <|> (if x /= "@ifstar"
                      then fail ""
                      else try $ do
                                                      inpT <- getInput
                                                      true <- betweenBracesTokensText mode
                                                      false <- betweenBracesTokensText mode
                                                      texSpace mode
                                                      star <- optionMaybe $ char '*'
                                                      case star of 
                                                           Just _ -> do 
                                                                               inp <- getInput
                                                                               setInput $  ( sp ++ (texAsTxt false) ++ " *" ++ inp) 
                                                           Nothing -> do 
                                                                               inp <- getInput
                                                                               setInput $  (sp ++  (texAsTxt true) ++ inp) 
                                                      return $ TexEmpty ""

                 )
                 <|> (if x /= "ifmmode"
                      then fail ""
                      else try $ do
                                                      texSpace mode
                                                      t2 <- manyTill (try $ parseTexItem mode)   (try ( do texSpace mode 
                                                                                                           string "\\fi"
                                                                                                           notFollowedBy letter))
                                                      (true,false) <- return $ span (\tT-> not $ L.isSuffixOf "\\else" (texAsTxt tT)) t2 
                                                      if mode == "math" 
                                                           then do 
                                                                               inp <- getInput
                                                                               setInput $  ( sp ++ (concat $ map (texAsTxt) true) ++ inp)  
                                                           else do 
                                                                               inp <- getInput
                                                                               setInput $  (sp ++  (concat $ map (texAsTxt) false) ++ inp) 
                                                      return $ TexEmpty ""
                 )
                 <|> (if x /= "ifnum"
                      then fail ""
                      else try $ do
                                                      texSpace mode
                                                      i1 <- nextItem mode
                                                      texSpace mode
                                                      sign <- ((char '<' >> (return (<)))
                                                               <|>
                                                               (char '>' >> (return (>)))
                                                               <|>
                                                               (char '=' >> (return (==))))
                                                      i2 <- nextItem mode
                                                      texSpace mode
                                                      t2 <- manyTill (try $ parseTexItem mode)  (try ( do texSpace mode 
                                                                                                          string "\\fi"
                                                                                                          notFollowedBy letter))
                                                      (true,false) <- return $ span (\tT-> not $ L.isSuffixOf "\\else" (texAsTxt tT)) t2 
                                                      if sign (readIntDef 0 $ texAsTxt i1) (readIntDef 0 $ texAsTxt i2)
                                                           then do 
                                                                               inp <- getInput
                                                                               setInput $ (sp ++ (concat $ map (texAsTxt) true) ++ inp)
                                                           else do 
                                                                               inp <- getInput
                                                                               setInput $  (sp ++  (concat $ map (texAsTxt) $ if null false then false else tail false) ++ inp) 
                                                      return $ TexEmpty ""
                 )
                 <|> (if x /= "ifx"
                      then fail ""
                      else try $ do
                                                      try $ texSpace mode
                                                      texCommandToken mode
                                                      try $ texSpace mode
                                                      texCommandToken mode
                                                      texSpace mode

                                                      t2 <- manyTill (try $ parseTexItem mode)   (try ( do texSpace mode 
                                                                                                           string "\\fi"
                                                                                                           notFollowedBy letter))
                                                      (true,false) <- return $ span (\tT-> not $ L.isSuffixOf "\\else" (texAsTxt tT)) t2 
                                                      if null false
                                                       then  do 
                                                                              inp <- getInput
                                                                              setInput $ ( (concat $ map (texAsTxt) true) ++ inp) 
                                                                              return $ TexEmpty "" 
                                                       else  do 
                                                                              inp <- getInput
                                                                              setInput $ ( (concat $ map (texAsTxt) false) ++ inp) 
                                                                              return $ TexEmpty ""
                 )
                 <|> (if x /= "iftrue"
                      then fail ""
                      else try $ do
                                                      optionMaybe (try $ manyTill (parseTexToken mode) (try ((texSpace mode) >> string "\\else")))
                                                      r <- manyTill (parseTexToken mode) (try ((texSpace mode) >> string "\\fi"))
                                                      inp <- getInput
                                                      setInput $ ( (concat $ map (texAsTxt) r) ++ inp) 
                                                      return $ TexEmpty ""
                 )
                 <|> (if x /= "newbox"
                      then fail ""
                      else try $ do
                                                      (try $ texCommandToken mode >> return "")
                                                      return $ TexEmpty ""
                 )
                 <|> (if x /= "box"
                      then fail ""
                      else try $ do
                                                      try $ texSpace mode
                                                      (try $ many1 digit) <|> (try $ texCommandToken mode >> return "")
                                                      return $ TexEmpty ""
                 )
                 <|> (if x /= "setbox"
                      then fail ""
                      else try $ do
                                                      try $ texSpace mode
                                                      (try $ many1 digit) <|> (try $ texCommandToken mode >> return "")
                                                      sp <- texSpace mode
                                                      option "" (string "=")
                                                      sp2 <- texSpace mode
                                                      char '\\'
                                                      xT <- do (try (many1 (try ((try letter) <|> (try $ char '*') <|> (char '@')))))
                                                                <|> (count 1 anyChar)
                                                      parseBox p sp xT mode 
                                                      return $ TexEmpty ""
                 )
                 <|> (if x /= "font"
                      then fail ""
                      else try $ do
                                                      try $ texSpace mode 
                                                      texCommandToken mode
                                                      texSpace mode
                                                      option "" (string "=")
                                                      texSpace mode
                                                      many1 letter
                                                      texSpace mode 
                                                      many1 digit 
                                                      texSpace mode 
                                                      option "" ((do string "at"
                                                                     texSpace mode
                                                                     texDimention mode
                                                                 ) 
                                                                 <|> (do string "scaled"
                                                                         texSpace mode
                                                                         ((try $ many1 digit)
                                                                          <|> (try $ texDimention mode)
                                                                          <|> (try $ do string "\\magstep"
                                                                                        texSpace mode
                                                                                        ((many1 digit) <|> (string "half"))
                                                                              ))))
                                                      return $ TexEmpty ""
                 )
                 <|> (if x /= "newarrow" then fail ""; else try $ do
                                                       count 6 (parseTexToken mode)
                                                       return $ TexEmpty "")
                 <|> (if x /= "vskip" && x /= "vskip*"
                      && x /= "vfill" && x /= "vfill*" 
                      && x /= "vfil" && x /= "vfil*" 
                      && x /= "vfilll" && x /= "vfilll*" 
                      && x /= "bigskip" && x /= "bigskip*" 
                      && x /= "medskip" && x /= "medskip*"
                      && x /= "smallskip" && x /= "smallskip*"
                      && x /= "addvspace" && x /= "addvspace*"
                      && x /= "vspace" && x /= "vspace*"
                      then fail ""
                      else try $ do (texMeasure mode) ; return $ TexEmpty "\n\n")

                 <|> (if x /= "hspace" && x /= "hspace*" 
                      && x /= "rightarrowfill" && x /= "leftarrowfill" && x /= "hss"
                      && x /= "hskip" && x /= "hskip*" 
                      && x /= "hfill" && x /= "hfill*"
                      && x /= "hfil" && x /= "hfil*"
                      && x /= "hfilll" && x /= "hfilll*"
                      && x /= "hrulefill" && x /= "hrulefill*"
                      && x /= "dotfill" && x /= "dotfill*"
                      && x /= "spaceskip"
                      then fail ""
                      else try $ do (texMeasure mode) ; return $ TexEmpty sp)
                 <|> (if x /= "qbezier"
                      then fail ""
                      else try $ do
                                   x1 <- optionMaybe $ try $ string "[" >> texMeasure mode >> texSpace mode >> string "]"
                                   x2 <- texSpace mode >> string "(" >> texMeasure mode >> texSpace mode >> (string ",") >>  texSpace mode >> texMeasure mode >> texSpace mode >> string ")"
                                   x3 <- texSpace mode >> string "(" >> texMeasure mode >> texSpace mode >> (string ",") >>  texSpace mode >> texMeasure mode >> texSpace mode >> string ")"
                                   x4 <- texSpace mode >> string "(" >> texMeasure mode >> texSpace mode >> (string ",") >>  texSpace mode >> texMeasure mode >> texSpace mode >> string ")"
                                   p2 <- getPosition
                                   return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':x) [TexEmpty "(1,1)(2,2)(3,3)"] sp
                 )
                 <|> (if x /= "line" && x /= "line*" 
                      then fail ""
                      else try $ do
                                   x2 <- texSpace mode >> string "(" >> texMeasure mode >> texSpace mode >> (string ",") >>  texSpace mode >> texMeasure mode >> texSpace mode >> string ")"
                                   betweenBraces mode
                 )
                 <|> (if x /= "circle" && x /= "circle*" 
                      then fail ""
                      else try $ do
                                   betweenBraces mode
                 )
                 <|> (if x /= "makebox"
                      then fail ""
                      else try $ do
                                   ((optionMaybe $ try $ string "[" >> texMeasure mode >> texSpace mode >> string "]")
                                    <|>
                                    (optionMaybe $ try $ string "(" >> texMeasure mode >> texSpace mode >> ((string ",")<|>(string "+")) >>  texSpace mode >> texMeasure mode >> texSpace mode >> string "]"))
                                   optionMaybe $ try $ string "[" >> manyTill anyChar (string "]")
                                   betweenBraces mode
                 )
                 <|> (if x /= "framebox" 
                      then fail ""
                      else try $ do
                                   optionMaybe $ try $ string "[" >> texMeasure mode >> texSpace mode >> string "]"
                                   optionMaybe $ try $ string "[" >> manyTill anyChar (string "]")
                                   betweenBraces mode
                 )
                 <|> (if x /= "raisebox"
                      then fail ""
                      else try $ do
                                   string "{" >> texMeasure mode >> texSpace mode >> string "}"
                                   optionMaybe $ try $ string "[" >> texMeasure mode >> texSpace mode >> string "]"
                                   optionMaybe $ try $ string "[" >> texMeasure mode >> texSpace mode >> string "]"
                                   betweenBraces mode
                 )
                 <|> (if x /= "resizebox" 
                      then fail ""
                      else try $ do
                                   string "{" >> texMeasure mode >> texSpace mode >> string "}"
                                   string "{" >> texMeasure mode >> texSpace mode >> string "}"
                                   betweenBraces mode
                 )
                 <|> (if x /= "scalebox"  
                      then fail ""
                      else try $ do
                                   string "{" >> texMeasure mode >> texSpace mode >> string "}"
                                   betweenBraces mode
                 )
                 <|> (if x /= "pbox" 
                      then fail ""
                      else try $ do
                                   optionMaybe $ try $ string "[" >> manyTill anyChar (string "]")
                                   string "{" >> texMeasure mode >> texSpace mode >> string "}"
                                   betweenBraces mode
                 )
                 <|> (if x /= "parbox" 
                      then fail ""
                      else try $ do
                                   optionMaybe (try $ string "[" >> manyTill anyChar (string "]"))
                                   optionMaybe (try $ string "[" >> texMeasure mode >> texSpace mode >> string "]")
                                   optionMaybe (try $ string "[" >> manyTill anyChar (string "]"))
                                   string "{" >> texMeasure mode >> texSpace mode >> string "}"
                                   betweenBraces mode
                 )
                 <|> (if x /= "kern"  then fail ""; else try $ do texMeasure mode ; return $ TexEmpty "")
                 <|> (if x /= "label"  then fail ""; else try $ do ((betweenBracesTokens mode >> return (TexEmpty ""))))
                 <|> (if x /= "titleformat"  then fail ""; else try $ 
                         do ((betweenBracesTokens mode) <|> (texCommandToken mode))
                            optionMaybe $ betweenBrackets mode
                            many1 (betweenBracesTokens mode)
                            return (TexEmpty "")
                 )
                 <|> (if x /= "titleformat*"  then fail ""; else try $ do (((many1 ((betweenBracesTokens mode) <|> (texCommandToken mode))) >> return (TexEmpty ""))))
                 <|> (if x /= "titlespacing" && x /= "titlespacing*"  then fail ""; else try $ do (((count 4 (betweenBracesTokens mode)) >> return (TexEmpty ""))))
                 <|> (if x /= "input"  then fail ""; else try $ do ((betweenBracesTokens mode >> return "") <|> (texSpace mode >> many1 (letter <|> char '.'))) ; return $ TexEmpty "")
                 <|> (if x /= "tikzstyle" then fail ""; else try $ do
                                                      betweenBracesTokens mode 
                                                      option "" $ string "="
                                                      betweenBrackets mode
                                                      return $ TexEmpty "")
                 <|> (if not (isTexSymbol x)
                         then fail ""
                         else try $ do 
                                       p2 <- getPosition
                                       return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':x) [] sp )
                 <|> (if x /= "char" then fail ""; else try $ do
                                                       pT <- getPosition
                                                       r <- optionMaybe $ try $ ((texSpace mode) >> char '=')
                                                       esp <- try $ texSpace mode
                                                       ms <- (try $ do 
                                                                       char '\"'
                                                                       h <- many1 hexDigit
                                                                       return $ [chr $ fst $ head $ readHex h]
                                                             )
                                                             <|>
                                                             (many1 digit) 
                                                             <|> 
                                                             (do optionMaybe $ char '`'
                                                                 optionMaybe $ char '\\'
                                                                 c <- anyChar
                                                                 return $ [c]
                                                             )
                                                       p2 <- getPosition
                                                       b <- return $ TexToken (Start (sourceLine pT) (sourceColumn pT)) (Stop (sourceLine p2) (sourceColumn p2)) (esp ++ ms) ""
                                                       return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ("\\char") ([b]) sp )
                 <|> (if mode /= "math" && (not $ isDefinedSize x coms) && (not $ isDefinedSize x optionals) && ( not $ isSwitch x)
                      then try $ do
                                   arg <- ((try $ (many digit) >> texMeasureO mode) <|> (try $ commandDimentions mode))
                                   p2 <- getPosition
                                   return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':x) [arg] sp
                      else fail ""
                 )
                 <|> (try ( parseBox p sp x mode))
                 <|> (try (if mode /= "math"
                           then fail ""
                           else try $ do
                                        p2 <- getPosition
                                        return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':x) [] sp ))
                 <|> (try $ do
                                 op <- case (argsSize x optionals) of
                                       Nothing   -> return []
                                       Just size -> (try $ (do 
                                                             m <- count size (option Nothing $ (try $ do try (texSpace mode)
                                                                                                         bT <- try (betweenBrackets mode)
                                                                                                         return $ Just bT))
                                                             return $ catMaybes m))
                                 b <- case (argsSize x coms) of
                                      Nothing   -> (try $ many ((try (do try (texSpace mode)
                                                                         try (betweenBraces mode))) 
                                                               <|> (try (do try (texSpace mode)
                                                                            try (betweenBrackets mode))) ))
                                      Just size -> (try $ count size (try $ do try (texSpace mode)
                                                                               try (parseTexItem mode)))
                                 p2 <- getPosition
                                 return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':x) (b) sp )
                     )

isTexSymbol x = case Map.lookup x texSymbols of
                   Just m  -> True
                   Nothing -> False

printTexSymbol x = case Map.lookup x texSymbols of
                   Just m  -> m
                   Nothing -> ""

texSymbols = Map.fromList [("textasciicircum","^"),("textless","<"),("textasciitilde","~"),("textordfeminine","ª"),("textasteriskcentered","*")
                          ,("textordmasculine","º"),("textbackslash","\\"),("textparagraph","¶"),("textbar","|"),("textperiodcentered","·")
                          ,("textbraceleft","{"),("textquestiondown","¿"),("textbraceright","}"),("textquotedblleft","“"),("textbullet","•")
                          ,("textquotedblright","”"),("textcopyright","©"),("textquoteleft","‘"),("textdagger","†"),("textquoteright","’")
                          ,("textdaggerdbl","‡"),("textregistered","®"),("textdollar","$"),("textsection","§"),("textellipsis","…")
                          ,("textsterling","£"),("textemdash","—"),("texttrademark","™"),("textendash","–"),("textunderscore","_")
                          ,("textexclamdown","¡"),("textvisiblespace","␣"),("textgreater",">"),("_","_"),("ddag","‡")
                          ,("P","¶"),("copyright","©"),("S","§"),("dag","†"),("pounds","£"),("aa","å"),("DH","Ð"),("L","Ł"),("o","ø")
                          ,("ss","ß"),("AA","Å"),("dh","ð"),("l","ł"),("O","Ø"),("SS","SS"),("AE","Æ"),("DJ","Đ"),("NG","Ŋ"),("OE","Œ")
                          ,("TH","Þ"),("ae","æ"),("dj","đ"),("ng","ŋ"),("oe","œ"),("th","þ"),("euro","€"),("textbaht","฿")
                          ,("textguarani","₲"),("textwon","₩"),("textcent","¢"),("textlira","₤"),("textyen","¥"),("textdong","₫")
                          ,("textnaira","₦"),("textcolonmonetary","₡"),("texteuro","€"),("textpeso","₱"),("textcurrency","¤")
                          ,("-", ""), ("#","#"),("dagger","†"),("ddagger","‡"),("endguillemets","»"),("guillemotright","»")
                          ,("fg","»"),("guillemets","«"),("guillemotleft","«"),("ieme","e"),("iemes","es"),("ier","er"),("iers","ers"),("iere","re"),("ieres","res")
                          ,("No","N°"),("no","n°"),("Numero","N°"),("numero","n°"),("og","«"),("slash","/")
                          ,("textnospace",""),("!",""),(","," "),("$","$"),("%","%"),("&","&"),("dots","…")
                          ,("flat","♭"),("i","ı"),("j","j"),("ldots","…"),("quad"," "),("qquad"," "),("sharp","♯"),("}","}"),("{","{"),("nobreakspace"," ")
                          ,("textdiv","÷"),("texttimes","×"),("textbrokenbar","¦"),("textasciidieresis","¨"),("textcopyright","©")
                          ,("textlnot","¬"),("textasciimacron","¯"),("textdegree","°"),("textpm","±"),("texttwosuperior","²")
                          ,("textthreesuperior","³"),("textasciiacute","´"),("textmu","µ"),("textpilcrow","¶"),("textasciicedilla","a"),("textonesuperior","¹")
                          ,("textonequarter","¼"),("textonehalf","½"),("textthreequarters","¾")
                          ,("textbardbl","‖"),("textperthousand","‰"),("textacutedbl","″"),("textreferencemark","※"),("textinterrobang","‽"),("textfractionsolidus","⁄")
                          ,("textfrenchfranc","₣"),("textnumero","№"),("textcircledP","℗"),("textohm","Ω"),("textestimated","℮"),("textleftarrow","←")
                          ,("textuparrow","↑"),("textrightarrow","→"),("textdownarrow","↓"),("textsurd","√"),("textopenbullet","◦"),("textbigcircle","◯")
                          ,("textmusicalnote","♪"),("textlangle","〈"),("textrangle","〉"),("texttwelveudash","—"),("textthreequartersemdash","—"),("textquotesingle","'")
                          ,("textflorin","ƒ"),("postbox","#"),("Postbox","#"),("boxvoid","□"),("boxtriangleup","□"),("boxcirc","□"),("boxplus","□"),("boxempty","□")]


readIntDef :: Int -> String -> Int
readIntDef d i = case takeWhile (isDigit) i of
                      [] -> d
                      x -> read i

csname mode = do
                p <- getPosition
                sp <- texSpace mode
                string "\\csname"
                notFollowedBy letter
                texSpace mode
                x <- ((try (many1 (try ((try letter) <|> (try $ char '*') <|> (char '@')))))
                      <|> (count 1 anyChar))
                texSpace mode
                string "\\endcsname"
                notFollowedBy letter
                texSpace mode
                p2 <- getPosition
                return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':x) [] sp

getCommandName (TexCommand _ _ ('\\':x) _ sp) = Just (x,sp)
getCommandName _  = Nothing


boxes = ["vtop","mbox","vbox","hbox","fbox","scalebox","framebox","splittextbox"
        ,"stopacrolinkbox","rotatebox","raisebox","reflectbox"
        ,"parbox","ovalbox","boxed","doublebox","shadowbox"]

parseBox p sp xx mode = do 
                if elem xx boxes
                then do
                   texSpace mode
                   pref <- (try $ optionMaybe (try $ do
                                     pT <- getPosition
                                     sp1 <- texSpace mode
                                     pr <- ((try $ string "to") <|> (try $ string "in") <|> (try $ string "spread"))
                                     sp2 <- texSpace mode
                                     m <- (try $ texMeasure mode)
                                     sp2 <- texSpace mode 
                                     pT2 <- getPosition
                                     return $ 
                                              TexToken (Start (sourceLine pT) (sourceColumn pT)) 
                                                       (Stop (sourceLine pT2) (sourceColumn pT2)) 
                                                       (sp1 ++ pr ++ sp2 ++ m) "")
                           )
                   optionMaybe $ try $ texMeasure mode
                   many $ try $ betweenBrackets mode 
                   b <- option [] (try $ do bT <- betweenBraces "tex"
                                            return $ [bT])
                   pb <- case pref of
                              Nothing -> return $ b
                              Just p -> return $ (p : b)
                   p2 <- getPosition
                   return $ TexCommand (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) ('\\':xx) b sp
                else fail ""

commandDimentions mode
                  = do
                     p <- getPosition
                     sp <- try $ texSpace mode
                     m <- try $ texDimention mode
                     p2 <- getPosition
                     return $ TexToken (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) (m) sp

texMeasureO mode
                  = do
                     p <- getPosition
                     sp <- try $ texSpace mode
                     m <- try $ texMeasure mode
                     p2 <- getPosition
                     return $ TexDimention (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) (m) sp


texRule mode = do 
                      p <- getPosition
                      texSpace mode
                      s <- (string "height" <|> string "depth" <|> string "width")
                      t <- texMeasure mode
                      p2 <- getPosition
                      return $ TexDimention (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) (s ++ t) ""

texMeasure mode = do
                    sp1 <- texSpace mode
                    e <- option "" $ try $ string "="
                    tryExpand mode
                    sp2 <- texSpace mode
                    rt <- (
                           (try $ texMeasureT mode)
                           <|>
                           (do char '{'
                               texSpace mode
                               r <- ((try $ texMeasureT mode))
                               texSpace mode
                               char '}'
                               return r
                           ))
                    return $ sp1 ++ e ++ sp2 ++ rt

texMeasureT mode = 
                  do sp1 <- texSpace mode
                     minsT <- option "" (string "by")
                     dm <- ((try $ texDimention mode) <|> (try $ texCount mode))
                     return $ minsT ++ dm

regDimention mode = do
                      char '\\'
                      x <- ((try (many1 (try ((try letter) <|> (try $ char '*') <|> (char '@')))))
                            <|> (count 1 anyChar))
                      if elem x ["wd","ht","dp","dimen","skip","muskip","toks","box"]
                      then do
                             texSpace mode
                             d <- many1 digit
                             return $ "\\" ++ x ++ d
                      else fail ""

regCount mode = do
                      char '\\'
                      x <- ((try (many1 (try ((try letter) <|> (try $ char '*') <|> (char '@')))))
                            <|> (count 1 anyChar))
                      if elem x ["count","language"]
                      then do
                             texSpace mode
                             d <- many1 digit
                             return $ "\\" ++ x ++ d
                      else fail ""

texCount mode = do
                 sp1 <- texSpace mode
                 tryExpand mode
                 mins <- option "" ((string "-") <|> (string "+"))
                 sp2 <- texSpace mode
                 tryExpand mode
                 ((try $ regCount mode)
                  <|>
                  ( try $
                   do texSpace mode
                      number <- (many1 ((try digit) <|> (try $ char '.') <|> (try $ char ',')))
                      if number == "." || number == "," 
                         then fail "" 
                         else return number
                  )
                  <|>
                  ( do sp4 <- texSpace mode
                       xT <- (try $ texCommandToken mode)
                       Just (x,sp) <- return $ getCommandName xT
                       st <- getState
                       case (findMacro ('\\':x) (macroState st)) of
                            Just (TexRegistry pp1 pp2 cmd "count" v spp) -> return $ sp4 ++ sp ++ "\\" ++ x
                            Just (TexRegistry pp1 pp2 cmd "" v spp) -> return $ sp4 ++ sp ++ "\\" ++ x
                            _        -> fail ""
                  ))

texDimention mode = 
               do sp <- texSpace mode
                  dm <- texDimentionT1 mode
                  pl <- optionMaybe ( try $ do texSpace mode
                                               ((string "plus") <|> (string "minus"))
                                               texSpace mode
                                               texDimentionT1 mode)
                  mn <- optionMaybe ( try $ do texSpace mode
                                               ((string "plus") <|> (string "minus"))
                                               texSpace mode
                                               texDimentionT1 mode)
                  return $ sp ++ dm

texDimentionT1 mode = 
               do sp1 <- texSpace mode
                  tryExpand mode
                  mins <- option "" ((string "-") <|> (string "+"))
                  ((try $ do
                            sp2 <- texSpace mode
                            number <- if mode /= "nostrech"
                                         then option "" (try $ texCount mode)
                                         else return ""
                            if number == "." || number == "," 
                            then fail "" 
                            else((try $ do
                                          sp4 <- texSpace mode
                                          tryExpand mode
                                          xTT <- texCommandToken mode
                                          Just (x,sp) <- return $ getCommandName xTT
                                          st <- getState
                                          case (findMacro ('\\':x) (macroState st)) of
                                              Just (TexRegistry pp1 pp2 cmd t v spp)
                                                       -> return $ let rt = mins ++ sp2 ++ number ++ sp4 ++ sp ++ "\\" ++ x in 
                                                                   if null rt then fail "" else sp1 ++ rt 
                                              _        -> fail ""
                                 )
                                 <|>
                                 (try $ do texSpace mode
                                           tryExpand mode
                                           regDimention mode)
                                 ))
                   <|>
                   (try $ do
                             sp4 <- texSpace mode
                             tryExpand mode
                             nm <- (many1 ((try digit) <|> (try $ char '.') <|> (try $ char ',')))
                             number <- if nm == "." || nm == "," 
                                        then fail "" 
                                        else return nm
                             sp3 <- try $ texSpace mode 
                             tr <- option "" (string "true") 
                             m <-  optionMaybe  (try $ 
                                                     do texSpace mode
                                                        ((try $ string "pt") 
                                                         <|> (try $ string "cm") 
                                                         <|> (try $ string "mm") 
                                                         <|> (try $ string "in") 
                                                         <|> (try $ string "pc") 
                                                         <|> (try $ string "ex") 
                                                         <|> (try $ string "bp") 
                                                         <|> (try $ string "dd") 
                                                         <|> (try $ string "cc") 
                                                         <|> (try $ string "sp") 
                                                         <|> (try $ string "filll") 
                                                         <|> (try $ string "fill") 
                                                         <|> (try $ string "fil") 
                                                         <|> (try $ string "em")))
                             rt <- case m of
                                        Nothing  -> return $ mins ++ sp4 ++ number ++ sp3 ++ tr
                                        Just mm  -> return $ mins ++ sp4 ++ number ++ sp3 ++ tr ++ mm
                             if null rt then fail "" else return $ sp1 ++ rt
                   )
                   )


coms = [("textit",1)            ,("mathit",1)          ,("mathrm",1)          ,("textbf",1)             ,("tsub",1)
       ,("tsup",1)              ,("lstinline",0)       ,("columnwidth",0)     ,("title",1)              ,("lstset",1)
       ,("bf",0)                ,("rm",0)              ,("it",0)              ,(",",0)                  ,(".",0)
       ,(";",0)                 ,(":",0)               ,("!",0)               ,("#",0)                  ,("$",0)
       ,("%",0)                 ,("&",0)               ,("-",0)               ,("_",0)                  ,("+",0)
       ,("=",0)                 ,("*",0)               ,("?",0)               ,("/",0)                  ,("<",0)
       ,(">",0)                 ,("~",0)               ,("`",0)               ,("{",0)                  ,("}",0)
       ,("object",1)            ,("objectname",1)      ,("color",1)           ,("section",1)            ,("section*",1)
       ,("subsection",1)        ,("subsection*",1)     ,("subsubsection",1)   ,("subsubsection*",1)     ,("subsubsubsection",1)
       ,("subsubsubsection*",1) ,("noindent",0)        ,("maketitle",0)       ,("allowdisplaybreaks",0) ,("centerline",1)
       ,("settowidth",2)        ,("settoheight",2)     ,("settodepth",2) 
       ,("textnormal",1)        ,("normalfont",0)      ,("emph",1)            ,("em",0)                 ,("textrm",1)
       ,("rmfamily",0)          ,("textsf",1)          ,("sffamily",0)        ,("texttt",1)             ,("ttfamily",0)
       ,("textup",1)            ,("upshape",0)         ,("itshape",0)         ,("textsl",1)             ,("slshape",0)
       ,("textsc",1)            ,("scshape",0)         ,("uppercase",1)       ,("lowercase",1)          ,("bfseries",0)
       ,("textmd",1)            ,("mdseries",0)        ,("textlf",1)          ,("lfseries",0)
       ,("normalem",0)          ,("uline",1)           ,("uwave",1)           ,("sout",1)               ,("xout",1)
       ,("dotuline",1)          ,("dashuline",1)       ,("uuline",1)          ,("chemfig",1)
       ,("nameref",1)           ,("labelcref",1)       ,("cpageref",1)        ,("crefrange",2)          ,("cpagerefrange",1)       ,("hyperref",1)
--       ,("",)
       ]


optionals = [
       ("lstinline",1)          ,("noindent",0)        ,("title",1)         ,("tsub",1)                   ,("tsup",1)
       ,("bf",0)                ,("rm",0)              ,("it",0)            ,("allowdisplaybreaks",0)     ,("maketitle",0)
       ,("object",1)            ,("color",1)           ,("objectname",1)    ,("section",1)                ,("section*",1)        
       ,("subsection",1)        ,("subsection*",1)     ,("subsubsection",1) ,("subsubsection*",1)         ,("subsubsubsection",1)
       ,("subsubsubsection*",1) ,(",",0)               ,(".",0)             ,(";",0)                      ,(":",0)
       ,("!",0)                 ,("#",0)               ,("$",0)             ,("%",0)                      ,("&",0)
       ,("-",0)                 ,("_",0)               ,("+",0)             ,("=",0)                      ,("*",0)
       ,("?",0)                 ,("/",0)               ,("<",0)             ,(">",0)                      ,("~",0)
       ,("`",0)                 ,("{",0)               ,("}",0)             ,("chemfig",0)
       ,("textnormal",0)        ,("normalfont",0)      ,("emph",0)            ,("em",0)                 ,("textrm",0)
       ,("rmfamily",0)          ,("textsf",0)          ,("sffamily",0)        ,("texttt",0)             ,("ttfamily",0)
       ,("textup",0)            ,("upshape",0)         ,("itshape",0)         ,("textsl",0)             ,("slshape",0)
       ,("textsc",0)            ,("scshape",0)         ,("uppercase",0)       ,("lowercase",0)          ,("bfseries",0)
       ,("textmd",0)            ,("mdseries",0)        ,("textlf",0)          ,("lfseries",0)
       ,("normalem",0)          ,("uline",0)           ,("uwave",0)           ,("sout",0)               ,("xout",0)
       ,("dotuline",0)          ,("dashuline",0)       ,("uuline",0)          ,("nameref",0)            ,("labelcref",0)
       ,("cpageref",0)          ,("crefrange",0)       ,("cpagerefrange",0)   ,("hyperref",1)
       ]

argsSize xx coms =  lookup xx coms

isDefinedSize xx coms = case argsSize xx coms of
                             Nothing -> False
                             Just _ -> True

texSpaceToken mode
              = do p <- getPosition
                   sp <- texSpace mode
                   if null sp 
                    then fail ""
                    else do
                          p2 <- getPosition
                          return $ TexSpace (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) sp " " 
texSymbol mode
          = do p <- getPosition
               inp <- getInput
               sp <- (try (texSpace mode))
               x <- (try anyChar)
               p2 <- getPosition
               return $ TexSymbol (Start (sourceLine p) (sourceColumn p)) (Stop (sourceLine p2) (sourceColumn p2)) [x] sp

eol mode =  (try (string "\r\n")) <|> (try (string "\n\r")) <|> (try (string "\n")) <|> string "\r" <?> "end of line"

dings = Map.fromList [("33","!"),("71","G"),("109","m"),("181","μ"),("219","¤"),("34","\""),("72","H"),("110","n"),("182","∂"),("220","‹"),("35","#"),("73","I"),("111","o"),("183","∑"),("221","›"),("36","$"),("74","J"),("112","p"),("184","∏"),("222","fi"),("37","%"),("75","K"),("113","q"),("185","π"),("223","fl"),("38","&"),("76","L"),("114","r"),("186","∫"),("224","‡"),("39","'"),("77","M"),("115","s"),("187","ª"),("225","·"),("40","("),("78","N"),("116","t"),("188","º"),("226","‚"),("41",")"),("79","O"),("117","u"),("189","Ω"),("227","„"),("42","*"),("80","P"),("118","v"),("190","æ"),("228","‰"),("43","+"),("81","Q"),("119","w"),("191","ø"),("229","Â"),("44",","),("82","R"),("120","x"),("192","¿"),("230","Ê"),("45","-"),("83","S"),("121","y"),("193","¡"),("231","Á"),("46","."),("84","T"),("122","z"),("194","¬"),("232","Ë"),("47","/"),("85","U"),("123","{"),("195","√"),("233","È"),("48","0"),("86","V"),("124","|"),("196","ƒ"),("234","Í"),("49","1"),("87","W"),("125","}"),("197","≈"),("235","Î"),("50","2"),("88","X"),("126","~"),("198","∆"),("236","Ï"),("51",""),("89","Y"),("161","°"),("199","«"),("237","Ì"),("52","4"),("90","Z"),("162","¢"),("200","»"),("238","Ó"),("53","5"),("91","["),("163","£"),("201","…"),("239","Ô"),("54","6"),("92","\\"),("164","§"),("241","Ò"),("55","7"),("93","]"),("165","•"),("203","À"),("242","Ú"),("56","8"),("94","^"),("166","¶"),("204","Ã"),("243","Û"),("57","9"),("95","_"),("167","ß"),("205","Õ"),("244","Ù"),("58",":"),("96","`"),("168","®"),("206","Œ"),("245","ı"),("59",";"),("97","a"),("169","©"),("207","œ"),("246","ˆ"),("60","<"),("98","b"),("170","™"),("208","–"),("61","="),("99","c"),("209","—"),("62",">"),("100","d"),("210","“"),("63","?"),("101","e"),("173","≠"),("211","”"),("64","@"),("102","f"),("174","Æ"),("212","‘"),("65","A"),("103","g"),("175","Ø"),("213","’"),("66","B"),("104","h"),("176","∞"),("214","÷"),("67","C"),("105","i"),("177","±"),("215","◊"),("68","D"),("106","j"),("178","≤"),("216","ÿ"),("69","E"),("107","k"),("179","≥"),("217","Ÿ"),("70","F"),("108","l"),("180","¥"),("218","⁄")]    -- " '
ding x = case Map.lookup x dings of
              Just xx -> xx
              Nothing -> x

doNotRedefine = ["\\vskip", "\\wordbreak" ,"\\break","\\lq","\\rq","\\char","\\ding","\\and","\\ref","\\reftext","\\interref"
                ,"\\multiref","\\pageref","\\vref","\\eref","\\secref","\\tt","\\figref","\\mysec","\\citeA","\\Sec","\\autoref","\\Autoref","\\autoref*"
                ,"\\cref","\\eqref","\\myfig","\\liref","\\lireftwo","\\eqnref","\\ineqref","\\Liref","\\prettyref","\\object"
                ,"\\objectname","\\fullciteA","\\myeq","\\myapp","\\mytable","\\Fref","\\Eqref","\\fref","\\nocite" ,"\\nocite*" 
                ,"\\onlinecite","\\onlinecite*","\\citeauthor","\\citeauthor*","\\cites","\\cites*","\\citeN","\\citeN*","\\citen"
                ,"\\citen*","\\shortcites","\\shortcites*","\\citeyearNP","\\citeyearNP*","\\citeANP","\\citeANP*","\\citeNP","\\citeNP*"
                ,"\\shortciteN","\\shortciteN*","\\shortciteNP","\\shortciteNP*","\\citepalias","\\citepalias*","\\citetalias","\\citetalias*"
                ,"\\citep","\\citep*","\\citet","\\citet*","\\opencite","\\opencite*","\\cite","\\cite*","\\citealt","\\citealt*","\\citealp"
                ,"\\citealp*","\\newcite","\\newcite*","\\citeyear","\\citeyear*","\\citeyearpar","\\citeyearpar*","\\inlinecite","\\inlinecite*"
                ,"\\shortcite","\\shortcite*","\\shortciteA","\\noparen","\\citeaffixed","\\citeaffixed*","\\citeasnoun","\\citeasnoun*"
                ,"\\possessivecite","\\possessivecite*","\\citetext","\\citetext*","\\citenum","\\citenum*","\\Citeauthor","\\Citeauthor*"
                ,"\\Citep","\\Citep*","\\Citet","\\Citet*","\\label","\\lstdefinelanguage","\\kwd","\\foreignlanguage","\\colorbox"
                ,"\\title","\\institute","\\author","\\address","\\noindent","\\subtitle","\\abstract","\\paragraph","\\chapter","\\chapter*"
                ,"\\SEC","\\secput","\\textcolor","\\section","\\section*","\\subsection","\\subsection*","\\subsubsection","\\subsubsection*"
                ,"\\subsubsubsection","\\subsubsubsection*","\\mbox","\\hbox","\\vbox","\\textit","\\textbf","\\textrm","\\emph","\\em","\\textsuperscript"
                ,"\\textsubscript","\\tsub","\\tsup","\\textnormal","\\textsf","\\protect","\\texttt","\\textup","\\textsl","\\textsc"
                ,"\\uppercase","\\lowercase","\\textmd"  ,"\\subheading","\\underline","\\text","\\newline","\\centerline","\\leftline"
                ,"\\rightline","\\llap","\\rlap","\\clap","\\item","\\url","\\path"
                ]

showTex (TexComment _ _ "" sp) = sp 
showTex (TexComment _ _ txt sp) = sp ++ txt
showTex (TexCommand _ _ txt texs sp) = sp ++ txt ++ (concat $ map (showTex) texs)
showTex (TexNewCommand _ _ tex cnt Nothing texs sp) =  sp ++ (showTex tex) ++ "[" ++ (show cnt) ++ "]{" ++ (concat $ map (showTex) texs) ++ "}"  
showTex (TexNewCommand _ _ tex cnt (Just txt) texs sp) =  sp ++ (showTex tex) ++ "[" ++ (show cnt) ++ "][" ++ txt ++ "]{" ++ (concat $ map (showTex) texs) ++ "}"  
showTex (TexNewCommandArg _ _ cnt txt sp) = sp ++ txt ++ (show cnt)
showTex (TexNewCommandArgExp _ _ cnt ) = (show cnt)
showTex (TexDef _ _ tex texs texs2 sp) =  sp ++ (showTex tex) ++ (concat $ map (showTex) texs) ++ "{" ++ (concat $ map (showTex) texs2) ++ "}"
showTex (TexDefArg _ _ txt) =  txt
showTex (TexDefArgExp _ _ cnt)  = (show cnt)
showTex (TexToken _ _ txt sp) = sp ++ txt 
showTex (TexDigit _ _ txt sp) = sp ++ txt 
showTex (TexSymbol _ _ txt sp) = sp ++ txt 
showTex (TexSpace _ _ txt sp) = sp ++ txt 
showTex (TexPar _ _ txt sp) = "\n\n"
showTex (TexVerbatim _ _ txt sp) = sp ++ txt
showTex (Tex _ _ texs ) = (concat $ map (showTex) texs)
showTex (TexBraces _ _ txt1 txt2 texs sp) = sp ++ txt1 ++ (concat $ map (showTex) texs) ++ txt2    
showTex (TexMath _ _ txt1 txt2 texs sp) = sp ++ txt1 ++ (concat $ map (showTex) texs) ++ txt2    
showTex (TexMathDisp _ _ txt1 txt2 texs sp) = sp ++ txt1 ++ (concat $ map (showTex) texs) ++ txt2    
showTex (TexGroup _ _ txt1 txt2 texs sp) = sp ++ txt1 ++ (concat $ map (showTex) texs) ++ txt2    
showTex (TexEmpty sp) = sp


spp [] = []
spp x = "<Space>" ++ x ++ "</Space>\n" 


showTexTXT (TexComment _ _ txt sp) = pspace $ rs sp
showTexTXT (TexCommand p1 p2 ('\\':'L':'E':'T':xs) texs sp) = showTexTXT (TexCommand p1 p2 ('\\':xs) texs sp)
showTexTXT (TexCommand _ _ "{" texs sp) = (pspace $ rs sp)
--showTexTXT (TexCommand _ _ "\\\\" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\\\" texs sp) = (pspace $ rs sp) ++ "\n"
showTexTXT (TexCommand _ _ "\\vskip" texs sp) = (pspace $ rs sp) ++ "\n"
showTexTXT (TexCommand _ _ "\\wordbreak" texs sp) = (pspace $ rs sp)
showTexTXT (TexCommand _ _ "\\break" texs sp) = (pspace $ rs sp) ++ "\n"
showTexTXT (TexCommand _ _ "\\-" texs sp) = (pspace $ rs sp)
showTexTXT (TexCommand _ _ "\\`" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\'" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\^" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\\"" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)   --"
showTexTXT (TexCommand _ _ "\\~" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\=" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\." texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\u" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\v" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\H" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\t" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\c" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\k" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\d" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\b" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\," texs sp) = (pspace $ rs sp) ++ " "
showTexTXT (TexCommand _ _ "\\\n" texs sp) = (pspace $ rs sp) ++ " "
showTexTXT (TexCommand _ _ "\\;" texs sp) = (pspace $ rs sp) ++ " "
showTexTXT (TexCommand _ _ "\\/" texs sp) = (pspace $ rs sp) ++ " "
showTexTXT (TexCommand _ _ ['\\',x] texs sp) = (pspace $ rs sp) ++ [x]++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\lq" texs sp) = (pspace $ rs sp) ++ "'"
showTexTXT (TexCommand _ _ "\\rq" texs sp) = (pspace $ rs sp) ++ "'"
showTexTXT (TexCommand _ _ "\\char" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\ding" texs sp) = (pspace $ rs sp) ++ (ding $ concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\and" texs sp) = (pspace $ rs sp) ++ "&"
showTexTXT (TexCommand _ _ "\\ref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\reftext" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\interref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\multiref" texs sp) = (pspace $ rs sp) ++ "_REF_"    --"\multiref[]{}"
showTexTXT (TexCommand _ _ "\\pageref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\vref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\eref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\secref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\tt" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\nameref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\labelcref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\cpageref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\crefrange" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\cpagerefrange" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\hyperref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\figref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\mysec" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\citeA" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\Sec" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\LONG" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\SHORT" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\PAPER" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\ACMV" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\Autoref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\autoref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\autoref*" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\cref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\eqref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\myfig" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\liref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\lireftwo" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\eqnref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\ineqref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\Liref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\prettyref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\object" texs sp) = (pspace $ rs sp) ++ "_REF_"    
showTexTXT (TexCommand _ _ "\\objectname" texs sp) = (pspace $ rs sp) ++ "_REF_"  
showTexTXT (TexCommand _ _ "\\fullciteA" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\myeq" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\myapp" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\mytable" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\Fref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\Eqref" texs sp) = (pspace $ rs sp) ++ "_REF_"
showTexTXT (TexCommand _ _ "\\fref" texs sp) = (pspace $ rs sp) ++ "_REF_"
--showTexTXT (TexCommand _ _ "\\nocite" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\nocite" texs sp) = (pspace $ rs sp) 
showTexTXT (TexCommand _ _ "\\nocite*" texs sp) = (pspace $ rs sp) 
showTexTXT (TexCommand _ _ "\\onlinecite" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\onlinecite*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeauthor" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeauthor*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\cites" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\cites*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeN" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeN*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citen" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citen*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\shortcites" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\shortcites*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeyearNP" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeyearNP*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeANP" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeANP*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeNP" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeNP*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\shortciteN" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\shortciteN*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\shortciteNP" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\shortciteNP*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citepalias" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citepalias*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citetalias" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citetalias*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citep" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citep*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citet" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citet*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\opencite" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\opencite*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\cite" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\cite*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citealt" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citealt*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citealp" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citealp*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\newcite" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\newcite*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeyear" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeyear*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeyearpar" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeyearpar*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\inlinecite" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\inlinecite*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\shortcite" texs sp) = (pspace $ rs sp )++ "_CITE_"
showTexTXT (TexCommand _ _ "\\shortcite*" texs sp) = (pspace $ rs sp )++ "_CITE_"
showTexTXT (TexCommand _ _ "\\shortciteA" texs sp) = (pspace $ rs sp )++ "_CITE_"
showTexTXT (TexCommand _ _ "\\noparen" texs sp) = (pspace $ rs sp )++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeaffixed" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeaffixed*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeasnoun" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citeasnoun*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\possessivecite" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\possessivecite*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citetext" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citetext*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citenum" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\citenum*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\Citeauthor" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\Citeauthor*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\Citep" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\Citep*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\Citet" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\Citet*" texs sp) = (pspace $ rs sp) ++ "_CITE_"
showTexTXT (TexCommand _ _ "\\chemfig" texs sp) = (pspace $ rs sp) ++ "_CHEMFIG_"
showTexTXT (TexCommand _ _ "\\label" texs sp) = (pspace $ rs sp)
showTexTXT (TexCommand _ _ "\\lstdefinelanguage" texs sp) = (pspace $ rs sp)
showTexTXT (TexCommand _ _ "\\kwd" texs sp) = (pspace $ rs sp)
showTexTXT (TexCommand _ _ "\\foreignlanguage" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) (if length texs < 2 then []; else (tail texs)))
showTexTXT (TexCommand _ _ "\\colorbox" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\title" texs sp) = "\n" ++ (concat $ map (showTexTXT) (if length texs < 2 then texs; else (tail texs))) ++ "\n"
--showTexTXT (TexCommand _ _ "\\title" texs sp) = "\n"
showTexTXT (TexCommand _ _ "\\institute" texs sp) = "\n_INSTITUTE_"
showTexTXT (TexCommand _ _ "\\author" texs sp) = "\n_AUTHOR_"
showTexTXT (TexCommand _ _ "\\address" texs sp) = "\n_ADDRESS_"
showTexTXT (TexCommand _ _ "\\noindent" texs sp) = "\n" ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\subtitle" texs sp) = "\n" ++ (concat $ map (showTexTXT) texs) ++ "\n"
showTexTXT (TexCommand _ _ "\\abstract" texs sp) = "\n" ++ (concat $ map (showTexTXT) texs) ++ "\n"
showTexTXT (TexCommand _ _ "\\paragraph" texs sp) = "\n" ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\chapter" texs sp) = "\n" ++ (concat $ map (showTexTXT) texs) ++ "\n"
showTexTXT (TexCommand _ _ "\\enumsentence" texs sp) = "\n" ++ (concat $ map (showTexTXT) texs) ++ "\n"
showTexTXT (TexCommand _ _ "\\eenumsentence" texs sp) = "\n" ++ (concat $ map (showTexTXT) texs) ++ "\n"
showTexTXT (TexCommand _ _ "\\chapter*" texs sp) = "\n" ++ (concat $ map (showTexTXT) texs) ++ "\n"
showTexTXT (TexCommand _ _ "\\SEC" texs sp) = "\n" ++ (concat $ map (showTexTXT) (take 1 texs)) ++ "\n"  
showTexTXT (TexCommand _ _ "\\secput" texs sp) = "\n" ++ (concat $ map (showTexTXT) (if length texs < 2 then texs; else (tail texs))) ++ "\n"
showTexTXT (TexCommand _ _ "\\textcolor" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\section" texs sp) = "\n" ++ (concat $ map (showTexTXT) (if length texs < 2 then texs; else (tail texs))) ++ "\n"
showTexTXT (TexCommand _ _ "\\section*" texs sp) = "\n" ++ (concat $ map (showTexTXT) (if length texs < 2 then texs; else (tail texs))) ++ "\n"
showTexTXT (TexCommand _ _ "\\subsection" texs sp) = "\n" ++ (concat $ map (showTexTXT) (if length texs < 2 then texs; else (tail texs))) ++ "\n"
showTexTXT (TexCommand _ _ "\\subsection*" texs sp) = "\n" ++ (concat $ map (showTexTXT) (if length texs < 2 then texs; else (tail texs))) ++ "\n"
showTexTXT (TexCommand _ _ "\\subsubsection" texs sp) = "\n" ++ (concat $ map (showTexTXT) (if length texs < 2 then texs; else (tail texs))) ++ "\n"
showTexTXT (TexCommand _ _ "\\subsubsection*" texs sp) = "\n" ++ (concat $ map (showTexTXT) (if length texs < 2 then texs; else (tail texs))) ++ "\n"
showTexTXT (TexCommand _ _ "\\subsubsubsection" texs sp) = "\n" ++ (concat $ map (showTexTXT) (if length texs < 2 then texs; else (tail texs))) ++ "\n"
showTexTXT (TexCommand _ _ "\\subsubsubsection*" texs sp) = "\n" ++ (concat $ map (showTexTXT) (if length texs < 2 then texs; else (tail texs))) ++ "\n"
showTexTXT (TexCommand _ _ "\\mbox" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\hbox" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\vbox" texs sp) = (pspace $ rs sp) ++ (concat $ map (showTexTXT) texs)
showTexTXT (TexCommand _ _ "\\textit"