{-
Copyright (C) 2009 John MacFarlane <jgm@berkeley.edu>

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
-}

{- | Functions for parsing a LaTeX formula to a Haskell representation.
-}

module Text.TeXMath.Parser (expr, formula, Exp(..), TeXSymbolType(..), ArrayLine, Alignment(..))
where

import Control.Monad
import Data.Char (isAlphaNum)
import qualified Data.Map as M
import Text.ParserCombinators.Parsec
import qualified Text.ParserCombinators.Parsec.Token as P
import Text.ParserCombinators.Parsec.Language

data TeXSymbolType = Ord | Op | Bin | Rel | Open | Close | Pun | Accent
deriving (Show, Read, Eq)

data Alignment = AlignLeft | AlignCenter | AlignRight | AlignDefault
deriving (Show, Read, Eq)

type ArrayLine = [[Exp]]

data Exp =
ENumber String
| EGrouped [Exp]
| EIdentifier String
| EMathOperator String
| ESymbol TeXSymbolType String
| ESpace String
| EBinary String Exp Exp
| ESub Exp Exp
| ESuper Exp Exp
| ESubsup Exp Exp Exp
| EOver Exp Exp
| EUnder Exp Exp
| EUnderover Exp Exp Exp
| EUnary String Exp
| EScaled String Exp
| EStretchy Exp
| EArray [Alignment] [ArrayLine]
| EText String String
deriving (Show, Read, Eq)

texMathDef :: LanguageDef st
texMathDef = LanguageDef
{ commentStart   = ""
, commentEnd     = ""
, commentLine    = "%"
, nestedComments = False
, identStart     = letter
, identLetter    = letter
, opStart        = opLetter texMathDef
, opLetter       = oneOf ":_+*/=^-(),;.?'~[]<>!"
, reservedOpNames= []
, reservedNames  = []
, caseSensitive  = True
}

-- The parser

expr1 :: GenParser Char st Exp
expr1 =  choice [
inbraces
, variable
, number
, texSymbol
, text
, root
, unary
, binary
, enclosure
, array
, diacritical
, escaped
]

formula :: GenParser Char st [Exp]
formula = do
whiteSpace
f <- many expr
eof
return f

expr :: GenParser Char st Exp
expr = subSup <|> superOrSubscripted <|> expr1

inbraces :: GenParser Char st Exp
inbraces = liftM EGrouped (braces $many$ notFollowedBy (char '}') >> expr)

inbrackets :: GenParser Char st Exp
inbrackets = liftM EGrouped (brackets $many$ notFollowedBy (char ']') >> expr)

number :: GenParser Char st Exp
number = lexeme $liftM ENumber$ many1 digit

enclosure :: GenParser Char st Exp
enclosure = basicEnclosure <|> left <|> right <|> scaledEnclosure

basicEnclosure :: GenParser Char st Exp
basicEnclosure = choice $map (\(s, v) -> try (symbol s) >> return v) enclosures left :: GenParser Char st Exp left = try$ do
try (symbol "\\left")
enc <- basicEnclosure <|> (symbol "." >> return (ESymbol Open "\xFEFF"))
case enc of
(ESymbol Open _) -> tilRight enc <|> return (EStretchy enc)
_ -> pzero

right :: GenParser Char st Exp
right = try $do try (symbol "\\right") enc <- basicEnclosure <|> (symbol "." >> return (ESymbol Open "\xFEFF")) case enc of (ESymbol Close x) -> return (EStretchy$ ESymbol Open x)
_ -> pzero

-- We want stuff between \left( and \right) to be in an mrow,
-- so that the scaling is based just on this unit, and not the
-- whole containing formula.
tilRight :: Exp -> GenParser Char st Exp
tilRight start = try $do contents <- manyTill expr (try$ symbol "\\right" >> lookAhead basicEnclosure)
end <- basicEnclosure
return $EGrouped$ EStretchy start : (contents ++ [EStretchy end])

