%D \module
%D   [       file=x-newmml,
%D        version=2005.06.10, % 1999.12.20,
%D          title=\CONTEXT\ XML Macros,
%D       subtitle=MathML,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

%D Remark: from now on this is a module and no longer an xtag
%D filter. In due time it will replace the older renderer (which
%D we will keep around for sentimental reasons). This variant has
%D no namespace support yet, but eventually we will use a \MKIV\
%D version.

\useXMLfilter[stk]

\ifx\inlinemathematics\undefined
    \def\inlinemathematics   {\dontleavehmode\mathematics} % already in kernel
    \long\def\inlinemath #1{\dontleavehmode\relax\ifmmode#1\else $#1$\fi}
\fi

% \defineXMLentity[x000AF]{\normalorfiller{x}\hrulefill}
% CHECK FOR: \xmlrent
% \enablemathpunctuation

%D Then we start defining the rendering macros:

\writestatus{loading}{ConTeXt XML Macros / MathML}

\startmodule [mathml]

%D First we load the entities:

\usemodule[newmme]

% \setupmodule[a=c]
% \setupmodule[a=c]

\unprotect

\def\MMLrm{\mr}

\def\MMLseparator#1{{#1}} % nils space after separator

%D First we define some general formula elements.

\defineXMLenvironment [formula] [label=,sublabel=]
  {\dostartXMLformula\placeformula}
  {\dostopXMLformula}

\defineXMLenvironment [subformula] [label=,sublabel=]
  {\dostartXMLformula\placesubformula}
  {\dostopXMLformula}

\def\dostartXMLformula#1%
  {\doifelsenothingXMLop{label}
     {\startformula}
     {\expanded{#1[\XMLop{label}]{\XMLop{sublabel}}}\startformula}}

\def\dostopXMLformula
  {\stopformula}

%D Since I only had the draft of MathML 2 as example of
%D rendering, there are probably a lot of omissions and
%D misinterpretations. At least I learned some bits and
%D pieces of math rendering.
%D
%D The main complications were not so much the math, but to
%D find the most efficient way to handle elements without
%D spacing beging messed up. The first implementation was
%D aimed at getting reasonable output, this second
%D implementation is already better in terms of handling
%D nesting, and I will definitely need a third one that has
%D more efficient and less ugly code.
%D
%D The \TEX\ part is not that complicated and once the
%D preprocessor was okay, the rest way just a lot of keying
%D and testing. It all comes down to gobbling, redefining,
%D and not so much to parsing.
%D
%D The second implementation expanded the whole math sequence
%D into an internal \TEX\ representation. This is a rather clean
%D and fast process. Filtering and testing takes place by
%D redefining the internal representation macros.
%D
%D The third implementation may look a bit more messy in some
%D respects. This is because in \TEX\ it's not that trivial to
%D implement a tree handler. We use a stack for the \type {apply}
%D element and other sequential content. Occasionally we need to
%D peek into child elements which involves messy code. This
%D implementation is closer to the normal \XML\ handling in
%D \CONTEXT.

%D We start with the parent elements and the option handler.

\defineXMLdirective [mathml] \setupMMLappearance

\defineXMLargument [math]  \automathematics
\defineXMLargument [imath] \inlinemathematics
\defineXMLargument [dmath] \displaymathematics
\defineXMLargument [m]     \inlinemathematics

%D In the styles, options can be set with:

\def\setupMMLappearance[#1]{\dodoubleargument\getparameters[@@MML#1]}

\def\startusingMMLarguments % optional maken
  {\begingroup
  %\expandXMLta % expand entities first
   \getXMLta}

\def\stopusingMMLarguments % optional maken
  {\endgroup}

\def\MMLargumentprefix{@@MML\currentXMLelement}

%D We will apply inner math to all bits and pieces made up by an
%D \type {apply}.

\def\MMLmathinner
  {\ifinner \expandafter \firstofoneargument \else \expandafter \mathinner \fi}

%D A few math related macros:

\let\MMLctempresetlist\empty \def\setMMLcreset{\edef\MMLctempresetlist}

\newcount\MMLapplydepth \def\MMLcreset{\MMLapplydepth\zerocount}

% Stack handler

\startXMLmapping[xmlstack:test]

  \defineXMLnested
    [apply]
    {\startsavingXMLelements}
    {\stopsavingXMLelements}

\stopXMLmapping

%D Auxiliary MathML macros: (to be generalized)

\def\doifelseMMCfunction
  {\begingroup
   \XMLdoifonstackelse{fn}
     {\donetrue}
     {\XMLdoifonstackelse{apply}
        {\defXMLfirstnamedtext\ascii{apply}%
         \startsavingXMLelements % best use a substack so that we do not need to \edef
         \ascii
         \stopsavingXMLelements}
        {}%
      \XMLdoifonstackelse{fn}
        {\donetrue}
        {\defineXMLsave[ci][type=]%
         \XMLfirstnamed{ci}%
         \doifelse{\XMLpar{ci}{type}{}}{fn}
           {\donetrue}
           {\donefalse}}}%
  \ifdone
    \endgroup\expandafter\firstoftwoarguments
  \else
    \endgroup\expandafter\secondoftwoarguments
  \fi}

\def\doifelseMMCfunctioninapply#1#2% grouped
  {\begingroup
   \startXMLmapping[xmlstack:test]% take fast alternative
   \getXMLstackdata{#1}%
   \expanded{\doifinsetelse{\getXMLstackname\plusone}{#2}}
     {\stopXMLmapping
      \endgroup\firstoftwoarguments }
     {\stopXMLmapping
      \endgroup\secondoftwoarguments}}

\def\dodoifelseMMCfunctioninapply#1#2%
  {\startXMLmapping[xmlstack:test]% take fast alternative
   \getXMLstackdata{#1}%
   \expanded{\doifinsetelse{\getXMLstackname\plusone}{#2}}
     {\stopXMLmapping
      \firstoftwoarguments }
     {\stopXMLmapping
      \secondoftwoarguments}}

%D Special features:

\newtoks \@@postponedMMLactions \setfalse \somepostponedMMLactions

\def\postponeMMLactions#1%
  {\global\settrue\somepostponedMMLactions
   \global\@@postponedMMLactions\expandafter{\the\@@postponedMMLactions#1}}

\def\postponedMMLactions
  {\global\setfalse\somepostponedMMLactions
   \@EA\global\@EA\@@postponedMMLactions\@EA\emptytoks
   \the\@@postponedMMLactions}

%D A couple of lists:

\def\MMLcmainresetlist
  {times,divide,power,%
   lt,gt,eq,leq,geq,%
   in,inverse,%
   fn,%
   floor,ceiling,%
   mean,%
   selector,%
   abs,int,limit,sum,product,%
   outerproduct,innerproduct,scalarproduct}

\def\MMLcfunctionlist
  {sin,arcsin,sinh,arcsinh,%
   cos,arccos,cosh,arccosh,%
   tan,arctan,tanh,arctanh,%
   cot,arccot,coth,arccoth,%
   csc,arccsc,csch,arccsch,%
   sec,arcsec,sech,arcsech,%
   ln,exp,log,%
   abs,int,limit,sum,product,%
   fn} % ?

\def\MMLcconstructlist
  {diff,partialdiff,root} % apply goes wrong on 1/2 * (a_2 + b_3)

% apply
%
%D We use inner and grouping (begin/end and no b/e) else we
%D get problems with 1/2(1+2) and alike (todo: ask taco).
%D
%D The problem with apply is that we need to take care of
%D several situations, like:
%D
%D \starttyping
%D <apply> <.../> ...
%D <apply> <fn> ...
%D <apply> <apply> <ci> ...
%D <apply> <apply> <fn> <ci> ...
%D \stoptyping
%D
%D Because we translated version 2 of this renderer into
%D version 3 the following definitions may be sub optimal or
%D more complex than actually needed.

\defineXMLnested % why nested? could be just an environment
  [apply]
  [open=,close=]
  {\setups{mmc:apply:start}}
  {\setups{mmc:apply:stop}}

\startsetups mmc:apply:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:apply:stop
    \stopsavingXMLelements
    \MMLmathinner {
        \expanded{\doifinsetelse{\getXMLstackname\plusone}{\MMLcmainresetlist,\MMLctempresetlist}}
           \MMLcreset
           \donothing
        \ifcase\MMLapplydepth \else
           \doifXMLparelse{apply}{open} \donothing{\getXMLarguments{apply}{open="("}}% slow
           \doifXMLparelse{apply}{close}\donothing{\getXMLarguments{apply}{close=")"}}% slow
        \fi
        \doifXMLparelse{apply}{open}{\left\XMLpar{apply}{open}{}}\donothing
        \advance\MMLapplydepth\plusone
        \begingroup
            \let\MMLctempresetlist\empty
            \doifelse {\getXMLstackname\plusone} {apply} {
                % <apply> <apply> ... </apply> <ci> .. </ci> </apply>
                \doifelseMMCfunctioninapply \plusone {plus,minus} {
                    % yet incomplete and rather untested
                    % <apply> <apply> <minus/> <tan/> <cos/> </apply> <ci>x</ci> </apply>
                } {
                    \MMLcreset
                }
                \getXMLstackdata\plusone
                \ifconditional\somepostponedMMLactions
                    \postponedMMLactions
                \else
                    \left(\MMLcreset\getXMLstackdata\plustwo\right)
                \fi
            } {
                \doifelse {\getXMLstackname\plusone} {fn} {
                    % also postpone
                    \directsetup{mmc:fn:apply}
                } {
                    \doifelse {\getXMLstackname\plusone} {csymbol} {
                        % also postpone
                        \directsetup{mmc:csymbol:apply}
                    } {
                        \doifelse {\getXMLstackname\plusone} {ci} {
                            \getXMLstackdata\plusone
                            \ifnum\XMLstacklevel>\plusone
                               \left(\MMLcreset\flushXMLstackwith\plustwo{\MMLseparator,}\right)
                            \fi
                        } {
                            \getXMLstackdata\plusone
                        }
                    }
                }
            }
        \endgroup
        \advance\MMLapplydepth\minusone
        \directsetup{apply:flush}
        \doifXMLparelse{apply}{close}{\right\XMLpar{apply}{close}{}}\donothing
      }
    \endgroup
\stopsetups

\startsetups apply:flush
\relax
    \ifcase\MMLapplydepth
        \ifconditional\somepostponedMMLactions
            \postponedMMLactions
            \ifx\MMLpowerelement\empty\else
                ^{\MMLcreset\MMLpowerelement\empty}
                \global\let\MMLpowerelement\empty
            \fi
        \fi
    \fi
\stopsetups

% reln

\defineXMLnestedenvironmentsave [reln]
  {\writestatus{XML}{MathML element "reln" is obsolete}}
  {}

% fn

\startsetups mmc:fn:plusminus
    \ifnum\XMLstacklevel>\plustwo
        \MMLcreset
        \left(\expandafter\flushXMLstackwith\expandafter\plustwo\expandafter{\XMLfnoperator}\right)
    \else
        \getXMLstackdata\plustwo
    \fi
\stopsetups

\startsetups mmc:fn:minusplus
    \directsetup{mmc:fn:plusminus}
\stopsetups

\defineXMLnested
    [fn]
    {\directsetup{mmc:fn:start}}
    {\directsetup{mmc:fn:stop}}

\startsetups mmc:fn:apply
    \begingroup
    \startsavingXMLelements
    \rawXMLstacktext\plusone % still on stack, no check, just fn content
    \stopsavingXMLelements
    \doifelse {\getXMLstackname\plusone} {ci} {
        \flattenXMLcontent{\getXMLstackdata\plusone}
        \doifsetupselse{mmc:fn:\flattenedXMLcontent} {
            \global\defXMLstackdata\XMLfnoperator\plusone
            \expanded{\endgroup\noexpand\directsetup{mmc:fn:\flattenedXMLcontent}}
        } {
            \endgroup
            \MMLcreset
            \getXMLstackdata\plusone
            \ifnum\XMLstacklevel>\plusone
                \getXMLentity{NegThinSpace}
                \left(\MMLcreset\flushXMLstackwith\plustwo{\MMLseparator,}\right)
            \fi
        }
    } {
        \endgroup
        \MMLcreset
        \getXMLstackdata\plusone
    }
\stopsetups

\startsetups mmc:fn:start
    \ifnum\XMLstacklevel>\plustwo
      \def\MMCfnleft {\left(}
      \def\MMCfnright{\right)}
    \else
      \let\MMCfnleft \relax
      \let\MMCfnright\relax
    \fi
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:fn:stop
    \stopsavingXMLelements
    \doifelse {\getXMLstackname\plusone} {ci} {
        \flattenXMLcontent{\getXMLstackdata\plusone}
        \doifsetupselse{mmc:fn:\flattenedXMLcontent} {
                \global\defXMLstackdata\XMLfnoperator\plusone
                \directsetup{mmc:fn:\flattenedXMLcontent}
            } {
                \MMLcreset
                \getXMLstackdata\plusone
            }
        \endgroup
    } {
        \doifelse {\getXMLstackname\plusone} {apply} {
            \doifelseMMCfunctioninapply \plusone {plus,minus} {
                \left(
                \getXMLstackdata\plusone
                \right)
            } {
                \getXMLstackdata\plusone
            }
            \endgroup
            \ifnum\XMLstacklevel>\plusone
                \left(
                \getXMLstackdata\plustwo
                \right)
            \fi
        } {
            \MMLcreset
            \getXMLentity{NegThinSpace}
            \MMCfnleft
            \ifnum\XMLstacklevel=\plustwo\MMLccomma\fi
            \flushXMLstackwith\plustwo\MMLccomma
            \MMCfnright
            \endgroup
        }
    }
\stopsetups

% c*

\defineXMLargument [ci]      [type=]         {\XMLval{mmc:ci}{\XMLop{type}}    {\firstofoneargument}}
\defineXMLargument [cn]      [type=,base=]   {\XMLval{mmc:cn}{\XMLop{type}}    {\firstofoneargument}}
\defineXMLargument [csymbol] [encoding=text] {\XMLval{mmc:cs}{\XMLop{encoding}}{\firstofoneargument}}

%D The next definition provide a kind of plug-in mechanism (see
%D the open math extension module).

\defineXMLsingular
  [csymbol]
  [encoding=text,
   definitionURL=]
  {\doifsomething{\XMLop{definitionURL}}{\directsetup{mmc:csymbol:apply}}}

\startsetups mmc:csymbol:apply
    \begingroup
    \startsavingXMLelements
    \rawXMLstacktext\plusone % still on stack, no check, just attr test
    \stopsavingXMLelements
    % http://www.publishers.com/SomeName
    \lowercasestring\XMLpar{csymbol}{definitionURL}{}\to\mmcSymbolURL
    \doifsetupselse{mmc:csymbol:} {\mmcSymbolURL} {
        \expanded{\endgroup\noexpand\directsetup{mmc:csymbol:\mmcSymbolURL}}
    } {
        % SomeName (fallback)
        \splitfilename{\XMLpar{csymbol}{definitionURL}{}}
        \doifsetupselse{mmc:csymbol:\splitoffbase} {
            \expanded{\endgroup\noexpand\directsetup{mmc:csymbol:\splitoffbase}}
        } {
            \endgroup
            \XMLval{mmc:cs}{\XMLop{encoding}}{\firstofoneargument}
        }
    }
\stopsetups

%D Alternative b will convert periods into comma's:
%D
%D \startbuffer
%D \startXMLdata
%D <imath><apply><cn>1.23</cn></apply></imath>
%D <dmath><apply><cn>1.23</cn></apply></dmath>
%D \stopXMLdata
%D
%D \type{\setupMMLappearance[cn] [alternative=b]}
%D
%D \startXMLdata
%D <imath><apply><cn>1.23</cn></apply></imath>
%D <dmath><apply><cn>1.23</cn></apply></dmath>
%D \stopXMLdata
%D \stopbuffer
%D
%D \start \typebuffer \getbuffer \stop

\setupMMLappearance[cn] [\c!alternative=\v!a]

\defineXMLargument[cn][type=,base=]{\MMLdocn}

\def\MMLdocn#1%
  {\begingroup
   \doif\@@MMLcnalternative\v!b{\redefinemathcharacter [.][ord][mi]["3B]\relax}%
   \XMLval{mmc:cn}{\XMLop{type}}{\firstofoneargument}{#1}%
   \endgroup}

\defineXMLsingular [sep] {\MMLcsep} \def\MMLcsep{\,}

\setupMMLappearance[polar]    [\c!alternative=\v!a]  % a|b|c
\setupMMLappearance[float]    [\c!symbol=\v!no]      % \v!yes|dot
\setupMMLappearance[enotation][\c!symbol=\v!no]      % \v!yes|dot
\setupMMLappearance[base]     [\c!symbol=\v!numbers] % digits|characters|text|no

\mapXMLvalue {mmc:ci} {set}               {\MMLcCIset}
\mapXMLvalue {mmc:ci} {vector}            {\MMLcCIvector}
\mapXMLvalue {mmc:ci} {matrix}            {\MMLcCImatrix}
\mapXMLvalue {mmc:ci} {function}          {\MMLcCIfunction}
\mapXMLvalue {mmc:ci} {complex-cartesian} {\MMLccartesian}
\mapXMLvalue {mmc:ci} {complex}           {\MMLccartesian}
\mapXMLvalue {mmc:ci} {complex-polar}     {\MMLcpolar}
\mapXMLvalue {mmc:ci} {polar}             {\MMLcpolar}
\mapXMLvalue {mmc:ci} {fn}                {\MMLcCIfunction}

\mapXMLvalue {mmc:cn} {integer}           {\MMLcCNinteger}
\mapXMLvalue {mmc:cn} {logical}           {\MMLcCNlogical}
\mapXMLvalue {mmc:cn} {rational}          {\MMLcCNrational}
\mapXMLvalue {mmc:cn} {complex-cartesian} {\MMLccartesian}
\mapXMLvalue {mmc:cn} {complex}           {\MMLccartesian}
\mapXMLvalue {mmc:cn} {complex-polar}     {\MMLcpolar}
\mapXMLvalue {mmc:cn} {polar}             {\MMLcpolar}
\mapXMLvalue {mmc:cn} {e-notation}        {\MMLcenotation} % new
\mapXMLvalue {mmc:cn} {float}             {\MMLcfloat}     % obsolete
\mapXMLvalue {mmc:cn} {real}              {\MMLcfloat}

\mapXMLvalue {mmc:cs} {text}              {\MMLcCStext}

\def\MMLcpolar#1%
  {\doifdefinedelse{MMLcdopolar\@@MMLpolaralternative}
     {\getvalue{MMLcdopolar\@@MMLpolaralternative}{#1}}
     {#1}}

\def\MMLcdopolara#1%
  {\def\MMLcsep{\MMLseparator,}\getXMLentity{polar}\left(#1\right)}

\def\MMLcdopolarb#1%
  {\def\MMLcsep##1\empty
     {\getXMLentity{exponentiale}^{##1\mskip2mu\getXMLentity{imaginaryi}}}
   #1\empty}

\def\MMLcdopolarc#1%
  {\def\MMLcsep##1\empty
     {\getXMLentity{exp}\left(##1\mskip2mu\getXMLentity{imaginaryi}\right)}%
   #1\empty}

\def\MMLccartesian#1%
  {\def\MMLcsep{+}#1\getXMLentity{imaginaryi}}

% float will be obsolete, and is replace by e-notation

\def\MMLcfloat#1%
  {\doifelse\@@MMLfloatsymbol\v!no
%      {{\MMLrm#1}}% make sure that e shows up ok
     {\mfunction{#1}}% make sure that e shows up ok
     {% we should ignore \entities !
      \beforesplitstring#1\at e\to\first
      \aftersplitstring #1\at e\to\last
      \ifx\first\empty #1\else
      \ifx\last \empty #1\else
        \first
        \doifelse\@@MMLfloatsymbol{dot}\cdot\times
        10^{\last}%
      \fi\fi}}

% we now have:

\def\MMLcenotation#1%
  {\doifelse\@@MMLenotationsymbol\v!no
%      {\def\MMLcsep         {\unskip{\MMLrm e}\ignorespaces}}
     {\def\MMLcsep         {\unskip\mfunction{e}\ignorespaces}}
     {\def\MMLcsep##1\empty{\doifelse\@@MMLenotationsymbol{dot}\cdot\times10^{##1}}}%
   #1\empty}

\def\MMLcCIset#1%
  {{\bbd#1}}

\def\widevec#1%
  {\vbox{\mathsurround\zeropoint\ialign{##\crcr
     \rightarrowfill\crcr\noalign{\nointerlineskip}%
      $\hfil\displaystyle{#1}\hfil$\crcr}}}

\def\MMLcCIvector#1%
  {\widevec{#1}}

\def\MMLcCImatrix#1%
  {{\bi#1}}

\def\MMLcCIfunction#1%
  {#1\getXMLentity{NegThinSpace}}

\def\MMLcCNinteger#1%
  {\doifXMLparelse{cn}{base}
     {\def\MMLcCNbase{\XMLpar{cn}{base}{}}%
      \doifelse\@@MMLbasesymbol\v!no
        {\MMLcCNbasedata{#1}}
%         {\MMLcCNbasedata{#1}_{\hbox{$\MMLrm\scriptscriptstyle
        {\MMLcCNbasedata{#1}_{\mfunction{%
         \processaction
           [\@@MMLbasesymbol]
           [\v!characters=>\MMLcCNbasestring BODH,
                  \v!text=>\MMLcCNbasestring{BIN}{OCT}{DEC}{HEX},
%              \s!unknown=>\MMLcCNbase]$}}}}
               \s!unknown=>\MMLcCNbase]}}}}
     {#1}}

\def\MMLcCNbasedata#1%
%   {\ifnum\MMLcCNbase>10{\MMLrm#1}\else#1\fi}
  {\ifnum\MMLcCNbase>10\mfunction{#1}\else#1\fi}

\def\MMLcCNbasestring#1#2#3#4%
  {\ifnum\MMLcCNbase= 2 #1\else
   \ifnum\MMLcCNbase= 8 #2\else
   \ifnum\MMLcCNbase=10 #3\else
   \ifnum\MMLcCNbase=16 #4\else
         \MMLcCNbase      \fi\fi\fi\fi}

\def\MMLcCNlogical#1%
%   {{\MMLrm#1}}
  {\mfunction{#1}}

\bgroup \catcode`\<=\active

    % quick and dirty, best track the stack (todo)

    \gdef\MMLcCNrational#1%
      {\ConvertConstantAfter\doifinstringelse{sep}{#1}
         {\doMMLcCNrational#1\empty}
         {#1}}

    \gdef\doMMLcCNrational#1<sep#2>#3\empty
      {\hbox{$\frac{#1}{#3}$}}

\egroup

\def\MMLcCStext#1%
%   {{\MMLrm#1}}
  {\mfunction{#1}}

% interval

\defineXMLnested [interval]
  [closure=closed]
  {\directsetup{mmc:interval:start}}
  {\directsetup{mmc:interval:stop}}

\startsetups mmc:interval:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:interval:stop
    \stopsavingXMLelements
    \XMLval{mmc:int}{\XMLpar{interval}{closure}{closed}}{error}
    \endgroup
\stopsetups

\startsetups mmc:interval:fetch
    \defineXMLnested [interval]
        [closure=closed]
        {\directsetup{mmc:interval:fetch:start}}
        {\directsetup{mmc:interval:fetch:stop}}
\stopsetups

\startsetups mmc:interval:fetch:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:interval:fetch:stop
    \stopsavingXMLelements
    \globallet\MMCintervalfrom\empty
    \globallet\MMCintervalto  \empty
    \ifcase\XMLstacklevel
    \or
      \xdef\MMCintervalfrom{\getXMLstackdata\plusone}
    \or
      \xdef\MMCintervalfrom{\getXMLstackdata\plusone}
      \xdef\MMCintervalto  {\getXMLstackdata\plustwo}
    \fi
    \endgroup
\stopsetups

\setupMMLappearance[interval][\c!alternative=\v!a,\c!separator={,}]

\mapXMLvalue {mmc:int} {closed}
  {\left[\getXMLstackdata\plusone\MMLseparator\@@MMLintervalseparator\getXMLstackdata\plustwo\right]}

\mapXMLvalue {mmc:int} {open-closed}
  {\doifelse\@@MMLintervalalternative\v!b
     {\left<\getXMLstackdata\plusone\MMLseparator\@@MMLintervalseparator\getXMLstackdata\plustwo\right]}
     {\left(\getXMLstackdata\plusone\MMLseparator\@@MMLintervalseparator\getXMLstackdata\plustwo\right]}}

\mapXMLvalue {mmc:int} {closed-open}
  {\doifelse\@@MMLintervalalternative\v!b
     {\left[\getXMLstackdata\plusone\MMLseparator\@@MMLintervalseparator\getXMLstackdata\plustwo\right>}
     {\left[\getXMLstackdata\plusone\MMLseparator\@@MMLintervalseparator\getXMLstackdata\plustwo\right)}}

\mapXMLvalue {mmc:int} {open}
  {\doifelse\@@MMLintervalalternative\v!b
     {\left<\getXMLstackdata\plusone\MMLseparator\@@MMLintervalseparator\getXMLstackdata\plustwo\right>}
     {\left(\getXMLstackdata\plusone\MMLseparator\@@MMLintervalseparator\getXMLstackdata\plustwo\right)}}

% inverse

\defineXMLcommand [inverse] {\directsetup{mmc:inverse}}

\startsetups mmc:inverse
    \ifnum\XMLstacklevel>\plustwo
      \getXMLentity{\getXMLstackname\plustwo}^{-1}
      \left[\getXMLstackdata\plusthree\right]
    \else
      \xdef\MMLpowerelement{-1}
      \expanded{\postponeMMLactions{\rawXMLstackdata\plustwo}}
      \eraseXMLdataonstack\plustwo
    \fi
\stopsetups

% condition

\defineXMLnested
    [condition]
    {\directsetup{mmc:condition:start}}
    {\directsetup{mmc:condition:stop}}

\startsetups mmc:condition:start
%     \XMLdoifonstackelse{bvar} {
%         \XMLfirstnamed{bvar}\mid
%     } { }
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:condition:stop
    \stopsavingXMLelements
    \flushXMLstackfrom\plusone
    \endgroup
\stopsetups

% declare

\setupMMLappearance[declare][\c!state=\v!start]

\defineXMLnested
    [declare]
    {\directsetup{mmc:declare:start}}
    {\directsetup{mmc:declare:stop}}

\startsetups mmc:declare:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:declare:stop
    \stopsavingXMLelements
    \doif\@@MMLdeclarestate\v!start {
        \getXMLentity{declare}\getXMLstackdata\plusone
        \ifnum\XMLstacklevel>\plusone
            \getXMLentity{ThickSpace}
            \getXMLentity{as}
            \getXMLentity{ThickSpace}
        \fi
        \getXMLstackdata\plustwo
    }
    \endgroup
\stopsetups

% lambda

\setupMMLappearance[lambda][\c!alternative=b]

\defineXMLnested
    [lambda]
    {\directsetup{mmc:lambda:start}}
    {\directsetup{mmc:lambda:stop}}

\startsetups mmc:lambda:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:lambda:stop
    \stopsavingXMLelements
    \doifelse\@@MMLlambdaalternative\v!a {
        \getXMLentity{lambda}(\flushXMLstackwith\plusone{\MMLseparator,})
    } {
        \countXMLnamedstack{bvar}
        \ifnum\scratchcounter>\plusone
            \left(\flushXMLnamedstackwith\plusone{bvar}{\MMLseparator,}\right)
        \else
            \XMLfirstnamed{bvar}
        \fi
        \getXMLentity{mapsto}
        \MMLcreset
        \XMLfirstnamed{apply,reln,ci,cn}
    }
    \endgroup
\stopsetups

\startsetups mmc:lambda:simple
    \defineXMLnested
        [lambda]
        {\directsetup{mmc:lambda:simple:start}}
        {\directsetup{mmc:lambda:simple:stop}}
\stopsetups

\startsetups mmc:lambda:simple:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:lambda:simple:stop
    \stopsavingXMLelements
    \MMLcreset % new
    \XMLfirstnamed{apply}
    \endgroup
\stopsetups

% compose

\defineXMLcommand [compose] {\directsetup{mmc:compose}}

\startsetups mmc:compose
    \begingroup
    \MMLcreset
    \let\MMLcCIfunction\firstofoneargument % brrr
    \doifelseMMCfunction {
       \left(\flushXMLstackwith\plustwo\circ\right)
    } {
       \flushXMLstackwith\plustwo\circ
    }
    \endgroup
\stopsetups

\defineXMLcommand [image]    {\directsetup{mmc:image}}

\startsetups mmc:image
    \getXMLentity{image}
    \left(
    \begingroup
    \startlocalsetups [mmc:function]
        \getXMLentity\currentXMLelement
    \stoplocalsetups
    \getXMLstackdata\plustwo
    \endgroup
    \right)
\stopsetups

\setupMMLappearance[piece][\c!separator=]

\def\setMMLcPIECEseparator
  {\processaction
     [\@@MMLpieceseparator]
     [    \v!yes=>\def\theMMLpieceseparator{,\@col@amp@},
           \v!no=>\let\theMMLpieceseparator\@col@amp@,
      \s!default=>\let\theMMLpieceseparator\@col@amp@,
      \s!unknown=>\def\theMMLpieceseparator{\,\,\hbox{\@@MMLpieceseparator}\,\,}]}

\defineXMLargument[piecewise] {\cases}

\defineXMLnested
    [piece]
    {\directsetup{mmc:piece:start}}
    {\directsetup{mmc:piece:stop}}

\defineXMLenvironmentsave
    [otherwise]
    {}
    {\directsetup{mmc:otherwise}}

\startsetups mmc:piece:start
    \startsavingXMLelements
    \setMMLcPIECEseparator
\stopsetups

\startsetups mmc:piece:stop
    \stopsavingXMLelements
    \edef\ascii{\getXMLstackdata\plusone}
    \@EA\XMLRtoks\@EA{\ascii\theMMLpieceseparator}
    \edef\ascii{\getXMLstackdata\plustwo}
    \@EA\appendtoks\@EA\mathematics\@EA{\ascii}\to\XMLRtoks
    \the\XMLRtoks\crcr
\stopsetups

\startsetups mmc:otherwise
    \XMLflush{otherwise}\MMLcPIECEseparator\@col@amp@\mathematics{\getXMLentity{otherwise}}\crcr
\stopsetups

\defineXMLcommand [quotient] {\directsetup{mmc:quotient}}

\startsetups mmc:quotient
    \lfloor\getXMLstackdata\plustwo/\getXMLstackdata\plusthree\rfloor
\stopsetups

\defineXMLcommand [factorial] {\getXMLstackdata\plustwo !}

\defineXMLcommand [divide] [\MMLargumentprefix] [] {\directsetup{mmc:divide}} % brr not nested

\setupMMLappearance [divide] [\c!level=\!!maxcard,\c!alternative=\v!a]

\startsetups mmc:divide
    \startusingMMLarguments
        \increment\MMLcDIVIDElevel
        \doifelse \@@MMLdividealternative\v!b {
            \getXMLstackdata\plustwo/\getXMLstackdata\plusthree
        } {
            \ifnum\MMLcDIVIDElevel>\@@MMLdividelevel\space
                \getXMLstackdata\plustwo/\getXMLstackdata\plusthree
            \else
                \MMLcreset
                \frac{\MMLcreset\getXMLstackdata\plustwo}{\MMLcreset\getXMLstackdata\plusthree}%
            \fi
        }
        \decrement\MMLcDIVIDElevel
    \stopusingMMLarguments
\stopsetups

% min max

\defineXMLcommand [min] {\min\directsetup{mmc:minmax}}
\defineXMLcommand [max] {\max\directsetup{mmc:minmax}}

\startsetups mmc:minmax
    \doifelse{\getXMLstackdata\plustwo}{bvar} {
        {}_{\getXMLstackdata\plustwo}
        \left\{\flushXMLstackwith\plusthree{\MMLseparator,}\right\}
    } {
        \left\{\flushXMLstackwith\plustwo  {\MMLseparator,}\right\}
    }
\stopsetups

% minus plus

\defineXMLcommand [minus]                         {\directsetup{mmc:minus}}
\defineXMLcommand [plus]  [\MMLargumentprefix] [] {\directsetup{mmc:plus}}

\setupMMLappearance [plus] [\c!alternative=\v!a] % b = no sign -> 3 1/4
\setupMMLappearance [sign] [\c!reduction=\v!yes]

\startsetups mmc:minus
    \doif \@@MMLsignreduction \v!yes {
        \setMMLcreset{fn,\MMLcfunctionlist}
    }
    \ifcase\XMLstacklevel
    \or
        % self
    \or
        -\getXMLstackdata\plustwo
    \else
        \flushXMLstackwith\plustwo-
    \fi
\stopsetups

\startsetups mmc:plus
    \startusingMMLarguments
        \doifelse \@@MMLsignreduction \v!yes {
            \setMMLcreset{fn,plus,minus,\MMLcfunctionlist,\MMLcconstructlist}% was plus/, minus/
            \doifelse{\getXMLstackname\plustwo} {apply} {
                % branch needed, else (a-b) + (c-d) goes wrong
                % reset check in case of (-x) + 37
                \begingroup
                \dodoifelseMMCfunctioninapply \plustwo {minus} {
                    \ifnum\XMLstacklevel>\plustwo
                        \endgroup
                    \else
                        \endgroup
                        \MMLcreset
                    \fi
                } {
                    \endgroup
                }
                \doifelse \@@MMLplusalternative \v!b {
                    \getXMLstackdata\plustwo \,
                } {
                    \flushXMLstackwith\plustwo +
                }

            } {
                \flushXMLstackwith\plustwo {
                    \doifelse {\getXMLstackname\recurselevel} {apply} {
                        \begingroup
                        \dodoifelseMMCfunctioninapply \recurselevel {minus} {
                            \ifnum\XMLstacklevel>\plustwo +\fi
                        } {
                            \doifelse \@@MMLplusalternative \v!b {
                                \, % maybe 2 1/3
                            } {
                                +
                            }
                        }
                        \endgroup
                        \MMLcreset
                    } {
                        +
                    }
                }
            }
        } {
            \ifcase\XMLstacklevel
            \or
                % self
            \or
                +\getXMLstackdata\plustwo
            \else
                \flushXMLstackwith\plustwo+
            \fi
        }
    \stopusingMMLarguments
\stopsetups

% power

\defineXMLcommand [power] {\directsetup{mmc:power}}

\setupMMLappearance[power][\c!reduction=\v!yes]

\let\MMLpowerelement\empty

\startsetups mmc:power
    \doifelse {\getXMLstackname\plustwo} {apply}  {
        \doifelse\@@MMLpowerreduction\v!yes {
            \doifelseMMCfunctioninapply \plustwo \MMLcfunctionlist {
                \xdef\MMLpowerelement{\getXMLstackdata\plusthree}% postpone
                \MMLcreset\getXMLstackdata\plustwo
            } {
                \left(\MMLcreset\getXMLstackdata\plustwo\right)^{\MMLcreset\getXMLstackdata\plusthree}
            }
        } {
            \left(\MMLcreset\getXMLstackdata\plustwo\right)^{\MMLcreset\getXMLstackdata\plusthree}
        }
    } {
        \getXMLstackdata\plustwo^{\MMLcreset\getXMLstackdata\plusthree}
    }
\stopsetups

% rem

\defineXMLcommand [rem] {\flushXMLstackwith\plustwo{\getXMLentity{mod}}}

\setupMMLappearance [times] [\c!symbol=\v!no,\c!auto=\v!yes] % new, auto catches cn cn cn

\defineXMLcommand [times] [\MMLargumentprefix] [] {\directsetup{mmc:times}}

\startsetups mmc:times
    \startusingMMLarguments
        \setMMLcreset{\MMLcfunctionlist,\MMLcconstructlist}%
        \doifelse\@@MMLtimesauto\v!no {
            \let\@@MMLtimes@@symbol\@@MMLtimessymbol
        } {
            \countXMLnamedstack {cn}
            \ifnum\scratchcounter>\plusone
               \doifinsetelse\@@MMLtimessymbol{\v!yes,\v!no} {
                    \let\@@MMLtimes@@symbol\v!yes
                } {
                    \let\@@MMLtimes@@symbol\@@MMLtimessymbol
                }
            \else
               \let\@@MMLtimes@@symbol\@@MMLtimessymbol
            \fi
        }
        \doifelse\@@MMLtimes@@symbol\v!yes {
            \flushXMLstackwith\plustwo\times
        } {
            \doifelse\@@MMLtimes@@symbol{dot} {
                \flushXMLstackwith\plustwo\cdot
            } {
                \doifelse\@@MMLtimes@@symbol{times} {
                    \flushXMLstackwith\plustwo\times
                } {
                    \flushXMLstackwith\plustwo\empty
                }
            }
        }
    \stopusingMMLarguments
\stopsetups

\defineXMLcommand [root] {\directsetup{mmc:root}}

\setupMMLappearance[root][\c!symbol=\v!yes]

\startsetups mmc:root
    \XMLdoifonstackelse {degree} {
        \root
            \doifnot\@@MMLrootsymbol\v!no{\MMLcreset\XMLfirstnamed{degree}}
        \of
    } {
        \sqrt
    }
        {\MMLcreset\XMLfirstnamed{apply,reln,ci,cn}}
\stopsetups

% gcd

\defineXMLcommand [gcd] {\gcd\left(\MMLcreset\flushXMLstackwith\plustwo{\MMLseparator,}\right)}

% and or xor implies

\defineXMLcommand [and]     {\flushXMLstackwith\plustwo{\getXMLentity{and}}}
\defineXMLcommand [or]      {\flushXMLstackwith\plustwo{\getXMLentity{or}}}
\defineXMLcommand [xor]     {\flushXMLstackwith\plustwo{\getXMLentity{xor}}}
\defineXMLcommand [implies] {\flushXMLstackwith\plustwo{\getXMLentity{implies}}}

% not

\defineXMLcommand [not]     {\getXMLentity{not}\getXMLstackdata\plustwo}

% forall exists

\defineXMLcommand [forall] {\directsetup{mmc:forall}}
\defineXMLcommand [exists] {\directsetup{mmc:exists}}

%D We need to shift left below rotated A.

\startsetups mmc:forall
    \getXMLentity{forall}
    \getXMLentity{NegThinSpace}
    \directsetup{mmc:forall-exists}
\stopsetups

\startsetups mmc:exists
    \getXMLentity{exists}
    \directsetup{mmc:forall-exists}
\stopsetups

\startsetups mmc:forall-exists
    _{\flushXMLnamedstackwith\plustwo{bvar}{\MMLseparator,}}
    \XMLdoifonstackelse {condition} {
        \getXMLentity{ThickSpace}
        \begingroup
            \XMLfirstnamed{condition}
        \endgroup
        \countXMLnamedstack {apply,reln,ci,cn}
        \ifcase\scratchcounter
        \or
            % == snelle volgende
            \left\vert \MMLcreset
            \getXMLentity{MediumSpace}
            \flushXMLnamedstackwith\plustwo{apply,reln,ci,cn}\empty
            \right.
        \else
            % special case
            % \defineXMLignore[condition]
            \collectXMLnamedstack{apply,reln,ci,cn}{\hfill\crcr}
            \left\vert
            \matrix{\the\XMLRtoks}
            \right.
        \fi
    } {
        :\XMLfirstnamed{apply,reln,ci,cn}
    }
\stopsetups

\defineXMLcommand [abs]       {\left\vert \MMLcreset \flushXMLstackfrom\plustwo \right\vert}
\defineXMLcommand [conjugate] {{\overline{\MMLcreset \flushXMLstackfrom\plustwo}}} % watch extra {}
\defineXMLcommand [arg]       {\getXMLentity{arg}      \left(\MMLcreset\flushXMLstackfrom\plustwo\right)}
\defineXMLcommand [real]      {\getXMLentity{real}     \left(\MMLcreset\flushXMLstackfrom\plustwo\right)}
\defineXMLcommand [imaginary] {\getXMLentity{imaginary}\left(\MMLcreset\flushXMLstackfrom\plustwo\right)}
\defineXMLcommand [lcm]       {\getXMLentity{lcm}      \left(\flushXMLstackwith\plustwo{\MMLseparator,}\right)}
\defineXMLcommand [floor]     {\getXMLentity{lfloor}   \flushXMLstackfrom\plustwo \getXMLentity{rfloor}}
\defineXMLcommand [ceiling]   {\getXMLentity{lceiling} \flushXMLstackfrom\plustwo \getXMLentity{rceiling}}

% relations

\defineXMLcommand [eq]         [\MMLargumentprefix] [\c!align=] {\MMLcrelation=}
\defineXMLcommand [neq]        [\MMLargumentprefix] [\c!align=] {\MMLcrelation\neq}
\defineXMLcommand [gt]         [\MMLargumentprefix] [\c!align=] {\MMLcrelation>}
\defineXMLcommand [lt]         [\MMLargumentprefix] [\c!align=] {\MMLcrelation<}
\defineXMLcommand [geq]        [\MMLargumentprefix] [\c!align=] {\MMLcrelation\geq}
\defineXMLcommand [leq]        [\MMLargumentprefix] [\c!align=] {\MMLcrelation\leq}
\defineXMLcommand [equivalent] [\MMLargumentprefix] [\c!align=] {\MMLcrelation\equiv}
\defineXMLcommand [approx]     [\MMLargumentprefix] [\c!align=] {\MMLcrelation\approx}
\defineXMLcommand [factorof]   [\MMLargumentprefix] [\c!align=] {\MMLcrelation\mid}

\setupMMLappearance[relation][\c!align=\v!no]

\def\MMLcrelation
  {\startusingMMLarguments
   \MMLcreset
   \edef\@@MMLrelationalign{\executeifdefined{\MMLargumentprefix\c!align}\@@MMLrelationalign}%
   \processaction
     [\@@MMLrelationalign]
     [\v!last=>\let\next\lastMMLcrelation ,
     \v!first=>\let\next\firstMMLcrelation,
       \v!yes=>\let\next\leftMMLcrelation ,
      \v!left=>\let\next\leftMMLcrelation ,
     \v!right=>\let\next\rightMMLcrelation,
   \s!default=>\let\next\noMMLcrelation   ,
   \s!unknown=>\let\next\noMMLcrelation   ]
   \next}

\def\noMMLcrelation#1%
  {\flushXMLstackwith\plustwo{#1}
   \stopusingMMLarguments}

\def\lastMMLcrelation#1% weird, probably bugged
  {\XMLRtoks\emptytoks
   \dostepwiserecurse\plustwo\XMLstacklevel\plusone
     {\appendetoks\noexpand\getXMLstackdata{\recurselevel}\to\XMLRtoks
      \ifnum\recurselevel<\numexpr\XMLstacklevel-1\relax
        \appendtoks\@col@amp@#1\crcr\to\XMLRtoks
      \else\ifnum\recurselevel=\numexpr\XMLstacklevel-1\relax
        \appendtoks\@col@amp@#1\to\XMLRtoks
      \fi\fi}%
   \eqalign{\the\XMLRtoks\crcr}%
   \stopusingMMLarguments}

\def\firstMMLcrelation#1%
  {\collectXMLstackrows\plusthree{\crcr\@col@amp@#1}%
   \eqalign{\getXMLstackdata\plustwo\@col@amp@#1\the\XMLRtoks}%
   \stopusingMMLarguments}

\def\leftMMLcrelation#1%
  {\collectXMLstackrows\plustwo{\@col@amp@#1\crcr}%
   \eqalign{\the\XMLRtoks}%
   \stopusingMMLarguments}

\def\rightMMLcrelation#1%
  {\collectXMLstackrows\plustwo{\crcr#1{}\@col@amp@}%
   \eqalign{\@col@amp@\the\XMLRtoks\crcr}%
   \stopusingMMLarguments}

\defineXMLcommand [becomes] {\MMLcrelation{:=}}

\addtocommalist{becomes/}\MMLcmainresetlist

% calculus and vector calculus

\setupMMLappearance[int][\c!location=\v!top]

\def\doMMLlimits#1%
  {\doifelsevalue{@@MML#1\c!location}\v!top\limits\nolimits}

\defineXMLnested
    [domainofapplication]
    {\directsetup{mmc:domainofapplication:start}}
    {\directsetup{mmc:domainofapplication:stop}}

\startsetups mmc:domainofapplication:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:domainofapplication:stop
    \stopsavingXMLelements
%     \MMLcreset
    \flushXMLstackfrom\plusone
    \endgroup
\stopsetups

\defineXMLcommand [int] {\directsetup{mmc:int}}

\startsetups mmc:int
    \MMLcreset
    \XMLdoifonstackelse{domainofapplication} {
        \int\doMMLlimits{int}_{\XMLfirstnamed{domainofapplication}}\relax
    } {
        \XMLdoifonstackelse{condition} {
            \int\doMMLlimits{int}_{\XMLfirstnamed{condition}}\relax
        } {
            \XMLdoifonstackelse{lowlimit} {
                \int\doMMLlimits{int}
                    _{\XMLfirstnamed{lowlimit}}
                    ^{\XMLfirstnamed{uplimit}}
            } {
                % funny, why do we have lowlimit/uplimit then
                \XMLdoifonstackelse{interval} {
                    \begingroup
                    \startlocalsetups mmc:interval:start %
                        \begingroup
                        \startsavingXMLelements
                    \stoplocalsetups
                    \startlocalsetups mmc:interval:stop %
                        \stopsavingXMLelements
                        \xdef\MMLfirstelement {\getXMLstackdata\plusone}
                        \xdef\MMLsecondelement{\getXMLstackdata\plustwo}
                        \endgroup
                    \stoplocalsetups
                    \globallet\MMLfirstelement \empty
                    \globallet\MMLsecondelement\empty
                    \XMLfirstnamed{interval}
                    \endgroup
                    \int\doMMLlimits{int}
                        _{\MMLfirstelement}
                        ^{\MMLsecondelement}
                } {
                    \int
                }
            }
        }
    }
    \MMLcreset
    \XMLdoifonstackelse{apply} {
        \doifelseMMCfunction {
            \XMLfirstnamed{apply}
        } {
            % if there are too many () now, we need to be more clever
            \left(\XMLfirstnamed{apply}\right)
        }
    } {
        \XMLfirstnamed{ci}
    }
    \XMLdoifonstackelse{bvar} {
        \,% \getXMLentity{ThinSpace}%
%         {\MMLrm\getXMLentity{mathematicald}}
        \mfunction{\getXMLentity{mathematicald}}
        \XMLfirstnamed{bvar}
    } {
        % nothing
    }
\stopsetups

\setupMMLappearance[diff][\c!location=\v!top,\c!alternative=\v!a]

\defineXMLcommand [diff]        {\directsetup{mmc:diff}}
\defineXMLcommand [partialdiff] {\directsetup{mmc:partialdiff}}

% \setupMMLappearance[diff][alternative=b]
%
% \startXMLdata
% <math><apply><apply><diff/><bvar><ci>x</ci></bvar><ci>f</ci></apply><ci>a</ci></apply></math>
% <math><apply><apply><diff/><bvar><ci>x</ci></bvar><degree>2</degree><ci>f</ci></apply><ci>a</ci></apply></math>
% \stopXMLdata

% d^y/dx^2
%
% \startXMLdata
% <math><apply><diff/>
%   <bvar><ci>x</ci><cn type="integer">2</cn></bvar>
%   <lambda><bvar><ci>x</ci></bvar><ci>y</ci></lambda>
% </apply></math>
% \stopXMLdata

\startsetups mmc:diff
   \MMLcreset
   \doifelse\@@MMLdiffalternative\v!a {
        \XMLdoifonstackelse{lambda} {
            % a special case (mathadore/openmath)
            \begingroup
                \defineXMLsave[ci]
                \defineXMLsave[cn]
                \defineXMLprocess[lambda]
                \defineXMLprocess[bvar]
                \frac {
                    d^{\XMLfirstnamed{bvar}\XMLflush{cn}}{\XMLfirstnamed{lambda}\XMLflush{ci}}
                } {
                    d{\XMLfirstnamed{bvar}\XMLflush{ci}}^{\XMLfirstnamed{bvar}\XMLflush{cn}}
                }
            \endgroup
        } {
            \XMLdoifonstackelse{bvar} {
                \frac {
                    \XMLdoifonstackelse{degree} {
                        \collectXMLnamedstack{degree}\empty
                    } {
                        \collectXMLnamedstacknamed{bvar}{degree}+
                    }
                    \mfunction{\getXMLentity{mathematicald}}
                    ^{\the\XMLRtoks}
                    \doif\@@MMLdifflocation\v!top {
                        \XMLdoifonstackelse{ci} {
                            \XMLfirstnamed{ci}
                        } {
                            \MMLcreset\XMLfirstnamed{apply}
                        }
                    }
                } {
                    \mfunction{\getXMLentity{mathematicald}}
                    \begingroup
                        \defineXMLsave[degree]
                        \XMLfirstnamed{bvar}
                        \doifXMLdata{degree} {
                            ^{\XMLflush{degree}}
                        }
                    \endgroup
                }
                \doifnot\@@MMLdifflocation\v!top {
                    \left(\MMLcreset\XMLfirstnamed{apply,ci}\right)
                }
            } {
                \flushXMLstackfrom\plustwo^\prime
            }
        }
    } {
        \MMLcreset
        \XMLfirstnamed{apply,ci}
        % there can be problems with nested diff's: ^^{} error
        % so we add an empty group here
        {}^
        {
            \XMLdoifonstackelse{degree} {
                \defXMLfirstnamedtext\ascii{degree}
                \dorecurse\ascii\prime
            } {
                \prime
            }
        }
    }
\stopsetups

\startsetups mmc:partialdiff
    \XMLdoifonstackelse{list} {
        \getXMLentity{capitaldifferentiald}_{
            \begingroup
                \setfalse\MMLlistdelimiters
                \XMLallnamed{list}
            \endgroup
        }
        \XMLfirstnamed{apply,reln,ci,cn}
    } {
        \XMLdoifonstackelse{bvar} {
            \frac {
                \XMLdoifonstackelse{degree} {
                    \collectXMLnamedstack{degree}\empty
                } {
                    \collectXMLnamedstacknamed{bvar}{degree}+
                }
                \getXMLentity{differentiald}^{\the\XMLRtoks}
                % \let\MMLcDEGREE\gobbletwoarguments
                % \doifelseMMCfunction\MMLcreset\donothing
                \MMLcreset
                \XMLfirstnamed{apply,reln,ci,cn}
            } {
                \defineXMLnested[bvar]
                    {\directsetup{mmc:bvar:diff:start}}
                    {\directsetup{mmc:bvar:diff:stop}}
                \XMLfirstnamed{bvar}
            }
        } {
            \XMLfirstnamed{apply,reln,ci,cn}
        }
    }
\stopsetups

\startsetups mmc:bvar:diff:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:bvar:diff:stop
    \stopsavingXMLelements
    \getXMLentity{differentiald}\XMLfirstnamed{apply,reln,ci,cn}
    \XMLdoifonstackelse{degree} {
        ^{\XMLfirstnamed{degree}}
    } {
        % nothing
    }
    \endgroup
\stopsetups

\def\subMMLcelement  #1#2{_{#2}}
\def\superMMLcelement#1#2{^{#2}}

\defineXMLprocess [lowlimit]
\defineXMLprocess [uplimit]
\defineXMLprocess [bvar]
\defineXMLprocess [degree]

% option:
%
% \defineXMLentity [div]  {\mathematics{\triangledown\times}}
% \defineXMLentity [curl] {\mathematics{\triangledown     .}}
% \defineXMLentity [grad] {\mathematics{\triangledown      }}

\defineXMLcommand [divergence] {\getXMLentity{divergence}\directsetup{mmc:donamedfunction}}
\defineXMLcommand [grad]       {\getXMLentity      {grad}\directsetup{mmc:donamedfunction}}
\defineXMLcommand [curl]       {\getXMLentity      {curl}\directsetup{mmc:donamedfunction}}
\defineXMLcommand [laplacian]  {\getXMLentity {laplacian}\directsetup{mmc:donamedfunction}}

\defineXMLcommand [ident]      {\getXMLentity  {identity}\directsetup{mmc:donamedfunction}}
% \defineXMLcommand [domain]     {\getXMLentity    {domain}\directsetup{mmc:donamedfunction}}
% \defineXMLcommand [codomain]   {\getXMLentity  {codomain}\directsetup{mmc:donamedfunction}}

\defineXMLcommand[domain]  {\directsetup{mmc:domain:action}}
\defineXMLcommand[codomain]{\directsetup{mmc:codomain:action}}

\setupMMLappearance[domain]  [symbol=]
\setupMMLappearance[codomain][symbol=]

\startsetups mmc:domain:action
    \doifelsenothing\@@MMLdomainsymbol {
        \getXMLentity{domain}\directsetup{mmc:donamedfunction}
    } {
        \@@MMLdomainsymbol_{\flushXMLstackfrom\plustwo}
    }
\stopsetups
\startsetups mmc:codomain:action
    \doifelsenothing\@@MMLcodomainsymbol {
        \getXMLentity{codomain}\directsetup{mmc:donamedfunction}
    } {
        \@@MMLcodomainsymbol_{\flushXMLstackfrom\plustwo}
    }
\stopsetups


\startsetups mmc:donamedfunction
%     \left(
%     \begingroup
    \MMLcreset\flushXMLstackfrom\plustwo
%     \endgroup
%     \right)
\stopsetups

% theory of sets

\defineXMLnested [set]
  {\setups{mmc:set:start}}
  {\setups{mmc:set:stop}}

\startsetups mmc:set:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:set:stop
    \stopsavingXMLelements
    \XMLdoifonstackelse{condition} {
        \left\{\XMLfirstnamed{bvar}\,\middle\vert\,\XMLfirstnamed{condition}\right\}
    } {
        \left\{\flushXMLstackwith\plusone{\MMLseparator,}\right\}
    }
    \endgroup
\stopsetups

\defineXMLnested [list]
  {\setups{mmc:list:start}}
  {\setups{mmc:list:stop}}

\settrue\MMLlistdelimiters

\startsetups mmc:list:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:list:stop
    \stopsavingXMLelements
    \ifconditional\MMLlistdelimiters\left [\fi
    \begingroup
    \settrue\MMLlistdelimiters
    \flushXMLstackwith\plusone{\MMLseparator,}
    \endgroup
    \ifconditional\MMLlistdelimiters\right]\fi
    \endgroup
\stopsetups

\defineXMLcommand [union]       {\MMLcset\cup}
\defineXMLcommand [intersect]   {\MMLcset\cap}
\defineXMLcommand [in]          {\MMLcset\in}
\defineXMLcommand [notin]       {\MMLcset{\not\in}}
\defineXMLcommand [subset]      {\MMLcset\subset}
\defineXMLcommand [prsubset]    {\MMLcset\subseteq}
\defineXMLcommand [notsubset]   {\MMLcset{\not\subset}}
\defineXMLcommand [notprsubset] {\MMLcset{\not\subseteq}}
\defineXMLcommand [setdiff]     {\MMLcset\setminus}

\def\MMLcset#1{\getXMLstackdata\plustwo#1\getXMLstackdata\plusthree}

\defineXMLcommand [card]             {\left\vert\flushXMLstackfrom\plustwo\right\vert}
\defineXMLcommand [cartesianproduct] {\flushXMLstackwith\plustwo\times}

% sequences and series

\defineXMLcommand [sum]    {\MMLcSUMandPRODUCT{sum}\sum}
\defineXMLcommand [product]{\MMLcSUMandPRODUCT{product}\prod}

\setupMMLappearance[sum]    [\c!location=\v!top]
\setupMMLappearance[product][\c!location=\v!top]

\def\stackMMLsubscripts#1%
  {\vbox
     {\baselineskip\zeropoint % hack, taco vragen
      \halign{$\scriptstyle\hss##\hss$\cr#1\crcr}}}

\def\MMLcSUMandPRODUCT#1#2%
  {\begingroup
   \XMLdoifonstackelse{condition,bvar,lowlimit}
     {\def\MMLcSUMlow
        {_{\XMLdoifonstackelse{condition}
             {\collectXMLnamedstack{condition}{\crcr}%
              \stackMMLsubscripts{\the\XMLRtoks}}
             {\XMLdoifonstackelse{bvar}
                {\XMLfirstnamed{bvar}%
                 \XMLdoifonstackelse{lowlimit}{=}{}}%
                {}%
              \XMLfirstnamed{lowlimit}}}}}
     {\let\MMLcSUMlow\empty}%
   \XMLdoifonstackelse{uplimit}
     {\def\MMLcSUMup{^{\XMLfirstnamed{uplimit}}}}
     {\let\MMLcSUMup\empty}%
   \XMLdoifonstackelse{interval} % open math converter gives this
     {\begingroup
      \directsetup{mmc:interval:fetch}%
      \XMLfirstnamed{interval}%
      \endgroup
      \ifx\MMCintervalfrom\empty\else
        \def\MMLcSUMlow{_{\XMLdoifonstackelse{bvar}{\XMLfirstnamed{bvar}{=}}{}\MMCintervalfrom}}%
      \fi
      \ifx\MMCintervalto\empty \else
        \def\MMLcSUMup{^{\MMCintervalto}}%
      \fi}
     {}%
   \MMLcreset#2\doMMLlimits{#1}\MMLcSUMup\MMLcSUMlow
   \directsetup{mmc:lambda:simple}% a bit of open math conversion mess
   \MMLcreset\XMLfirstnamed{apply,lambda,ci}%
   \endgroup}

\defineXMLcommand [limit] {\directsetup{mmc:limit}}

\setupMMLappearance[limit][\c!location=\v!top]

\startsetups mmc:limit
   \MMLcreset \lim
   \doMMLlimits{limit}_{
      \MMLcreset
      \XMLdoifonstackelse {condition} {
        \XMLfirstnamed{condition}
      } {
        \XMLdoifonstackelse {bvar} {
           \XMLfirstnamed{bvar}\rightarrow
        } {
        }
        \XMLfirstnamed{lowlimit}
      }
   }
   \begingroup
   \MMLcreset
   \directsetup{mmc:lambda:simple}% a bit of open math conversion mess
   \XMLfirstnamed{apply,lambda}% lambda needed for openmath
   \endgroup
\stopsetups

\defineXMLcommand [tendsto] [type=default] {\directsetup{mmc:tendsto}}

\startsetups mmc:tendsto
    \MMLcreset \getXMLstackdata\plustwo
    \processaction
        [\XMLpar{tendsto}{type}{default}]
        [  above=>\downarrow,
           below=>\uparrow,
         unknown=>\rightarrow]
    \MMLcreset \getXMLstackdata\plusthree
\stopsetups

% elementary classical functions

\defineXMLcommand [exp]     {\directsetup{mmc:exp}}
\defineXMLcommand [ln]      {\directsetup{mmc:function}}
\defineXMLcommand [log]     {\directsetup{mmc:log}}
\defineXMLignore  [logbase]

\setupMMLappearance[log][\c!location=\v!right]

\startsetups mmc:exp
    \getXMLentity{exponentiale}^{\XMLfirstnamed{apply,reln,ci,cn}}
\stopsetups

\startsetups mmc:log
   \XMLdoifonstackelse {logbase} {
        \doifelse\@@MMLloglocation\v!left {
            \mathop{{}^{{\defineXMLprocess[logbase]\XMLfirstnamed{logbase}}}
            \getXMLentity{NegThinSpace}
            \getXMLentity{log}}
        } {
            \getXMLentity{log}_{{\defineXMLprocess[logbase]\XMLfirstnamed{logbase}}}
        }
    } {
        \getXMLentity{log}
    }
    \MMLcreset
    % mmc:function:argument assumes that the apply is second in the row (*1*)
    % \removeXMLdatafromstack{logbase}
    \directsetup{mmc:function:argument}
\stopsetups

% statistics

\defineXMLcommand [mean]     {\overline{\getXMLstackdata\plustwo}}
\defineXMLcommand [sdev]     {\sigma(\MMLcreset\getXMLstackdata\plustwo)}
\defineXMLcommand [variance] {\sigma(\MMLcreset\getXMLstackdata\plustwo)^2}
\defineXMLcommand [median]   {\getXMLentity{median}(\MMLcreset\getXMLstackdata\plustwo)}
\defineXMLcommand [mode]     {\getXMLentity{mode}(\MMLcreset\getXMLstackdata\plustwo)}

% moments

\defineXMLcommand [moment]      {\directsetup{mmc:moment}}
\defineXMLprocess [momentabout]

\startsetups mmc:moment
    \left\langle\XMLfirstnamed{apply,reln,ci,cn}^{\XMLfirstnamed{degree}}\right\rangle
    \XMLdoifonstackelse{momentabout} {
        _{\XMLfirstnamed{momentabout}}
    } {
    }
\stopsetups

% linear algebra

\defineXMLcommand [vector] {\directsetup{mmc:vector}} % sequence

\setupMMLappearance [vector] [\c!direction=\v!horizontal,\c!separator={,}]

\defineXMLnested
    [vector]
    {\directsetup{mmc:vector:start}}
    {\directsetup{mmc:vector:stop}}

\startsetups mmc:vector:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:vector:stop
    \stopsavingXMLelements
    \ifnum\XMLstacklevel>\plusone
        \doifelse\@@MMLvectordirection\v!horizontal {
            \left(\flushXMLstackwith\plusone{\MMLseparator\@@MMLvectorseparator}\right)
        } {
            \collectXMLstack\crcr
            \MMLcreset\left(\matrix{\the\XMLRtoks}\right)
        }
    \else
      \overrightarrow{\charhtstrut\getXMLstackdata\plusone}
    \fi
    \endgroup
\stopsetups

\defineXMLnestedenvironmentsave [matrix]    {} {\directsetup{mmc:matrix}}
\defineXMLnestedenvironmentsave [matrixrow] {} {\directsetup{mmc:matrixrow}}

\unexpanded\def\@col@amp@{&}

\settrue\MMCdelmatrix %( ) when true

\startsetups mmc:matrix
    \begingroup
    \MMLcreset
    \defineXMLnestedenvironmentsave [matrixrow] {} {\directsetup{mmc:matrixrow:do}}
    \ifconditional\MMCdelmatrix
        \left(\matrix{\XMLflush{matrix}}\right)
    \else
        \settrue\MMCdelmatrix
        \matrix{\XMLflush{matrix}}
    \fi
    \endgroup
\stopsetups

\startsetups mmc:matrixrow
    \begingroup
    \MMLcreset
    \left(\matrix{\directsetup{mmc:matrixrow:do}}\right)
    \endgroup
\stopsetups

\startsetups mmc:matrixrow:do
    \begingroup
    \startsavingXMLelements
    \XMLflush{matrixrow}
    \stopsavingXMLelements
    \collectXMLstackrows\plusone\@col@amp@
    \edef\ascii{\the\XMLRtoks}
    \edef\ascii{\ascii}
    \expandafter\endgroup\ascii\crcr
\stopsetups

\defineXMLcommand [determinant] {\directsetup{mmc:determinant}}
\defineXMLcommand [transpose]   {\directsetup{mmc:transpose}}
\defineXMLcommand [selector]    {\directsetup{mmc:selector}}

\startsetups mmc:determinant
    \begingroup
    \left|
    \setfalse\MMCdelmatrix
    \getXMLstackdata\plustwo
    \right|
    \endgroup
\stopsetups

\startsetups mmc:transpose
%     \getXMLstackdata\plustwo^{\MMLrm T}
    \getXMLstackdata\plustwo^{\mfunction{T}}
\stopsetups

\startsetups mmc:selector
    \MMLmathinner{\getXMLstackdata\plustwo}_{\MMLcreset\flushXMLstackwith\plusthree{\MMLseparator,}}
\stopsetups

\defineXMLcommand [vectorproduct] {\getXMLstackdata\plustwo\getXMLentity{vectorproduct}\getXMLstackdata\plusthree}
\defineXMLcommand [scalarproduct] {\getXMLstackdata\plustwo\getXMLentity{scalarproduct}\getXMLstackdata\plusthree}
\defineXMLcommand [outerproduct]  {\getXMLstackdata\plustwo\getXMLentity {outerproduct}\getXMLstackdata\plusthree}

% semantic mapping elements

\defineXMLnested
    [semantics]
    {\directsetup{mmc:semantics:start}}
    {\directsetup{mmc:semantics:stop}}

\startsetups mmc:semantics:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:semantics:stop
    \stopsavingXMLelements
    \XMLdoifonstackelse {annotation} {
        \flushXMLnamedstackwith\plusone{annotation}\empty
    } {
        \flushXMLnamedstackwith\plusone{apply}\empty
    }
    \endgroup
\stopsetups

\defineXMLenvironmentsave
  [annotation]
  [encoding=]
  {}
  {\directsetup{mmc:annotation}}

\startsetups mmc:annotation
    \expanded{\doifinset{\XMLpar{annotation}{encoding}{}}{TeX,tex,TEX,ConTeXt,context,CONTEXT}} {
        \XMLtexdata{annotation}
    }
\stopsetups

\defineXMLignore  [annotation-xml]

% misc

\defineXMLcommand [integers]       {\getXMLentity{integers}}
\defineXMLcommand [reals]          {\getXMLentity{reals}}
\defineXMLcommand [rationals]      {\getXMLentity{rationals}}
\defineXMLcommand [naturalnumbers] {\getXMLentity{naturalnumbers}}
\defineXMLcommand [complexes]      {\getXMLentity{complexes}}
\defineXMLcommand [primes]         {\getXMLentity{primes}}
\defineXMLcommand [exponentiale]   {\getXMLentity{ExponentialE}}
\defineXMLcommand [imaginaryi]     {\getXMLentity{ImaginaryI}}
\defineXMLcommand [notanumber]     {\mathop{\mfunction{NaN}}}
\defineXMLcommand [true]           {\mathop{\mfunction{true}}}
\defineXMLcommand [false]          {\mathop{\mfunction{false}}}
\defineXMLcommand [emptyset]       {\mathop{\O}}
\defineXMLcommand [pi]             {\pi}
\defineXMLcommand [eulergamma]     {\gamma}
\defineXMLcommand [infinity]       {\infty}

% gonio functions

\defineXMLcommand[sin] {\directsetup{mmc:function}} \defineXMLcommand[arcsin] {\directsetup{mmc:function}}
\defineXMLcommand[sinh]{\directsetup{mmc:function}} \defineXMLcommand[arcsinh]{\directsetup{mmc:function}}
\defineXMLcommand[cos] {\directsetup{mmc:function}} \defineXMLcommand[arccos] {\directsetup{mmc:function}}
\defineXMLcommand[cosh]{\directsetup{mmc:function}} \defineXMLcommand[arccosh]{\directsetup{mmc:function}}
\defineXMLcommand[tan] {\directsetup{mmc:function}} \defineXMLcommand[arctan] {\directsetup{mmc:function}}
\defineXMLcommand[tanh]{\directsetup{mmc:function}} \defineXMLcommand[arctanh]{\directsetup{mmc:function}}
\defineXMLcommand[cot] {\directsetup{mmc:function}} \defineXMLcommand[arccot] {\directsetup{mmc:function}}
\defineXMLcommand[coth]{\directsetup{mmc:function}} \defineXMLcommand[arccoth]{\directsetup{mmc:function}}
\defineXMLcommand[csc] {\directsetup{mmc:function}} \defineXMLcommand[arccsc] {\directsetup{mmc:function}}
\defineXMLcommand[csch]{\directsetup{mmc:function}} \defineXMLcommand[arccsch]{\directsetup{mmc:function}}
\defineXMLcommand[sec] {\directsetup{mmc:function}} \defineXMLcommand[arcsec] {\directsetup{mmc:function}}
\defineXMLcommand[sech]{\directsetup{mmc:function}} \defineXMLcommand[arcsech]{\directsetup{mmc:function}}

\setupMMLappearance[function][\c!reduction=\v!yes]

\startsetups mmc:function
    \getXMLentity\currentXMLelement
    \ifx\MMLpowerelement\empty\else
      ^{\MMLcreset\MMLpowerelement\empty}
      \getXMLentity{NegThinSpace}
      \global\let\MMLpowerelement\empty
    \fi
    \doif {\getXMLstackname\plusone} {\currentXMLelement} {
        % rather fuzzy test; looks like an apply case
        \directsetup{mmc:function:argument}
    }
\stopsetups

\startsetups mmc:function:argument
    \doifelse\@@MMLfunctionreduction\v!yes {
        % \doifelse {\getXMLstackname\plustwo} {apply} {
        %     \doifelseMMCfunctioninapply \plustwo \MMLcfunctionlist \donefalse \donetrue
        %
        % best is to grab the apply (independent of order), (*1*), so:
        %
        \XMLdoifonstackelse {apply} {
            \doifelseMMCfunctioninapply \XMLstackposition {\MMLcfunctionlist,divide} \donefalse \donetrue
        } {
            \donefalse
        }
    } {
        \donetrue
    }
    % beware, we still flush from 2 up
    \ifdone
        \left(\MMLcreset\flushXMLstackfrom\plustwo\right)
    \else
        \MMLcreset\flushXMLstackfrom\plustwo
    \fi
\stopsetups

% presentation mml

\def\resetMMLseparator
  {\newcounter\MMLxxcounter
   \let\lastMMLseparator\empty}

\def\grabMMLseparator#1%
  {\increment\MMLxxcounter
   \newcounter\MMLyycounter
   \expanded{\dograbMMLseparator#1\noexpand\relax}}

\def\dograbMMLseparator
  {\increment\MMLyycounter
   \doifnextcharelse\relax
     {\lastMMLseparator\gobbleoneargument}
     {\doifnextcharelse\xmlrent\grabMMLseparatora\grabMMLseparatorb}}

\def\grabMMLseparatora#1\xmlrent#2%
  {\ifnum\MMLxxcounter=\MMLyycounter\space
     \def\lastMMLseparator{\xmlrent{#2}}%
   \fi
   \dograbMMLseparator}

\def\grabMMLseparatorb#1%
  {\ifnum\MMLxxcounter=\MMLyycounter\space
     \doifXMLentityelse{#1}
       {\def\lastMMLseparator{\xmlrent{#1}}}
       {\def\lastMMLseparator{#1}}%
   \fi
   \dograbMMLseparator}

%

\defineXMLargument [mi] \MMLpMI
\defineXMLargument [mn] \MMLpMN
\defineXMLargument [mo] \MMLpMO

\def\MMLpMI#1%
  {\begingroup
   \setMMLpmathstyle{mstyle}%
   #1%
   \endgroup}

% \def\MMLpMN#1%
%   {\begingroup
%    \MMLrm
%    \setMMLpmathstyle{mstyle}%
%    #1%
%    \endgroup}

\def\MMLpMN#1%
  {\mfunction{\setMMLpmathstyle{mstyle}#1}}

\def\MMLpMO#1% yes or no
  {\flattenXMLcontent{#1}%
   \doifXMLentityelse\flattenedXMLcontent
     {\getXMLentity\flattenedXMLcontent}
     {\ConvertConstantAfter\doifinstringelse{\xmlrent}{#1} % TODO ! ! ! ! ! ! ! !
        {#1}
        {\hbox
           {\setMMLpmathstyle{mstyle}%
            \ignorespaces#1\unskip}}}}

% we need to get rid of spaces: <mo> &RightArrow; </mo>

\def\MMLpMO#1% yes or no
  {\flattenXMLcontent{#1}%
   \doifXMLentityelse\flattenedXMLcontent
     {\getXMLentity\flattenedXMLcontent}
     {\ignorespaces#1\removeunwantedspaces}}

\def\doMMLleft #1{\pushmacro\left \let\left \empty\normalleft #1\popmacro\left}
\def\doMMLright#1{\pushmacro\right\let\right\empty\normalright#1\popmacro\right}

\let\MMLpopen \empty
\let\MMLpclose\empty

\defineXMLnested [mfenced] [open=(,close=),separators=]
  {\directsetup{mmp:mfenced:start}}
  {\directsetup{mmp:mfenced:stop}}

\startsetups mmp:mfenced:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmp:mfenced:stop
    \stopsavingXMLelements
    \edef\MMLpopen {\XMLpar{mfenced}{open} {}}
    \edef\MMLpclose{\XMLpar{mfenced}{close}{}}
    \ifx\MMLpopen \space\let\MMLpopen \empty\fi
    \ifx\MMLpclose\space\let\MMLpclose\empty\fi
    \ifx\MMLpopen\empty
        \ifx\MMLpclose\empty
        \else
            \doMMLleft.
        \fi
    \else
      \doMMLleft\MMLpopen
    \fi
    \pushmacro\MMLpopen
    \pushmacro\MMLpclose
    \doifelsenothing{\XMLpar{mfenced}{separators}{}} {
        \flushXMLstackfrom\plusone
    } {
        \resetMMLseparator
        \flushXMLstackwith\plusone {
            \begingroup
            \let\myspecialnormalvert\myspecialstretchvert
            \grabMMLseparator{\XMLpar{mfenced}{separators}{}}
            \endgroup
        }
    }
    \popmacro\MMLpclose
    \popmacro\MMLpopen
    \ifx\MMLpclose\empty
        \ifx\MMLpopen\empty
        \else
            \doMMLright.
        \fi
    \else
        \doMMLright\MMLpclose
    \fi
    \endgroup
\stopsetups

% \startbuffer
% <math><mfenced separators="" open="(" close=")"><mi>x</mi></mfenced></math>
% <math><mfenced separators="" open=""  close=")"><mi>x</mi></mfenced></math>
% <math><mfenced separators="" open="(" close="" ><mi>x</mi></mfenced></math>
% <math><mfenced separators="" open=""  close="" ><mi>x</mi></mfenced></math>
% <math><mfenced separators="" open=""  close=" "><mi>x</mi></mfenced></math>
% \stopbuffer
%
% \processXMLbuffer

\defineXMLnestedenvironmentsave [menclose] [notation=]
    {\directsetup{mmp:menclose:start}}
    {\directsetup{mmp:menclose:stop}}

\startsetups mmp:menclose:start
    \begingroup
\stopsetups

\startsetups mmp:menclose:stop
    \doifelse{\XMLpar{menclose}{notation}{}}{longdiv} {
        \overline{)\XMLflush{menclose}}
    } {
        \XMLflush{menclose}
    }
    \endgroup
\stopsetups

\defineXMLnested [mfrac] [linethickness=]
    {\directsetup{mmp:mfrac:start}}
    {\directsetup{mmp:mfrac:stop}}

\startsetups mmp:mfrac:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmp:mfrac:stop
    \stopsavingXMLelements
    \doifXMLparelse{mfrac}{linethickness} {
        \edef\theXMLpar{\XMLpar{mfrac}{linethickness}{1}}
        \processaction
           [\theXMLpar]
           [    thin=>\scratchdimen=.2pt,
              medium=>\scratchdimen=.4pt,
               thick=>\scratchdimen=.8pt,
             unknown=>\setdimensionwithunit\scratchdimen{\theXMLpar}{}]
         {{\getXMLstackdata\plusone}\above\scratchdimen{\getXMLstackdata\plustwo}}
    } {
        \frac{\getXMLstackdata\plusone}{\getXMLstackdata\plustwo}
    }
   \endgroup
\stopsetups

\defineXMLargument
  [ms]
  [lquote=\xmlrent{quot},
   rquote=\xmlrent{quot},
   fontweight=,
   fontstyle=,
   mathstyle=,
   mathvariant=,
   background=,
   color=]
  {\MMLpSTRING}

\def\MMLpSTRING#1%
  {\hbox
    {\tf % else encoding problems
     \MMLpTEXT{\XMLpar{ms}{lquote}{}%
     \doMMPpbackground{ms}{\doMMPpcolor{ms}{\setMMLptextstyle{ms}\ignorespaces#1\removeunwantedspaces}}%
     \XMLpar{ms}{rquote}{}}}}

\defineXMLenvironment
  [mstyle]
  [fontweight=,
   fontstyle=,
   mathstyle=,
   mathvariant=,
   background=,
   color=]
  {\begingroup}
  {\endgroup}

\defineXMLargument [mtext]    [CPA] \MMLpTEXT
\defineXMLargument [merror]   [CPA] \MMLpERROR
\defineXMLargument [mphantom] [CPA] \MMLpPHANTOM
\defineXMLargument [mpadded]  [CPA] \MMLpPADDED

\mapXMLvalue{mmp}{normal}     {\tf} \mapXMLvalue{mmp}{double-stuck} {\bf}
\mapXMLvalue{mmp}{bolditalic} {\bi} \mapXMLvalue{mmp}{bold-italic}  {\bi}
\mapXMLvalue{mmp}{boldslanted}{\bs} \mapXMLvalue{mmp}{bold-slanted} {\bs}
\mapXMLvalue{mmp}{boldnormal} {\bf} \mapXMLvalue{mmp}{bold}         {\bf}
\mapXMLvalue{mmp}{slanted}    {\sl} \mapXMLvalue{mmp}{normalslanted}{\sl}
\mapXMLvalue{mmp}{italic}     {\it} \mapXMLvalue{mmp}{normalitalic} {\it}
\mapXMLvalue{mmp}{fraktur}    {\bf} \mapXMLvalue{mmp}{bold-fraktur} {\bf}
\mapXMLvalue{mmp}{script}     {\tf} \mapXMLvalue{mmp}{bold-script}  {\bf}

% and all kind of other crappy names

\def\setMMLptextstyle#1%
  {\XMLval{mmp}{\XMLpar{#1}{fontweight}{}\XMLpar{#1}{fontstyle}{}}{}}

\def\setMMLpmathstyle#1%
  {\XMLval{mmp}{\XMLpar{#1}{mathvariant}{}}{}}

\def\doMMPpcolor#1#2%
  {\doifXMLparelse{#1}{color}{\color[\XMLpar{#1}{color}{}]{#2}}{#2}}

\def\doMMPpbackground#1#2%
  {\doifXMLparelse{#1}{background}
     {\inframed
        [\c!frame=\v!off,
         \c!background=\v!color,
         \c!backgroundcolor=\XMLpar{#1}{background}{}]
        {#2}}
     {#2}}

\def\MMLpTEXT#1%
  {\hbox
    {\tf % else encoding problems
     \doMMPpbackground{ms}{\doMMPpcolor{ms}{\setMMLptextstyle{ms}\ignorespaces#1\removeunwantedspaces}}}}

\def\MMLpERROR#1%
  {\hbox{$\displaystyle#1$}}

\def\MMLpPHANTOM#1%
  {\phantom{\ignorespaces{}#1\unskip}} % watch spacing {} hack

\def\MMLpPADDED#1%
  {#1}

% mrow

\defineXMLenvironment [mrow] {\resetMMLbounds} {\finishMMLbounds}

% \def\MMLleft #1{\increment\MMLboundslevel\left #1}
% \def\MMLright#1{\right#1\decrement\MMLboundslevel}

% \def\resetMMLbounds
%   {\let\MMLboundslevel\!!plusone\left.}

% \def\finishMMLbounds
%   {\dorecurse\MMLboundslevel{\right.}}

\def\resetMMLbounds
  {\pushmacro\MMLboundslevel
   \newcounter\MMLboundslevel}

\def\MMLleft #1%
  {\increment\MMLboundslevel
   \normalleft#1}

\def\MMLright#1%
  {\ifnum\MMLboundslevel=0 \normalleft.\!\fi
   \normalright#1%
   \decrement\MMLboundslevel}

\def\finishMMLbounds
  {\ifnum\MMLboundslevel>0
    \normalright.\!%
    \decrement\MMLboundslevel
    \expandafter\finishMMLbounds
   \else
     \popmacro\MMLboundslevel
   \fi}

\defineXMLnested [msqrt] {\directsetup{mmp:msqrt:start}} {\directsetup{mmp:msqrt:stop}}
\defineXMLnested [mroot] {\directsetup{mmp:mroot:start}} {\directsetup{mmp:mroot:stop}}

\startsetups mmp:msqrt:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmp:msqrt:stop
    \stopsavingXMLelements
    \sqrt{\flushXMLstackfrom\plusone}
    \endgroup
\stopsetups

\startsetups mmp:mroot:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmp:mroot:stop
    \stopsavingXMLelements
    \root{\getXMLstackdata\plustwo}\of{\getXMLstackdata\plusone}
    \endgroup
\stopsetups

\setupMMLappearance[scripts][\c!alternative=\v!a]

\defineXMLnested [msub]    {\directsetup{mmp:msub:start}} {\directsetup{mmp:msub:stop}}
\defineXMLnested [msup]    {\directsetup{mmp:msup:start}} {\directsetup{mmp:msup:stop}}
\defineXMLnested [msubsup] {\directsetup{mmp:msbp:start}} {\directsetup{mmp:msbp:stop}}

\startsetups mmp:msub:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmp:msub:stop
    \stopsavingXMLelements
    \doifelse\@@MMLscriptsalternative\v!a {
        {\getXMLstackdata\plusone}_{\getXMLstackdata\plustwo}
    } {
        \getXMLstackdata\plusone_{\getXMLstackdata\plustwo}
    }
    \endgroup
\stopsetups

\startsetups mmp:msup:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmp:msup:stop
    \stopsavingXMLelements
    \doifelse\@@MMLscriptsalternative\v!a {
        {\getXMLstackdata\plusone}^{\getXMLstackdata\plustwo}
    } {
        \getXMLstackdata\plusone^{\getXMLstackdata\plustwo}
    }
    \endgroup
\stopsetups

\startsetups mmp:msbp:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmp:msbp:stop
    \stopsavingXMLelements
    \getXMLstackdata\plusone_{\getXMLstackdata\plustwo}^{\getXMLstackdata\plusthree}
    \endgroup
\stopsetups

\defineXMLnested [mover]      {\directsetup{mmp:mover:start}}      {\directsetup{mmp:mover:stop}}
\defineXMLnested [munder]     {\directsetup{mmp:munder:start}}     {\directsetup{mmp:munder:stop}}
\defineXMLnested [munderover] {\directsetup{mmp:munderover:start}} {\directsetup{mmp:munderover:stop}}

\startsetups mmp:mover:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmp:mover:stop
    \stopsavingXMLelements
    \mathop{\vbox{\mathsurround\zeropoint\ialign{\hss##\hss\crcr\noalign{\kern3\points}%
      \disabledelimiter\doMMLfiller{\getXMLstackdata\plustwo}
      \crcr\noalign{\kern3\points\nointerlineskip}%
      \disabledelimiter\doMMLfiller{\getXMLstackdata\plusone}
      \crcr}}}
    \limits
    \endgroup
\stopsetups

\startsetups mmp:munder:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmp:munder:stop
    \stopsavingXMLelements
    \mathop{\vtop{\mathsurround\zeropoint\ialign{\hss##\hss\crcr
      \disabledelimiter\doMMLfiller{\getXMLstackdata\plusone}
      \crcr\noalign{\kern3\points\nointerlineskip}%
      \disabledelimiter\doMMLfiller{\getXMLstackdata\plustwo}
      \crcr\noalign{\kern3\points}}}}
    \limits
    \endgroup
\stopsetups

\startsetups mmp:munderover:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmp:munderover:stop
    \stopsavingXMLelements
    \getXMLstackdata\plusone
      _{\disablefiller\disabledelimiter\getXMLstackdata\plustwo}
      ^{\disablefiller\disabledelimiter\getXMLstackdata\plusthree}
    \endgroup
\stopsetups

\def\doMMLfiller#1% bugged
   {\pushmacro\doMMLfiller
    \let\doMMLfiller\gobbleoneargument
    \gdef\dodoMMLfiller{\disablefiller\mathematics{#1}}%
    \hbox
      {\def\normalorfiller##1##2%
         {\gdef\dodoMMLfiller{\enablefiller#1}%
          \let\normalorfiller\gobbletwoarguments}%
       $#1$}%
    \popmacro\doMMLfiller
    \dodoMMLfiller}

% tables

% obsolete: \setupMMLappearance[mtable][\c!alternative=\v!a]

\mapXMLvalue {mmp:mtable} {align:left}   {right}
\mapXMLvalue {mmp:mtable} {align:right}  {left}
\mapXMLvalue {mmp:mtable} {align:center} {middle}

\mapXMLvalue {mmp:mtable} {frame:none}   {off}
\mapXMLvalue {mmp:mtable} {frame:solid}  {on}
\mapXMLvalue {mmp:mtable} {frame:on}     {on}

\defineXMLnested
    [mtable]
    [columnalign=,
     columnspacing=.25ex,
     rowspacing=.25ex,
     frame=,
     color=,
     background=]
    {\directsetup{mmp:mtable:start}}
    {\directsetup{mmp:mtable:stop}}

\defineXMLnestedargument
    [mtr]
    {\MMPmtableHANDLEtr}

\defineXMLnestedargument
    [mlabeledtr]
    {\MMPmtableHANDLEtr}

\defineXMLnestedargument
    [mtd]
    [columnalign=,
     columnspacing=.25ex,
     rowspacing=.25ex,
     frame=,
     color=,
     background=]
    {\MMPmtableHANDLEtd}

\startsetups mmp:mtable:start
    \vcenter \bgroup
    \MMLpTABLEsplitter{background} \c!backgroundcolor
    \MMLpTABLEsplitter{color}      \c!color
    \MMLpTABLEmapper  {frame}      \c!frame
    \MMLpTABLEmapper  {columnalign}\c!align
    \setMMLpunit{\XMLpar{mtable}{rowspacing}\empty}{.25ex}
    \let\MMLpTABLEoffset\MMLpunit
    \bTABLE[\c!frame=\v!off,\c!background=\v!color,\c!offset=\MMLpTABLEoffset]
\stopsetups

\startsetups mmp:mtable:stop
    \eTABLE
    \egroup
\stopsetups

\long\def\MMPmtableHANDLEtr#1{%
    \bTR\ignorespaces#1\removeunwantedspaces\eTR
}

\long\def\MMPmtableHANDLEtd#1{%
   \let\theMMLpTABLEmap\empty
   \MMLpTABLEmap{background} \c!backgroundcolor
   \MMLpTABLEmap{color}      \c!color
   \MMLpTABLEmap{frame}      \c!frame
   \MMLpTABLEmap{columnalign}\c!align
   \expanded{\bTD[\theMMLpTABLEmap]}%
    $\ignorespaces#1\removeunwantedspaces$\eTD
}

\def\MMLpTABLEmapper#1#2%
  {\doifXMLparelse{mtable}{#1}
     {\newcounter\MMLcounter
      \def\docommand##1%
        {\increment\MMLcounter
         \expanded{\setupTABLE[column][\MMLcounter][#2=\XMLval{mmp:mtable}{#2:##1}\empty]}}%
       \expanded{\processseparatedlist[\XMLpar{mtable}{#1}\empty]}[ ]\docommand}
     {}}

\def\MMLpTABLEsplitter#1#2%
  {\doifXMLparelse{mtable}{#1}
     {\newcounter\MMLcounter
      \def\docommand##1%
        {\increment\MMLcounter
         \expanded{\setupTABLE[column][\MMLcounter][#2=##1]}}%
       \expanded{\processseparatedlist[\XMLpar{mtable}{#1}\empty]}[ ]\docommand}
     {}}

\def\MMLpTABLEmap#1#2%
  {\doifXMLparelse{mtd}{#1}
     {\edef\theMMLpTABLEmap{#2=\XMLval{mmp:mtable}{#2:\XMLpar{mtd}{#1}\empty}\empty,\theMMLpTABLEmap}}
     {}}

\defineXMLsingular [mspace] [width=.5em] {\directsetup{mmp:mspace}}

\startsetups mmp:mspace
    \setMMLpunit{\XMLpar{mspace}{width}{}}{.5em}
    \hskip\MMLpunit\relax
\stopsetups

\def\setMMLpunit#1#2% i've forgotten what this means
  {\setbox\scratchbox=\hbox
     {\edef\ascii{#1}%
      \@EA\aftersplitstring\ascii\at.\to\ascii
      \scratchcounter=\ifx\ascii\empty#1\else\ascii\fi
      \unskip\unskip}%
   \ifdim\wd\scratchbox=\zeropoint
     \edef\MMLpunit{#1em}%
   \else
     \edefconvertedargument\ascii{#1}%
     \convertasciiafter\doifinstringelse{em}{\ascii}{\edef\MMLpunit{#1}}{%
     \convertasciiafter\doifinstringelse{ex}{\ascii}{\edef\MMLpunit{#1}}{%
     \convertasciiafter\doifinstringelse{pt}{\ascii}{\edef\MMLpunit{#1}}{%
                                                     \edef\MMLpunit{#2}}}}%
  \fi}

% end of tables

\def\setMMLpunit#1#2%
  {\setbox\scratchbox=\hbox
     {\edef\ascii{#1}%
      \@EA\aftersplitstring\ascii\at.\to\ascii
      \scratchcounter=\ifx\ascii\empty#1\else\ascii\fi
      \unskip\unskip}%
   \ifdim\wd\scratchbox=\zeropoint
     \edef\MMLpunit{#1em}%
   \else
     \edefconvertedargument\ascii{#1}%
     \convertasciiafter\doifinstringelse{em}{\ascii}{\edef\MMLpunit{#1}}{%
     \convertasciiafter\doifinstringelse{ex}{\ascii}{\edef\MMLpunit{#1}}{%
     \convertasciiafter\doifinstringelse{pt}{\ascii}{\edef\MMLpunit{#1}}{%
                                                     \edef\MMLpunit{#2}}}}%
  \fi}

\defineXMLsingular [mspace] [width=.5em] {\directsetup{mmp:mspace}}

\startsetups mmp:mspace
    \setMMLpunit{\XMLpar{mspace}{width}{}}{.5em}
    \hskip\MMLpunit
\stopsetups

\defineXMLsingular [mglyph] [fontfamily=,index=1,alt=] {\directsetup{mmp:mglyph}}

\startsetups mmp:mglyph
    \def\MMLpglyph{\XMLpar{mglyph}{fontfamily}{}}%
    \doifelsenothing{\MMLpglyph} {
        \hbox{\tttf[fontfamily unspecified]}
    } {
        \doifdefinedelse{\MMLpglyph} {
            \hbox{\getvalue{\MMLpglyph}\char0\XMLpar{mglyph}{index}{1}}
        } {
            \doifelsenothing{\XMLpar{mglyph}{alt}{}} {
                \hbox{\tttf[unknown fontfamily \XMLpar{mglyph}{fontfamily}{}]}
            } {
                \hbox{\tttf\XMLpar{mglyph}{alt}{}}
            }
        }
    }
\stopsetups

\defineXMLsingular [malignmark]  {}
\defineXMLsingular [none]        {}
\defineXMLsingular [mprescripts] {}

\defineXMLnested
   [mmultiscripts]
   {\setups{mmp:mmultiscripts:start}}
   {\setups{mmp:mmultiscripts:stop}}

\startsetups mmp:mmultiscripts:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmp:mmultiscripts:stop
    \stopsavingXMLelements
    \donefalse
    \scratchcounter\zerocount
    \dorecurse\XMLstacklevel {
        % watch the extra {}'s
        \ifdone
            \ifodd\scratchcounter
                _{\getXMLstackdata\recurselevel}
            \else
                ^{\getXMLstackdata\recurselevel}{}
            \fi
        \else
            \doif{\getXMLstackname\recurselevel}{mprescripts}{\donetrue{}}
        \fi
        \ifdone \advance\scratchcounter\plusone \fi

    }
    \donetrue
    \scratchcounter\zerocount
    \dorecurse\XMLstacklevel {
        \ifdone
            % watch the extra {}'s
            \ifcase\scratchcounter
                \getXMLstackdata\recurselevel
            \else\ifodd\scratchcounter
                _{\getXMLstackdata\recurselevel}
            \else
                ^{\getXMLstackdata\recurselevel}{}
            \fi\fi
        \fi
        \doif{\getXMLstackname\recurselevel}{mprescripts}{\donefalse}
        \ifdone \advance\scratchcounter\plusone \fi
    }
    \endgroup
\stopsetups

% experimental patches

\startmoduletestsection

\let\MMLdoL\donothing
\let\MMLdoR\donothing

\startsetups mmc:apply:start
    \begingroup
    \startsavingXMLelements
\stopsetups

\startsetups mmc:apply:stop
    \stopsavingXMLelements
    \MMLmathinner {
        \expanded{\doifinsetelse{\getXMLstackname\plusone}{\MMLcmainresetlist,\MMLctempresetlist}}
           \MMLcreset
           \donothing
        \ifcase\MMLapplydepth \else
           \doifXMLparelse{apply}{open} \donothing{\getXMLarguments{apply}{open="("}}% slow
           \doifXMLparelse{apply}{close}\donothing{\getXMLarguments{apply}{close=")"}}% slow
        \fi
        \advance\MMLapplydepth\plusone
        \begingroup
        \doifXMLparelse{apply}{open} % now inside the group
          {\edef\MMLdoL{\noexpand\left \XMLpar{apply}{open} {(}}
           \edef\MMLdoR{\noexpand\right\XMLpar{apply}{close}{)}}}
          {\let\MMLdoL\donothing
           \let\MMLdoR\donothing}
        \let\MMLctempresetlist\empty
        \doifelse {\getXMLstackname\plusone} {apply} {
            % <apply> <apply> ... </apply> <ci> .. </ci> </apply>
            \doifelseMMCfunctioninapply \plusone {plus,minus} {
% [a]
                % yet incomplete and rather untested
                % <apply> <apply> <minus/> <tan/> <cos/> </apply> <ci>x</ci> </apply>
            } {
% [b]
                \MMLcreset
            }
            \MMLdoL
            \getXMLstackdata\plusone
            \ifconditional\somepostponedMMLactions
                \postponedMMLactions
            \else
                \left(\MMLcreset\getXMLstackdata\plustwo\right)
            \fi
            \MMLdoR
        } {
            \doifelse {\getXMLstackname\plusone} {fn} {
% [c]
                % \MMLdoL/R are to be taken care of in the next setup
                \directsetup{mmc:fn:apply}
            } {
                \doifelse {\getXMLstackname\plusone} {csymbol} {
                    % \MMLdoL/R are to be taken care of in the next setup
% [d]
                    \directsetup{mmc:csymbol:apply}
                } {
                    \doifelse {\getXMLstackname\plusone} {ci} {
% [e]
                        % \MMLdoL/R are to be taken care of in the next setup
                        \directsetup{mmc:ci:apply}
                    } {
% [f]
                        \MMLdoL
                        \getXMLstackdata\plusone
                        \MMLdoR
                    }
                }
            }
        }
        \endgroup
        \advance\MMLapplydepth\minusone
        \directsetup{apply:flush}
      }
    \endgroup
\stopsetups

\startsetups mmc:fn:apply
    \begingroup
    \startsavingXMLelements
    \rawXMLstacktext\plusone % still on stack, no check, just fn content
    \stopsavingXMLelements
    \doifelse {\getXMLstackname\plusone} {ci} {
        \flattenXMLcontent{\getXMLstackdata\plusone}
        \doifsetupselse{mmc:fn:\flattenedXMLcontent} {
          % \MMLdoL/MMLdoR to be handled in plugin
            \global\defXMLstackdata\XMLfnoperator\plusone
            \expanded{\endgroup\noexpand\directsetup{mmc:fn:\flattenedXMLcontent}}
        } {
            \endgroup
            \MMLcreset
            \MMLdoL
            \getXMLstackdata\plusone
            \ifnum\XMLstacklevel>\plusone
                \getXMLentity{NegThinSpace}
                \left(\MMLcreset\flushXMLstackwith\plustwo{\MMLseparator,}\right)
            \fi
            \MMLdoR
        }
    } {
        \endgroup
        \MMLcreset
        \MMLdoL
        \getXMLstackdata\plusone
        \MMLdoR
    }
\stopsetups

\startsetups mmc:csymbol:apply
    \begingroup
    \defineXMLsave[csymbol][definitionURL=,encoding=]
    \rawXMLstackdata\plusone % was text % still on stack, no check, just attr test
    % \MMLdoL/MMLdoR to be handled in plugin
    \lowercasestring\XMLpar{csymbol}{definitionURL}{}\to\mmcSymbolURL
    \doifsetupselse{mmc:csymbol:\mmcSymbolURL} {
        \expanded{\endgroup\noexpand\directsetup{mmc:csymbol:\mmcSymbolURL}}
    } {
        \endgroup
       %\XMLval{mmc:cs}{\XMLop{encoding}}{\firstofoneargument}% fails when no content
        \XMLval{mmc:cs}{\XMLop{encoding}}{}
    }
\stopsetups

\defineXMLsingular
  [csymbol]
  [encoding=text,
   definitionURL=]
  {\directsetup{mmc:csymbol:apply:singular}}

\startsetups mmc:csymbol:apply:singular
    \lowercasestring\XMLpar{csymbol}{definitionURL}{}\to\mmcSymbolURL
    \directsetup{mmc:csymbol:\mmcSymbolURL}
\stopsetups

\startsetups mmc:ci:apply
    \getXMLstackdata\plusone
    \ifnum\XMLstacklevel>\plusone
       \left(\MMLcreset\flushXMLstackwith\plustwo{\MMLseparator,}\right)
    \fi
\stopsetups

\def\xflushXMLstackwith#1#2#3#4% num bgroup egroup whatever
  {\dostepwiserecurse{#1}\XMLstacklevel\plusone
     {#2\relax
      \ifnum\recurselevel>#1\relax#4\fi
      \getXMLstackdata\recurselevel
      #3}}

\def\xflushXMLstackfrom#1#2#3%
  {\dostepwiserecurse{#1}\XMLstacklevel\plusone
     {#2\getXMLstackdata\recurselevel#3}}

% <apply><divide/>
%     <apply><minus/>
%         <apply><minus/><ci>b</ci></apply>
%         <apply><minus/><ci>b</ci></apply>
%         <apply><root/> <ci>a</ci></apply>
%     </apply>
%     <apply><minus/>
%         <apply><minus/><ci>b</ci><ci>b</ci></apply>
%         <apply><minus/><ci>b</ci></apply>
%         <apply><root/> <ci>a</ci></apply>
%     </apply>
% </apply>

\startsetups mmc:minus
    \doif \@@MMLsignreduction \v!yes {
        \setMMLcreset{fn,\MMLcfunctionlist}
    }
    \ifcase\XMLstacklevel
    \or
       % self
    \or
       -\getXMLstackdata\plustwo
    \else
        \dostepwiserecurse\plustwo\XMLstacklevel\plusone {
            \begingroup
            \doifelse {\getXMLstackname\recurselevel} {apply} {
                \ifnum\recurselevel=\plustwo
                    \begingroup
                    \dodoifelseMMCfunctioninapply \recurselevel {minus} {
                        \ifnum\XMLstacklevel>\plustwo
                            \endgroup
                        \else
                            \endgroup
                            \MMLcreset
                        \fi
                    } {
                        \endgroup
                    }
                \else
                    \doifelseMMCfunctioninapply \recurselevel {\MMLcfunctionlist,\MMLcconstructlist} {
                        \MMLcreset
                    } {
                    }
                \fi
            } {
            }
            \getXMLstackdata\recurselevel
            \ifnum\recurselevel<\XMLstacklevel\relax
                -
            \fi
            \endgroup
        }
    \fi
\stopsetups

\stopmoduletestsection

\stopmodule

\protect \endinput
