%D \module
%D   [       file=math-ini,
%D        version=2001.04.12,
%D          title=\CONTEXT\ Math Macros,
%D       subtitle=Initializations,
%D         author={Hans Hagen \& Taco Hoekwater},
%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.

\writestatus{loading}{ConTeXt Math Macros / Initializations}

% todo: make all definitions global since file loaded only once

%D This module provides namespaces for math fonts, thereby
%D permitting mixed usage of math fonts. Although not strictly
%D needed, we also provide a family name mapping mechanism as
%D used in the (original) AMS math definition files, but here
%D these names can recursively be remapped and if needed,
%D dynamically be changed. We've tried to minimize the number
%D of definition commands and use plain \TEX\ definitions as
%D fallback. We've tried to follow a couple of conventions
%D from plain and AMS math in order to achieve backward
%D compatinility. We also kept an eye on future usage of these
%D modules in the perspective of MathML and unicode fonts.

\unprotect

\def\@ml@{@ml@} % math list (used for collection)
\def\@mf@{@mf@} % math family
%def\@mh@{@mh@} % math handler (not used)
\def\@mt@{@mt@} % math token
\def\@mc@{@mc@} % math collection

\def\@@mathlimopcomm#1{\mathop{#1}} %no \limits
\def\@@mathnolopcomm#1{\mathop{#1}\nolimits}
\def\@@mathboxcomm  #1{\dontleavehmode\hbox{$\mathsurround\zeropoint#1$}}

\chardef\mathordcode    = 0  \let\mathordcomm     \mathord
\chardef\mathopcode     = 1  \let\mathopcomm      \mathop
\chardef\mathbincode    = 2  \let\mathbincomm     \mathbin
\chardef\mathrelcode    = 3  \let\mathrelcomm     \mathrel
\chardef\mathopencode   = 4  \let\mathopencomm    \mathopen
\chardef\mathclosecode  = 5  \let\mathclosecomm   \mathclose
\chardef\mathpunctcode  = 6  \let\mathpunctcomm   \mathpunct
\chardef\mathalphacode  = 7  \let\mathalphacomm   \firstofoneargument
\chardef\mathinnercode  = 0  \let\mathinnercomm   \mathinner
\chardef\mathnothingcode= 0  \let\mathnothingcomm \firstofoneargument
\chardef\mathlimopcode  = 1  \let\mathlimopcomm   \@@mathlimopcomm
\chardef\mathnolopcode  = 1  \let\mathnolopcomm   \@@mathnolopcomm
\chardef\mathchoicecode = 0  \let\mathchoicecomm  \@@mathchoicecomm
\chardef\mathboxcode    = 0  \let\mathboxcomm     \@@mathboxcomm

\chardef\mathaccentcode = 8
\chardef\mathradicalcode= 9

\def\@@mathchoicecomm#1{[todo #1]}

\def\puremathcode#1{\the\csname math#1code\endcsname}
\def\puremathcomm#1{\csname     math#1comm\endcsname}

\newif\iftracemathcollection

% Simple variant:
%
% \def\dohandlemathtoken#1%
%   {\csname\@mt@
%      \ifcsname\@mt@\mathcollection#1\endcsname
%        \mathcollection
%      \else\ifcsname\@mt@\nomathcollection#1\endcsname
%        \nomathcollection
%      \fi\fi
%    #1\endcsname}

%D Because a command can have a different meaning in math
%D and in text mode, we provide a selector. We also provide
%D the pure alternatives as \type {\mathcharacter} and \type
%D {\textcharacter}.

% \ifx\dohandlecommand\undefined \wait \fi % troubles ! but not in mkiv so ...

\let\mathcharacter\dohandlemathtoken
\let\textcharacter\dohandlecommand % better \dohandletexttoken

% More clever layout:
%
% \def\dohandlemathtoken#1%
%   {\csname
%      \ifmmode
%        \ifcsname\@mt@\mathcollection#1\endcsname
%          \@mt@\mathcollection
%        \else\ifcsname\@mt@\nomathcollection#1\endcsname
%          \@mt@\nomathcollection
%        \else\ifcsname\characterencoding#1\endcsname
%          \characterencoding
%        \else
%          \nocharacterencoding
%        \fi\fi\fi
%      \else
%        \ifcsname\characterencoding#1\endcsname
%          \characterencoding
%        \else
%          \nocharacterencoding
%        \fi
%      \fi
%    #1\endcsname}
%
% fallback to math when in text mode (handy for unicode vectors)

\def\dohandlemathtoken#1%
  {\csname
     \ifmmode
       \ifcsname\@mt@\mathcollection#1\endcsname
         \@mt@\mathcollection
       \else\ifcsname\@mt@\nomathcollection#1\endcsname
         \@mt@\nomathcollection
       \else\ifcsname\characterencoding#1\endcsname
         \characterencoding
       \else
         \nocharacterencoding
       \fi\fi\fi
     \else
       \ifcsname\characterencoding#1\endcsname
         \characterencoding
       \else\ifcsname\nocharacterencoding#1\endcsname
         \nocharacterencoding
       \else\ifcsname\@mt@\mathcollection#1\endcsname
         \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\mathcollection
       \else\ifcsname\@mt@\nomathcollection#1\endcsname
         \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\nomathcollection
       \else
         \nocharacterencoding
       \fi\fi\fi\fi
     \fi
   #1\endcsname}

%D Now we redefine the text encoding handler.

%D A better fallback:

% Just ETEX which is the default nowadays.

\def\dohandlemathtoken#1%
  {\csname
     \ifmmode
       \ifcsname\@mt@\mathcollection:\outerencoding#1\endcsname
         \@mt@\mathcollection:\outerencoding
       \else\ifcsname\@mt@\mathcollection#1\endcsname
         \@mt@\mathcollection
       \else\ifcsname\@mt@\nomathcollection#1\endcsname
         \@mt@\nomathcollection
       \else\ifcsname\characterencoding#1\endcsname
         \characterencoding
       \else
         \nocharacterencoding
       \fi\fi\fi\fi
     \else
       \ifcsname\characterencoding#1\endcsname
         \characterencoding
       \else\ifcsname\nocharacterencoding#1\endcsname
         \nocharacterencoding
       \else\ifcsname\@mt@\mathcollection:\outerencoding#1\endcsname
         \@mt@\mathcollection:\outerencoding
       \else\ifcsname\@mt@\mathcollection#1\endcsname
         \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\mathcollection
       \else\ifcsname\@mt@\nomathcollection#1\endcsname
         \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\nomathcollection
       \else
         \nocharacterencoding
       \fi\fi\fi\fi\fi
     \fi
   #1\endcsname}

\let\dohandlecommand\dohandlemathtoken

\def\definefamilysynonym
  {\dotripleempty\dodefinefamilysynonym}

\def\dodefinefamilysynonym[#1][#2][#3]% [mathcollection] [] []
  {\ifthirdargument
     \setvalue{\@mf@#1#2}{#3}%
   \else
     \setvalue{\@mf@  #1}{#2}%
   \fi}

\let\mathsubfamily\empty

\def\purefamily   #1{\csname    \truefamily{#1}\mathsubfamily\s!fam\endcsname}
\def\purefamilyhex#1{\csname hex\truefamily{#1}\mathsubfamily\s!fam\endcsname}

\def\truefamily#1%
  {\ifcsname\@mf@\mathcollection#1\endcsname
     \@EA\truefamily\csname\@mf@\mathcollection#1\endcsname
   \else\ifcsname\@mf@#1\endcsname
     \@EA\truefamily\csname\@mf@#1\endcsname
   \else\ifcsname\@mf@\nomathcollection#1\endcsname
     \@EA\truefamily\csname\@mf@\nomathcollection#1\endcsname
   \else
     #1%
   \fi\fi\fi}

\newif\ifdynamicmathfamilies \dynamicmathfamiliestrue % true per 2003.11.25; needed for mixed bold math

\let\normalpurefamilyhex\purefamilyhex

% todo: reset collection (tok legen) en opnieuw laden met true

\def\definemathsymbol
  {\dosixtupleempty\dodefinemathsymbol}

\def\dodefinemathsymbol[#1][#2][#3][#4][#5][#6]%
  {\unexpanded\setgvalue{#1}{\dohandlemathtoken{#1}}%
   \ifdynamicmathfamilies \let\purefamilyhex\relax \fi
   \setevalue{\@mt@\mathcollection#1}%
     {\ifsixthargument
        \ifnum\puremathcode{#2}=\mathradicalcode
          \radical"%
        \else
          \delimiter"%
          \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
        \fi
        \purefamilyhex{#3}\uchexnumbers{#4}%
        \purefamilyhex{#5}\uchexnumbers{#6}\space
      \else\iffourthargument
        \ifnum\puremathcode{#2}=\mathaccentcode
          \mathaccent\else\mathchar
        \fi
       "\ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
        \purefamilyhex{#3}\uchexnumbers{#4}\space
      \fi\fi}%
   \let\purefamilyhex\normalpurefamilyhex
   \tracemathsymbol{#1}}

\def\tracemathsymbol#1%
  {\iftracemathcollection
     {\endgraf
      \hbox{\tex{#1}~:~{\mathematics{\getvalue{#1}{}}}}
      \endgraf}%
   \fi}

\def\definemathcharacter
  {\dosixtupleempty\dodefinemathcharacter}

% \def\dodefinemathcharacter[#1][#2][#3][#4][#5][#6]%
%   {\setmathtoks
%    \ifdynamicmathfamilies \let\purefamilyhex\relax \fi
%    \doifnumberelse{#1}
%      {\scratchcounter#1}
%      {\scratchcounter\@EA`\string#1}%
%    \appendetoks
%       \ifsixthargument
%         \delcode\the\scratchcounter="%
%           \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
%           \purefamilyhex{#3}\uchexnumbers{#4}%
%           \purefamilyhex{#5}\uchexnumbers{#6}\space
%       \else\iffourthargument
%         \mathcode\the\scratchcounter="%
%           \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
%           \purefamilyhex{#3}\uchexnumbers{#4}\space
%       \fi\fi\to\mathtoks
%    \let\purefamilyhex\normalpurefamilyhex
%    \tracemathcharacter{#1}}

\newtoks\mathscratchtoks

\def\definemathcharacter
  {\chardef\mathcharactermode\zerocount
   \dosixtupleempty\dodefinemathcharacter}

\def\redefinemathcharacter
  {\chardef\mathcharactermode\plusone
   \dosixtupleempty\dodefinemathcharacter}

\def\dodefinemathcharacter[#1][#2][#3][#4][#5][#6]%
  {\ifcase\mathcharactermode
     \setmathtoks
   \or
     \let\mathtoks\mathscratchtoks \mathtoks\emptytoks
   \fi
   \ifdynamicmathfamilies \let\purefamilyhex\relax \fi
   \doifnumberelse{#1}
     {\scratchcounter#1}
     {\scratchcounter\@EA`\string#1}%
   \appendetoks
      \ifsixthargument
        \delcode\the\scratchcounter="%
          \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
          \purefamilyhex{#3}\uchexnumbers{#4}%
          \purefamilyhex{#5}\uchexnumbers{#6}\space
      \else\iffourthargument
        \mathcode\the\scratchcounter="%
          \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
          \purefamilyhex{#3}\uchexnumbers{#4}\space
      \fi\fi
   \to \mathtoks
   \let\purefamilyhex\normalpurefamilyhex
   \ifcase\mathcharactermode
     \expandafter\tracemathcharacter
   \or
     \the\mathtoks
     \mathtoks\emptytoks
     \expandafter\gobbleoneargument
   \fi{#1}} % maybe lookahead

\def\tracemathcharacter#1%
  {\iftracemathcollection
     {\endgraf
      \doifnumberelse{#1}
        {\hbox{\tttf\rawcharacter{#1}~:~{\mathematics{\rawcharacter{#1}}}}}
        {\hbox{\type{#1}~:~{\mathematics{#1}}}}
      \endgraf}%
   \fi}

\def\definemathcommand
  {\dotripleempty\dodefinemathcommand}

\def\dodefinemathcommand[#1][#2][#3]#4% command class args meaning
  {\unexpanded\setgvalue{#1}{\dohandlemathtoken{#1}}%
   \ifthirdargument
     \processaction
       [#3]
       [one=>\setvalue{\@mt@\mathcollection#1}##1{\puremathcomm{#2}{#4{##1}}},
        two=>\setvalue{\@mt@\mathcollection#1}##1##2{\puremathcomm{#2}{#4{##1}{##2}}}]%
   \else\ifsecondargument
     \setvalue{\@mt@\mathcollection#1}{\puremathcomm{#2}{#4}}%
   \else
     \setvalue{\@mt@\mathcollection#1}{\puremathcomm{nothing}{#4}}%
   \fi\fi
   \tracemathcommand{#1}}

\def\tracemathcommand#1%
  {\iftracemathcollection
     \endgraf\hbox{\tex{#1}~:~{\mathematics{\getvalue{#1}{}}}}\endgraf
   \fi}

\def\startmathcollection[#1]%
  {\pushmacro\mathcollection
   \setmathcollection{#1}}

\def\setmathcollection#1%
  {\edef\mathcollection{#1}%
   \doifundefined{\@ml@\mathcollection}
     {\expandafter\newtoks\csname\@ml@\mathcollection\endcsname}}

\def\stopmathcollection
  {\popmacro\mathcollection}

\def\startrawmathcollection
  {\startmathcollection}

\def\stoprawmathcollection
  {\stopmathcollection}

\newtoks\mathtoks

\def\setmathtoks
  {\@EA\let\@EA\mathtoks\csname\@ml@\mathcollection\endcsname}

\def\currentmathcollection{\mathcollection}

\let\nomathcollection\s!default

\def\enablemathcollection[#1]%
  {\doifnot{#1}\s!default
     {\setmathcollection\s!default
      \the\csname\@ml@\mathcollection\endcsname}%
   \setmathcollection{#1}%
   \the\csname\@ml@\mathcollection\endcsname}

% hook 'm into the font mechanism

\definefilesynonym[\f!mathprefix\s!default][\f!mathprefix tex]

\def\usemathcollection
  {\dodoubleempty\dousemathcollection}

\def\dousemathcollection[#1][#2]%
  {\pushmacro\fontclass
   \pushmacro\mathclass
   \ifsecondargument
     \edef\fontclass{#1}%
     \edef\mathclass{#2}%
   \else
     \edef\mathclass{#1}%
   \fi
   \doinputonce{\truefilename{\f!mathprefix\mathclass}.mkii}%
   \doifsomething\fontclass{\setevalue{\@mc@\fontclass\@mc@}{\mathclass}}%
   \popmacro\mathclass
   \popmacro\fontclass}

\let\mathclass\nomathcollection

\letvalue{\@mc@\@mc@}\nomathcollection

% \def\autoenablemathcollection
%   {\doifdefinedelse{\@mc@\fontclass\@mc@}
%      {\enablemathcollection[\getvalue{\@mc@\fontclass\@mc@}]}
%      {\enablemathcollection[\s!default]}} % ? ? ?

\def\autoenablemathcollection
  {\expanded{\enablemathcollection[\executeifdefined{\@mc@\fontclass\@mc@}\nomathcollection]}}

\appendtoks\autoenablemathcollection\to\mathstrategies

\fetchruntimecommand \showmathcharacters {\f!mathprefix\s!run}
\fetchruntimecommand \showmathtoken      {\f!mathprefix\s!run}

\def\resetmathcollection[#1]%
  {\def\mathcollection{#1}%
   \forgetdoingonce{\f!mathprefix\mathcollection.mkii}%
   \setmathtoks
   \ifx\mathtoks\relax\else\mathtoks\emptytoks\fi}

%D \macros
%D   {ifmathpunctuation, enablemathpunctuation,
%D    definemathpunctuation}
%D
%D This will replace periods by comma's:
%D
%D \starttyping
%D \definemathpunctuation . textcomma textperiod
%D \definemathpunctuation , textcomma textcomma
%D
%D \appendtoks
%D    \redefinemathcharacter [.] [ord] [mi] ["3B]%
%D \to \everymathpunctuation
%D \stoptyping

% \newif\ifmathpunctuation
%
% \def\enablemathpunctuation{\mathpunctuationtrue}
%
% \def\definemathpunctuation #1 #2 #3 %
%   {\appendtoks
%      \initializemathpunctuation{#1}{#2}{#3}%
%    \to\everymathematics}
%
% \def\initializemathpunctuation#1#2#3% sloowww
%   {\ifmathpunctuation % hm move this test to everymath, or better a separate token list
%      \mathcode`#1="8000
%      \defineactivecharacter #1 {\dohandlemathpunctuation{#2}{#3}}%
%    \fi}
%
% \unexpanded\def\dohandlemathpunctuation#1#2% \if fails in mathml interval
%   {\def\next{\csname\ifx\space\nexttoken#2\else#1\fi\endcsname}%
%    \futurelet\nexttoken\next}

\newtoks\everymathpunctuation

\def\enablemathpunctuation % can be called inside math, so after \everymathematics
  {\relax
   \ifmmode
     \the\everymathpunctuation
   \fi
   \appendtoksonce
     \the\everymathpunctuation
   \to\everymathematics}

\def\definemathpunctuation #1 #2 #3 %
  {\appendtoks
     \initializemathpunctuation{#1}{#2}{#3}%
   \to\everymathpunctuation}

\def\initializemathpunctuation#1#2#3% sloowww
  {\mathcode`#1="8000
   \defineactivecharacter #1 {\dohandlemathpunctuation{#2}{#3}}}

\unexpanded\def\dohandlemathpunctuation#1#2% \if fails in mathml interval
  {\def\next{\csname\ifx\space\nexttoken#2\else#1\fi\endcsname}%
   \futurelet\nexttoken\next}

%D \startbuffer
%D \enablemathpunctuation$(1,2) (1, 2) (1{,}2) \hbox{foo, not bar}$
%D \stopbuffer
%D
%D \typebuffer
%D
%D \blank{\getbuffer}\blank

%D needed for sin, cos etc

\def\mfunction        #1{{\mr#1}}

% \def\mlimitsfunction  #1{\mathlimopcomm{{\mr#1}}
% \def\mnolimitsfunction#1{\mathnolopcomm{{\mr#1}}

%D Taco posted this solution as response to a mail by Olivier, so
%D let's integrate it here.

% \def\setmathfunctionstyle#1% rm ss tt
%   {\def\mfunction##1% no families, just scaling a la text
%      {\mathchoice
%         {\hbox{\csname#1\endcsname\tf  ##1}}
%         {\hbox{\csname#1\endcsname\tf  ##1}}
%         {\hbox{\csname#1\endcsname\tfx ##1}}
%         {\hbox{\csname#1\endcsname\tfxx##1}}}}

\def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option

\def\setmathfunctionstyle#1% rm ss tt
  {\doifsomething{#1}
     {\def\currentmscaledstyle{#1}%
      \def\mathopnolimits##1{\mathop{\mscaledtext{##1}}\nolimits}%
      \def\mfunction##1{\mscaledtext{##1}}}}

\def\mscaledtext#1%
  {\mathchoice
     {\hbox{\csname\currentmscaledstyle\endcsname\tf  #1}}
     {\hbox{\csname\currentmscaledstyle\endcsname\tf  #1}}
     {\hbox{\csname\currentmscaledstyle\endcsname\tfx #1}}
     {\hbox{\csname\currentmscaledstyle\endcsname\tfxx#1}}}

%D We can force the way functions are typeset by manipulating the text
%D option:
%D
%D \starttyping
%D \definetypeface[iwona][ss][sans][iwona][default][encoding=texnansi]
%D \definetypeface[iwona][mm][math][iwona][default][encoding=texnansi,text=ss]
%D \stoptyping
%D
%D This hooks into the math handler with:

\appendtoks
    \setmathfunctionstyle\currentmathtextstyle
\to \everybodyfont

%D Usage:
%D
%D \starttyping
%D \setmathfunctionstyle\fontstyle % or {rm} or {ss} or ..
%D \rm test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
%D \ss test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
%D \tt test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
%D \stoptyping

\edef\hexmrfam {0} \edef\hexbsfam {8}
\edef\hexmifam {1} \edef\hexbifam {9}
\edef\hexsyfam {2} \edef\hexscfam {A}
\edef\hexexfam {3} \edef\hextffam {B}
\edef\hexitfam {4} \edef\hexmafam {C}
\edef\hexslfam {5} \edef\hexmbfam {D}
\edef\hexbffam {6} \edef\hexmcfam {E}
\edef\hexnnfam {7} \edef\hexmdfam {F}

\definefamilysynonym [default] [letters]   [mr]
\definefamilysynonym [default] [operators] [sy]
\definefamilysynonym [default] [lcgreek]   [mi]
\definefamilysynonym [default] [ucgreek]   [mr]
\definefamilysynonym [default] [vargreek]  [mi]
\definefamilysynonym [default] [mitfamily] [mi]
\definefamilysynonym [default] [calfamily] [sy]

\definefamilysynonym [default] [0] [mr]
\definefamilysynonym [default] [1] [mi]
\definefamilysynonym [default] [2] [sy]
\definefamilysynonym [default] [3] [ex]

\enablemathcollection[default]

\usemathcollection [default] [tex]
\usemathcollection [default] [ams]
\usemathcollection [default] [uni]

\enablemathcollection[default]

%D Some goodies:

\def\Angstrom{\nomathematics{\Aring}}

%D Bold math:
%D
%D \starttyping
%D \usetypescript [lucida] [texnansi]
%D
%D \definetypeface [boldmath] [rm] [serif]
%D   [lucida] [default] [encoding=texnansi]
%D \definetypeface [boldmath] [tt] [mono]
%D   [lucida] [default] [encoding=texnansi]
%D \definetypeface [boldmath] [ss] [sans]
%D   [lucida] [default] [encoding=texnansi]
%D \definetypeface [boldmath] [mm] [boldmath]
%D   [lucida] [default] [encoding=texnansi]
%D
%D \switchtobodyfont[lucida,10pt]
%D
%D \showmathtoken{Gamma} $\Gamma \Delta \alpha \delta \zeta$
%D
%D \switchtobodyfont[boldmath,10pt]
%D
%D \showmathtoken{Gamma} $\Gamma \Delta \alpha \delta \zeta$
%D \stoptyping

%D \macros
%D   {nonknuthmode, donknuthmode}
%D
%D The underscore is frequently used in manuals but unfortunately \TEX\ prefers
%D it to be a math specific character. And since computer modern fonts didn't
%D have an underscore, one had to use commands to fake one. Nowadays we do
%D have underscores in latin modern, and since all other fonts have them, we
%D decided to get away from the restriction to use the underscore character in
%D text mode.
%D
%D \starttyping
%D \def\test#1{#1}
%D
%D \nonknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
%D
%D \donknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
%D \stoptyping
%D
%D The result is as expected: the first line typesets ok, while the second
%D one triggers an error message.

\bgroup

    \ifx\normalsuber\undefined \def\normalsuber{_} \fi
    \ifx\normalsuper\undefined \def\normalsuper{^} \fi

    \catcode`_=\active
    \catcode`^=\active

    \gdef\nonknuthmode
      {\appendtoks\let_\normalsuber\let^\normalsuper\to\everymathematics
       \mathcode`_="8000
       \mathcode`^="8000
       \catcode`_=\@@other
       \catcode`^=\@@other
       \let\nonknuthmode\relax}

    \gdef\donknuthmode
      {\catcode`_=\@@subscript
       \catcode`^=\@@superscript}

\egroup

%D \macros
%D   {checkdelimiters, fakeleftdelimiter, fakerightdelimiter}
%D
%D Handy for non matching situations (as with mathml):
%D
%D \starttyping
%D \checkdelimiters{... bla bla ...}
%D \fakeleftdelimiter
%D  ... bla bla ...
%D \fakerightdelimiter
%D \stoptyping

\newcount\delimitercount

\def\leftfakedelimiter {\advance\delimitercount\minusone\gobbleoneargument}%
\def\rightfakedelimiter{\advance\delimitercount\plusone \gobbleoneargument}%

\def\checkdelimiters#1%
  {\delimitercount\zerocount
   \setbox\scratchbox\hbox\bgroup
     \let\left \leftfakedelimiter
     \let\right\rightfakedelimiter
     $#1\expandafter$\expandafter
   \egroup
   \expandafter\delimitercount\the\delimitercount\relax}

\def\fakeleftdelimiter {\ifnum\delimitercount>\zerocount\left .\fi}
\def\fakerightdelimiter{\ifnum\delimitercount<\zerocount\right.\fi}

%D Needed for unicode:

\def\nulloperator{\mathortext{\mathop{\null}}{\null}}

%D To be dealt with ...

\mathcode`\ ="8000 % \space
\mathcode`\'="8000 % ^\prime
\mathcode`\_="8000 % \_

\protect \endinput

\tracemathcollectiontrue
                                                   \input math-tex \page
\setupbodyfont[ams] \enablemathcollection[default] \input math-ams \page
\setupbodyfont[lbr] \enablemathcollection[lbr]     \input math-lbr \page
\setupbodyfont[eul] \enablemathcollection[eul]     \input math-eul \stoptext