scaledEnclosure :: GenParser Char st Exp
scaledEnclosure = try $do cmd <- command case M.lookup cmd scalers of Just r -> liftM (EScaled r . EStretchy) basicEnclosure Nothing -> pzero arrayLine :: GenParser Char st ArrayLine arrayLine = notFollowedBy (try$ char '\\' >> symbol "end" >> return '\n') >>
sepBy1 (many (notFollowedBy (try $char '\\' >> char '\\') >> expr)) (symbol "&") array :: GenParser Char st Exp array = stdarray <|> eqnarray <|> cases <|> matrix matrix :: GenParser Char st Exp matrix = matrixWith "pmatrix" "(" ")" <|> matrixWith "bmatrix" "[" "]" <|> matrixWith "Bmatrix" "{" "}" <|> matrixWith "vmatrix" "\x2223" "\x2223" <|> matrixWith "Vmatrix" "\x2225" "\x2225" matrixWith :: String -> String -> String -> GenParser Char st Exp matrixWith keywd opendelim closedelim = inEnvironment keywd$ do
aligns <- option [] arrayAlignments
lines' <- sepEndBy1 arrayLine (try $symbol "\\\\") return$ EGrouped [ ESymbol Open opendelim
, EArray aligns lines'
, ESymbol Close closedelim]

stdarray :: GenParser Char st Exp
stdarray = inEnvironment "array" do aligns <- option [] arrayAlignments liftM (EArray aligns) sepEndBy1 arrayLine (try $symbol "\\\\") eqnarray :: GenParser Char st Exp eqnarray = inEnvironment "eqnarray"$
liftM (EArray [AlignRight, AlignCenter, AlignLeft]) $sepEndBy1 arrayLine (try$ symbol "\\\\")

cases :: GenParser Char st Exp
cases = inEnvironment "cases" $do rs <- sepEndBy1 arrayLine (try$ symbol "\\\\")
return $EGrouped [EStretchy (ESymbol Open "{"), EArray [] rs] arrayAlignments :: GenParser Char st [Alignment] arrayAlignments = try$ do
as <- braces (many letter)
let letterToAlignment 'l' = AlignLeft
letterToAlignment 'c' = AlignCenter
letterToAlignment 'r' = AlignRight
letterToAlignment _   = AlignDefault
return $map letterToAlignment as inEnvironment :: String -> GenParser Char st Exp -> GenParser Char st Exp inEnvironment envType p = do try$ do char '\\'
symbol "begin"
braces $symbol envType >> optional (symbol "*") result <- p char '\\' symbol "end" braces$ symbol envType >> optional (symbol "*")
return result

variable :: GenParser Char st Exp
variable = do
v <- letter
spaces
return $EIdentifier [v] subSup :: GenParser Char st Exp subSup = try$ do
a <- expr1
char '_'
b <- expr1
char '^'
c <- expr
return $ESubsup a b c superOrSubscripted :: GenParser Char st Exp superOrSubscripted = try$ do
a <- expr1
c <- oneOf "^_"
b <- expr
case c of
'^' -> return $ESuper a b '_' -> return$ ESub a b
_   -> pzero

escaped :: GenParser Char st Exp
escaped = lexeme $try$
char '\\' >>
liftM (ESymbol Ord . (:[])) (satisfy $not . isAlphaNum) command :: GenParser Char st 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 "normal")
, ("\\text",   EText "normal")
, ("\\mbox",   EText "normal")
, ("\\mathbf", EText "bold")
, ("\\textbf", EText "bold")
, ("\\mathit", EText "italic")
, ("\\textit", EText "italic")
, ("\\mathtt", EText "monospace")
, ("\\texttt", EText "monospace")
, ("\\mathsf", EText "sans-serif")
, ("\\mathbb", EText "double-struck")
, ("\\mathcal", EText "script")
, ("\\mathfrak", EText "fraktur")
]

diacritical :: GenParser Char st Exp
diacritical = try $do c <- command case M.lookup c diacriticals of Just r -> liftM r inbraces 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 :: GenParser Char st Exp unary = try$ do
c <- command
unless (c elem unaryOps) pzero
a <- inbraces
return $EUnary c a text :: GenParser Char st Exp text = try$ do
c <- command
case M.lookup c textOps of
Just f   -> liftM f $braces (many (noneOf "}" <|> (char '\\' >> char '}'))) Nothing -> pzero -- note: sqrt can be unary, \sqrt{2}, or binary, \sqrt[3]{2} root :: GenParser Char st Exp root = try$ do
try (symbol "\\sqrt") <|> symbol "\\surd"
a <- inbrackets
b <- inbraces
return $EBinary "\\sqrt" b a binary :: GenParser Char st Exp binary = try$ do
c <- command
unless (c elem binaryOps) pzero
a <- inbraces
b <- inbraces
return $EBinary c a b texSymbol :: GenParser Char st Exp texSymbol = try$ do
sym <- operator <|> command
case M.lookup sym symbols of
Just s   -> return s
Nothing  -> pzero

