Eq-1.0: EqManips/Renderer/Mathml.hs
{-# LANGUAGE NewQualifiedOperators #-}
module EqManips.Renderer.Mathml( mathmlRender ) where
import EqManips.Types hiding ( matrix )
import EqManips.Algorithm.Utils
import EqManips.Propreties
import EqManips.Renderer.Latex
import EqManips.Renderer.EqCode
import EqManips.Renderer.RenderConf
mathmlRender :: Conf -> Formula TreeForm -> String
mathmlRender conf (Formula f) =
str "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">\n"
. semantics ( presMarkup
. annotation "MathML-Content" contentMarkup
. annotation "Eq-language" (str . cleanify $ unparse f)
. annotation "LaTeX" (str . cleanify . latexRender conf $ Formula f))
. str "</math>\n" $ ""
where contentMarkup = content f
presMarkup = mrow $ prez conf f
semantics = tagger "semantics"
annotation kind c =
str ("<annotation-xml encoding=\"" ++ kind ++ "\">\n")
. c . str "\n</annotation-xml>\n"
str :: String -> ShowS
str = (++)
char :: Char -> ShowS
char = (:)
mathMlOfEntity :: Entity -> String
mathMlOfEntity Pi = "<pi/>"
mathMlOfEntity Nabla = "<grad/>"
mathMlOfEntity Infinite = "<infinity/>"
mathMlOfEntity Ellipsis = "⋯"
tagger :: String -> ShowS -> ShowS
tagger tag f = str ('<': tag ++ ">") . f . str ("</" ++ tag ++ ">")
cleanify :: String -> String
cleanify = concatMap deAnchor
where deAnchor '<' = "<"
deAnchor '>' = ">"
deAnchor '&' = "&"
deAnchor a = [a]
mo, msup, mi, mn, mfrac, mrow, parens,
msubsup, msqrt, mfenced, mtable,
mtd, mtr :: ShowS -> ShowS
mo = tagger "mo"
mi = tagger "mi"
mn = tagger "mn"
mfrac = tagger "mfrac"
mrow = tagger "mrow"
parens f = str "<mo>(</mo>" . f . str "<mo>)</mo>"
msubsup = tagger "msubsup"
msup = tagger "msup"
msqrt = tagger "msqrt"
mfenced f = str "<mfenced open=\"[\" close=\"]\">\n" . f . str "</mfenced>\n"
mtable = tagger "mtable"
mtd = tagger "mtd"
mtr = tagger "mtr"
enclose :: Char -> Char -> ShowS -> ShowS
enclose beg end f = str ("<mo>" ++ (beg : "</mo>")) . f . str ("<mo>" ++ (end : "</mo>"))
prez :: Conf -> FormulaPrim -> ShowS
prez conf = presentation conf Nothing
--centerdot
--
presentation :: Conf -> Maybe (BinOperator, Bool) -> FormulaPrim -> ShowS
presentation _ _ (Block _ _ _) = mi $ str "block"
presentation _ _ (Variable v) = mi $ str v
presentation _ _ (NumEntity e) = mn $ str $ mathMlOfEntity e
presentation _ _ (Truth t) = mn $ shows t
presentation _ _ (CInteger i) = mn $ shows i
presentation _ _ (CFloat d) = mn $ shows d
presentation conf inf (Meta _ _ f) = presentation conf inf f
presentation _ _ (Lambda _ _clauses) = id
presentation conf _ (BinOp _ OpPow [a,b]) =
msup $ mrow (presentation conf (Just (OpPow, False)) a)
. mrow (presentation conf (Just (OpPow, True)) b)
presentation conf _ (BinOp _ OpDiv [a,b]) =
mfrac $ mrow (prez conf a)
. mrow (prez conf b)
presentation conf (Just (pop,isRight)) f@(BinOp _ op _)
| needParenthesis isRight pop op = parens $ prez conf f
| otherwise = prez conf f
presentation conf Nothing (BinOp _ OpMul [a,b])
| mulAsDot conf = presentation conf (Just (OpMul, False)) a
. mo (str "·")
. presentation conf (Just (OpMul, True)) b
| otherwise = presentation conf (Just (OpMul, False)) a
. mo (str "×")
. presentation conf (Just (OpMul, True)) b
presentation conf Nothing (BinOp _ op [a,b]) =
presentation conf (Just (op, False)) a
. mo (str . cleanify $ binopString op)
. presentation conf (Just (op, True)) b
-- Unary operators
presentation conf _ (UnOp _ OpCeil f) = str "<mo>⌈</mo>"
. prez conf f
. str "<mo>⌉</mo>"
presentation conf _ (UnOp _ OpFloor f) = str "<mo>⌊</mo>"
. prez conf f
. str "<mo>⌋</mo>"
presentation conf _ (UnOp _ OpFrac f) = enclose '{' '}' $ prez conf f
presentation conf _ (UnOp _ OpAbs f) = enclose '|' '|' $ prez conf f
presentation conf _ (UnOp _ OpSqrt f) = msqrt $ prez conf f
presentation conf _ (UnOp _ OpFactorial f)
| f `hasProp` LeafNode = prez conf f . mo (char '!')
| otherwise = parens (prez conf f) . mo (char '!')
presentation conf _ (UnOp _ OpNegate f)
| f `hasProp` LeafNode = mo (char '-') . prez conf f
| otherwise = mo (char '-') . parens (prez conf f)
presentation conf _ (UnOp _ op f)
| f `hasProp` LeafNode = mo (str $ unopString op) . prez conf f
| otherwise = mo (str $ unopString op) . parens (prez conf f)
presentation conf _ (Sum _ begin end what) =
msubsup ( mo (str "∑")
. mrow (prez conf begin)
. mrow (prez conf end)) . mrow (prez conf what)
presentation conf _ (Product _ begin end what) =
msubsup ( mo (str "∏")
. mrow (prez conf begin)
. mrow (prez conf end)) . mrow (prez conf what)
presentation conf _ (Integrate _ begin end what var) =
msubsup ( mo (str "∫")
. mrow (prez conf begin)
. mrow (prez conf end))
. mrow (prez conf what . mi (str "d") . prez conf var)
presentation conf _ (Derivate _ f var) =
mfrac ( mi (char 'd')
. mrow (mi (char 'd') . prez conf var)) . prez conf f
presentation conf _ (App _ func args) =
prez conf func . parens (interspereseS (mo $ char ',') $ map (prez conf) args)
presentation conf _ (Matrix _ _ _ lsts) =
mfenced $ mtable $ concatS [mtr $ concatS [ mtd $ prez conf cell | cell <- row] | row <- lsts ]
presentation _ _ f = error $ "\n\nWrong MathML presentation rendering : " ++ unparse f ++ "\n" ++ show f
-----------------------------------------------
---- Content
-----------------------------------------------
ci, cn, apply, lowlimit,
uplimit, matrix, matrixrow,
bvar :: ShowS -> ShowS
ci = tagger "ci"
cn = tagger "cn"
apply = tagger "apply"
lowlimit = tagger "lowlimit"
uplimit = tagger "uplimit"
matrix = tagger "matrix"
matrixrow = tagger "matrixrow"
bvar = tagger "bvar"
stringOfUnOp :: UnOperator -> String
stringOfUnOp OpSin = "<sin/>"
stringOfUnOp OpSinh = "<sinh/>"
stringOfUnOp OpASin = "<arcsin/>"
stringOfUnOp OpASinh = "<arcsinh/>"
stringOfUnOp OpCos = "<cos/>"
stringOfUnOp OpCosh = "<cosh/>"
stringOfUnOp OpACos = "<arccos/>"
stringOfUnOp OpACosh = "<arccosh/>"
stringOfUnOp OpTan = "<tan/>"
stringOfUnOp OpTanh = "<tanh/>"
stringOfUnOp OpATan = "<arctan/>"
stringOfUnOp OpATanh = "<arctanh/>"
stringOfUnOp OpLn = "<ln/>"
stringOfUnOp OpLog = "<log/>"
stringOfUnOp OpExp = "<exp/>"
stringOfUnOp OpAbs = "<abs/>"
stringOfUnOp OpFloor = "<floor/>"
stringOfUnOp OpCeil = "<ceiling/>"
stringOfUnOp OpSqrt = "<root/>"
stringOfUnOp OpFactorial = "<factorial/>"
stringOfUnOp OpNegate = "<minus/>"
stringOfUnOp OpFrac = "<ci>frac</ci>"
stringOfBinOp :: BinOperator -> String
stringOfBinOp OpAdd = "<plus/>"
stringOfBinOp OpAnd = "<and/>"
stringOfBinOp OpDiv = "<quotient/>"
stringOfBinOp OpEq = "<eq/>"
stringOfBinOp OpGe = "<geq/>"
stringOfBinOp OpGt = "<gt/>"
stringOfBinOp OpLe = "<leq/>"
stringOfBinOp OpLt = "<lt/>"
stringOfBinOp OpMul = "<times/>"
stringOfBinOp OpNe = "<neq/>"
stringOfBinOp OpOr = "<or/>"
stringOfBinOp OpPow = "<power/>"
stringOfBinOp OpSub = "<minus/>"
stringOfBinOp OpAttrib = "<!-- Attrib -->"
stringOfBinOp OpLazyAttrib = "<!-- LazyAttrib -->"
stringOfBinOp OpCons = "<!-- Cons -->"
bigOperator :: String -> String -> FormulaPrim -> FormulaPrim -> FormulaPrim
-> ShowS
bigOperator operator var def end what =
apply $ str operator
. bvar (str var)
. lowlimit (content def)
. uplimit (content end)
. content what
-- | Give 2 xml trees, one for presentation and one
-- for content. Shitty MathML.
content :: FormulaPrim -> ShowS
content (Block _ _ _) = ci $ str "block"
content (Variable v) = ci $ str v
content (NumEntity e) = cn . str $ mathMlOfEntity e
content (Truth True) = str "<true/>"
content (Truth False) = str "<false/>"
content (CInteger i) = cn $ shows i
content (CFloat d) = cn $ shows d
content (Meta _ _ f) = content f
content (Lambda _ _clauses) = id
content (UnOp _ op f) =
apply $ str (stringOfUnOp op)
. content f
content (BinOp _ op lst) =
apply $ str (stringOfBinOp op)
. concatMapS content lst
content (Product _ (BinOp _ OpEq [Variable v, def]) end what) =
bigOperator "<product/>" v def end what
content (Sum _ (BinOp _ OpEq [Variable v, def]) end what) =
bigOperator "<sum/>" v def end what
content (Matrix _ _ _ lsts) =
matrix $ concatS [matrixrow $ concatMapS content row | row <- lsts]
content (Integrate _ begin end what var) =
apply $ str "<int/>"
. bvar (content var)
. lowlimit (content begin)
. uplimit (content end)
. content what
content (Derivate _ f var) =
apply $ str "<diff/>"
. bvar (content var)
. content f
content (App _ func args) =
apply $ content func
. concatMapS content args
content _ = id