\NeedsTeXFormat{LaTeX2e} \ProvidesPackage{notation}[2001/12/29 v0.3 (Kevin Watkins)] %%% Contents % Description % Grammar % Preprocessing % Ambiguity % Definitions % Other means of invoking translation % The \subscriptedvar macro % Design considerations %%% Description % This package provides a simple mechanism for translating ASCII % representations of symbols into the corresponding TeX control % sequences. The simplest way to invoke the package is to use the % environment \begin{notation}...\end{notation}. The contents of the % environment will be parsed as a and translated, and then % evaluated. No evaluation occurs until the translation is complete. % One can also use the control sequence \plainnotation, followed by % exactly one , which is similarly parsed and translated. % Note that an is self-delimiting. %%% Grammar % The grammar accepted by the package is as follows, in terms of the % token stream generated by the usual TeX preprocessing rules % summarized under ``Preprocessing''. The translation of each item is % indicated. I use [foo] for the result of recursively translating % , and for itself copied without translation. % ::= % --> { [sequence] } % % | \begin{} \end{} % --> \begin{} [sequence] % \end{} % (the are not translated) % % | _1 ... _n % where n is the arity of the % --> the definition of the token with the translations % of the argument items substituted for #1 ... # % but nothing otherwise expanded or evaluated % % | _1 ... _n % where n is the arity of the % --> the definition of the token with the itself substituted for #1 and the % translations of the argument items substituted for % #2 ... # but nothing otherwise expanded or % evaluated % % | \escape{} % --> % % | % --> % % | % --> % ::= % --> [arg item] % (the space is suppressed) % % | % --> [sequence] % (the outer grouping delimiters are suppressed) % % | % where the does not start with or % % --> [item] % ::= | % ::= | % ::= {} % | [] % ::= % | % ::= { | \bgroup % ::= } | \egroup % is a TeX control sequence other than \bgroup % \egroup \begin \end or \escape % is a TeX character token % is anything TeX thinks of as a space character % is TeX's usual notion of a sequence of { } balanced % tokens %%% Preprocessing % In all cases, the normal TeX ``mouth'' rules apply: % 1. Uses of \ are translated to control sequences. % 2. Spaces are suppressed after control sequences and other spaces. % 3. Blank lines are translated to \par. % 4. Comments are discarded. % 5. Ignored characters are ignored. % 6. Invalid characters are rejected. %%% Ambiguity % To the extent that the above grammar is ambiguous, it always prefers % ``shift'' to ``reduce'' (in yacc terminology). In particular, the % longest greedy match is always used to determine what the next % in the input is. If the longest greedy match is % both an and a the % is always preferred. If the longest greedy match is a single % character that is both a and an , the is preferred. %%% Definitions % Notation tokens may be defined as follows. Any definition is local % to the \begingroup...\endgroup pair or LaTeX environment in which it % appears. % \deftok{}{} % % Defines a new 0-ary consisting of , with % definition (in which ## must be used for a literal #). % \deftok{}[]{} % % Defines a new n-ary consisting of , with % definition (which may contain the substitution indicators #1 % ... #, or ## for a literal #). % \deflex{}{} % % Defines a class of 0-ary s consisting of all % non-empty sequences of characters from , with % definition (which may contain the substitution indicator #1 % or ## for a literal #). % \deflex{}[]{} % % Defines a class of n-ary s consisting of all % non-empty sequences of characters from , with % definition (which may contain the substitution indicators #1 % ... #, or ## for a literal #). % A is a list of either s or % pairs of s separated by \- (which stands for all % the characters between the pair of characters in the ASCII ordering) %%% Other means of invoking translation % The macros \mathnotation and \displaymathnotation behave like % \plainnotation except that they evaluate the result of the % translation in math mode or display math mode, respectively. % The \easynotation macro makes ", >, and >> initiate translation, % except that in math mode > stands for itself. (The characters " and % > are not normally allowed in text mode.) Each translates a single % self-delimited . The " character and >> evaluate the % translation immediately while > puts the result in math mode. % \easynotation is local to the \begingroup...\endgroup pair or LaTeX % environment in which it appears. Beware that some LaTeX % environments (particularly arrays) override > within the environment % for their own purposes. Also note that arrays typically do not % evaluate their contents at all until the entire array has been % parsed and split into lines and columns, EXCEPT that the first token % of each line is often expanded, which can cause extremely painful % order-of-evaluation issues if the first thing on a line is any kind % of macro. This can be overcome by prepending the offending line % with the do-nothing macro \relax. % \beginnotenv{} initiates translation of an as % though it had started with \begin{} (so the will be % terminated by a matching \end{}), and the translation of the % result is then evaluated (including the \end{} but not the % implicit \begin{}). This is so that an environment can be % defined such that the body will be processed in notation mode. The % notation environment itself is defined as: % % \newenvironment{notation}{\beginnotenv{notation}}{} % \beginnotenvwith{}{}{} is like % \beginnotenv{} except that is prepended to the % result and is appended to the result. This is necessary to % realize constructs such as the following: % % \newenvironment{notarray} % {\beginnotenvwith{notarray}{\begin{array}}{\end{array}}} % {} % % (Because the array environment is doing its own crazy preprocessing, % it has to see a literal \end{array} in the input at the moment the % \begin{array} is evaluated.) %%% The \subscriptedvar macro % The \subscriptedvar macro is independent of the notation translation % mechanism, but useful in conjunction with it. It induces the % following behavior: % \defvariable{foo}{FOO} % \defvariable{foot}{TOE} % \defvariable*{bar}{BAR(#1)} % \defvariable{qwe}{QWE(#1)} % in math mode: % \subscriptedvar{foo} --> FOO % \subscriptedvar{foob} --> FOO_{b} % \subscriptedvar{foot} --> TOE % \subscriptedvar{bar} --> BAR() % \subscriptedvar{bart} --> BAR(t) % \subscriptedvar{qwe} --> QWE() % \subscriptedvar{qwer} --> QWE(r)_{r} % \subscriptedvar{baz} --> \simplevar{baz} % in text mode: % \subscriptedvar{} --> % \simplevar{} --> \simplevar{} % \simplevar{} --> % \simplevar{a} --> \lowervar{a} % \simplevar{ab} --> \lowervar{a}_{b} % \simplevar{a} --> \lowervar{a}_{} % \simplevar{aa} --> \Lowervar{a} % \simplevar{aa} --> \Lowervar{a}_{} % \simplevar{aaa} --> \LOWERvar{a} % \simplevar{aaa} --> \LOWERvar{a}_{} % \simplevar{aaaa} --> \simplevar{aaa} % \simplevar{A} --> \uppervar{A} % \simplevar{A} --> \uppervar{A}_{} % \simplevar{AA} --> \Uppervar{A} % \simplevar{AA} --> \Uppervar{A}_{} % \simplevar{AAA} --> \UPPERvar{A} % \simplevar{AAA} --> \UPPERvar{A}_{} % \simplevar{AAAA \simplevar{AAA} % by default: % \lowervar and \uppervar are \relax % \Lowervar and \Uppervar are \mathcal % \LOWERvar and \UPPERvar are \mathfrak %%% Design considerations % All the text to be substituted, and the text being interpreted, must % be stored in token lists, not macros, because of the difficulty of % escaping the # character. Newly read tokens can be passed as arguments % because the { and } characters are translated to \bgroup and \egroup. % Of course, that means that \bgroup and \egroup themselves won't be % handled properly. I should have NOT@read take a second continuation % for control sequences (including implicit characters). However, I am % not currently aware of any technique which would permit me to % distinguish between implicit and explicit group and space characters % in a non-destructive way. % BUG: I need to detect control sequences that are implicit characters % and treat them as control sequences rather than characters. % \NOT@tl MUST BE ASSIGNED TO GLOBALLY \newtoks\NOT@tl\newtoks\NOT@gl\newtoks\NOT@tok\newtoks\NOT@chars \newcount\NOT@args\newcount\NOT@class\newcount\NOT@classes \newif\ifNOT@braces\newif\ifNOT@suppressEE \NOT@classes0 % \let\NOT@ifnextchar\@ifnextchar \def\NOT@confused#1{\PackageError{notation}% {Unexpected #1}% {A #1 was found where more tokens were expected.}} \def\NOT@badchar{\PackageError{notation}% {Bad token character}% {An illegal control sequence or grouping character was present in a token definition.}} \def\NOT@badend{\PackageError{notation}% {Mismatched end environment} {Mismatched end environment}} \def\NOT@append#1#2{\expandafter\NOT@push\expandafter{\the#2}#1} \long\def\NOT@push#1#2{#2\expandafter{\the#2#1}} \long\def\NOT@unshift#1#2{\expandafter\NOT@appr\expandafter{\the#2}{#1}#2} \long\def\NOT@appr#1#2#3{#3{#2#1}} % first we need to use futurelet to get a look at the thing \def\NOT@read#1{\let\reserved@a#1\futurelet\@let@token\NOT@read@} \def\NOT@read@{% \ifcat\noexpand\@let@token\bgroup \@temptokena{\bgroup}\let\reserved@b\NOT@readskip \else\ifcat\noexpand\@let@token\egroup \@temptokena{\egroup}\let\reserved@b\NOT@readskip \else\ifcat\noexpand\@let@token\@sptoken \@temptokena{ }\let\reserved@b\NOT@readskip \else % now we know it's safe to read as a parameter % (we need to read it as a parameter because we need explicit characters) \let\reserved@b\reserved@a \fi\fi\fi \reserved@b} \def\NOT@readskip{\afterassignment\NOT@readskip@\let\@let@token= } \def\NOT@readskip@{\expandafter\reserved@a\expandafter{\the\@temptokena}} \long\def\NOT@classof#1#2{% \expandafter\let\expandafter\reserved@a\csname!CO\string#1\endcsname \ifx\reserved@a\relax#2-1 \else#2\reserved@a\relax\fi} \def\NOT@once#1{\begingroup\long\def\NOT@R{\endgroup#1}\NOT@bracesfalse\NOT@I} \def\NOT@oneenv#1#2{% \begingroup \long\def\NOT@R{% \edef\reserved@a{#1}\edef\reserved@b{\the\NOT@tok}% \ifx\reserved@a\reserved@b\else\NOT@badend\fi \endgroup#2}% \begingroup \NOT@gl{}\NOT@bracestrue\NOT@suppressEEtrue\NOT@ES} % skipping white space \def\NOT@I{\NOT@read\NOT@I@} \long\def\NOT@I@#1{% \ifcat\noexpand#1\@sptoken \long\def\reserved@a##1{\NOT@read\NOT@I@}% \else \let\reserved@a\NOT@S@ \fi \reserved@a{#1}} % starting to read a new token \def\NOT@S{\NOT@read\NOT@S@} \long\def\NOT@S@#1{% \ifcat\noexpand#1\bgroup \let\reserved@a\NOT@BG \else\ifcat\noexpand#1\egroup \let\reserved@a\NOT@EG \else\ifx#1\escape \let\reserved@a\escape \else\ifx#1\begin \let\reserved@a\NOT@BE \else\ifx#1\end \let\reserved@a\NOT@EE \else\ifcat\noexpand#1\relax \global\NOT@tl{#1}\let\reserved@a\NOT@R \else \begingroup \NOT@classof{#1}\NOT@class \NOT@tok{#1}\NOT@chars\expandafter{\string#1}% \ifnum\NOT@class=-1 % \let\reserved@a\NOT@T \else \let\reserved@a\NOT@G \fi \fi\fi\fi\fi\fi\fi \reserved@a} \def\NOT@BG{\begingroup\NOT@gl{}\let\NOT@R\NOT@BGcont\NOT@bracestrue\NOT@S} \def\NOT@BGcont{\NOT@append\NOT@gl\NOT@tl\NOT@S} \def\NOT@EG{% \ifx\NOT@R\NOT@BGcont\else\NOT@confused{right brace}\fi \global\NOT@tl\NOT@gl\endgroup \ifNOT@braces \global\NOT@tl\expandafter{\expandafter{\the\NOT@tl}}% \fi \NOT@R} \long\def\escape#1{\global\NOT@tl{#1}\NOT@R} \def\NOT@BE#1{\begingroup\NOT@gl{\begin{#1}}\NOT@bracestrue\NOT@suppressEEfalse\NOT@ES} \def\NOT@BEcont{\relax\NOT@append\NOT@gl\NOT@tl\NOT@S} \def\NOT@EE#1{% \ifx\NOT@R\NOT@BEcont\else\ifx\NOT@R\NOT@EScont\else\NOT@confused{end of environment}\fi\fi \ifNOT@suppressEE\global\NOT@tok{#1}\else\NOT@push{\end{#1}}\NOT@gl\fi \global\NOT@tl\NOT@gl\endgroup\NOT@R} % skipping potential \begin{env} arguments \def\NOT@ES{\futurelet\@let@token\NOT@ES@} \long\def\NOT@ES@{% \ifcat\noexpand\@let@token\bgroup \let\reserved@a\NOT@ESarg \else\ifx\@let@token[% \let\reserved@a\NOT@ESopt \else \let\NOT@R\NOT@BEcont \let\reserved@a\NOT@S \fi\fi \reserved@a} \long\def\NOT@ESarg#1{\NOT@push{{#1}}\NOT@gl\NOT@ES} \long\def\NOT@ESopt[#1]{\NOT@push{[#1]}\NOT@gl\NOT@ES} % continuing to try to read a lex token \def\NOT@G{\NOT@read\NOT@G@} \long\def\NOT@G@#1{% \long\def\reserved@b##1{\NOT@T##1}% \ifcat\noexpand#1\bgroup \else\ifcat\noexpand#1\egroup \else\ifcat\noexpand#1\relax \else \NOT@classof{#1}\@tempcnta \ifnum\@tempcnta=\NOT@class \NOT@push{#1}\NOT@tok \expandafter\NOT@push\expandafter{\string#1}\NOT@chars \long\def\reserved@b##1{\NOT@read\NOT@G@}% \fi \fi\fi\fi \reserved@b{#1}} % continuing to try to read a tok token \def\NOT@T{\begingroup\NOT@tok{}\NOT@Tc} \long\def\NOT@Ta#1{% \long\def\reserved@a##1{\expandafter\NOT@D\the\NOT@tok##1}% \ifcat\noexpand#1\bgroup \else\ifcat\noexpand#1\egroup \else\ifcat\noexpand#1\relax \else \expandafter\ifx\csname!XT\the\NOT@chars\string#1\endcsname\empty \let\reserved@a\NOT@Tb \fi \fi\fi\fi \reserved@a{#1}} \long\def\NOT@Tb#1{% \NOT@push{#1}\NOT@tok \expandafter\NOT@push\expandafter{\string#1}\NOT@chars\NOT@Tc} \def\NOT@Tc{% \expandafter\ifx\csname!PT\the\NOT@chars\endcsname\relax \else \global\@temptokena\NOT@tok\global\NOT@chars\NOT@chars \endgroup \NOT@class-2 \NOT@append\NOT@tok\@temptokena \begingroup \NOT@tok{}% \fi \NOT@read\NOT@Ta} % done reading a character token % NOT@class = -1 if undefined, -2 if tok token, classnum if lex token % NOT@toks is the actual token list % NOT@chars is its character representation % all other symbols have been pushed back onto the input \long\def\NOT@D{% \endgroup \ifnum\NOT@class=-1 % \global\NOT@tl\NOT@tok\endgroup \let\reserved@a\NOT@R \else \ifnum\NOT@class=-2 % \expandafter\let\expandafter\NOT@defn\csname!DT\the\NOT@chars\endcsname \NOT@args\csname!AT\the\NOT@chars\endcsname\relax \expandafter\let\expandafter\NOT@apply\csname!PT\the\NOT@chars\endcsname \else \expandafter\let\expandafter\NOT@defn\csname!DC\the\NOT@class\endcsname \NOT@args\csname!AC\the\NOT@class\endcsname\relax \expandafter\let\expandafter\NOT@apply\csname!PC\the\NOT@class\endcsname \fi \NOT@gl{}\let\NOT@R\NOT@Acont\NOT@bracesfalse \let\reserved@a\NOT@A \fi \reserved@a} % done reading an argument \def\NOT@Acont{% \NOT@tl\expandafter{\expandafter{\the\NOT@tl}}% \NOT@append\NOT@gl\NOT@tl\advance\NOT@args-1 \NOT@A} % possibly preparing to read (another) argument \def\NOT@A{% \ifnum\NOT@args=0 % \expandafter\NOT@doapply\expandafter{\the\NOT@gl}\endgroup \let\reserved@a\NOT@R \else \let\reserved@a\NOT@I \fi \reserved@a} % finished reading all arguments \long\def\NOT@doapply#1{\expandafter\NOT@apply\expandafter{\the\NOT@tok}{#1}} \long\def\NOT@apply@specific#1#2{\global\NOT@tl\expandafter{\NOT@defn#2}} \long\def\NOT@apply@generic#1#2{\global\NOT@tl\expandafter{\NOT@defn{#1}#2}} % Translating a notation expression \newcommand{\plainnotation}{\NOT@once{\the\NOT@tl}} \newlength{\mathnotsurround} \setlength{\mathnotsurround}{0pt} \newcommand{\mathnotation}{\NOT@once{\(\hspace{\mathnotsurround}\the\NOT@tl\hspace{\mathnotsurround}\)}} \newcommand{\displaymathnotation}{\NOT@once{\[\the\NOT@tl\]}} \def\beginnotenv#1{\NOT@oneenv{#1}{\the\NOT@tl\end{#1}}} \def\beginnotenvwith#1#2#3{% \long\def\NOT@finishup##1{#2##1#3}% \NOT@oneenv{#1}{\expandafter\NOT@finishup\expandafter{\the\NOT@tl}\end{#1}}} \def\notation{\beginnotenv{notation}} \def\endnotation{} % Defining notation tokens \long\def\deflex#1{% \advance\NOT@classes1 \NOT@class\NOT@classes\relax \expandafter\NOT@chars\expandafter{\expandafter C\the\NOT@class}% \NOT@read\NOT@lexa#1\NOT@lexa} \long\def\NOT@lexa#1{% \ifcat\noexpand#1\bgroup\NOT@badchar\fi \ifcat\noexpand#1\egroup\NOT@badchar\fi \ifx#1\NOT@lexa \NOT@args1 \let\NOT@apply\NOT@apply@generic \let\reserved@a\NOT@def \else \ifcat\noexpand#1\relax\NOT@badchar\fi \@tempcnta`#1 % \let\reserved@a\NOT@testrange \fi \reserved@a} \def\NOT@testrange{\NOT@read\NOT@testrangea} \long\def\NOT@testrangea#1{% \ifx#1\-% \long\def\reserved@a##1{\NOT@read\NOT@dorange}% \else \long\def\reserved@a##1{\NOT@dolex\NOT@lexa{##1}}% \fi \reserved@a{#1}} \long\def\NOT@dorange#1{% \ifcat\noexpand#1\bgroup\NOT@badchar\fi \ifcat\noexpand#1\egroup\NOT@badchar\fi \ifcat\noexpand#1\relax\NOT@badchar\fi \@tempcntb`#1 \NOT@dorangea\NOT@read\NOT@lexa} \def\NOT@dorangea{% \ifnum\@tempcnta>\@tempcntb\else \NOT@dolex\advance\@tempcnta1 \NOT@dorangea\fi} \def\NOT@dolex{\expandafter\NOT@dolex@\expandafter{\the\NOT@class}} \def\NOT@dolex@#1{{\uccode`A=\@tempcnta\uppercase{\global\NOT@tl{A}}}% \expandafter\def\csname!CO\the\NOT@tl\endcsname{#1}} \long\def\deftok#1{\NOT@chars{T}\NOT@read\NOT@toka#1\NOT@toka} \long\def\NOT@toka#1{% \ifcat\noexpand#1\bgroup\NOT@badchar\fi \ifcat\noexpand#1\egroup\NOT@badchar\fi \ifx#1\NOT@toka \NOT@args0 \let\NOT@apply\NOT@apply@specific \let\reserved@a\NOT@def \else \ifcat\noexpand#1\relax\NOT@badchar\fi \expandafter\NOT@push\expandafter{\string#1}\NOT@chars \expandafter\let\csname!X\the\NOT@chars\endcsname\empty \def\reserved@a{\NOT@read\NOT@toka}% \fi \reserved@a} \def\NOT@def{\NOT@ifnextchar[{\NOT@defa}{\NOT@defa[0]}} \def\NOT@defa[#1]{% \expandafter\edef\csname!A\the\NOT@chars\endcsname{#1}% \expandafter\let\csname!P\the\NOT@chars\endcsname\NOT@apply \advance\NOT@args#1\relax\advance\NOT@args1 \NOT@defb} \def\NOT@defb{% \ifnum\NOT@args=1 % \def\reserved@a{\long\expandafter\def\csname!D\the\NOT@chars\endcsname}% \else \advance\NOT@args-1 % \edef\reserved@a{\noexpand\NOT@defb####\the\NOT@args}% \fi \reserved@a} % Support for subscripted variable names \newtoks\@ta\newtoks\@tb \newcommand*{\reverse}[1]{\@ta={}\@rev#1\end\the\@ta} \def\@rev{\NOT@ifnextchar\end{\let\reserved@a}{\@revunshift}} \def\@revunshift#1{\NOT@unshift{#1}\@ta\@rev} \newcommand*{\@ifalpha}[3]{% \@tempcnta=`#1\relax \long\def\reserved@a{#3}% \ifnum\the\@tempcnta<`A\else \ifnum`Z<\the\@tempcnta\else \long\def\reserved@a{#2}% \fi \fi \ifnum\the\@tempcnta<`a\else \ifnum`z<\the\@tempcnta\else \long\def\reserved@a{#2}% \fi \fi \reserved@a} \newcommand*{\@iflower}[3]{% \@tempcnta=`#1\relax \long\def\reserved@a{#3}% \ifnum\the\@tempcnta<`a\else \ifnum`z<\the\@tempcnta\else \long\def\reserved@a{#2}% \fi \fi \reserved@a} \newcommand{\lowervar}[1]{#1} \newcommand{\Lowervar}[1]{\mathcal{#1}} \newcommand{\LOWERvar}[1]{\mathfrak{#1}} \newcommand{\uppervar}[1]{#1} \newcommand{\Uppervar}[1]{\mathcal{#1}} \newcommand{\UPPERvar}[1]{\mathfrak{#1}} % \maybesubscript{} -> % \maybesubscript{A} -> _{A} \newcommand{\maybesubscript}[1]{\@maybesub#1\end} \def\@maybesub{\NOT@ifnextchar\end{\let\@first}{\@maybesub@}} \def\@maybesub@#1\end{_{#1}} % \simplevar{12ABC} -> 12A_{BC} % \simplevar{12AABC} -> 12\mathcal{A}_{BC} % \simplevar{12AAABC} -> 12\mathfrak{A}_{BC} \newcommand{\simplevar}[1]{\@simplevar#1\end} \def\@simplevar{\NOT@ifnextchar\end{\@maybesub}{\@simplevar@}} \def\@simplevar@#1{\@ifalpha#1{\@simplevar@@#1}{#1\@simplevar}} \def\@simplevar@@#1{\NOT@ifnextchar#1{\@simplevar@@@}{\@iflower#1{\lowervar{#1}\@maybesub}{\uppervar{#1}\@maybesub}}} \def\@simplevar@@@#1{\NOT@ifnextchar#1{\@simplevar@@@@}{\@iflower#1{\Lowervar{#1}\@maybesub}{\Uppervar{#1}\@maybesub}}} \def\@simplevar@@@@#1{\NOT@ifnextchar#1{\@simplevar@@@@}{\@iflower#1{\LOWERvar{#1}\@maybesub}{\UPPERvar{#1}\@maybesub}}} \newcommand{\defvariable}{\@ifstar{\@defvar}{\@defv@r}} \def\@defvar#1#2{\@ta={}\@rev#1\end \expandafter\def\csname!S\the\@ta\endcsname##1{#2}} \def\@defv@r#1#2{\@ta={}\@rev#1\end \expandafter\def\csname!S\the\@ta\endcsname##1{#2\maybesubscript{##1}}} \newcommand{\subscriptedvar}[1]{\relax\ifmmode\long\def\reserved@a{\@sv#1\end}\else\long\def\reserved@a{#1}\fi\reserved@a} \def\@sv{\NOT@ifnextchar\end{\let\reserved@a}{\@sv@}} \def\@sv@#1{\@ifalpha#1{\@sv@@#1}{#1\@sv}} \def\@sv@@#1\end{\@ta={}\@tb={}\@rev#1\end\expandafter\@try\the\@ta\end} \def\@try{\NOT@ifnextchar\end{\expandafter\@simplevar\the\@tb}{\@try@}} \def\@try@#1#2\end{\@ifundefined{!S#1#2}{\NOT@unshift{#1}\@tb\@try#2\end}{\expandafter\@try@@\the\@tb\end{!S#1#2}}} \def\@try@@#1\end#2{\@nameuse{#2}{#1}} % Support for single-character \notation invocation \def\easy@active{% \catcode`"=\active % \catcode`>=\active % \expandafter\def\expandafter\dospecials\expandafter{\dospecials\do\"\do\>}% }% {% \easy@active \global\def\easy@a{\NOT@ifnextchar>{\easy@aa}{\mathnotation}}% \global\def\easy@aa>{\plainnotation}% \global\def\easy@defs{% \def>{\relax\ifmmode\let\next\greater\else\let\next\easy@a\fi\next}% \let"\plainnotation }% }% \def\easynotation{\let\greater>\easy@active\easy@defs} % Useful function to skip a particular token \def\maybeskip#1{\NOT@ifnextchar#1{\let\@let@token= }{}} \long\def\maybeskipthen#1#2{\NOT@tok{#2}\NOT@ifnextchar#1{\afterassignment\@maybeskipthen\let\@let@token= }{\@maybeskipthen}} \def\@maybeskipthen{\the\NOT@tok}