\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 <sequence> 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 <arg item>, which is similarly parsed and translated.
% Note that an <arg item> 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
% <foo>, and <foo> for <foo> itself copied without translation.

% <item> ::= <begin group> <sequence> <end group>
%              --> { [sequence] }
%
%         |  \begin{<balanced>} <begin args> <sequence> \end{<balanced>}
%              --> \begin{<balanced>} <begin args> [sequence]
%                  \end{<balanced>}
%              (the <begin args> are not translated)
%
%         |  <explicit token> <arg item>_1 ... <arg item>_n
%            where n is the arity of the <explicit token>
%              --> the definition of the token with the translations
%                  of the argument items substituted for #1 ... #<n>
%                  but nothing otherwise expanded or evaluated
%
%         |  <lexical token> <arg item>_1 ... <arg item>_n
%            where n is the arity of the <lexical token>
%              --> the definition of the token with the <lexical
%                  token> itself substituted for #1 and the
%                  translations of the argument items substituted for
%                  #2 ... #<n+1> but nothing otherwise expanded or
%                  evaluated
%
%         |  \escape{<balanced>}
%              --> <balanced>
%
%         |  <ordinary character>
%              --> <ordinary character>
%
%         |  <control sequence>
%              --> <control sequence>

% <arg item> ::= <space> <arg item>
%                  --> [arg item]
%                  (the space is suppressed)
%
%             |  <begin group> <sequence> <end group>
%                  --> [sequence]
%                  (the outer grouping delimiters are suppressed)
%
%             |  <item>
%                where the <item> does not start with <space> or
%                <begin group>
%                  --> [item]

% <sequence> ::= <empty> | <item> <sequence>

% <begin args> ::= <empty> | <begin arg> <begin args>
% <begin arg> ::= {<balanced>}
%              |  [<balanced>]

% <notation token> ::= <explicit token>
%                   |  <lexical token>

% <begin group> ::= { | \bgroup
% <end group>   ::= } | \egroup

% <control sequence> is a TeX control sequence other than \bgroup
% \egroup \begin \end or \escape

% <ordinary character> is a TeX character token

% <space> is anything TeX thinks of as a space character

% <balanced> 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
% <notation token> in the input is.  If the longest greedy match is
% both an <explicit token> and a <lexical token> the <explicit token>
% is always preferred.  If the longest greedy match is a single
% character that is both a <notation token> and an <ordinary
% character>, the <notation token> 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{<ordinary characters>}{<body>}
%
% Defines a new 0-ary <explicit token> consisting of <chars>, with
% definition <body> (in which ## must be used for a literal #).

% \deftok{<ordinary characters>}[<arity>]{<body>}
%
% Defines a new n-ary <explicit token> consisting of <chars>, with
% definition <body> (which may contain the substitution indicators #1
% ... #<n>, or ## for a literal #).

% \deflex{<character class>}{<body>}
%
% Defines a class of 0-ary <lexical token>s consisting of all
% non-empty sequences of characters from <character class>, with
% definition <body> (which may contain the substitution indicator #1
% or ## for a literal #).

% \deflex{<character class>}[<arity>]{<body>}
%
% Defines a class of n-ary <lexical token>s consisting of all
% non-empty sequences of characters from <character class>, with
% definition <body> (which may contain the substitution indicators #1
% ... #<n+1>, or ## for a literal #).

% A <character class> is a list of either <ordinary character>s or
% pairs of <ordinary character>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 <arg item>.  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{<chars>} initiates translation of an <item> as
% though it had started with \begin{<chars>} (so the <item> will be
% terminated by a matching \end{<chars>}), and the translation of the
% result is then evaluated (including the \end{<chars>} but not the
% implicit \begin{<chars>}).  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{<chars>}{<prepend>}{<append>} is like
% \beginnotenv{<chars>} except that <prepend> is prepended to the
% result and <append> 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{<chars>} --> <chars>

% \simplevar{<non-alpha><chars>} --> <non-alpha>\simplevar{<chars>}
% \simplevar{}                   --> <empty>
% \simplevar{a}                  --> \lowervar{a}
% \simplevar{ab}                 --> \lowervar{a}_{b}
% \simplevar{a<not a><chars>}    --> \lowervar{a}_{<not a><chars>}
% \simplevar{aa}                 --> \Lowervar{a}
% \simplevar{aa<not a><chars>}   --> \Lowervar{a}_{<not a><chars>}
% \simplevar{aaa}                --> \LOWERvar{a}
% \simplevar{aaa<not a><chars>}  --> \LOWERvar{a}_{<not a><chars>}
% \simplevar{aaaa<chars>}        --> \simplevar{aaa<chars>}
% \simplevar{A}                  --> \uppervar{A}
% \simplevar{A<not A><chars>}    --> \uppervar{A}_{<not A><chars>}
% \simplevar{AA}                 --> \Uppervar{A}
% \simplevar{AA<not A><chars>}   --> \Uppervar{A}_{<not A><chars>}
% \simplevar{AAA}                --> \UPPERvar{A}
% \simplevar{AAA<not A><chars>}  --> \UPPERvar{A}_{<not A><chars>}
% \simplevar{AAAA<chars}         --> \simplevar{AAA<chars>}

% 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>{\displaymathnotation}%
  \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}
