module Text.TeXMath.Parser (parseFormula)
where
import Control.Monad
import Data.Char (isDigit, isAscii)
import qualified Data.Map as M
import Text.ParserCombinators.Parsec
import qualified Text.ParserCombinators.Parsec.Token as P
import Text.ParserCombinators.Parsec.Language
import Text.TeXMath.Types
import Control.Applicative ((<*), (*>), (<$>))
type TP = GenParser Char ()
texMathDef :: LanguageDef st
texMathDef = LanguageDef
{ commentStart = "\\label{"
, commentEnd = "}"
, commentLine = "%"
, nestedComments = False
, identStart = letter
, identLetter = letter
, opStart = opLetter texMathDef
, opLetter = oneOf ":_+*/=^-(),;.?'~[]<>!"
, reservedOpNames= []
, reservedNames = []
, caseSensitive = True
}
expr1 :: TP Exp
expr1 = choice [
inbraces
, variable
, number
, texSymbol
, text
, root
, unary
, binary
, enclosure
, environment
, diacritical
, escaped
, unicode
, ensuremath
]
parseFormula :: String -> Either String [Exp]
parseFormula inp =
either (Left . show) (Right . id) $ parse formula "formula" inp
formula :: TP [Exp]
formula = do
whiteSpace
f <- many expr
whiteSpace
eof
return f
expr :: TP Exp
expr = do
optional (try $ symbol "\\displaystyle")
a <- expr1
limits <- limitsIndicator
subSup limits a <|> superOrSubscripted limits a <|> return a
limitsIndicator :: TP (Maybe Bool)
limitsIndicator =
try (symbol "\\limits" >> return (Just True))
<|> try (symbol "\\nolimits" >> return (Just False))
<|> return Nothing
inbraces :: TP Exp
inbraces = liftM EGrouped (braces $ many $ notFollowedBy (char '}') >> expr)
texToken :: TP Exp
texToken = texSymbol <|> inbraces <|> inbrackets <|>
do c <- anyChar
spaces
return $ if isDigit c
then (ENumber [c])
else (EIdentifier [c])
inbrackets :: TP Exp
inbrackets = liftM EGrouped (brackets $ many $ notFollowedBy (char ']') >> expr)
number :: TP Exp
number = lexeme $ liftM ENumber $ many1 digit
enclosure :: TP Exp
enclosure = basicEnclosure <|> left <|> right <|> scaledEnclosure
basicEnclosure :: TP Exp
basicEnclosure = choice $ map (\(s, v) -> try (symbol s) >> return v) enclosures
left :: TP Exp
left = try $ do
symbol "\\left"
enc <- basicEnclosure <|> (try (symbol ".") >> return (ESymbol Open "\xFEFF"))
case enc of
(ESymbol Open _) -> tilRight enc <|> return (EStretchy enc)
_ -> pzero
right :: TP Exp
right = try $ do
symbol "\\right"
enc <- basicEnclosure <|> (try (symbol ".") >> return (ESymbol Close "\xFEFF"))
case enc of
(ESymbol Close x) -> return (EStretchy $ ESymbol Open x)
_ -> pzero
tilRight :: Exp -> TP Exp
tilRight start = try $ do
contents <- manyTill expr
(try $ symbol "\\right" >> lookAhead basicEnclosure)
end <- basicEnclosure
let startChar = case start of
ESymbol _ c -> c
_ -> ""
let endChar = case end of
ESymbol _ c -> c
_ -> ""
return $ EDelimited startChar endChar contents
scaledEnclosure :: TP Exp
scaledEnclosure = try $ do
cmd <- command
case M.lookup cmd scalers of
Just r -> liftM (EScaled r . EStretchy) basicEnclosure
Nothing -> pzero
endLine :: TP Char
endLine = try $ do
symbol "\\\\"
optional inbrackets
return '\n'
arrayLine :: TP ArrayLine
arrayLine = notFollowedBy (try $ symbol "\\end" >> return '\n') >>
sepBy1 (many (notFollowedBy endLine >> expr)) (symbol "&")
arrayAlignments :: TP [Alignment]
arrayAlignments = try $ do
as <- braces (many letter)
let letterToAlignment 'l' = AlignLeft
letterToAlignment 'c' = AlignCenter
letterToAlignment 'r' = AlignRight
letterToAlignment _ = AlignDefault
return $ map letterToAlignment as
environment :: TP Exp
environment = try $ do
symbol "\\begin"
name <- char '{' *> manyTill anyChar (char '}')
spaces
let name' = filter (/='*') name
case M.lookup name' environments of
Just env -> env <* spaces <* symbol "\\end"
<* braces (string name) <* spaces
Nothing -> mzero
environments :: M.Map String (TP Exp)
environments = M.fromList
[ ("array", stdarray)
, ("eqnarray", eqnarray)
, ("align", align)
, ("aligned", align)
, ("alignat", inbraces *> spaces *> align)
, ("alignedat", inbraces *> spaces *> align)
, ("flalign", flalign)
, ("flaligned", flalign)
, ("cases", cases)
, ("pmatrix", matrixWith "(" ")")
, ("bmatrix", matrixWith "[" "]")
, ("Bmatrix", matrixWith "{" "}")
, ("vmatrix", matrixWith "\x2223" "\x2223")
, ("Vmatrix", matrixWith "\x2225" "\x2225")
, ("split", align)
, ("multiline", gather)
, ("gather", gather)
, ("gathered", gather)
]
matrixWith :: String -> String -> TP Exp
matrixWith opendelim closedelim = do
aligns <- option [] arrayAlignments
lines' <- sepEndBy1 arrayLine endLine
return $ EDelimited opendelim closedelim [EArray aligns lines']
stdarray :: TP Exp
stdarray = do
aligns <- option [] arrayAlignments
(EArray aligns) <$> sepEndBy1 arrayLine endLine
gather :: TP Exp
gather = (EArray []) <$> sepEndBy arrayLine endLine
eqnarray :: TP Exp
eqnarray = (EArray [AlignRight, AlignCenter, AlignLeft]) <$>
sepEndBy1 arrayLine endLine
align :: TP Exp
align = (EArray [AlignRight, AlignLeft]) <$>
sepEndBy1 arrayLine endLine
flalign :: TP Exp
flalign = (EArray [AlignLeft, AlignRight]) <$>
sepEndBy1 arrayLine endLine
cases :: TP Exp
cases = do
rs <- sepEndBy1 arrayLine endLine
return $ EDelimited "{" "" [EArray [] rs]
variable :: TP Exp
variable = do
v <- letter
spaces
return $ EIdentifier [v]
isConvertible :: Exp -> Bool
isConvertible (EMathOperator x) = x `elem` convertibleOps
where convertibleOps = [ "lim","liminf","limsup","inf","sup"
, "min","max","Pr","det","gcd"
]
isConvertible (ESymbol Rel _) = True
isConvertible (ESymbol Bin _) = True
isConvertible (ESymbol Op x) = x `elem` convertibleSyms
where convertibleSyms = ["\x2211","\x220F","\x22C2",
"\x22C3","\x22C0","\x22C1","\x2A05","\x2A06",
"\x2210","\x2A01","\x2A02","\x2A00","\x2A04"]
isConvertible _ = False
isUnderover :: Exp -> Bool
isUnderover (EOver _ (ESymbol Accent "\xFE37")) = True
isUnderover (EOver _ (ESymbol Accent "\x23B4")) = True
isUnderover (EUnder _ (ESymbol Accent "\xFE38")) = True
isUnderover (EUnder _ (ESymbol Accent "\x23B5")) = True
isUnderover _ = False
subSup :: Maybe Bool -> Exp -> TP Exp
subSup limits a = try $ do
let sub1 = symbol "_" >> expr1
let sup1 = symbol "^" >> expr1
(b,c) <- try (do {m <- sub1; n <- sup1; return (m,n)})
<|> (do {n <- sup1; m <- sub1; return (m,n)})
return $ case limits of
Just True -> EUnderover a b c
Nothing | isConvertible a -> EDownup a b c
| isUnderover a -> EUnderover a b c
_ -> ESubsup a b c
superOrSubscripted :: Maybe Bool -> Exp -> TP Exp
superOrSubscripted limits a = try $ do
c <- oneOf "^_"
spaces
b <- expr
case c of
'^' -> return $ case limits of
Just True -> EOver a b
Nothing | isConvertible a -> EUp a b
| isUnderover a -> EOver a b
_ -> ESuper a b
'_' -> return $ case limits of
Just True -> EUnder a b
Nothing | isConvertible a -> EDown a b
| isUnderover a -> EUnder a b
_ -> ESub a b
_ -> pzero
escaped :: TP Exp
escaped = lexeme $ try $
char '\\' >>
liftM (ESymbol Ord . (:[])) (satisfy isEscapable)
where isEscapable '{' = True
isEscapable '}' = True
isEscapable '$' = True
isEscapable '%' = True
isEscapable '&' = True
isEscapable '_' = True
isEscapable '#' = True
isEscapable '^' = True
isEscapable ' ' = True
isEscapable _ = False
unicode :: TP Exp
unicode = lexeme $ liftM (ESymbol Ord . (:[])) $ satisfy (not . isAscii)
ensuremath :: TP Exp
ensuremath = try $ lexeme (string "\\ensuremath") >> inbraces
command :: TP String
command = try $ char '\\' >> liftM ('\\':) (identifier <|> lexeme (count 1 anyChar))
unaryOps :: [String]
unaryOps = ["\\sqrt", "\\surd"]
textOps :: M.Map String (String -> Exp)
textOps = M.fromList
[ ("\\textrm", EText TextNormal . parseText)
, ("\\mathrm", EText TextNormal)
, ("\\mathup", EText TextNormal)
, ("\\text", EText TextNormal . parseText)
, ("\\mbox", EText TextNormal)
, ("\\mathbf", EText TextBold)
, ("\\mathbfup", EText TextBold)
, ("\\textbf", EText TextBold . parseText)
, ("\\mathit", EText TextItalic)
, ("\\textit", EText TextItalic . parseText)
, ("\\mathtt", EText TextMonospace)
, ("\\texttt", EText TextMonospace)
, ("\\mathsf", EText TextSansSerif)
, ("\\mathsfup", EText TextSansSerif)
, ("\\mathbb", EText TextDoubleStruck)
, ("\\mathcal", EText TextScript)
, ("\\mathscr", EText TextScript)
, ("\\mathfrak", EText TextFraktur)
, ("\\mathbfit", EText TextBoldItalic)
, ("\\mathbfsfup", EText TextBoldSansSerif)
, ("\\mathbfsfit", EText TextBoldSansSerifItalic)
, ("\\mathbfscr", EText TextBoldScript)
, ("\\mathbffrak", EText TextBoldFraktur)
, ("\\mathbfcal", EText TextBoldScript)
, ("\\mathsfit", EText TextSansSerifItalic)
]
parseText :: String -> String
parseText ('`':'`':xs) = '\x201C' : parseText xs
parseText ('\'':'\'':xs) = '\x201D' : parseText xs
parseText ('\'':xs) = '\x2019' : parseText xs
parseText ('-':'-':'-':xs) = '\x2014' : parseText xs
parseText ('-':'-':xs) = '\x2013' : parseText xs
parseText ('\\':'l':'d':'o':'t':'s':xs) = '\x2026' : parseText xs
parseText ('~':xs) = '\xA0' : parseText xs
parseText (x:xs) = x : parseText xs
parseText [] = []
diacritical :: TP Exp
diacritical = try $ do
c <- command
case M.lookup c diacriticals of
Just r -> liftM r texToken
Nothing -> pzero
diacriticals :: M.Map String (Exp -> Exp)
diacriticals = M.fromList
[ ("\\acute", \e -> EOver e (ESymbol Accent "\x00B4"))
, ("\\grave", \e -> EOver e (ESymbol Accent "\x0060"))
, ("\\breve", \e -> EOver e (ESymbol Accent "\x02D8"))
, ("\\check", \e -> EOver e (ESymbol Accent "\x02C7"))
, ("\\dot", \e -> EOver e (ESymbol Accent "."))
, ("\\ddot", \e -> EOver e (ESymbol Accent ".."))
, ("\\mathring", \e -> EOver e (ESymbol Accent "\x00B0"))
, ("\\vec", \e -> EOver e (ESymbol Accent "\x20D7"))
, ("\\overrightarrow", \e -> EOver e (ESymbol Accent "\x20D7"))
, ("\\overleftarrow", \e -> EOver e (ESymbol Accent "\x20D6"))
, ("\\hat", \e -> EOver e (ESymbol Accent "\x005E"))
, ("\\widehat", \e -> EOver e (ESymbol Accent "\x0302"))
, ("\\tilde", \e -> EOver e (ESymbol Accent "~"))
, ("\\widetilde", \e -> EOver e (ESymbol Accent "\x02DC"))
, ("\\bar", \e -> EOver e (ESymbol Accent "\x203E"))
, ("\\overbrace", \e -> EOver e (ESymbol Accent "\xFE37"))
, ("\\overbracket", \e -> EOver e (ESymbol Accent "\x23B4"))
, ("\\overline", \e -> EOver e (ESymbol Accent "\x00AF"))
, ("\\underbrace", \e -> EUnder e (ESymbol Accent "\xFE38"))
, ("\\underbracket", \e -> EUnder e (ESymbol Accent "\x23B5"))
, ("\\underline", \e -> EUnder e (ESymbol Accent "\x00AF"))
]
unary :: TP Exp
unary = try $ do
c <- command
unless (c `elem` unaryOps) pzero
a <- texToken
return $ EUnary c a
text :: TP Exp
text = try $ do
c <- command
case M.lookup c textOps of
Just f -> liftM f $ braces (many (noneOf "}" <|> (char '\\' >> char '}')))
Nothing -> pzero
root :: TP Exp
root = try $ do
try (symbol "\\sqrt") <|> symbol "\\surd"
a <- inbrackets
b <- texToken
return $ EBinary "\\sqrt" b a
binary :: TP Exp
binary = try $ do
c <- command
unless (c `elem` binaryOps) pzero
a <- texToken
b <- texToken
return $ EBinary c a b
texSymbol :: TP Exp
texSymbol = try $ do
sym <- operator <|> command
case M.lookup sym symbols of
Just s -> return s
Nothing -> pzero
lexer :: P.TokenParser st
lexer = P.makeTokenParser texMathDef
lexeme :: CharParser st a -> CharParser st a
lexeme = P.lexeme lexer
whiteSpace :: CharParser st ()
whiteSpace = P.whiteSpace lexer
identifier :: CharParser st String
identifier = lexeme (P.identifier lexer)
operator :: CharParser st String
operator = lexeme $ many1 (char '\'')
<|> liftM (:[]) (opLetter texMathDef)
symbol :: String -> CharParser st String
symbol = lexeme . P.symbol lexer
braces :: CharParser st a -> CharParser st a
braces = lexeme . P.braces lexer
brackets :: CharParser st a -> CharParser st a
brackets = lexeme . P.brackets lexer
binaryOps :: [String]
binaryOps = ["\\frac", "\\tfrac", "\\dfrac", "\\stackrel", "\\overset", "\\underset", "\\binom"]
scalers :: M.Map String String
scalers = M.fromList
[ ("\\bigg", "2.2")
, ("\\Bigg", "2.9")
, ("\\big", "1.2")
, ("\\Big", "1.6")
, ("\\biggr", "2.2")
, ("\\Biggr", "2.9")
, ("\\bigr", "1.2")
, ("\\Bigr", "1.6")
, ("\\biggl", "2.2")
, ("\\Biggl", "2.9")
, ("\\bigl", "1.2")
, ("\\Bigl", "1.6")
]
enclosures :: [(String, Exp)]
enclosures = [ ("(", ESymbol Open "(")
, (")", ESymbol Close ")")
, ("[", ESymbol Open "[")
, ("]", ESymbol Close "]")
, ("\\{", ESymbol Open "{")
, ("\\}", ESymbol Close "}")
, ("\\lbrack", ESymbol Open "[")
, ("\\lbrace", ESymbol Open "{")
, ("\\rbrack", ESymbol Close "]")
, ("\\rbrace", ESymbol Close "}")
, ("\\llbracket", ESymbol Open "\x27E6")
, ("\\rrbracket", ESymbol Close "\x27E7")
, ("\\langle", ESymbol Open "\x27E8")
, ("\\rangle", ESymbol Close "\x27E9")
, ("\\lfloor", ESymbol Open "\x230A")
, ("\\rfloor", ESymbol Close "\x230B")
, ("\\lceil", ESymbol Open "\x2308")
, ("\\rceil", ESymbol Close "\x2309")
, ("|", ESymbol Open "\x2223")
, ("|", ESymbol Close "\x2223")
, ("\\|", ESymbol Open "\x2225")
, ("\\|", ESymbol Close "\x2225")
, ("\\lvert", ESymbol Open "\x7C")
, ("\\rvert", ESymbol Close "\x7C")
, ("\\vert", ESymbol Close "\x7C")
, ("\\lVert", ESymbol Open "\x2225")
, ("\\rVert", ESymbol Close "\x2225")
, ("\\Vert", ESymbol Close "\x2016")
, ("\\ulcorner", ESymbol Open "\x231C")
, ("\\urcorner", ESymbol Close "\x231D")
]
symbols :: M.Map String Exp
symbols = M.fromList [
("+", ESymbol Bin "+")
, ("-", ESymbol Bin "\x2212")
, ("*", ESymbol Bin "*")
, (",", ESymbol Pun ",")
, (".", ESymbol Pun ".")
, (";", ESymbol Pun ";")
, (":", ESymbol Pun ":")
, ("?", ESymbol Pun "?")
, (">", ESymbol Rel ">")
, ("<", ESymbol Rel "<")
, ("!", ESymbol Ord "!")
, ("'", ESymbol Ord "\x02B9")
, ("''", ESymbol Ord "\x02BA")
, ("'''", ESymbol Ord "\x2034")
, ("''''", ESymbol Ord "\x2057")
, ("=", ESymbol Rel "=")
, (":=", ESymbol Rel ":=")
, ("\\mid", ESymbol Bin "\x2223")
, ("\\parallel", ESymbol Rel "\x2225")
, ("\\backslash", ESymbol Bin "\x2216")
, ("/", ESymbol Bin "/")
, ("\\setminus", ESymbol Bin "\\")
, ("\\times", ESymbol Bin "\x00D7")
, ("\\alpha", EIdentifier "\x03B1")
, ("\\beta", EIdentifier "\x03B2")
, ("\\chi", EIdentifier "\x03C7")
, ("\\delta", EIdentifier "\x03B4")
, ("\\Delta", ESymbol Op "\x0394")
, ("\\epsilon", EIdentifier "\x03B5")
, ("\\varepsilon", EIdentifier "\x025B")
, ("\\eta", EIdentifier "\x03B7")
, ("\\gamma", EIdentifier "\x03B3")
, ("\\Gamma", ESymbol Op "\x0393")
, ("\\iota", EIdentifier "\x03B9")
, ("\\kappa", EIdentifier "\x03BA")
, ("\\lambda", EIdentifier "\x03BB")
, ("\\Lambda", ESymbol Op "\x039B")
, ("\\mu", EIdentifier "\x03BC")
, ("\\nu", EIdentifier "\x03BD")
, ("\\omega", EIdentifier "\x03C9")
, ("\\Omega", ESymbol Op "\x03A9")
, ("\\phi", EIdentifier "\x03D5")
, ("\\varphi", EIdentifier "\x03C6")
, ("\\Phi", ESymbol Op "\x03A6")
, ("\\pi", EIdentifier "\x03C0")
, ("\\Pi", ESymbol Op "\x03A0")
, ("\\psi", EIdentifier "\x03C8")
, ("\\Psi", ESymbol Ord "\x03A8")
, ("\\rho", EIdentifier "\x03C1")
, ("\\sigma", EIdentifier "\x03C3")
, ("\\Sigma", ESymbol Op "\x03A3")
, ("\\tau", EIdentifier "\x03C4")
, ("\\theta", EIdentifier "\x03B8")
, ("\\vartheta", EIdentifier "\x03D1")
, ("\\Theta", ESymbol Op "\x0398")
, ("\\upsilon", EIdentifier "\x03C5")
, ("\\xi", EIdentifier "\x03BE")
, ("\\Xi", ESymbol Op "\x039E")
, ("\\zeta", EIdentifier "\x03B6")
, ("\\pm", ESymbol Bin "\x00B1")
, ("\\mp", ESymbol Bin "\x2213")
, ("\\triangleleft", ESymbol Bin "\x22B2")
, ("\\triangleright", ESymbol Bin "\x22B3")
, ("\\cdot", ESymbol Bin "\x22C5")
, ("\\star", ESymbol Bin "\x22C6")
, ("\\ast", ESymbol Bin "\x002A")
, ("\\times", ESymbol Bin "\x00D7")
, ("\\div", ESymbol Bin "\x00F7")
, ("\\circ", ESymbol Bin "\x2218")
, ("\\bullet", ESymbol Bin "\x2022")
, ("\\oplus", ESymbol Bin "\x2295")
, ("\\ominus", ESymbol Bin "\x2296")
, ("\\otimes", ESymbol Bin "\x2297")
, ("\\bigcirc", ESymbol Bin "\x25CB")
, ("\\oslash", ESymbol Bin "\x2298")
, ("\\odot", ESymbol Bin "\x2299")
, ("\\land", ESymbol Bin "\x2227")
, ("\\wedge", ESymbol Bin "\x2227")
, ("\\lor", ESymbol Bin "\x2228")
, ("\\vee", ESymbol Bin "\x2228")
, ("\\cap", ESymbol Bin "\x2229")
, ("\\cup", ESymbol Bin "\x222A")
, ("\\sqcap", ESymbol Bin "\x2293")
, ("\\sqcup", ESymbol Bin "\x2294")
, ("\\uplus", ESymbol Bin "\x228E")
, ("\\amalg", ESymbol Bin "\x2210")
, ("\\bigtriangleup", ESymbol Bin "\x25B3")
, ("\\bigtriangledown", ESymbol Bin "\x25BD")
, ("\\dag", ESymbol Bin "\x2020")
, ("\\dagger", ESymbol Bin "\x2020")
, ("\\ddag", ESymbol Bin "\x2021")
, ("\\ddagger", ESymbol Bin "\x2021")
, ("\\lhd", ESymbol Bin "\x22B2")
, ("\\rhd", ESymbol Bin "\x22B3")
, ("\\unlhd", ESymbol Bin "\x22B4")
, ("\\unrhd", ESymbol Bin "\x22B5")
, ("\\lt", ESymbol Rel "<")
, ("\\gt", ESymbol Rel ">")
, ("\\ne", ESymbol Rel "\x2260")
, ("\\neq", ESymbol Rel "\x2260")
, ("\\le", ESymbol Rel "\x2264")
, ("\\leq", ESymbol Rel "\x2264")
, ("\\leqslant", ESymbol Rel "\x2264")
, ("\\ge", ESymbol Rel "\x2265")
, ("\\geq", ESymbol Rel "\x2265")
, ("\\geqslant", ESymbol Rel "\x2265")
, ("\\equiv", ESymbol Rel "\x2261")
, ("\\ll", ESymbol Rel "\x226A")
, ("\\gg", ESymbol Rel "\x226B")
, ("\\doteq", ESymbol Rel "\x2250")
, ("\\prec", ESymbol Rel "\x227A")
, ("\\succ", ESymbol Rel "\x227B")
, ("\\preceq", ESymbol Rel "\x227C")
, ("\\succeq", ESymbol Rel "\x227D")
, ("\\subset", ESymbol Rel "\x2282")
, ("\\supset", ESymbol Rel "\x2283")
, ("\\subseteq", ESymbol Rel "\x2286")
, ("\\supseteq", ESymbol Rel "\x2287")
, ("\\sqsubset", ESymbol Rel "\x228F")
, ("\\sqsupset", ESymbol Rel "\x2290")
, ("\\sqsubseteq", ESymbol Rel "\x2291")
, ("\\sqsupseteq", ESymbol Rel "\x2292")
, ("\\sim", ESymbol Rel "\x223C")
, ("\\simeq", ESymbol Rel "\x2243")
, ("\\approx", ESymbol Rel "\x2248")
, ("\\cong", ESymbol Rel "\x2245")
, ("\\Join", ESymbol Rel "\x22C8")
, ("\\bowtie", ESymbol Rel "\x22C8")
, ("\\in", ESymbol Rel "\x2208")
, ("\\ni", ESymbol Rel "\x220B")
, ("\\owns", ESymbol Rel "\x220B")
, ("\\propto", ESymbol Rel "\x221D")
, ("\\vdash", ESymbol Rel "\x22A2")
, ("\\dashv", ESymbol Rel "\x22A3")
, ("\\models", ESymbol Rel "\x22A8")
, ("\\perp", ESymbol Rel "\x22A5")
, ("\\smile", ESymbol Rel "\x2323")
, ("\\frown", ESymbol Rel "\x2322")
, ("\\asymp", ESymbol Rel "\x224D")
, ("\\notin", ESymbol Rel "\x2209")
, ("\\gets", ESymbol Rel "\x2190")
, ("\\leftarrow", ESymbol Rel "\x2190")
, ("\\to", ESymbol Rel "\x2192")
, ("\\rightarrow", ESymbol Rel "\x2192")
, ("\\leftrightarrow", ESymbol Rel "\x2194")
, ("\\uparrow", ESymbol Rel "\x2191")
, ("\\downarrow", ESymbol Rel "\x2193")
, ("\\updownarrow", ESymbol Rel "\x2195")
, ("\\Leftarrow", ESymbol Rel "\x21D0")
, ("\\Rightarrow", ESymbol Rel "\x21D2")
, ("\\Leftrightarrow", ESymbol Rel "\x21D4")
, ("\\iff", ESymbol Rel "\x21D4")
, ("\\Uparrow", ESymbol Rel "\x21D1")
, ("\\Downarrow", ESymbol Rel "\x21D3")
, ("\\Updownarrow", ESymbol Rel "\x21D5")
, ("\\mapsto", ESymbol Rel "\x21A6")
, ("\\longleftarrow", ESymbol Rel "\x2190")
, ("\\longrightarrow", ESymbol Rel "\x2192")
, ("\\longleftrightarrow", ESymbol Rel "\x2194")
, ("\\Longleftarrow", ESymbol Rel "\x21D0")
, ("\\Longrightarrow", ESymbol Rel "\x21D2")
, ("\\Longleftrightarrow", ESymbol Rel "\x21D4")
, ("\\longmapsto", ESymbol Rel "\x21A6")
, ("\\sum", ESymbol Op "\x2211")
, ("\\prod", ESymbol Op "\x220F")
, ("\\bigcap", ESymbol Op "\x22C2")
, ("\\bigcup", ESymbol Op "\x22C3")
, ("\\bigwedge", ESymbol Op "\x22C0")
, ("\\bigvee", ESymbol Op "\x22C1")
, ("\\bigsqcap", ESymbol Op "\x2A05")
, ("\\bigsqcup", ESymbol Op "\x2A06")
, ("\\coprod", ESymbol Op "\x2210")
, ("\\bigoplus", ESymbol Op "\x2A01")
, ("\\bigotimes", ESymbol Op "\x2A02")
, ("\\bigodot", ESymbol Op "\x2A00")
, ("\\biguplus", ESymbol Op "\x2A04")
, ("\\int", ESymbol Op "\x222B")
, ("\\iint", ESymbol Op "\x222C")
, ("\\iiint", ESymbol Op "\x222D")
, ("\\oint", ESymbol Op "\x222E")
, ("\\prime", ESymbol Ord "\x2032")
, ("\\dots", ESymbol Ord "\x2026")
, ("\\ldots", ESymbol Ord "\x2026")
, ("\\cdots", ESymbol Ord "\x22EF")
, ("\\vdots", ESymbol Ord "\x22EE")
, ("\\ddots", ESymbol Ord "\x22F1")
, ("\\forall", ESymbol Op "\x2200")
, ("\\exists", ESymbol Op "\x2203")
, ("\\Re", ESymbol Ord "\x211C")
, ("\\Im", ESymbol Ord "\x2111")
, ("\\aleph", ESymbol Ord "\x2135")
, ("\\hbar", ESymbol Ord "\x210F")
, ("\\ell", ESymbol Ord "\x2113")
, ("\\wp", ESymbol Ord "\x2118")
, ("\\emptyset", ESymbol Ord "\x2205")
, ("\\infty", ESymbol Ord "\x221E")
, ("\\partial", ESymbol Ord "\x2202")
, ("\\nabla", ESymbol Ord "\x2207")
, ("\\triangle", ESymbol Ord "\x25B3")
, ("\\therefore", ESymbol Pun "\x2234")
, ("\\angle", ESymbol Ord "\x2220")
, ("\\diamond", ESymbol Op "\x22C4")
, ("\\Diamond", ESymbol Op "\x25C7")
, ("\\lozenge", ESymbol Op "\x25CA")
, ("\\neg", ESymbol Op "\x00AC")
, ("\\lnot", ESymbol Ord "\x00AC")
, ("\\bot", ESymbol Ord "\x22A5")
, ("\\top", ESymbol Ord "\x22A4")
, ("\\square", ESymbol Ord "\x25AB")
, ("\\Box", ESymbol Op "\x25A1")
, ("\\wr", ESymbol Ord "\x2240")
, ("\\!", ESpace "-0.167em")
, ("\\,", ESpace "0.167em")
, ("\\>", ESpace "0.222em")
, ("\\:", ESpace "0.222em")
, ("\\;", ESpace "0.278em")
, ("~", ESpace "0.333em")
, ("\\quad", ESpace "1em")
, ("\\qquad", ESpace "2em")
, ("\\arccos", EMathOperator "arccos")
, ("\\arcsin", EMathOperator "arcsin")
, ("\\arctan", EMathOperator "arctan")
, ("\\arg", EMathOperator "arg")
, ("\\cos", EMathOperator "cos")
, ("\\cosh", EMathOperator "cosh")
, ("\\cot", EMathOperator "cot")
, ("\\coth", EMathOperator "coth")
, ("\\csc", EMathOperator "csc")
, ("\\deg", EMathOperator "deg")
, ("\\det", EMathOperator "det")
, ("\\dim", EMathOperator "dim")
, ("\\exp", EMathOperator "exp")
, ("\\gcd", EMathOperator "gcd")
, ("\\hom", EMathOperator "hom")
, ("\\inf", EMathOperator "inf")
, ("\\ker", EMathOperator "ker")
, ("\\lg", EMathOperator "lg")
, ("\\lim", EMathOperator "lim")
, ("\\liminf", EMathOperator "liminf")
, ("\\limsup", EMathOperator "limsup")
, ("\\ln", EMathOperator "ln")
, ("\\log", EMathOperator "log")
, ("\\max", EMathOperator "max")
, ("\\min", EMathOperator "min")
, ("\\Pr", EMathOperator "Pr")
, ("\\sec", EMathOperator "sec")
, ("\\sin", EMathOperator "sin")
, ("\\sinh", EMathOperator "sinh")
, ("\\sup", EMathOperator "sup")
, ("\\tan", EMathOperator "tan")
, ("\\tanh", EMathOperator "tanh")
]