-- The lexer
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 \$ liftM (:[]) (opLetter texMathDef)
<|> many1 (char '\'')

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")
]

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 "\x230B")
, ("\\langle", ESymbol Open "\x3009")
, ("\\rangle", ESymbol Close "\x300A")
, ("\\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")
, ("\\vert", ESymbol Open "\x2223")
, ("\\vert", ESymbol Close "\x2223")
, ("\\Vert", ESymbol Open "\x2225")
, ("\\Vert", ESymbol Close "\x2225")
]

symbols :: M.Map String Exp
symbols = M.fromList [
("+", ESymbol Bin "+")
, ("-", ESymbol Bin "-")
, ("*", 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", ESymbol Ord "\x03B1")
, ("\\beta", ESymbol Ord "\x03B2")
, ("\\chi", ESymbol Ord "\x03C7")
, ("\\delta", ESymbol Ord "\x03B4")
, ("\\Delta", ESymbol Op "\x0394")
, ("\\epsi", ESymbol Ord "\x03B5")
, ("\\varepsilon", ESymbol Ord "\x025B")
, ("\\eta", ESymbol Ord "\x03B7")
, ("\\gamma", ESymbol Ord "\x03B3")
, ("\\Gamma", ESymbol Op "\x0393")
, ("\\iota", ESymbol Ord "\x03B9")
, ("\\kappa", ESymbol Ord "\x03BA")
, ("\\lambda", ESymbol Ord "\x03BB")
, ("\\Lambda", ESymbol Op "\x039B")
, ("\\mu", ESymbol Ord "\x03BC")
, ("\\nu", ESymbol Ord "\x03BD")
, ("\\omega", ESymbol Ord "\x03C9")
, ("\\Omega", ESymbol Op "\x03A9")
, ("\\phi", ESymbol Ord "\x03C6")
, ("\\varphi", ESymbol Ord "\x03D5")
, ("\\Phi", ESymbol Op "\x03A6")
, ("\\pi", ESymbol Ord "\x03C0")
, ("\\Pi", ESymbol Op "\x03A0")
, ("\\psi", ESymbol Ord "\x03C8")
, ("\\Psi", ESymbol Ord "\x03A8")
, ("\\rho", ESymbol Ord "\x03C1")
, ("\\sigma", ESymbol Ord "\x03C3")
, ("\\Sigma", ESymbol Op "\x03A3")
, ("\\tau", ESymbol Ord "\x03C4")
, ("\\theta", ESymbol Ord "\x03B8")
, ("\\vartheta", ESymbol Ord "\x03D1")
, ("\\Theta", ESymbol Op "\x0398")
, ("\\upsilon", ESymbol Ord "\x03C5")
, ("\\xi", ESymbol Ord "\x03BE")
, ("\\Xi", ESymbol Op "\x039E")
, ("\\zeta", ESymbol Ord "\x03B6")
, ("\\frac12", ESymbol Ord "\x00BD")
, ("\\frac14", ESymbol Ord "\x00BC")
, ("\\frac34", ESymbol Ord "\x00BE")
, ("\\frac13", ESymbol Ord "\x2153")
, ("\\frac23", ESymbol Ord "\x2154")
, ("\\frac15", ESymbol Ord "\x2155")
, ("\\frac25", ESymbol Ord "\x2156")
, ("\\frac35", ESymbol Ord "\x2157")
, ("\\frac45", ESymbol Ord "\x2158")
, ("\\frac16", ESymbol Ord "\x2159")
, ("\\frac56", ESymbol Ord "\x215A")
, ("\\frac18", ESymbol Ord "\x215B")
, ("\\frac38", ESymbol Ord "\x215C")
, ("\\frac58", ESymbol Ord "\x215D")
, ("\\frac78", ESymbol Ord "\x215E")
, ("\\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")
, ("\\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")
, ("\\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")
]