% \iffalse meta-comment
%
%% File: xparse.dtx (C) Copyright 1999 Frank Mittelbach, Chris Rowley,
%%                      David Carlisle
%%                  (C) Copyright 2004-2008 Frank Mittelbach,
%%                      The LaTeX3 Project
%%                  (C) Copyright 2009-2015 The LaTeX3 Project
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
%% license or (at your option) any later version.  The latest version
%% of this license is in the file
%%
%%    http://www.latex-project.org/lppl.txt
%%
%% This file is part of the "l3packages bundle" (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX Project Team.
%%
%% -----------------------------------------------------------------------
%%
%
%<*driver|package>
% The version of expl3 required is tested as early as possible, as
% some really old versions do not define \ProvidesExplPackage.
\RequirePackage{expl3}[2015/07/28]
%<package>\@ifpackagelater{expl3}{2015/07/28}
%<package>  {}
%<package>  {%
%<package>    \PackageError{xparse}{Support package l3kernel too old}
%<package>      {%
%<package>        Please install an up to date version of l3kernel\MessageBreak
%<package>        using your TeX package manager or from CTAN.\MessageBreak
%<package>        \MessageBreak
%<package>        Loading xparse will abort!%
%<package>      }%
%<package>    \endinput
%<package>  }
\GetIdInfo$Id: xparse.dtx 5700 2015-07-28 19:26:39Z joseph $
  {L3 Experimental document command parser}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
\usepackage{amstext}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \providecommand\acro[1]{\textsc{\MakeLowercase{#1}}}
% \newenvironment{arg-description}{%
%   \begin{itemize}\def\makelabel##1{\hss\llap{\bfseries##1}}}{\end{itemize}}
%
% \title{^^A
%   The \textsf{xparse} package\\ Document command parser^^A
%   \thanks{This file describes v\ExplFileVersion,
%     last revised \ExplFileDate.}^^A
% }
%
% \author{^^A
%  The \LaTeX3 Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released \ExplFileDate}
%
% \maketitle
%
% \begin{documentation}
%
% The \pkg{xparse} package provides a high-level interface for
% producing document-level commands. In that way, it is intended as
% a replacement for the \LaTeXe{} \cs{newcommand} macro. However,
% \pkg{xparse} works so that the interface to a function (optional
% arguments, stars and mandatory arguments, for example) is separate
% from the internal implementation. \pkg{xparse} provides a normalised
% input for the internal form of a function, independent of the
% document-level argument arrangement.
%
% At present, the functions in \pkg{xparse} which are regarded as
% \enquote{stable} are:
% \begin{itemize}
%   \item \cs{DeclareDocumentCommand}
%   \item \cs{NewDocumentCommand}
%   \item \cs{RenewDocumentCommand}
%   \item \cs{ProvideDocumentCommand}
%   \item \cs{DeclareDocumentEnvironment}
%   \item \cs{NewDocumentEnvironment}
%   \item \cs{RenewDocumentEnvironment}
%   \item \cs{ProvideDocumentEnvironment}
%   \item \cs{DeclareExpandableDocumentCommand}
%   \item \cs{IfNoValue(TF)}
%   \item \cs{IfBoolean(TF)}
% \end{itemize}
% with the other functions currently regarded as \enquote{experimental}. Please
% try all of the commands provided here, but be aware that the
% experimental ones may change or disappear.
%
% \subsection{Specifying arguments}
%
% Before introducing the functions used to create document commands,
% the method for specifying arguments with \pkg{xparse} will be
% illustrated. In order to allow each argument to be defined
% independently, \pkg{xparse} does not simply need to know the
% number of arguments for a function, but also the nature of each
% one. This is done by constructing an \emph{argument specification},
% which defines the number of arguments, the type of each argument
% and any additional information needed for \pkg{xparse} to read the
% user input and properly pass it through to internal functions.
%
% The basic form of the argument specifier is a list of letters, where
% each letter defines a type of argument. As will be described below,
% some of the types need additional information, such as default values.
% The argument types can be divided into two, those which define
% arguments that are mandatory (potentially raising an error if not
% found) and those which define optional arguments. The mandatory types
% are:
% \begin{itemize}[font=\ttfamily]
%   \item[m] A standard mandatory argument, which can either be a single
%     token alone or multiple tokens surrounded by curly braces.
%     Regardless of the input, the argument will be passed to the
%     internal code surrounded by a brace pair. This is the \pkg{xparse}
%     type specifier for a normal \TeX{} argument.
%   \item[l] An argument which reads everything up to the first
%     open group token: in standard \LaTeX{} this is a left brace.
%   \item[r] Reads a \enquote{required} delimited argument, where the
%     delimiters are given as \meta{token1} and \meta{token2}:
%     \texttt{r}\meta{token1}\meta{token2}. If the opening \meta{token}
%     is missing, the default marker |-NoValue-| will be inserted after
%     a suitable error.
%   \item[R] As for \texttt{r}, this is a \enquote{required} delimited
%     argument but has a user-definable recovery \meta{default}, given
%     as \texttt{R}\meta{token1}\meta{token2}\marg{default}.
%   \item[u] Reads an argument \enquote{until} \meta{tokens} are encountered,
%     where the desired \meta{tokens} are given as an argument to the
%     specifier: \texttt{u}\marg{tokens}.
%   \item[v] Reads an argument \enquote{verbatim}, between the following
%     character and its next occurrence, in a way similar to the argument
%     of the \LaTeXe{} command \cs{verb}. Thus a \texttt{v}-type argument
%     is read between two matching tokens, which cannot be any of |%|, |\|,
%     |#|, |{|, |}| or \verb*| |.
%     The verbatim argument can also be enclosed between braces, |{| and |}|.
%     A command with a verbatim
%     argument will not work when it appears within an argument of
%     another function.
% \end{itemize}
% The types which define optional arguments are:
% \begin{itemize}[font=\ttfamily]
%   \item[o] A standard \LaTeX{} optional argument, surrounded with square
%     brackets, which will supply
%     the special |-NoValue-| marker if not given (as described later).
%   \item[d] An optional argument which is delimited by \meta{token1}
%     and \meta{token2}, which are given as arguments:
%     \texttt{d}\meta{token1}\meta{token2}. As with \texttt{o}, if no
%     value is given the special marker |-NoValue-| is returned.
%   \item[O] As for \texttt{o}, but returns \meta{default} if no
%     value is given.  Should be given as \texttt{O}\marg{default}.
%   \item[D] As for \texttt{d}, but returns \meta{default} if no
%     value is given: \texttt{D}\meta{token1}\meta{token2}\marg{default}.
%     Internally, the \texttt{o}, \texttt{d} and \texttt{O} types are
%     short-cuts to an appropriated-constructed \texttt{D} type argument.
%   \item[s] An optional star, which will result in a value
%     \cs{BooleanTrue} if a star is present and \cs{BooleanFalse}
%     otherwise (as described later).
%   \item[t] An optional \meta{token}, which will result in a value
%     \cs{BooleanTrue} if \meta{token} is present and \cs{BooleanFalse}
%     otherwise. Given as \texttt{t}\meta{token}.
%   \item[g] An optional argument given inside a pair of \TeX{} group
%     tokens (in standard \LaTeX, |{| \ldots |}|), which returns
%     |-NoValue-| if not present.
%   \item[G] As for \texttt{g} but returns \meta{default} if no value
%     is given: \texttt{G}\marg{default}.
% \end{itemize}
%
% Using these specifiers, it is possible to create complex input syntax
% very easily. For example, given the argument definition
% `|s o o m O{default}|', the input `|*[Foo]{Bar}|' would be parsed as:
% \begin{itemize}[nolistsep]
%   \item |#1| = |\BooleanTrue|
%   \item |#2| = |Foo|
%   \item |#3| = |-NoValue-|
%   \item |#4| = |Bar|
%   \item |#5| = |default|
% \end{itemize}
% whereas `|[One][Two]{}[Three]|' would be parsed as:
% \begin{itemize}[nolistsep]
%   \item |#1| = |\BooleanFalse|
%   \item |#2| = |One|
%   \item |#3| = |Two|
%   \item |#4| = ||
%   \item |#5| = |Three|
% \end{itemize}
%
% Delimited argument types (\texttt{d}, \texttt{o} and \texttt{r}) are
% defined such that they require matched pairs of delimiters when collecting
% an argument. For example
% \begin{verbatim}
%   \DeclareDocumentCommand{\foo}{o}{#1}
%   \foo[[content]] % #1 = "[content]"
%   \foo[[]         % Error: missing closing "]"
% \end{verbatim}
% Also note that |{| and |}| cannot be used as delimiters as they are used
% by \TeX{} as grouping tokens. Arguments to be grabbed inside these tokens
% must be created as either \texttt{m}- or \texttt{g}-type arguments.
%
% Within delimited arguments, non-balanced or otherwise awkward tokens may
% be included by protecting the entire argument with a brace pair
% \begin{verbatim}
%   \DeclareDocumentCommand{\foo}{o}{#1}
%   \foo[{[}]         % Allowed as the "[" is 'hidden'
% \end{verbatim}
% These braces will be stripped if they surround the \emph{entire} content
% of the optional argument
% \begin{verbatim}
%   \DeclareDocumentCommand{\foo}{o}{#1}
%   \foo[{abc}]         % => "abc"
%   \foo[ {abc}]         % => " {abc}"
% \end{verbatim}
%
% Two more tokens have a special meaning when creating an argument
% specifier. First, \texttt{+} is used to make an argument long (to
% accept paragraph tokens). In contrast to \LaTeXe's \cs{newcommand},
% this applies on an argument-by-argument basis. So modifying the
% example to `|s o o +m O{default}|' means that the mandatory argument
% is now \cs{long}, whereas the optional arguments are not.
%
% Secondly, the token \texttt{>} is used to declare so-called
% \enquote{argument processors}, which can be used to modify the contents of an
% argument before it is passed to the macro definition. The use of
% argument processors is a somewhat advanced topic, (or at least a less
% commonly used feature) and is covered in Section~\ref{sec:processors}.
%
% By default, an argument of type~\texttt{v} must be at most one line.
% Prefixing with \texttt{+} allows line breaks within the argument.  The
% argument is given as a string of characters with category codes~$12$
% or~$13$, except spaces, which have category code~$10$.
%
% \subsection{Spacing and optional arguments}
%
% \TeX{} will find the first argument after a function name irrespective
% of any intervening spaces. This is true for both mandatory and
% optional arguments. So |\foo[arg]| and \verb*|\foo   [arg]| are
% equivalent. Spaces are also ignored when collecting arguments up
% to the last mandatory argument to be collected (as it must exist).
% So after
% \begin{verbatim}
%   \DeclareDocumentCommand \foo { m o m } { ... }
% \end{verbatim}
% the user input |\foo{arg1}[arg2]{arg3}| and
% \verb*|\foo{arg1}  [arg2]   {arg3}| will both be parsed in the same
% way. However, spaces are \emph{not} ignored when parsing optional
% arguments after the last mandatory argument. Thus with
% \begin{verbatim}
%   \DeclareDocumentCommand \foo { m o } { ... }
% \end{verbatim}
% |\foo{arg1}[arg2]| will find an optional argument but
% \verb*|\foo{arg1} [arg2]| will not. This is so that trailing optional
% arguments are not picked up \enquote{by accident} in input.
%
% There is one major exception to the rules listed above: when \pkg{xparse} is used to define what \TeX\ defines as \enquote{control symbols} in which the function name is made up of a single character, such as \enquote{\cmd{\\}}, spaces are \emph{not} ignored directly after them even for mandatory arguments.
%
% \subsection{Required delimited arguments}
%
% The contrast between a delimited (\texttt{D}-type) and \enquote{required
% delimited} (\texttt{R}-type) argument is that an error will be raised if
% the latter is missing. Thus for example
% \begin{verbatim}
%   \DeclareDocumentCommand\foo{r()m}
%   \foo{oops}
% \end{verbatim}
% will lead to an error message being issued. The marker |-NoValue-|
% (\texttt{r}-type) or user-specified default (for \texttt{R}-type) will be
% inserted to allow error recovery.
%
% Users should note that support for required delimited arguments is somewhat
% experimental. Feedback is therefore very welcome on the \texttt{LaTeX-L}
% mailing list.
%
% \subsection{Verbatim arguments}
%
% Arguments of type~\texttt{v} are read in verbatim mode, which will
% result in the grabbed argument consisting of tokens of category codes
% $12$~(\enquote{other}) and $13$~(\enquote{active}), except spaces,
% which are given category code $10$~(\enquote{space}). The argument is
% delimited in a similar manner to the \LaTeXe{} \cs{verb} function.
%
% Functions containing verbatim arguments cannot appear in the arguments
% of other functions. The \texttt{v}~argument specifier includes code to check
% this, and will raise an error if the grabbed argument has already been
% tokenized by \TeX{} in an irreversible way.
%
% Users should note that support for verbatim arguments is somewhat
% experimental. Feedback is therefore very welcome on the \texttt{LaTeX-L}
% mailing list.
%
% \subsection{Declaring commands and environments}
%
% With the concept of an argument specifier defined, it is now
% possible to describe the methods available for creating both
% functions and environments using \pkg{xparse}.
%
% The interface-building commands are the preferred method for
% creating document-level functions in \LaTeX3. All of the functions
% generated in this way are naturally robust (using the \eTeX{}
% \cs{protected} mechanism).
%
% \begin{function}
%   {
%     \DeclareDocumentCommand ,
%     \NewDocumentCommand     ,
%     \RenewDocumentCommand   ,
%     \ProvideDocumentCommand
%   }
%   \begin{syntax}
%     \cs{DeclareDocumentCommand} \meta{Function} \Arg{arg spec} \Arg{code}
%   \end{syntax}
%   This family of commands are used to create a document-level
%   \meta{function}. The argument specification for the function is
%   given by \meta{arg spec},  and expanding
%   to be replaced by the \meta{code}.
% \end{function}
%
%   As an example:
%   \begin{verbatim}
%     \DeclareDocumentCommand \chapter { s o m }
%       {
%         \IfBooleanTF {#1}
%           { \typesetstarchapter {#3} }
%           { \typesetnormalchapter {#2} {#3} }
%       }
%   \end{verbatim}
%   would be a way to define a \cs{chapter} command which would
%   essentially behave like the current \LaTeXe{} command (except that it
%   would accept an optional argument even when a \texttt{*} was parsed).
%   The \cs{typesetnormalchapter} could test its first argument for being
%   |-NoValue-| to see if an optional argument was present.
%
%   The difference between the \cs{Declare\ldots}, \cs{New\ldots}
%   \cs{Renew\ldots} and \cs{Provide\ldots} versions is the behaviour
%   if \meta{function} is already defined.
%   \begin{itemize}
%     \item \cs{DeclareDocumentCommand} will always create the new
%       definition, irrespective of any existing \meta{function} with the
%       same name.
%    \item \cs{NewDocumentCommand} will issue an error if \meta{function}
%      has already been defined.
%    \item \cs{RenewDocumentCommand} will issue an error if \meta{function}
%      has not previously been defined.
%    \item \cs{ProvideDocumentCommand} creates a new definition for
%      \meta{function} only if one has not already been given.
%   \end{itemize}
%
%   \begin{texnote}
%      Unlike \LaTeXe{}'s \cs{newcommand} and relatives, the
%      \cs{DeclareDocumentCommand} family of functions do not prevent creation of
%      functions with names starting \cs{end\ldots}.
%   \end{texnote}
%
% \begin{function}
%   {
%     \DeclareDocumentEnvironment ,
%     \NewDocumentEnvironment     ,
%     \RenewDocumentEnvironment   ,
%     \ProvideDocumentEnvironment
%   }
%   \begin{syntax}
%     \cs{DeclareDocumentEnvironment} \Arg{environment} \Arg{arg spec}
%     ~~\Arg{start code} \Arg{end code}
%   \end{syntax}
%   These commands work in the same way as \cs{DeclareDocumentCommand},
%   etc., but create environments (\cs{begin}|{|\meta{function}|}| \ldots
%   \cs{end}|{|\meta{function}|}|). Both the \meta{start code} and
%   \meta{end code}
%   may access the arguments as defined by \meta{arg spec}.
% \end{function}
%
% \subsection{Testing special values}
%
% Optional arguments created using \pkg{xparse} make use of dedicated
% variables to return information about the nature of the argument
% received.
%
% \begin{function}[EXP,TF]{\IfNoValue}
%   \begin{syntax}
%     \cs{IfNoValueTF} \Arg{argument} \Arg{true code} \Arg{false code}
%     \cs{IfNoValueT} \Arg{argument} \Arg{true code}
%     \cs{IfNoValueF} \Arg{argument} \Arg{false code}
%   \end{syntax}
%   The \cs{IfNoValue(TF)} tests are used to check if \meta{argument} (|#1|,
%   |#2|, \emph{etc.}) is the special |-NoValue-| marker For example
%   \begin{verbatim}
%     \DeclareDocumentCommand \foo { o m }
%       {
%         \IfNoValueTF {#1}
%           { \DoSomethingJustWithMandatoryArgument {#2} }
%           {  \DoSomethingWithBothArguments {#1} {#2}   }
%       }
%   \end{verbatim}
%   will use a different internal function if the optional argument
%   is given than if it is not present.
%
%   Note that three tests are available, depending on which outcome
%   branches are required: \cs{IfNoValueTF}, \cs{IfNoValueT} and
%   \cs{IfNoValueF}.
%
%   As the \cs{IfNoValue(TF)} tests are expandable, it is possible to
%   test these values later, for example at the point of typesetting or
%   in an expansion context.
%
%   It is important to note that |-NoValue-| is constructed such that it
%   will \emph{not} match the simple text input |-NoValue-|, \emph{i.e.}
%   that
%   \begin{verbatim}
%     \IfNoValueTF{-NoValue-}
%   \end{verbatim}
%   will be logically \texttt{false}.
% \end{function}
%
% \begin{function}[EXP,TF]{\IfValue}
%   \begin{syntax}
%     \cs{IfValueTF} \Arg{argument} \Arg{true code} \Arg{false code}
%    \end{syntax}
%   The reverse form of the \cs{IfNoValue(TF)} tests are also available
%   as \cs{IfValue(TF)}. The context will determine which logical
%   form makes the most sense for a given code scenario.
% \end{function}
%
% \begin{variable}{\BooleanFalse, \BooleanTrue}
%   The \texttt{true} and \texttt{false} flags set when searching for
%   an optional token (using \texttt{s} or \texttt{t\meta{token}}) have
%   names which are accessible outside of code blocks.
% \end{variable}
%
% \begin{function}[EXP,TF]{\IfBoolean}
%   \begin{syntax}
%     \cs{IfBooleanTF} \meta{argument} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Used to test if \meta{argument} (|#1|, |#2|, \emph{etc.}) is
%   \cs{BooleanTrue} or \cs{BooleanFalse}. For example
%   \begin{verbatim}
%     \DeclareDocumentCommand \foo { s m }
%       {
%         \IfBooleanTF #1
%           { \DoSomethingWithStar {#2} }
%           { \DoSomethingWithoutStar {#2} }
%       }
%   \end{verbatim}
%   checks for a star as the first argument, then chooses the action to
%   take based on this information.
% \end{function}
%
% \subsection{Argument processors}
% \label{sec:processors}
%
% \pkg{xparse} introduces the idea of an argument processor, which is
% applied to an argument \emph{after} it has been grabbed by the
% underlying system but before it is passed to \meta{code}. An argument
% processor can therefore be used to regularise input at an early stage,
% allowing the internal functions to be completely independent of input
% form. Processors are applied to user input and to default values for
% optional arguments, but \emph{not} to the special \cs{NoValue} marker.
%
% Each argument processor is specified by the syntax
% \texttt{>}\marg{processor} in the argument specification. Processors
% are applied from right to left, so that
% \begin{verbatim}
%   >{\ProcessorB} >{\ProcessorA} m
% \end{verbatim}
% would apply \cs{ProcessorA}
% followed by \cs{ProcessorB} to the tokens grabbed by the \texttt{m}
% argument.
%
% \begin{variable}{\ProcessedArgument}
%   \pkg{xparse} defines a very small set of processor functions. In the
%   main, it is anticipated that code writers will want to create their
%   own processors. These need to accept one argument, which is the
%   tokens as grabbed (or as returned by a previous processor function).
%   Processor functions should return the processed argument as the
%   variable \cs{ProcessedArgument}.
% \end{variable}
%
% \begin{function}{\ReverseBoolean}
%   \begin{syntax}
%     \cs{ReverseBoolean}
%   \end{syntax}
%   This processor reverses the logic of \cs{BooleanTrue} and
%   \cs{BooleanFalse}, so that the example from earlier would become
%   \begin{verbatim}
%     \DeclareDocumentCommand \foo { > { \ReverseBoolean } s m }
%       {
%         \IfBooleanTF #1
%           { \DoSomethingWithoutStar {#2} }
%           { \DoSomethingWithStar {#2} }
%       }
%   \end{verbatim}
% \end{function}
%
% \begin{function}[updated = 2012-02-12]{\SplitArgument}
%   \begin{syntax}
%     \cs{SplitArgument} \Arg{number} \Arg{token}
%   \end{syntax}
%   This processor splits the argument given at each occurrence of the
%   \meta{token} up to a maximum of \meta{number} tokens (thus
%   dividing the input into $\text{\meta{number}} + 1$ parts).
%   An error is given if too many \meta{tokens} are present in the
%   input. The processed input is placed inside
%   $\text{\meta{number}} + 1$ sets of braces for further use.
%   If there are fewer than \Arg{number} of \Arg{tokens} in the argument
%   then \cs{NoValue} markers are added at the end of the processed
%   argument.
%   \begin{verbatim}
%     \DeclareDocumentCommand \foo
%       { > { \SplitArgument { 2 } { ; } } m }
%       { \InternalFunctionOfThreeArguments #1 }
%   \end{verbatim}
%   Any category code $13$ (active) \meta{tokens} will be replaced
%   before the split takes place. Spaces are trimmed at each end of each
%   item parsed.
% \end{function}
%
% \begin{function}{\SplitList}
%   \begin{syntax}
%     \cs{SplitList} \Arg{token(s)}
%   \end{syntax}
%   This processor splits the argument given at each occurrence of the
%   \meta{token(s)} where the number of items is not fixed. Each item is
%   then wrapped in braces within |#1|. The result is that the
%   processed argument can be further processed using a mapping function.
%   \begin{verbatim}
%     \DeclareDocumentCommand \foo
%       { > { \SplitList { ; } } m }
%       { \MappingFunction #1 }
%   \end{verbatim}
%   If only a single \meta{token} is used for the split, any
%   category code $13$ (active) \meta{token} will be replaced
%   before the split takes place.
% \end{function}
%
% \begin{function}[EXP]{\ProcessList}
%   \begin{syntax}
%     \cs{ProcessList} \Arg{list} \Arg{function}
%   \end{syntax}
%   To support \cs{SplitList}, the function \cs{ProcessList} is available
%   to apply a \meta{function} to every entry in a \meta{list}. The
%   \meta{function} should absorb one argument: the list entry. For example
%   \begin{verbatim}
%     \DeclareDocumentCommand \foo
%       { > { \SplitList { ; } } m }
%       { \ProcessList {#1} { \SomeDocumentFunction } }
%   \end{verbatim}
%
%   \textbf{This function is experimental.}
% \end{function}
%
% \begin{function}{\TrimSpaces}
%   \begin{syntax}
%     \cs{TrimSpaces}
%   \end{syntax}
%   Removes any leading and trailing spaces (tokens with character code~$32$
%   and category code~$10$) for the ends of the argument. Thus for example
%   declaring a function
%   \begin{verbatim}
%     \DeclareDocumentCommand \foo
%       { > { \TrimSpaces } m }
%       { \showtokens {#1} }
%   \end{verbatim}
%   and using it in a document as
%   \begin{verbatim}
%     \foo{ hello world }
%   \end{verbatim}
%   will show \texttt{hello world} at the terminal, with the space at each
%   end removed. \cs{TrimSpaces} will remove multiple spaces from the ends of
%   the input in cases where these have been included such that the standard
%   \TeX{} conversion of multiple spaces to a single space does not apply.
%
%   \textbf{This function is experimental.}
% \end{function}
%
% \subsection{Fully-expandable document commands}
%
% There are \emph{very rare} occasion when it may be useful to create
% functions using a fully-expandable argument grabber. To support this,
% \pkg{xparse} can create expandable functions as well as the usual
% robust ones. This imposes a number of restrictions on the nature of
% the arguments accepted by a function, and the code it implements.
% This facility should only be used when \emph{absolutely necessary};
% if you do not understand when this might be, \emph{do not use these
% functions}!
%
% \begin{function}{\DeclareExpandableDocumentCommand}
%   \begin{syntax}
%     \cs{DeclareExpandableDocumentCommand}
%     ~~~~\meta{function} \Arg{arg spec} \Arg{code}
%   \end{syntax}
%   This command is used to create a document-level \meta{function},
%   which will grab its arguments in a fully-expandable manner. The
%   argument specification for the function is given by \meta{arg spec},
%   and the function will execute \meta{code}. In  general, \meta{code} will
%   also be fully expandable, although it is possible that this will
%   not be the case (for example, a function for use in a table might
%   expand so that \cs{omit} is the first non-expandable token).
%
%   Parsing arguments expandably imposes a number of restrictions on
%   both the type of arguments that can be read and the error checking
%   available:
%   \begin{itemize}
%     \item The last argument (if any are present) must be one of the
%       mandatory types \texttt{m} or \texttt{r}.
%     \item All arguments are either short or long: it is not possible
%       to mix short and long argument types.
%     \item The mandatory argument types \texttt{l} and \texttt{u} are
%       not available.
%     \item The \enquote{optional group} argument types \texttt{g} and
%       \texttt{G} are not available.
%     \item The \enquote{verbatim} argument type \texttt{v} is not available.
%     \item It is not possible to differentiate between, for example
%       |\foo[| and |\foo{[}|: in both cases the \texttt{[} will be
%       interpreted as the start of an optional argument. As a result
%       result, checking for optional arguments is less robust than
%       in the standard version.
%   \end{itemize}
%   \pkg{xparse} will issue an error if an argument specifier is given
%   which does not conform to the first three requirements. The last
%   item is an issue when the function is used, and so is beyond the
%  scope of \pkg{xparse} itself.
% \end{function}
%
% \subsection{Access to the argument specification}
%
% The argument specifications for document commands and environments are
% available for examination and use.
%
% \begin{function}{\GetDocumentCommandArgSpec, \GetDocumentEnvironmentArgSpec}
%   \begin{syntax}
%     \cs{GetDocumentCommandArgSpec} \meta{function}
%     \cs{GetDocumentEnvironmentArgSpec} \meta{environment}
%   \end{syntax}
%   These functions transfer the current argument specification for the
%   requested \meta{function} or \meta{environment} into the token list
%   variable \cs{ArgumentSpecification}. If the \meta{function} or
%   \meta{environment} has no known argument specification then an error
%   is issued. The assignment to \cs{ArgumentSpecification} is local to
%   the current \TeX{} group.
% \end{function}
%
% \begin{function}
%   {\ShowDocumentCommandArgSpec,  \ShowDocumentEnvironmentArgSpec}
%   \begin{syntax}
%     \cs{ShowDocumentCommandArgSpec} \meta{function}
%     \cs{ShowDocumentEnvironmentArgSpec} \meta{environment}
%   \end{syntax}
%   These functions show the current argument specification for the
%   requested \meta{function} or \meta{environment} at the terminal. If
%   the \meta{function} or \meta{environment} has no known argument
%   specification then an error is issued.
% \end{function}
%
% \section{Load-time options}
%
% \DescribeOption{log-declarations}
% The package recognises the load-time option \texttt{log-declarations},
% which is a key--value option taking the value \texttt{true} and
% \texttt{false}. By default, the option is set to \texttt{true}, meaning
% that each command or environment declared is logged. By loading
% \pkg{xparse} using
% \begin{verbatim}
%   \usepackage[log-declarations=false]{xparse}
% \end{verbatim}
% this may be suppressed and no information messages are produced.
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{xparse} implementation}
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
%    \begin{macrocode}
%<@@=xparse>
%    \end{macrocode}
%
%    \begin{macrocode}
\ProvidesExplPackage
  {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
%    \end{macrocode}
%
% \subsection{Variables and constants}
%
% \begin{variable}{\c_@@_no_value_tl}
%   A special \enquote{awkward} token list: it contains two |-|~tokens with
%   different category codes. This is used as the marker for nothing being
%   returned when no optional argument is given.
%    \begin{macrocode}
\group_begin:
\char_set_lccode:nn { `\Q } { `\- }
\char_set_lccode:nn { `\N } { `\N }
\char_set_lccode:nn { `\V } { `\V }
\tl_to_lowercase:n
  {
    \group_end:
    \tl_const:Nn \c_@@_no_value_tl { QNoValue- }
  }
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\c_@@_shorthands_prop}
%   Shorthands are stored as a property list: this is set up here as it
%   is a constant.
%    \begin{macrocode}
\prop_new:N \c_@@_shorthands_prop
\prop_put:Nnn \c_@@_shorthands_prop { o } { d[] }
\prop_put:Nnn \c_@@_shorthands_prop { O } { D[] }
\prop_put:Nnn \c_@@_shorthands_prop { s } { t* }
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\c_@@_special_chars_seq}
%   In \IniTeX{} mode, we store special characters in a sequence.
%   Maybe |$| or |&| will have to be added later.
%    \begin{macrocode}
%<*initex>
\seq_new:N \c_@@_special_chars_seq
\seq_set_split:Nnn \c_@@_special_chars_seq { }
  { \  \\ \{ \} \# \^ \_ \% \~ }
%</initex>
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_all_long_bool}
%   For expandable commands, all arguments have the same long status, but this
%   needs to be checked. A flag is therefore needed to track whether arguments
%   are long at all.
%    \begin{macrocode}
\bool_new:N \l_@@_all_long_bool
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_args_tl}
%   Token list variable for grabbed arguments.
%    \begin{macrocode}
\tl_new:N \l_@@_args_tl
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_command_arg_specs_prop}
%   Used to record all document commands created, and the argument
%   specifications that go with these.
%    \begin{macrocode}
\prop_new:N \l_@@_command_arg_specs_prop
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_current_arg_int}
%   The number of the current argument being set up: this is used for creating
%   the expandable auxiliary functions, and also to indicate if all arguments
%   are \texttt{m}-type.
%    \begin{macrocode}
\int_new:N \l_@@_current_arg_int
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_environment_bool}
%   Generating environments uses the same mechanism as generating functions.
%   However, full processing of arguments is always needed for environments,
%   and so the function-generating code needs to know this.
%    \begin{macrocode}
\bool_new:N \l_@@_environment_bool
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_environment_arg_specs_prop}
%   Used to record all document environment created, and the argument
%   specifications that go with these.
%    \begin{macrocode}
\prop_new:N \l_@@_environment_arg_specs_prop
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_expandable_bool}
%   Used to indicate if an expandable command is begin generated, as this
%   affects both the acceptable argument types and how they are implemented.
%    \begin{macrocode}
\bool_new:N \l_@@_expandable_bool
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_expandable_aux_name_tl}
%   Used to create pretty-printing names for the auxiliaries: although the
%   immediate definition does not vary, the full expansion does and so it
%   does not count as a constant.
%    \begin{macrocode}
\tl_new:N \l_@@_expandable_aux_name_tl
\tl_set:Nn \l_@@_expandable_aux_name_tl
  {
    \l_@@_function_tl \c_space_tl
    ( arg~ \int_use:N \l_@@_current_arg_int )
  }
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_fn_tl}
%   For passing the pre-formed name of the auxiliary to be used as the
%   parsing function.
%    \begin{macrocode}
\tl_new:N \l_@@_fn_tl
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_function_tl}
%   Holds the control sequence name of the function currently being
%   defined: used to avoid passing this as an argument and to avoid repeated
%   use of \cs{cs_to_str:N}.
%    \begin{macrocode}
\tl_new:N \l_@@_function_tl
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_long_bool}
%   Used to indicate that an argument is long: this is used on a per-argument
%   basis for non-expandable functions, or for the entire set of arguments
%   when working expandably.
%    \begin{macrocode}
\bool_new:N \l_@@_long_bool
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_m_args_int}
%   The number of \texttt{m} arguments: if this is the same as the total
%   number of arguments, then a short-cut can be taken in the creation of
%   the grabber code.
%    \begin{macrocode}
\int_new:N \l_@@_m_args_int
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_mandatory_args_int}
%   Holds the total number of mandatory arguments for a function, which is
%   needed to tell whether further mandatory arguments follow an optional
%   one.
%    \begin{macrocode}
\int_new:N \l_@@_mandatory_args_int
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_processor_bool}
%   Indicates that the current argument will be followed by one or more
%   processors.
%    \begin{macrocode}
\bool_new:N \l_@@_processor_bool
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_processor_int}
%   In the grabber routine, each processor is saved with a number
%   recording the order it was found in. The total is then used to work
%   back through the grabbers so they apply to the argument right to left.
%    \begin{macrocode}
\int_new:N \l_@@_processor_int
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_signature_tl}
%   Used when constructing the signature (code for argument grabbing) to
%   hold what will become the implementation of the main function.
%    \begin{macrocode}
\tl_new:N \l_@@_signature_tl
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_tmp_tl}
%   Scratch space.
%    \begin{macrocode}
\tl_new:N \l_@@_tmp_tl
%    \end{macrocode}
% \end{variable}
%
% \subsection{Declaring commands and environments}
%
% \begin{macro}{\@@_declare_cmd:Nnn, \@@_declare_expandable_cmd:Nnn}
% \begin{macro}[aux]{\@@_declare_cmd_aux:Nnn}
% \begin{macro}[int]
%   {\@@_declare_cmd_internal:Nnn, \@@_declare_cmd_internal:cnx}
%   The main functions for creating commands set the appropriate flag then
%   use the same internal code to do the definition.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_declare_cmd:Nnn
  {
    \bool_set_false:N \l_@@_expandable_bool
    \@@_declare_cmd_aux:Nnn
  }
\cs_new_protected_nopar:Npn \@@_declare_expandable_cmd:Nnn
  {
    \bool_set_true:N \l_@@_expandable_bool
    \@@_declare_cmd_aux:Nnn
  }
%    \end{macrocode}
%  The first stage is to log information, both for the user in the log and
%  for programmatic use in a property list of all declared commands.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_declare_cmd_aux:Nnn #1#2
  {
    \cs_if_exist:NTF #1
      {
        \__msg_kernel_info:nnxx { xparse } { redefine-command }
          { \token_to_str:N #1 } { \tl_to_str:n {#2} }
      }
      {
        \__msg_kernel_info:nnxx { xparse } { define-command }
          { \token_to_str:N #1 } { \tl_to_str:n {#2} }
      }
    \prop_put:Nnn \l_@@_command_arg_specs_prop {#1} {#2}
    \bool_set_false:N \l_@@_environment_bool
    \@@_declare_cmd_internal:Nnn #1 {#2}
  }
%    \end{macrocode}
%   The real business of defining a document command starts with setting up
%   the appropriate name, then counting up the number of mandatory arguments.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_declare_cmd_internal:Nnn #1#2#3
  {
    \tl_set:Nx \l_@@_function_tl { \cs_to_str:N #1 }
    \@@_count_mandatory:n {#2}
    \@@_prepare_signature:n {#2}
    \int_compare:nNnTF \l_@@_current_arg_int = \l_@@_m_args_int
      {
        \bool_if:NTF \l_@@_environment_bool
          { \@@_declare_cmd_mixed:Nn #1 {#3} }
          { \@@_declare_cmd_all_m:Nn #1 {#3} }
      }
      { \@@_declare_cmd_mixed:Nn #1 {#3} }
    \@@_break_point:n {#2}
  }
\cs_generate_variant:Nn \@@_declare_cmd_internal:Nnn { cnx }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_break_point:n}
%   A marker used to escape from creating a definition if necessary.
%    \begin{macrocode}
\cs_new_eq:NN \@@_break_point:n \use_none:n
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_declare_cmd_all_m:Nn, \@@_declare_cmd_mixed:Nn}
% \begin{macro}[aux]
%   {\@@_declare_cmd_mixed_aux:Nn, \@@_declare_cmd_mixed_expandable:Nn}
%   When all of the arguments to grab are simple \texttt{m}-type, a short
%   cut can be taken to provide only a single function. In the case of
%   expandable commands, this can also happen for \texttt{+m} (as all arguments
%   in this case must be long).
%    \begin{macrocode}
\cs_new_protected:Npn \@@_declare_cmd_all_m:Nn #1#2
  {
    \cs_generate_from_arg_count:Ncnn #1
      {
        cs_set
        \bool_if:NF \l_@@_expandable_bool { _protected }
        \bool_if:NF \l_@@_all_long_bool { _nopar }
        :Npn
      }
      \l_@@_current_arg_int {#2}
  }
%    \end{macrocode}
%   In the case of mixed arguments, any remaining \texttt{m}-type ones are
%   first added to the signature, then the appropriate auxiliary is called.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_declare_cmd_mixed:Nn
  {
    \bool_if:NTF \l_@@_expandable_bool
      { \@@_declare_cmd_mixed_expandable:Nn }
      { \@@_declare_cmd_mixed_aux:Nn }
   }
%    \end{macrocode}
%   Creating standard functions with mixed arg.~specs sets up the main function
%   to zero the number of processors, set the name of the function (for the
%   grabber) and clears the list of grabbed arguments.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_declare_cmd_mixed_aux:Nn #1#2
  {
    \@@_flush_m_args:
    \cs_generate_from_arg_count:cNnn
      { \l_@@_function_tl \c_space_tl code }
      \cs_set_protected:Npn \l_@@_current_arg_int {#2}
    \cs_set_protected_nopar:Npx #1
      {
        \int_zero:N \l_@@_processor_int
        \tl_set:Nn \exp_not:N \l_@@_args_tl
          { \exp_not:c { \l_@@_function_tl \c_space_tl code } }
        \tl_set:Nn \exp_not:N \l_@@_fn_tl
          { \exp_not:c { \l_@@_function_tl \c_space_tl } }
        \exp_not:o \l_@@_signature_tl
        \exp_not:N \l_@@_args_tl
      }
  }
\cs_new_protected:Npn \@@_declare_cmd_mixed_expandable:Nn #1#2
  {
    \cs_generate_from_arg_count:cNnn
      { \l_@@_function_tl \c_space_tl code }
      \cs_set:Npn \l_@@_current_arg_int {#2}
    \cs_set_nopar:Npx #1
      {
        \exp_not:o \l_@@_signature_tl
        \exp_not:N \@@_grab_expandable_end:wN
        \exp_not:c { \l_@@_function_tl \c_space_tl code }
        \exp_not:N \q_@@
        \exp_not:c { \l_@@_function_tl \c_space_tl }
      }
    \bool_if:NTF \l_@@_all_long_bool
      { \cs_set:cpx }
      { \cs_set_nopar:cpx }
      { \l_@@_function_tl \c_space_tl } ##1##2 { ##1 {##2} }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_declare_env:nnnn}
% \begin{macro}[int]{\@@_declare_env_internal:nnnn}
%   The lead-off to creating an environment is much the same as that for
%   creating a command: issue the appropriate message, store the argument
%   specification then hand off to an internal function.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_declare_env:nnnn #1#2
  {
%<*initex>
    \cs_if_exist:cTF { environment~ #1 }
%</initex>
%<*package>
    \cs_if_exist:cTF {#1}
%</package>
      {
        \__msg_kernel_info:nnxx { xparse } { redefine-environment }
          {#1} { \tl_to_str:n {#2} }
      }
      {
        \__msg_kernel_info:nnxx { xparse } { define-environment }
          {#1} { \tl_to_str:n {#2} }
      }
    \prop_put:Nnn \l_@@_environment_arg_specs_prop {#1} {#2}
    \bool_set_false:N \l_@@_expandable_bool
    \bool_set_true:N \l_@@_environment_bool
    \@@_declare_env_internal:nnnn {#1} {#2}
  }
%    \end{macrocode}
%   Creating a document environment requires a few more steps than creating
%   a single command. In order to pass the arguments of the command to the
%   end of the function, it is necessary to store the grabbed arguments.
%   To do that, the function used at the end of the environment has to be
%   redefined to contain the appropriate information. To minimize the amount
%   of expansion at point of use, the code here is expanded now as well as
%   when used.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_declare_env_internal:nnnn #1#2#3#4
  {
    \@@_declare_cmd_internal:cnx { environment~ #1 } {#2}
      {
        \cs_set_protected_nopar:Npx \exp_not:c { environment~ #1 ~end~aux }
          {
            \exp_not:c { environment~ #1~end~aux~ }
            \exp_not:n { \tl_tail:N \l_@@_args_tl }
          }
        \exp_not:n {#3}
      }
    \cs_set_protected_nopar:cpx { environment~ #1 ~end }
      { \exp_not:c { environment~ #1 ~end~aux } }
    \cs_generate_from_arg_count:cNnn
      { environment~ #1 ~end~aux~ } \cs_set_protected:Npn
      \l_@@_current_arg_int {#4}
%<*package>
    \cs_set_eq:cc {#1}       { environment~ #1 }
    \cs_set_eq:cc { end #1 } { environment~ #1 ~end }
%</package>
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Counting mandatory arguments}
%
% \begin{macro}{\@@_count_mandatory:n}
% \begin{macro}{\@@_count_mandatory:N}
% \begin{macro}[aux]{\@@_count_mandatory:N}
%   To count up mandatory arguments before the main parsing run, the same
%   approach is used. First, check if the current token is a short-cut for
%   another argument type. If it is, expand it and loop again. If not, then
%   look for a \enquote{counting} function to check the argument type. No error
%   is raised here if one is not found as one will be raised by later code.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_count_mandatory:n #1
  {
    \int_zero:N \l_@@_mandatory_args_int
    \@@_count_mandatory:N #1
      \q_recursion_tail \q_recursion_tail \q_recursion_tail \q_recursion_stop
  }
\cs_new_protected:Npn \@@_count_mandatory:N #1
  {
    \quark_if_recursion_tail_stop:N #1
    \prop_get:NnNTF \c_@@_shorthands_prop {#1} \l_@@_tmp_tl
      { \exp_after:wN \@@_count_mandatory:N \l_@@_tmp_tl }
      { \@@_count_mandatory_aux:N #1 }
  }
\cs_new_protected:Npn \@@_count_mandatory_aux:N #1
  {
    \cs_if_free:cTF { @@_count_type_ \token_to_str:N #1 :w }
      { \@@_count_type_m:w }
      { \use:c { @@_count_type_ \token_to_str:N #1 :w } }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \@@_count_type_>:w,
%     \@@_count_type_+:w,
%     \@@_count_type_d:w,
%     \@@_count_type_D:w,
%     \@@_count_type_g:w,
%     \@@_count_type_G:w,
%     \@@_count_type_m:w,
%     \@@_count_type_t:w,
%     \@@_count_type_u:w
%   }
%   For counting the mandatory arguments, a function is provided for each
%   argument type that will mop any extra arguments and call the loop function.
%   Only the counting functions for mandatory arguments actually do anything:
%   the rest are simply there to ensure the loop continues correctly. There are
%   no count functions for \texttt{l} or \texttt{v} argument types as they are
%   exactly the same as \texttt{m}, and so a little code can be saved.
%
%   The second thing that can be done here is to check that the signature is
%   actually valid, such that all of the various argument types have the
%   correct number of data items associated with them.  If this fails to be
%   the case, the entire set up is abandoned to avoid any strange internal
%   errors. The opportunity is also taken to make sure that where a single
%   token is required, one has actually been supplied.
%    \begin{macrocode}
\cs_new_protected:cpn { @@_count_type_>:w } #1
  {
    \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn }
    \@@_count_mandatory:N
  }
\cs_new_protected_nopar:cpn { @@_count_type_+:w }
  { \@@_count_mandatory:N }
\cs_new_protected:Npn \@@_count_type_d:w #1#2
  {
    \@@_single_token_check:n {#1}
    \@@_single_token_check:n {#2}
    \quark_if_recursion_tail_stop_do:Nn #2 { \@@_bad_arg_spec:wn }
    \@@_count_mandatory:N
  }
\cs_new_protected:Npn \@@_count_type_D:w #1#2#3
  {
    \@@_single_token_check:n {#1}
    \@@_single_token_check:n {#2}
    \quark_if_recursion_tail_stop_do:nn {#3} { \@@_bad_arg_spec:wn }
    \@@_count_mandatory:N
  }
\cs_new_protected_nopar:Npn \@@_count_type_g:w
  { \@@_count_mandatory:N }
\cs_new_protected:Npn \@@_count_type_G:w #1
  {
    \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn }
    \@@_count_mandatory:N
  }
\cs_new_protected_nopar:Npn \@@_count_type_m:w
  {
    \int_incr:N \l_@@_mandatory_args_int
    \@@_count_mandatory:N
  }
\cs_new_protected:Npn \@@_count_type_r:w #1#2
  {
    \@@_single_token_check:n {#1}
    \@@_single_token_check:n {#2}
    \quark_if_recursion_tail_stop_do:Nn #2 { \@@_bad_arg_spec:wn }
    \int_incr:N \l_@@_mandatory_args_int
    \@@_count_mandatory:N
  }
\cs_new_protected:Npn \@@_count_type_R:w #1#2#3
  {
    \@@_single_token_check:n {#1}
    \@@_single_token_check:n {#2}
    \quark_if_recursion_tail_stop_do:nn {#3} { \@@_bad_arg_spec:wn }
    \int_incr:N \l_@@_mandatory_args_int
    \@@_count_mandatory:N
  }
\cs_new_protected:Npn \@@_count_type_t:w #1
  {
    \@@_single_token_check:n {#1}
    \quark_if_recursion_tail_stop_do:Nn #1 { \@@_bad_arg_spec:wn }
    \@@_count_mandatory:N
  }
\cs_new_protected:Npn \@@_count_type_u:w #1
  {
    \quark_if_recursion_tail_stop_do:nn {#1} { \@@_bad_arg_spec:wn }
    \int_incr:N \l_@@_mandatory_args_int
    \@@_count_mandatory:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_single_token_check:n}
% \begin{macro}[aux]{\@@_single_token_check_aux:nwn}
%   A spin-out function to check that what should be single tokens really
%   are single tokens.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_single_token_check:n #1
  {
    \tl_if_single:nF {#1}
      { \@@_single_token_check_aux:nwn {#1} }
  }
\cs_new_protected:Npn \@@_single_token_check_aux:nwn
  #1#2 \@@_break_point:n #3
  {
    \__msg_kernel_error:nnx { xparse } { not-single-token }
      { \tl_to_str:n {#1} } { \tl_to_str:n {#3} }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_bad_arg_spec:wn}
%   If the signature is wrong, this provides an escape from the entire
%   definition process.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_bad_arg_spec:wn #1 \@@_break_point:n #2
  { \__msg_kernel_error:nnx { xparse } { bad-arg-spec } { \tl_to_str:n {#2} } }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Preparing the signature: general mechanism}
%
% \begin{macro}{\@@_prepare_signature:n}
% \begin{macro}{\@@_prepare_signature:N}
% \begin{macro}{\@@_prepare_signature_bypass:N}
% \begin{macro}[aux]{\@@_prepare_signature_add:N}
%   Actually creating the signature uses the same loop approach as counting
%   up mandatory arguments. There are first a number of variables which need
%   to be set to track what is going on.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_prepare_signature:n #1
  {
    \bool_set_false:N \l_@@_all_long_bool
    \int_zero:N \l_@@_current_arg_int
    \bool_set_false:N \l_@@_long_bool
    \int_zero:N \l_@@_m_args_int
    \bool_set_false:N \l_@@_processor_bool
    \tl_clear:N \l_@@_signature_tl
    \@@_prepare_signature:N #1 \q_recursion_tail \q_recursion_stop
  }
%    \end{macrocode}
%  The main looping function does not take an argument,but carries out the
%  reset on the processor boolean. This is split off from the rest of the
%  process so that when actually setting up processors the flag-reset can
%  be bypassed.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_prepare_signature:N
  {
    \bool_set_false:N \l_@@_processor_bool
    \@@_prepare_signature_bypass:N
  }
\cs_new_protected:Npn \@@_prepare_signature_bypass:N #1
  {
    \quark_if_recursion_tail_stop:N #1
    \prop_get:NnNTF \c_@@_shorthands_prop {#1} \l_@@_tmp_tl
      { \exp_after:wN \@@_prepare_signature:N \l_@@_tmp_tl }
      {
        \int_incr:N \l_@@_current_arg_int
        \@@_prepare_signature_add:N #1
      }
  }
%    \end{macrocode}
%  For each known argument type there is an appropriate function to actually
%  do the addition to the signature. These are separate for expandable and
%  standard functions, as the approaches are different. Of course, if the type
%  is not known at all then a fall-back is needed.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_prepare_signature_add:N #1
  {
    \cs_if_exist_use:cF
      {
         @@_add
         \bool_if:NT \l_@@_expandable_bool { _expandable }
         _type_  \token_to_str:N #1 :w
      }
      {
        \__msg_kernel_error:nnx { xparse } { unknown-argument-type }
          { \token_to_str:N #1 }
        \bool_if:NTF \l_@@_expandable_bool
          { \@@_add_expandable_type_m:w }
          { \@@_add_type_m:w }
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Setting up a standard signature}
%
% All of the argument-adding functions work in essentially the same
% way, except the one for \texttt{m} arguments. Any collected \texttt{m}
% arguments are added to the signature, then the appropriate grabber
% is added to the signature. Some of the adding functions also pick up
% one or more arguments, and are also added to the signature. All of the
% functions then call the loop function \cs{@@_prepare_signature:N}.
%
% \begin{macro}{\@@_add_type_+:w}
%   Making the next argument long means setting the flag and knocking one back
%   off the total argument count. The \texttt{m} arguments are recorded here as
%   this has to be done for every case where there is then a long argument.
%    \begin{macrocode}
\cs_new_protected_nopar:cpn { @@_add_type_+:w }
  {
    \@@_flush_m_args:
    \bool_set_true:N \l_@@_long_bool
    \int_decr:N \l_@@_current_arg_int
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_type_>:w}
%   When a processor is found, the function \cs{@@_process_arg:n} is added
%   to the signature along with the processor code itself. When the signature
%   is used, the code will be added to an execution list by
%   \cs{@@_process_arg:n}. Here, the loop calls
%   \cs{@@_prepare_signature_bypass:N} rather than
%   \cs{@@_prepare_signature:N} so that the flag is not reset.
%    \begin{macrocode}
\cs_new_protected:cpn { @@_add_type_>:w } #1
  {
    \bool_set_true:N \l_@@_processor_bool
    \@@_flush_m_args:
    \int_decr:N \l_@@_current_arg_int
    \tl_put_right:Nn \l_@@_signature_tl { \@@_process_arg:n {#1} }
    \@@_prepare_signature_bypass:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_type_d:w, \@@_add_type_D:w}
%   To save on repeated code, \texttt{d} is actually turned into the same
%   grabber as is used by \texttt{D}, by putting the |-NoValue-| default in
%   the correct place.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_add_type_d:w #1#2
  { \exp_args:NNNo \@@_add_type_D:w #1 #2 \c_@@_no_value_tl }
\cs_new_protected:Npn \@@_add_type_D:w #1#2#3
  {
    \@@_flush_m_args:
    \@@_add_grabber_optional:N D
    \tl_put_right:Nn \l_@@_signature_tl { #1 #2 {#3} }
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_type_g:w}
%   The \texttt{g} type is simply an alias for \texttt{G} with the correct
%   default built-in.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_type_g:w
  { \exp_args:No \@@_add_type_G:w \c_@@_no_value_tl }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_type_G:w}
%   For the \texttt{G} type, the grabber and the default are added to the
%   signature.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_add_type_G:w #1
  {
    \@@_flush_m_args:
    \@@_add_grabber_optional:N G
    \tl_put_right:Nn \l_@@_signature_tl { {#1} }
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_type_l:w}
%   Finding \texttt{l} arguments is very simple: there is nothing to do
%   other than add the grabber.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_type_l:w
  {
    \@@_flush_m_args:
    \@@_add_grabber_mandatory:N l
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_type_m:w}
%   The \texttt{m} type is special as short arguments which are not
%   post-processed are simply counted at this stage. Thus there is a check
%   to see if either of these cases apply. If so, a one-argument grabber
%   is added to the signature. On the other hand, if a standard short
%   argument is required it is simply counted at this stage, to be
%   added later using \cs{@@_flush_m_args:}.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_type_m:w
  {
    \bool_if:nTF { \l_@@_long_bool || \l_@@_processor_bool }
      {
        \@@_flush_m_args:
        \@@_add_grabber_mandatory:N m
      }
      { \int_incr:N \l_@@_m_args_int }
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_type_r:w, \@@_add_type_R:w}
%   The \texttt{r}- and \texttt{R}-type arguments are very similar to the
%   \texttt{d}- and \texttt{D}-types.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_add_type_r:w #1#2
  { \exp_args:NNNo \@@_add_type_R:w #1 #2 \c_@@_no_value_tl }
\cs_new_protected:Npn \@@_add_type_R:w #1#2#3
  {
    \@@_flush_m_args:
    \@@_add_grabber_mandatory:N R
    \tl_put_right:Nn \l_@@_signature_tl { #1 #2 {#3} }
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_type_t:w}
%   Setting up a \texttt{t} argument means collecting one token for the test,
%   and adding it along with the grabber to the signature.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_add_type_t:w #1
  {
    \@@_flush_m_args:
    \@@_add_grabber_optional:N t
    \tl_put_right:Nn \l_@@_signature_tl { #1 }
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_type_u:w}
%   At the set up stage, the \texttt{u} type argument is identical to the
%   \texttt{G} type except for the name of the grabber function.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_add_type_u:w #1
  {
    \@@_flush_m_args:
    \@@_add_grabber_mandatory:N u
    \tl_put_right:Nn \l_@@_signature_tl { {#1} }
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_type_v:w}
%   At this stage, the \texttt{v} argument is identical to \texttt{l}.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_type_v:w
  {
    \@@_flush_m_args:
    \@@_add_grabber_mandatory:N v
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_flush_m_args:}
%   As \texttt{m} arguments are simply counted, there is a need to add
%   them to the token register in a block. As this function can only
%   be called if something other than \texttt{m} turns up, the flag can
%   be switched here. The total number of mandatory arguments added to
%   the signature is also decreased by the appropriate amount.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_flush_m_args:
  {
    \int_compare:nNnT \l_@@_m_args_int > \c_zero
      {
        \tl_put_right:Nx \l_@@_signature_tl
           { \exp_not:c { @@_grab_m_ \int_use:N \l_@@_m_args_int :w } }
        \int_set:Nn \l_@@_mandatory_args_int
          { \l_@@_mandatory_args_int - \l_@@_m_args_int }
      }
    \int_zero:N \l_@@_m_args_int
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_grabber_mandatory:N}
% \begin{macro}{\@@_add_grabber_optional:N}
%   To keep the various checks needed in one place, adding the grabber to
%   the signature is done here. For mandatory arguments, the only question
%   is whether to add a long grabber. For optional arguments, there is
%   also a check to see if any mandatory arguments are still to be added.
%   This is used to determine whether to skip spaces or not where
%   searching for the argument.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_grabber_mandatory:N #1
  {
    \tl_put_right:Nx \l_@@_signature_tl
      {
        \exp_not:c
          { @@_grab_ #1 \bool_if:NT \l_@@_long_bool { _long } :w }
      }
    \bool_set_false:N \l_@@_long_bool
    \int_decr:N \l_@@_mandatory_args_int
  }
\cs_new_protected_nopar:Npn \@@_add_grabber_optional:N #1
  {
    \tl_put_right:Nx \l_@@_signature_tl
      {
        \exp_not:c
          {
            @@_grab_ #1
            \bool_if:NT \l_@@_long_bool { _long }
            \int_compare:nNnF \l_@@_mandatory_args_int > \c_zero
              { _trailing }
            :w
          }
      }
    \bool_set_false:N \l_@@_long_bool
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Setting up expandable types}
%
% The approach here is not dissimilar to that for standard types, although
% types which are not supported in expandable functions give an error. There is
% also a need to define the per-function auxiliaries: this is done here, while
% the general grabbers are dealt with later.
%
% \begin{macro}{\@@_add_expandable_type_+:w}
%   Check that a plus is given only if it occurs for every argument.
%    \begin{macrocode}
\cs_new_protected_nopar:cpn { @@_add_expandable_type_+:w }
  {
    \bool_set_true:N \l_@@_long_bool
    \int_compare:nNnTF \l_@@_current_arg_int = \c_one
      { \bool_set_true:N \l_@@_all_long_bool }
      {
        \bool_if:NF \l_@@_all_long_bool
          { \__msg_kernel_error:nn { xparse } { inconsistent-long } }
      }
    \int_decr:N \l_@@_current_arg_int
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_expandable_type_>:w}
%   No processors in expandable arguments, so this issues an error.
%    \begin{macrocode}
\cs_new_protected:cpn { @@_add_expandable_type_>:w } #1
  {
    \__msg_kernel_error:nnx { xparse } { processor-in-expandable }
      { \token_to_str:c { \l_@@_function_tl } }
    \int_decr:N \l_@@_current_arg_int
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_expandable_type_d:w}
% \begin{macro}{\@@_add_expandable_type_D:w}
% \begin{macro}{\@@_add_expandable_type_D_aux:NNn}
% \begin{macro}{\@@_add_expandable_type_D_aux:Nn}
%   The set up for \texttt{d}- and \texttt{D}-type arguments is the same,
%   and involves constructing a rather complex auxiliary which is used
%   repeatedly when grabbing. There is an auxiliary here so that the
%   \texttt{R}-type can share code readily.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_add_expandable_type_d:w #1#2
  {
    \exp_args:NNNo
      \@@_add_expandable_type_D:w #1 #2 \c_@@_no_value_tl
  }
\cs_new_protected:Npn \@@_add_expandable_type_D:w #1#2
  {
    \token_if_eq_meaning:NNTF #1 #2
      {
        \@@_add_expandable_grabber_optional:n { D_alt }
        \@@_add_expandable_type_D_aux:Nn #1
      }
      {
        \@@_add_expandable_grabber_optional:n { D }
        \@@_add_expandable_type_D_aux:NNn #1#2
      }
  }
\cs_new_protected:Npn \@@_add_expandable_type_D_aux:NNn #1#2#3
  {
    \bool_if:NTF \l_@@_all_long_bool
      { \cs_set:cpx }
      { \cs_set_nopar:cpx }
      { \l_@@_expandable_aux_name_tl } ##1 ##2 #1 ##3 \q_@@ ##4 #2
      { ##1 {##2} {##3} {##4} }
    \tl_put_right:Nx \l_@@_signature_tl
      {
        \exp_not:c  { \l_@@_expandable_aux_name_tl }
        \exp_not:n { #1 #2 {#3} }
      }
    \bool_set_false:N \l_@@_long_bool
    \@@_prepare_signature:N
  }
%    \end{macrocode}
%  This route is needed if the two delimiting tokens are identical: in
%  contrast to the non-expandable route, the grabber here has to act
%  differently for this case.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_add_expandable_type_D_aux:Nn #1#2
  {
    \bool_if:NTF \l_@@_all_long_bool
      { \cs_set:cpx }
      { \cs_set_nopar:cpx }
      { \l_@@_expandable_aux_name_tl } ##1 #1 ##2 #1
      { ##1 {##2} }
    \tl_put_right:Nx \l_@@_signature_tl
      {
        \exp_not:c  { \l_@@_expandable_aux_name_tl }
        \exp_not:n { #1 {#2} }
      }
    \bool_set_false:N \l_@@_long_bool
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_add_expandable_type_g:w}
% \begin{macro}{\@@_add_expandable_type_G:w}
%   These are not allowed at all, so there is a complaint and a fall-back.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_expandable_type_g:w
  {
    \__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type }
      { g }
    \@@_add_expandable_type_m:w
  }
\cs_new_protected_nopar:Npn \@@_add_expandable_type_G:w #1
  {
    \__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type }
      { G }
    \@@_add_expandable_type_m:w
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_add_expandable_type_l:w}
%   Invalid in expandable contexts (as the next left brace may have been
%   inserted by \pkg{xparse} due to a failed search for an optional argument).
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_expandable_type_l:w
  {
    \__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type }
      { l }
    \@@_add_expandable_type_m:w
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_expandable_type_m:w}
%   Unlike the standard case, when working expandably each argument is always
%   grabbed separately unless the function takes only \texttt{m}-type
%   arguments. To deal with the latter case, the value of
%   \cs{l_@@_m_args_int} needs to be increased appropriately.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_expandable_type_m:w
  {
    \int_incr:N \l_@@_m_args_int
    \@@_add_expandable_grabber_mandatory:n { m }
    \bool_set_false:N \l_@@_long_bool
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_expandable_type_r:w}
% \begin{macro}{\@@_add_expandable_type_R:w}
%   The \texttt{r}- and \texttt{R}-types are very similar to \texttt{D}-type
%   arguments, and so the same internals are used.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_add_expandable_type_r:w #1#2
  {
    \exp_args:NNNo
      \@@_add_expandable_type_R:w #1 #2 \c_@@_no_value_tl
  }
\cs_new_protected:Npn \@@_add_expandable_type_R:w #1#2
  {
    \token_if_eq_meaning:NNTF #1 #2
      {
        \@@_add_expandable_grabber_optional:n { R_alt }
        \@@_add_expandable_type_D_aux:Nn #1
      }
      {
        \@@_add_expandable_grabber_optional:n { R }
        \@@_add_expandable_type_D_aux:NNn #1#2
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_add_expandable_type_t:w}
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_expandable_type_t:w #1
  {
    \@@_add_expandable_grabber_optional:n { t }
    \bool_if:NTF \l_@@_all_long_bool
      { \cs_set:cpn }
      { \cs_set_nopar:cpn }
      { \l_@@_expandable_aux_name_tl } ##1 #1 {##1}
    \tl_put_right:Nx \l_@@_signature_tl
      {
        \exp_not:c  { \l_@@_expandable_aux_name_tl }
        \exp_not:N #1
      }
    \bool_set_false:N \l_@@_long_bool
    \@@_prepare_signature:N
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_expandable_type_u:w}
%   Invalid in an expandable context as any preceding optional argument may
%   wrap part of the delimiter up in braces.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_expandable_type_u:w #1
  {
    \__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type }
      { u }
    \@@_add_expandable_type_m:w
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_expandable_type_v:w}
%  Another forbidden type.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_expandable_type_v:w
  {
    \__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type }
      { v }
    \@@_add_expandable_type_m:w
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \@@_add_expandable_grabber_mandatory:n,
%     \@@_add_expandable_grabber_optional:n
%   }
% \begin{macro}[aux]{\@@_add_expandable_long_check:}
%   Adding a grabber to the signature is very simple here, with only a test to
%   ensure that optional arguments still have mandatory ones to follow. This
%   is also a good place to check on the consistency of the long status of
%   arguments.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_add_expandable_grabber_mandatory:n #1
  {
    \@@_add_expandable_long_check:
    \tl_put_right:Nx \l_@@_signature_tl
      { \exp_not:c { @@_expandable_grab_ #1 :w } }
    \bool_set_false:N \l_@@_long_bool
    \int_decr:N \l_@@_mandatory_args_int
  }
\cs_new_protected_nopar:Npn \@@_add_expandable_grabber_optional:n #1
  {
    \@@_add_expandable_long_check:
    \int_compare:nNnF \l_@@_mandatory_args_int > \c_zero
      { \__msg_kernel_error:nn { xparse } { expandable-ending-optional } }
    \tl_put_right:Nx \l_@@_signature_tl
      { \exp_not:c { @@_expandable_grab_ #1 :w } }
    \bool_set_false:N \l_@@_long_bool
  }
\cs_new_protected_nopar:Npn \@@_add_expandable_long_check:
  {
    \bool_if:nT { \l_@@_all_long_bool && ! ( \l_@@_long_bool ) }
      { \__msg_kernel_error:nn { xparse } { inconsistent-long } }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Grabbing arguments}
%
% All of the grabbers follow the same basic pattern. The initial
% function sets up the appropriate information to define
% \cs{parse_grab_arg:w} to grab the argument. This means determining
% whether to use \cs{cs_set:Npn} or \cs{cs_set_nopar:Npn}, and for
% optional arguments whether to skip spaces. In all cases,
% \cs{@@_grab_arg:w} is then called to actually do the grabbing.
%
% \begin{macro}{\@@_grab_arg:w}
% \begin{macro}[aux]{\@@_grab_arg_auxi:w}
% \begin{macro}[aux]{\@@_grab_arg_auxii:w}
%   Each time an argument is actually grabbed, \pkg{xparse} defines a
%   function to do it. In that way, long arguments from previous functions
%   can be included in the definition of the grabber function, so that
%   it does not raise an error if not long. The generic function used
%   for this is reserved here. A couple of auxiliary functions are also
%   needed in various places.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_arg:w { }
\cs_new_protected:Npn \@@_grab_arg_auxi:w { }
\cs_new_protected:Npn \@@_grab_arg_auxii:w { }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_D:w}
% \begin{macro}{\@@_grab_D_long:w}
% \begin{macro}{\@@_grab_D_trailing:w}
% \begin{macro}{\@@_grab_D_long_trailing:w}
%   The generic delimited argument grabber. The auxiliary function does
%   a peek test before calling \cs{@@_grab_arg:w}, so that the
%   optional nature of the argument works as expected.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_D:w #1#2#3#4 \l_@@_args_tl
  {
    \@@_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected_nopar:Npn
      { _ignore_spaces }
  }
\cs_new_protected:Npn \@@_grab_D_long:w #1#2#3#4 \l_@@_args_tl
  {
    \@@_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected:Npn
      { _ignore_spaces }
  }
\cs_new_protected:Npn \@@_grab_D_trailing:w #1#2#3#4 \l_@@_args_tl
  { \@@_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected_nopar:Npn { } }
\cs_new_protected:Npn \@@_grab_D_long_trailing:w #1#2#3#4 \l_@@_args_tl
  { \@@_grab_D_aux:NNnnNn #1 #2 {#3} {#4} \cs_set_protected:Npn { } }
%    \end{macrocode}
% \begin{macro}[aux]{\@@_grab_D_aux:NNnnNn}
% \begin{macro}[aux]{\@@_grab_D_aux:NNnN}
%   This is a bit complicated. The idea is that, in order to check for
%   nested optional argument tokens (\texttt{[[...]]} and so on) the
%   argument needs to be grabbed without removing any braces at all. If
%   this is not done, then cases like |[{[}]| fail. So after testing for
%   an optional argument, it is collected piece-wise. Inserting a quark
%   prevents loss of braces, and there is then a test to see if there are
%   nested delimiters to handle.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_D_aux:NNnnNn #1#2#3#4#5#6
  {
    \@@_grab_D_aux:NNnN #1#2 {#4} #5
    \use:c { peek_meaning_remove #6 :NTF } #1
      { \@@_grab_arg:w }
      {
        \@@_add_arg:n {#3}
        #4 \l_@@_args_tl
      }
  }
%    \end{macrocode}
%   Inside the \enquote{standard} grabber, there is a test to see if the
%   grabbed argument is entirely enclosed by braces. There are a couple of
%   extra factors to allow for: the argument might be entirely empty, and
%   spaces at the start and end of the input must be retained around a brace
%   group.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_D_aux:NNnN #1#2#3#4
  {
    \cs_set_protected_nopar:Npn \@@_grab_arg:w
      {
        \exp_after:wN #4 \l_@@_fn_tl ####1 #2
          {
            \tl_if_in:nnTF {####1} {#1}
              { \@@_grab_D_nested:NNnnN #1 #2 {####1} {#3} #4 }
              {
                \tl_if_blank:oTF { \use_none:n ####1 }
                  { \@@_add_arg:o { \use_none:n ####1 } }
                  {
                    \str_if_eq_x:nnTF
                      { \exp_not:o { \use_none:n ####1 } }
                      { { \exp_not:o { \use_ii:nnn ####1 \q_nil } } }
                      { \@@_add_arg:o { \use_ii:nn ####1 } }
                      { \@@_add_arg:o { \use_none:n ####1 } }
                  }
                #3 \l_@@_args_tl
              }
          }
%    \end{macrocode}
%   This section needs a little explanation. In order to avoid loosing any
%   braces, a token needs to be inserted before the argument to be grabbed.
%   If the argument runs away because the closing token is missing then this
%   inserted token shows up in the terminal. Ideally, |#1| would therefore be
%   used directly, but that is no good as it will mess up the rest of the
%   grabber. Instead, a copy of |#1| with an altered category code is used,
%   as this will look right in the terminal but will not mess up the grabber.
%   The only issue then is that the category code of |#1| is unknown. So there
%   is a quick test to ensure that the inserted token can never be matched by
%   the grabber. (This assumes that |#1| and |#2| are not the same character
%   with different category codes, but that really should not happen in any
%   sensible document-level syntax.)
%    \begin{macrocode}
        \group_begin:
          \token_if_eq_catcode:NNTF #1 ^
            {
              \char_set_lccode:nn { `A } { `#1 }
              \tl_to_lowercase:n
                {
                  \group_end:
                  \l_@@_fn_tl A
                }
            }
            {
              \char_set_lccode:nn { `^ } { `#1 }
              \tl_to_lowercase:n
                {
                  \group_end:
                  \l_@@_fn_tl ^
                }
            }
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}[aux]{\@@_grab_D_nested:NNnnN}
% \begin{macro}[aux]{\@@_grab_D_nested:w}
% \begin{macro}{\l_@@_nesting_a_tl}
% \begin{macro}{\l_@@_nesting_b_tl}
% \begin{macro}{\q_@@}
%   Catching nested optional arguments means more work. The aim here is
%   to collect up each pair of optional tokens without \TeX{} helping out,
%   and without counting anything. The code above will already have
%   removed the leading opening token and a closing token, but the
%   wrong one. The aim is then to work through the material grabbed
%   so far and divide it up on each opening token, grabbing a closing
%   token to match (thus working in pairs). Once there are no opening
%   tokens, then there is a second check to see if there are any
%   opening tokens in the second part of the argument (for things
%   like |[][]|). Once everything has been found, the entire collected
%   material is added to the output as a single argument. The only tricky part
%   here is ensuring that any grabbing function that might run away is named
%   after the function currently being parsed and not after \pkg{xparse}. That
%   leads to some rather complex nesting! There is also a need to prevent the
%   loss of any braces, hence the insertion and removal of quarks along the
%   way.
%    \begin{macrocode}
\tl_new:N \l_@@_nesting_a_tl
\tl_new:N \l_@@_nesting_b_tl
\quark_new:N \q_@@
\cs_new_protected:Npn \@@_grab_D_nested:NNnnN #1#2#3#4#5
  {
    \tl_clear:N \l_@@_nesting_a_tl
    \tl_clear:N \l_@@_nesting_b_tl
    \exp_after:wN #5 \l_@@_fn_tl ##1 #1 ##2 \q_@@ ##3 #2
      {
        \tl_put_right:No \l_@@_nesting_a_tl { \use_none:n ##1 #1 }
        \tl_put_right:No \l_@@_nesting_b_tl { \use_i:nn #2 ##3 }
        \tl_if_in:nnTF {##2} {#1}
          {
            \l_@@_fn_tl
              \q_nil ##2 \q_@@ \ERROR
          }
          {
            \tl_put_right:Nx \l_@@_nesting_a_tl
              { \@@_grab_D_nested:w \q_nil ##2 \q_stop }
            \tl_if_in:NnTF \l_@@_nesting_b_tl {#1}
              {
                \tl_set_eq:NN \l_@@_tmp_tl \l_@@_nesting_b_tl
                \tl_clear:N \l_@@_nesting_b_tl
                \exp_after:wN \l_@@_fn_tl \exp_after:wN
                  \q_nil \l_@@_tmp_tl \q_nil \q_@@ \ERROR
              }
              {
                \tl_put_right:No \l_@@_nesting_a_tl
                  \l_@@_nesting_b_tl
                \@@_add_arg:V \l_@@_nesting_a_tl
                #4 \l_@@_args_tl
              }
          }
      }
    \l_@@_fn_tl #3 \q_nil \q_@@ \ERROR
  }
\cs_new:Npn \@@_grab_D_nested:w #1 \q_nil \q_stop
  { \exp_not:o { \use_none:n #1 } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_G:w}
% \begin{macro}{\@@_grab_G_long:w}
% \begin{macro}{\@@_grab_G_trailing:w}
% \begin{macro}{\@@_grab_G_long_trailing:w}
% \begin{macro}[aux]{\@@_grab_G_aux:nnNn}
%   Optional groups are checked by meaning, so that the same code will
%   work with, for example, Con\TeX{}t-like input.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_G:w #1#2 \l_@@_args_tl
  {
    \@@_grab_G_aux:nnNn {#1} {#2} \cs_set_protected_nopar:Npn
      { _ignore_spaces }
  }
\cs_new_protected:Npn \@@_grab_G_long:w #1#2 \l_@@_args_tl
  {
    \@@_grab_G_aux:nnNn {#1} {#2} \cs_set_protected:Npn { _ignore_spaces }
  }
\cs_new_protected:Npn \@@_grab_G_trailing:w #1#2 \l_@@_args_tl
  { \@@_grab_G_aux:nnNn {#1} {#2} \cs_set_protected_nopar:Npn { } }
\cs_new_protected:Npn \@@_grab_G_long_trailing:w #1#2 \l_@@_args_tl
  { \@@_grab_G_aux:nnNn {#1} {#2} \cs_set_protected:Npn { } }
\cs_new_protected:Npn \@@_grab_G_aux:nnNn #1#2#3#4
  {
    \exp_after:wN #3 \l_@@_fn_tl ##1
      {
        \@@_add_arg:n {##1}
        #2 \l_@@_args_tl
      }
    \use:c { peek_meaning #4 :NTF } \c_group_begin_token
      { \l_@@_fn_tl }
      {
        \@@_add_arg:n {#1}
        #2 \l_@@_args_tl
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_l:w}
% \begin{macro}{\@@_grab_l_long:w}
% \begin{macro}[aux]{\@@_grab_l_aux:nN}
%   Argument grabbers for mandatory \TeX{} arguments are pretty simple.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_l:w #1 \l_@@_args_tl
  { \@@_grab_l_aux:nN {#1} \cs_set_protected_nopar:Npn }
\cs_new_protected:Npn \@@_grab_l_long:w #1 \l_@@_args_tl
  { \@@_grab_l_aux:nN {#1} \cs_set_protected:Npn }
\cs_new_protected:Npn \@@_grab_l_aux:nN #1#2
  {
    \exp_after:wN #2 \l_@@_fn_tl ##1##
      {
        \@@_add_arg:n {##1}
        #1 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_m:w}
% \begin{macro}{\@@_grab_m_long:w}
%   Collecting a single mandatory argument is quite easy.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_m:w #1 \l_@@_args_tl
  {
    \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl ##1
      {
        \@@_add_arg:n {##1}
        #1 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
\cs_new_protected:Npn \@@_grab_m_long:w #1 \l_@@_args_tl
  {
    \exp_after:wN \cs_set_protected:Npn \l_@@_fn_tl ##1
      {
        \@@_add_arg:n {##1}
        #1 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_m_1:w}
% \begin{macro}{\@@_grab_m_2:w}
% \begin{macro}{\@@_grab_m_3:w}
% \begin{macro}{\@@_grab_m_4:w}
% \begin{macro}{\@@_grab_m_5:w}
% \begin{macro}{\@@_grab_m_6:w}
% \begin{macro}{\@@_grab_m_7:w}
% \begin{macro}{\@@_grab_m_8:w}
%   Grabbing 1--8 mandatory arguments. We don't need to worry about
%   nine arguments as this is only possible if everything is
%   mandatory. Each function has an auxiliary so that \cs{par} tokens
%   from other arguments still work.
%    \begin{macrocode}
\cs_new_protected:cpn { @@_grab_m_1:w } #1 \l_@@_args_tl
  {
    \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl ##1
      {
        \tl_put_right:Nn \l_@@_args_tl { {##1} }
        #1 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
\cs_new_protected:cpn { @@_grab_m_2:w } #1 \l_@@_args_tl
  {
    \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl
      ##1##2
      {
        \tl_put_right:Nn \l_@@_args_tl { {##1} {##2} }
        #1 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
\cs_new_protected:cpn { @@_grab_m_3:w } #1 \l_@@_args_tl
  {
    \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl
      ##1##2##3
      {
        \tl_put_right:Nn \l_@@_args_tl { {##1} {##2} {##3} }
        #1 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
\cs_new_protected:cpn { @@_grab_m_4:w } #1 \l_@@_args_tl
  {
    \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl
      ##1##2##3##4
      {
        \tl_put_right:Nn \l_@@_args_tl { {##1} {##2} {##3} {##4} }
        #1 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
\cs_new_protected:cpn { @@_grab_m_5:w } #1 \l_@@_args_tl
  {
    \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl
      ##1##2##3##4##5
      {
        \tl_put_right:Nn \l_@@_args_tl { {##1} {##2} {##3} {##4} {##5} }
        #1 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
\cs_new_protected:cpn { @@_grab_m_6:w } #1 \l_@@_args_tl
  {
    \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl
      ##1##2##3##4##5##6
      {
        \tl_put_right:Nn \l_@@_args_tl
          { {##1} {##2} {##3} {##4} {##5} {##6} }
        #1 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
\cs_new_protected:cpn { @@_grab_m_7:w } #1 \l_@@_args_tl
  {
    \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl
      ##1##2##3##4##5##6##7
      {
        \tl_put_right:Nn \l_@@_args_tl
          { {##1} {##2} {##3} {##4} {##5} {##6} {##7} }
        #1 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
\cs_new_protected:cpn { @@_grab_m_8:w } #1 \l_@@_args_tl
  {
    \exp_after:wN \cs_set_protected_nopar:Npn \l_@@_fn_tl
      ##1##2##3##4##5##6##7##8
      {
        \tl_put_right:Nn \l_@@_args_tl
          { {##1} {##2} {##3} {##4} {##5} {##6} {##7} {##8} }
        #1 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_R:w, \@@_grab_R_long:w}
% \begin{macro}[aux]{\@@_grab_R_aux:NNnnN}
%  The grabber for \texttt{R}-type arguments is basically the same as
%  that for \texttt{D}-type ones, but always skips spaces (as it is mandatory)
%  and has a hard-coded error message.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_R:w #1#2#3#4 \l_@@_args_tl
  { \@@_grab_R_aux:NNnnN #1 #2 {#3} {#4} \cs_set_protected_nopar:Npn }
\cs_new_protected:Npn \@@_grab_R_long:w #1#2#3#4 \l_@@_args_tl
  { \@@_grab_R_aux:NNnnN #1 #2 {#3} {#4} \cs_set_protected:Npn }
\cs_new_protected:Npn \@@_grab_R_aux:NNnnN #1#2#3#4#5
  {
    \@@_grab_D_aux:NNnN #1 #2 {#4} #5
    \peek_meaning_remove_ignore_spaces:NTF #1
      { \@@_grab_arg:w }
      {
        \__msg_kernel_error:nnxx { xparse } { missing-required }
          { \token_to_str:N #1 } { \tl_to_str:n {#3} }
        \@@_add_arg:n {#3}
        #4 \l_@@_args_tl
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_t:w}
% \begin{macro}{\@@_grab_t_long:w}
% \begin{macro}{\@@_grab_t_trailing:w}
% \begin{macro}{\@@_grab_t_long_trailing:w}
% \begin{macro}[aux]{\@@_grab_t_aux:NnNn}
%   Dealing with a token is quite easy. Check the match, remove the
%   token if needed and add a flag to the output.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_t:w #1#2 \l_@@_args_tl
  {
    \@@_grab_t_aux:NnNn #1 {#2} \cs_set_protected_nopar:Npn
      { _ignore_spaces }
  }
\cs_new_protected:Npn \@@_grab_t_long:w #1#2 \l_@@_args_tl
  { \@@_grab_t_aux:NnNn #1 {#2} \cs_set_protected:Npn { _ignore_spaces } }
\cs_new_protected:Npn \@@_grab_t_trailing:w #1#2 \l_@@_args_tl
  { \@@_grab_t_aux:NnNn #1 {#2} \cs_set_protected_nopar:Npn { } }
\cs_new_protected:Npn \@@_grab_t_long_trailing:w #1#2 \l_@@_args_tl
  { \@@_grab_t_aux:NnNn #1 {#2} \cs_set_protected:Npn { } }
\cs_new_protected:Npn \@@_grab_t_aux:NnNn #1#2#3#4
  {
    \exp_after:wN #3 \l_@@_fn_tl
      {
        \use:c { peek_meaning_remove #4 :NTF } #1
          {
            \@@_add_arg:n { \BooleanTrue }
            #2 \l_@@_args_tl
          }
          {
            \@@_add_arg:n { \BooleanFalse }
            #2 \l_@@_args_tl
          }
      }
    \l_@@_fn_tl
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_u:w}
% \begin{macro}{\@@_grab_u_long:w}
% \begin{macro}[aux]{\@@_grab_u_aux:nnN}
%   Grabbing up to a list of tokens is quite easy: define the grabber,
%   and then collect.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_u:w #1#2 \l_@@_args_tl
  { \@@_grab_u_aux:nnN {#1} {#2} \cs_set_protected_nopar:Npn }
\cs_new_protected:Npn \@@_grab_u_long:w #1#2 \l_@@_args_tl
  { \@@_grab_u_aux:nnN {#1} {#2} \cs_set_protected:Npn }
\cs_new_protected:Npn \@@_grab_u_aux:nnN #1#2#3
  {
    \exp_after:wN #3 \l_@@_fn_tl ##1 #1
      {
        \@@_add_arg:n {##1}
        #2 \l_@@_args_tl
      }
    \l_@@_fn_tl
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_v:w}
% \begin{macro}{\@@_grab_v_long:w}
% \begin{macro}{\@@_grab_v_aux:w}
% \begin{macro}{\@@_grab_v_group_end:}
% \begin{variable}{\l_@@_v_rest_of_signature_tl}
% \begin{variable}{\l_@@_v_arg_tl}
%   The opening delimiter is the first non-space token, and is never
%   read verbatim.  This is required by consistency with the case where
%   the preceding argument was optional and absent: then \TeX{} has
%   already read and tokenized that token when looking for the optional
%   argument.  The first thing is thus to check is that this delimiter
%   is a character, and to distinguish the case of a left brace (in that
%   case, \cs{group_align_safe_end:} is needed to compensate for the
%   begin-group character that was just seen).  Then set verbatim
%   catcodes with \cs{@@_grab_v_aux_catcodes:}.
%
%   The group keep catcode changes local, and
%   \cs{group_align_safe_begin/end:} allow to use a character
%   with category code~$4$ (normally |&|) as the delimiter.
%   It is ended by \cs{@@_grab_v_group_end:}, which smuggles
%   the collected argument out of the group.
%    \begin{macrocode}
\tl_new:N \l_@@_v_rest_of_signature_tl
\tl_new:N \l_@@_v_arg_tl
\cs_new_protected_nopar:Npn \@@_grab_v:w
  {
    \bool_set_false:N \l_@@_long_bool
    \@@_grab_v_aux:w
  }
\cs_new_protected_nopar:Npn \@@_grab_v_long:w
  {
    \bool_set_true:N \l_@@_long_bool
    \@@_grab_v_aux:w
  }
\cs_new_protected:Npn \@@_grab_v_aux:w #1 \l_@@_args_tl
  {
    \tl_set:Nn \l_@@_v_rest_of_signature_tl {#1}
    \group_begin:
      \group_align_safe_begin:
        \tex_escapechar:D = 92 \scan_stop:
        \tl_clear:N \l_@@_v_arg_tl
        \peek_meaning_remove_ignore_spaces:NTF \c_group_begin_token
          {
            \group_align_safe_end:
            \@@_grab_v_bgroup:
          }
          {
            \peek_N_type:TF
              { \@@_grab_v_aux_test:N }
              { \@@_grab_v_aux_abort:n { } }
          }
  }
\cs_new_protected_nopar:Npn \@@_grab_v_group_end:
  {
        \group_align_safe_end:
        \exp_args:NNNo
      \group_end:
    \tl_set:Nn \l_@@_v_arg_tl { \l_@@_v_arg_tl }
  }
%    \end{macrocode}
% \end{variable}
% \end{variable}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_v_aux_test:N}
% \begin{macro}
%   {
%     \@@_grab_v_aux_loop:N,
%     \@@_grab_v_aux_loop:NN,
%     \@@_grab_v_aux_loop_end:
%   }
%   Check that the opening delimiter is a character, setup category codes,
%   then start reading tokens one by one, keeping the delimiter as an argument.
%   If the verbatim was not nested, we will be grabbing one character
%   at each step. Unfortunately, it can happen that what follows the
%   verbatim argument is already tokenized. Thus, we check at each step
%   that the next token is indeed a \enquote{nice}
%   character, \emph{i.e.}, is not a character with
%   category code $1$ (begin-group), $2$ (end-group)
%   or $6$ (macro parameter), nor the space character,
%   with category code~$10$ and character code~$32$,
%   nor a control sequence.
%   The partially built argument is stored in \cs{l_@@_v_arg_tl}.
%   If we ever meet a token which we cannot grab (non-N-type),
%   or which is not a character according to
%   \cs{@@_grab_v_token_if_char:NTF}, then we bail out with
%   \cs{@@_grab_v_aux_abort:n}. Otherwise, we stop at the first
%   character matching the delimiter.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_v_aux_test:N #1
  {
    \@@_grab_v_token_if_char:NTF #1
      {
        \@@_grab_v_aux_put:N #1
        \@@_grab_v_aux_catcodes:
        \@@_grab_v_aux_loop:N #1
      }
      { \@@_grab_v_aux_abort:n {#1} #1 }
  }
\cs_new_protected:Npn \@@_grab_v_aux_loop:N #1
  {
    \peek_N_type:TF
      { \@@_grab_v_aux_loop:NN #1 }
      { \@@_grab_v_aux_abort:n { } }
  }
\cs_new_protected:Npn \@@_grab_v_aux_loop:NN #1 #2
  {
    \@@_grab_v_token_if_char:NTF #2
      {
        \token_if_eq_charcode:NNTF #1 #2
          { \@@_grab_v_aux_loop_end: }
          {
            \@@_grab_v_aux_put:N #2
            \@@_grab_v_aux_loop:N #1
          }
      }
      { \@@_grab_v_aux_abort:n {#2} #2 }
  }
\cs_new_protected_nopar:Npn \@@_grab_v_aux_loop_end:
  {
    \@@_grab_v_group_end:
    \exp_args:Nx \@@_add_arg:n { \tl_tail:N \l_@@_v_arg_tl }
    \l_@@_v_rest_of_signature_tl \l_@@_args_tl
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_v_bgroup:}
% \begin{macro}{\@@_grab_v_bgroup_loop:}
% \begin{macro}{\@@_grab_v_bgroup_loop:N}
% \begin{variable}{\l_@@_v_nesting_int}
%   If the opening delimiter is a left brace, we keep track of
%   how many left and right braces were encountered so far in
%   \cs{l_@@_v_nesting_int} (the methods used for optional
%   arguments cannot apply here), and stop as soon as it reaches~$0$.
%
%   Some care was needed when removing the opening delimiter, which
%   has already been assigned category code~$1$: using
%   \cs{peek_meaning_remove:NTF} in the \cs{@@_grab_v_aux:w}
%   function would break within alignments. Instead, we first
%   convert that token to a string, and remove the result as a
%   normal undelimited argument.
%    \begin{macrocode}
\int_new:N \l_@@_v_nesting_int
\cs_new_protected_nopar:Npx \@@_grab_v_bgroup:
  {
    \exp_not:N \@@_grab_v_aux_catcodes:
    \exp_not:n { \int_set_eq:NN \l_@@_v_nesting_int \c_one }
    \exp_not:N \@@_grab_v_aux_put:N \iow_char:N \{
    \exp_not:N \@@_grab_v_bgroup_loop:
  }
\cs_new_protected:Npn \@@_grab_v_bgroup_loop:
  {
    \peek_N_type:TF
      { \@@_grab_v_bgroup_loop:N }
      { \@@_grab_v_aux_abort:n { } }
  }
\cs_new_protected:Npn \@@_grab_v_bgroup_loop:N #1
  {
    \@@_grab_v_token_if_char:NTF #1
      {
        \token_if_eq_charcode:NNTF \c_group_end_token #1
          {
            \int_decr:N \l_@@_v_nesting_int
            \int_compare:nNnTF \l_@@_v_nesting_int > \c_zero
              {
                \@@_grab_v_aux_put:N #1
                \@@_grab_v_bgroup_loop:
              }
              { \@@_grab_v_aux_loop_end: }
          }
          {
            \token_if_eq_charcode:NNT \c_group_begin_token #1
              { \int_incr:N \l_@@_v_nesting_int }
            \@@_grab_v_aux_put:N #1
            \@@_grab_v_bgroup_loop:
          }
      }
      { \@@_grab_v_aux_abort:n {#1} #1 }
  }
%    \end{macrocode}
% \end{variable}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_v_aux_catcodes:}
% \begin{macro}{\@@_grab_v_aux_abort:n}
%   In a standalone format, the list of special characters is kept
%   as a sequence, \cs{c_@@_special_chars_seq}, and we use
%   \tn{dospecials} in package mode.
%   The approach for short verbatim arguments is to make the end-line
%   character a macro parameter character: this is forbidden by the
%   rest of the code. Then the error branch can check what caused the
%   bail out and give the appropriate error message.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_grab_v_aux_catcodes:
  {
%<*initex>
    \seq_map_function:NN
      \c_@@_special_chars_seq
      \char_set_catcode_other:N
%</initex>
%<*package>
    \cs_set_eq:NN \do \char_set_catcode_other:N
    \dospecials
%</package>
    \tex_endlinechar:D = `\^^M \scan_stop:
    \bool_if:NTF \l_@@_long_bool
      { \char_set_catcode_other:n { \tex_endlinechar:D } }
      { \char_set_catcode_parameter:n { \tex_endlinechar:D } }
  }
\cs_new_protected:Npn \@@_grab_v_aux_abort:n #1
  {
    \@@_grab_v_group_end:
    \@@_add_arg:o \c_@@_no_value_tl
    \group_begin:
    \char_set_lccode:nn { `\# } { \tex_endlinechar:D }
    \tl_to_lowercase:n
      { \group_end: \peek_meaning_remove:NTF ## }
      {
        \__msg_kernel_error:nnxxx { xparse } { verbatim-newline }
          { \exp_after:wN \token_to_str:N \l_@@_fn_tl }
          { \tl_to_str:N \l_@@_v_arg_tl }
          { \tl_to_str:n {#1} }
        \l_@@_v_rest_of_signature_tl \l_@@_args_tl
      }
      {
        \__msg_kernel_error:nnxxx { xparse } { verbatim-tokenized }
          { \exp_after:wN \token_to_str:N \l_@@_fn_tl }
          { \tl_to_str:N \l_@@_v_arg_tl }
          { \tl_to_str:n {#1} }
        \l_@@_v_rest_of_signature_tl \l_@@_args_tl
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_v_aux_put:N}
%   Storing one token in the collected argument. Most tokens are
%   converted to category code $12$, with the exception of active
%   characters, and spaces (not sure what should be done for those).
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_v_aux_put:N #1
  {
    \tl_put_right:Nx \l_@@_v_arg_tl
      {
        \token_if_active:NTF #1
          { \exp_not:N #1 } { \token_to_str:N #1 }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_grab_v_token_if_char:NTF}
%   This function assumes that the escape character is printable.
%   Then the string representation of control sequences is at least
%   two characters, and \cs{str_tail:n} only removes the escape
%   character. Macro parameter characters are doubled by
%   \cs{tl_to_str:n}, and will also yield a non-empty result,
%   hence are not considered as characters.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_grab_v_token_if_char:NTF #1
  { \str_if_eq_x:nnTF { } { \str_tail:n {#1} } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_arg:n, \@@_add_arg:V, \@@_add_arg:o}
% \begin{macro}[aux]{\@@_add_arg_aux:n, \@@_add_arg_aux:V}
%   The argument-storing system provides a single point for interfacing
%   with processors. They are done in a loop, counting downward. In this
%   way, the processor which was found last is executed first. The result
%   is that processors apply from right to left, as intended. Notice that
%   a set of braces are added back around the result of processing so that
%   the internal function will correctly pick up one argument for each
%   input argument.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_add_arg:n #1
  {
    \int_compare:nNnTF \l_@@_processor_int = \c_zero
      { \tl_put_right:Nn \l_@@_args_tl { {#1} } }
      {
        \tl_clear:N \ProcessedArgument
        \@@_if_no_value:nTF {#1}
          {
            \int_zero:N \l_@@_processor_int
            \tl_put_right:Nn \l_@@_args_tl { {#1} }
          }
          { \@@_add_arg_aux:n {#1} }
      }
  }
\cs_generate_variant:Nn \@@_add_arg:n { V , o }
\cs_new_protected:Npn \@@_add_arg_aux:n #1
  {
    \use:c { @@_processor_ \int_use:N \l_@@_processor_int :n } {#1}
    \int_decr:N \l_@@_processor_int
    \int_compare:nNnTF \l_@@_processor_int = \c_zero
      {
        \tl_put_right:Nx \l_@@_args_tl
          { { \exp_not:V \ProcessedArgument } }
      }
      { \@@_add_arg_aux:V \ProcessedArgument }
}
\cs_generate_variant:Nn \@@_add_arg_aux:n { V }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Grabbing arguments expandably}
%
% \begin{macro}[EXP]{\@@_expandable_grab_D:w}
% \begin{macro}[EXP, aux]{\@@_expandable_grab_D:NNNnwN}
% \begin{macro}[EXP, aux]{\@@_expandable_grab_D:NNNwNnnn}
% \begin{macro}[EXP, aux]{\@@_expandable_grab_D:Nw}
% \begin{macro}[EXP, aux]{\@@_expandable_grab_D:nnNNNwN}
%   The first step is to grab the first token or group. The generic grabber
%   \cs{\meta{function}}\verb*| | is just after \cs{q_@@}, we go and find
%   it.
%    \begin{macrocode}
\cs_new:Npn \@@_expandable_grab_D:w #1 \q_@@ #2
  { #2 { \@@_expandable_grab_D:NNNnwNn #1 \q_@@ #2 } }
%    \end{macrocode}
%   We then wish to test whether |#7|, which we just grabbed, is exactly |#2|.
%   Expand the only grabber function we have, |#1|, once: the two strings below
%   are equal if and only if |#7| matches |#2| exactly.\footnote{It is obvious
%   that if \texttt{\#7} matches \texttt{\#2} then the strings are equal. We
%   must check the converse. The right-hand-side of \cs{str_if_eq:onTF} does
%   not end with \texttt{\#3}, implying that the grabber function took
%   everything as its arguments. The first brace group can only be empty if
%   \texttt{\#7} starts with \texttt{\#2}, otherwise the brace group preceding
%   \texttt{\#7} would not vanish. The third brace group is empty, thus the
%   \cs{q_@@} that was used by our grabber \texttt{\#1} must be the one
%   that we inserted (not some token in \texttt{\#7}), hence the second brace
%   group contains the end of \texttt{\#7} followed by \texttt{\#2}. Since this
%   is \texttt{\#2} on the right-hand-side, and no brace can be lost there,
%   \texttt{\#7} must contain nothing else than its leading \texttt{\#2}.} If
%   |#7| does not match |#2|, then the optional argument is missing, we use the
%   default |#4|, and put back the argument |#7| in the input stream.
%   %^^A There is probably a bug similar to the non-expandable O{\par} bug.
%
%   If it does match, then interesting things need to be done. We will grab the
%   argument piece by piece, with the following pattern:
%   \begin{quote}
%     \meta{grabber} \Arg{tokens} \\
%     ~~\cs{q_nil} \Arg{piece 1} \meta{piece 2} \cs{ERROR} \cs{q_@@}\\
%     ~~\cs{q_nil} \meta{input stream}
%   \end{quote}
%   The \meta{grabber} will find an opening delimiter in \meta{piece 2}, take
%   the \cs{q_@@} as a second delimiter, and find more material delimited
%   by the closing delimiter in the \meta{input stream}. We then move the part
%   before the opening delimiter from \meta{piece 2} to \meta{piece 1}, and the
%   material taken from the \meta{input stream} to the \meta{piece 2}. Thus,
%   the argument moves gradually from the \meta{input stream} to the
%   \meta{piece 2}, then to the \meta{piece 1} when we have made sure to find
%   all opening and closing delimiters. This two-step process ensures that
%   nesting works: the number of opening delimiters minus closing delimiters in
%   \meta{piece 1} is always equal to the number of closing delimiters in
%   \meta{piece 2}. We stop grabbing arguments once the \meta{piece 2} contains
%   no opening delimiter any more, hence the balance is reached, and the final
%   argument is \meta{piece 1} \meta{piece 2}.
%    \begin{macrocode}
\cs_new:Npn \@@_expandable_grab_D:NNNnwNn #1#2#3#4#5 \q_@@ #6#7
  {
    \str_if_eq:onTF
      { #1 { } { } #7 #2 \q_@@ #3 }
      { { } { #2 } { } }
      {
        #1
          { \@@_expandable_grab_D:NNNwNnnn #1#2#3#5 \q_@@ #6 }
          \q_nil { } #2 \ERROR \q_@@ \ERROR
      }
      { #5 {#4} \q_@@ #6 {#7} }
  }
%    \end{macrocode}
%   At this stage, |#6| is \cs{q_nil} \Arg{piece 1} \meta{more for piece 1},
%   and we want to concatenate all that, removing \cs{q_nil}, and keeping the
%   opening delimiter |#2|. Simply use \cs{use_ii:nn}. Also, |#7| is
%   \meta{remainder of piece 2} \cs{ERROR}, and |#8| is \cs{ERROR} \meta{more
%   for piece 2}. We concatenate those, replacing the two \cs{ERROR} by the
%   closing delimiter |#3|.
%    \begin{macrocode}
\cs_new:Npn \@@_expandable_grab_D:NNNwNnnn #1#2#3#4 \q_@@ #5#6#7#8
  {
    \exp_args:Nof \@@_expandable_grab_D:nnNNNwN
      { \use_ii:nn #6 #2 }
      { \@@_expandable_grab_D:Nw #3 \exp_stop_f: #7 #8 }
    #1#2#3 #4 \q_@@ #5
  }
\cs_new:Npn \@@_expandable_grab_D:Nw #1#2 \ERROR \ERROR { #2 #1 }
%    \end{macrocode}
%   Armed with our two new \meta{pieces}, we are ready to loop. However, we
%   must first see if \meta{piece 2} (here |#2|) contains any opening
%   delimiter |#4|. Again, we expand |#3|, this time removing its whole output
%   with \cs{use_none:nnn}. The test is similar to \cs{tl_if_in:nnTF}. The
%   token list is empty if and only if |#2| does not contain the opening
%   delimiter. In that case, we are done, and put the argument (from which we
%   remove a spurious pair of delimiters coming from how we started the loop).
%   Otherwise, we go back to looping with
%   \cs{@@_expandable_grab_D:NNNwNnnn}. The code to deal with brace stripping
%   is much the same as for the non-expandable case.
%    \begin{macrocode}
\cs_new:Npn \@@_expandable_grab_D:nnNNNwN #1#2#3#4#5#6 \q_@@ #7
  {
    \exp_args:No \tl_if_empty:oTF
      { #3 { \use_none:nnn } #2 \q_@@ #5 #4 \q_@@ #5 }
      {
        \tl_if_blank:oTF { \use_none:nn #1#2 }
          { \@@_put_arg_expandable:ow { } }
          {
            \str_if_eq_x:nnTF
              { \exp_not:o { \use_none:nn #1#2 } }
              { { \exp_not:o { \use_iii:nnnn #1#2 \q_nil } } }
              { \@@_put_arg_expandable:ow { \use_iii:nnn #1#2 } }
              { \@@_put_arg_expandable:ow { \use_none:nn #1#2 } }
          }
          #6 \q_@@ #7
      }
      {
        #3
          { \@@_expandable_grab_D:NNNwNnnn #3#4#5#6 \q_@@ #7 }
          \q_nil {#1} #2 \ERROR \q_@@ \ERROR
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\@@_expandable_grab_D_alt:w}
% \begin{macro}[EXP]{\@@_expandable_grab_D_alt:NNnwNn}
% \begin{macro}[EXP]{\@@_expandable_grab_D_alt:Nw}
%   When the delimiters are identical, nesting is not possible and a simplified
%   approach is used. The test concept here is the same as for the case where
%   the delimiters are different.
%    \begin{macrocode}
\cs_new:Npn \@@_expandable_grab_D_alt:w #1 \q_@@ #2
  { #2 { \@@_expandable_grab_D_alt:NNnwNn #1 \q_@@ #2 } }
\cs_new:Npn \@@_expandable_grab_D_alt:NNnwNn #1#2#3#4 \q_@@ #5#6
  {
    \str_if_eq:onTF
      { #1 { } #6 #2 #2 }
      { { } #2 }
      {
        #1
          { \@@_expandable_grab_D_alt:Nwn #5 #4 \q_@@ }
          #6 \ERROR
      }
      { #4 {#3} \q_@@ #5 {#6} }
  }
\cs_new:Npn \@@_expandable_grab_D_alt:Nwn #1#2 \q_@@ #3
  {
    \tl_if_blank:oTF { \use_none:nn #1#2 }
      { \@@_put_arg_expandable:ow { } }
      {
        \str_if_eq_x:nnTF
          { \exp_not:o { \use_none:n #3 } }
          { { \exp_not:o { \use_ii:nnn #3 \q_nil } } }
          { \@@_put_arg_expandable:ow { \use_ii:nn #3 } }
          { \@@_put_arg_expandable:ow { \use_none:n #3 } }
      }
      #2 \q_@@ #1
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\@@_expandable_grab_m:w}
% \begin{macro}[EXP, aux]{\@@_expandable_grab_m_aux:wNn}
%   The mandatory case is easy: find the auxiliary after the \cs{q_@@}, and
%   use it directly to grab the argument.
%    \begin{macrocode}
\cs_new:Npn \@@_expandable_grab_m:w #1 \q_@@ #2
  { #2 { \@@_expandable_grab_m_aux:wNn #1 \q_@@ #2 } }
\cs_new:Npn \@@_expandable_grab_m_aux:wNn #1 \q_@@ #2#3
  { #1 {#3} \q_@@ #2 }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\@@_expandable_grab_R:w}
% \begin{macro}[EXP, aux]{\@@_expandable_grab_R_aux:NNwn}
%   Much the same as for the \texttt{D}-type argument, with only the lead-off
%   function varying.
%    \begin{macrocode}
\cs_new:Npn \@@_expandable_grab_R:w #1 \q_@@ #2
  { #2 { \@@_expandable_grab_R_aux:NNNnwNn #1 \q_@@ #2 } }
\cs_new:Npn \@@_expandable_grab_R_aux:NNNnwNn #1#2#3#4#5 \q_@@ #6#7
  {
    \str_if_eq:onTF
      { #1 { } { } #7 #2 \q_@@ #3 }
      { { } { #2 } { } }
      {
        #1
          { \@@_expandable_grab_D:NNNwNnnn #1#2#3#5 \q_@@ #6 }
          \q_nil { } #2 \ERROR \q_@@ \ERROR
      }
      {
        \__msg_kernel_expandable_error:nnn
          { xparse } { missing-required } {#2}
        #5 {#4} \q_@@ #6 {#7}
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\@@_expandable_grab_R_alt:w}
% \begin{macro}[EXP]{\@@_expandable_grab_R_alt_aux:NNnwNn}
%   When the delimiters are identical, nesting is not possible and a simplified
%   approach is used. The test concept here is the same as for the case where
%   the delimiters are different.
%    \begin{macrocode}
\cs_new:Npn \@@_expandable_grab_R_alt:w #1 \q_@@ #2
  { #2 { \@@_expandable_grab_R_alt_aux:NNnwNn #1 \q_@@ #2 } }
\cs_new:Npn \@@_expandable_grab_R_alt_aux:NNnwNn #1#2#3#4 \q_@@ #5#6
  {
    \str_if_eq:onTF
      { #1 { } #6 #2 #2 }
      { { } #2 }
      {
        #1
          { \@@_expandable_grab_D_alt:Nwn #5 #4 \q_@@ }
          #6 \ERROR
      }
      {
        \__msg_kernel_expandable_error:nnn
          { xparse } { missing-required } {#2}
        #4 {#3} \q_@@ #5 {#6}
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\@@_expandable_grab_t:w}
% \begin{macro}[EXP, aux]{\@@_expandable_grab_t_aux:NNwn}
%   As for a \texttt{D}-type argument, here we compare the grabbed tokens using
%   the only parser we have in order to work out if |#2| is exactly equal to
%   the output of the grabber.
%    \begin{macrocode}
\cs_new:Npn \@@_expandable_grab_t:w #1 \q_@@ #2
  { #2 { \@@_expandable_grab_t_aux:NNwn #1 \q_@@ #2 } }
\cs_new:Npn \@@_expandable_grab_t_aux:NNwn #1#2#3 \q_@@ #4#5
  {
    \str_if_eq:onTF { #1 { } #5 #2 } { #2 }
      { #3 { \BooleanTrue } \q_@@ #4 }
      { #3 { \BooleanFalse } \q_@@ #4 {#5} }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]
%   {\@@_put_arg_expandable:nw, \@@_put_arg_expandable:ow}
%   A useful helper, to store arguments when they are ready.
%    \begin{macrocode}
\cs_new:Npn \@@_put_arg_expandable:nw #1#2 \q_@@ { #2 {#1} \q_@@ }
\cs_generate_variant:Nn \@@_put_arg_expandable:nw { o }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\@@_grab_expandable_end:wN}
%   For the end of the grabbing sequence: get rid of the generic grabber and
%   insert the code function followed by its arguments.
%    \begin{macrocode}
\cs_new:Npn \@@_grab_expandable_end:wN #1 \q_@@ #2 {#1}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Argument processors}
%
% \begin{macro}{\@@_process_arg:n}
%   Processors are saved for use later during the grabbing process.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_process_arg:n #1
  {
    \int_incr:N \l_@@_processor_int
    \cs_set:cpn { @@_processor_ \int_use:N \l_@@_processor_int :n } ##1
      { #1 {##1} }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_process_to_str:n}
%   A basic argument processor: as much an example as anything else.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_process_to_str:n #1
  { \tl_set:Nx \ProcessedArgument { \tl_to_str:n {#1} } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_bool_reverse:N}
%   A simple reversal.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_bool_reverse:N #1
  {
    \bool_if:NTF #1
      { \tl_set:Nn \ProcessedArgument { \c_false_bool } }
      { \tl_set:Nn \ProcessedArgument { \c_true_bool } }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{variable}{\l_@@_split_list_seq, \l_@@_split_list_tl}
% \begin{macro}{\@@_split_list:nn}
% \begin{macro}[aux]{\@@_split_list_multi:nn, \@@_split_list_multi:nV}
% \begin{macro}[aux]{\@@_split_list_single:Nn}
%   Splitting can take place either at a single token or at a longer
%   identifier. To deal with single active tokens, a two-part procedure is
%   needed.
%    \begin{macrocode}
\seq_new:N \l_@@_split_list_seq
\tl_new:N \l_@@_split_list_tl
\cs_new_protected:Npn \@@_split_list:nn #1#2
  {
    \bool_if:nTF
      {
          \tl_if_single_p:n {#1} &&
        ! ( \token_if_cs_p:N #1 )
      }
      { \@@_split_list_single:Nn #1 {#2} }
      { \@@_split_list_multi:nn {#1} {#2} }
    }
\cs_set_protected:Npn \@@_split_list_multi:nn #1#2
  {
    \seq_set_split:Nnn \l_@@_split_list_seq {#1} {#2}
    \tl_clear:N \ProcessedArgument
    \seq_map_inline:Nn \l_@@_split_list_seq
      { \tl_put_right:Nn \ProcessedArgument { {##1} } }
  }
\cs_generate_variant:Nn \@@_split_list_multi:nn { nV }
\group_begin:
\char_set_catcode_active:N \@
\cs_new_protected:Npn \@@_split_list_single:Nn #1#2
  {
    \tl_set:Nn \l_@@_split_list_tl {#2}
    \group_begin:
    \char_set_lccode:nn { `\@ } { `#1 }
    \tl_to_lowercase:n
      {
         \group_end:
        \tl_replace_all:Nnn \l_@@_split_list_tl { @ } {#1}
      }
     \@@_split_list_multi:nV {#1}  \l_@@_split_list_tl
   }
\group_end:
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{variable}
%
% \begin{macro}{\@@_split_argument:nnn}
% \begin{macro}[aux]{\@@_split_argument_aux:nnnn}
% \begin{macro}[aux, EXP]{\@@_split_argument_aux:n}
% \begin{macro}[aux, EXP]{\@@_split_argument_aux:wn}
%   Splitting to a known number of items is a special version of splitting
%   a list, in which the limit is hard-coded and where there will always be
%   exactly the correct number of output items. An auxiliary function is
%   used to save on working out the token list length several times.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_split_argument:nnn #1#2#3
  {
    \@@_split_list:nn {#2} {#3}
    \exp_args:Nf \@@_split_argument_aux:nnnn
      { \tl_count:N \ProcessedArgument }
      {#1} {#2} {#3}
  }
\cs_new_protected:Npn \@@_split_argument_aux:nnnn #1#2#3#4
  {
    \int_compare:nNnF {#1} = { #2 + \c_one }
      {
        \int_compare:nNnTF {#1} > { #2 + \c_one }
          {
            \tl_set:Nx \ProcessedArgument
              {
                \exp_last_unbraced:NnNo
                  \@@_split_argument_aux:n
                  { #2 + \c_one }
                  \use_none_delimit_by_q_stop:w
                  \ProcessedArgument
                  \q_stop
              }
            \__msg_kernel_error:nnxxx { xparse } { split-excess-tokens }
              { \tl_to_str:n {#3} } { \int_eval:n { #2 + \c_one } }
              { \tl_to_str:n {#4} }
          }
          {
            \tl_put_right:Nx \ProcessedArgument
              {
                \prg_replicate:nn { #2 + \c_one - (#1) }
                  { { \exp_not:V \c_@@_no_value_tl } }
              }
          }
      }
  }
%    \end{macrocode}
%   Auxiliaries to leave exactly the correct number of arguments in
%   \cs{ProcessedArgument}.
%    \begin{macrocode}
\cs_new:Npn \@@_split_argument_aux:n #1
  { \prg_replicate:nn {#1} { \@@_split_argument_aux:wn } }
\cs_new:Npn \@@_split_argument_aux:wn #1 \use_none_delimit_by_q_stop:w #2
  {
    \exp_not:n { {#2} }
    #1
    \use_none_delimit_by_q_stop:w
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_trim_spaces:n}
%   This one is almost trivial.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_trim_spaces:n #1
  { \tl_set:Nx \ProcessedArgument { \tl_trim_spaces:n {#1} } }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Access to the argument specification}
%
% \begin{macro}{\@@_get_arg_spec:N}
% \begin{macro}{\@@_get_arg_spec:n}
% \begin{macro}{\ArgumentSpecification}
%   Recovering the argument specification is also trivial, using the
%   \cs{tl_set_eq:cN} function.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_get_arg_spec:N #1
  {
    \prop_get:NnNF \l_@@_command_arg_specs_prop {#1}
      \ArgumentSpecification
      {
        \__msg_kernel_error:nnx { xparse } { unknown-document-command }
          { \token_to_str:N #1 }
      }
  }
\cs_new_protected:Npn \@@_get_arg_spec:n #1
  {
    \prop_get:NnNF \l_@@_environment_arg_specs_prop {#1}
      \ArgumentSpecification
      {
        \__msg_kernel_error:nnx { xparse } { unknown-document-environment }
          { \tl_to_str:n {#1} }
      }
  }
\tl_new:N \ArgumentSpecification
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_show_arg_spec:N}
% \begin{macro}{\@@_show_arg_spec:n}
%   Showing the argument specification simply means finding it and then
%   calling the \cs{tl_show:N} function.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_show_arg_spec:N #1
  {
    \prop_get:NnNTF \l_@@_command_arg_specs_prop {#1}
      \ArgumentSpecification
      { \tl_show:N \ArgumentSpecification }
      {
        \__msg_kernel_error:nnx { xparse } { unknown-document-command }
          { \token_to_str:N #1 }
      }
  }
\cs_new_protected:Npn \@@_show_arg_spec:n #1
  {
    \prop_get:NnNTF \l_@@_environment_arg_specs_prop {#1}
      \ArgumentSpecification
      { \tl_show:N \ArgumentSpecification }
      {
        \__msg_kernel_error:nnx { xparse } { unknown-document-environment }
          { \tl_to_str:n {#1} }
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Utilities}
%
% \begin{macro}[TF]{\@@_if_no_value:n}
%   Tests for |-NoValue-|: this is similar to \cs{tl_if_in:nn} but set
%   up to be expandable.  The question mark prevents the auxiliary from
%   losing braces.
%    \begin{macrocode}
\group_begin:
\char_set_lccode:nn { `\Q } { `\- }
\char_set_lccode:nn { `\F } { `\F }
\char_set_lccode:nn { `\N } { `\N }
\char_set_lccode:nn { `\T } { `\T }
\char_set_lccode:nn { `\V } { `\V }
\tl_to_lowercase:n
  {
    \group_end:
    \prg_new_conditional:Npnn \@@_if_no_value:n #1 { T ,  F , TF }
      {
        \str_if_eq:onTF
          { \@@_if_value_aux:w ? #1 { } QNoValue- }
          { ? { } QNoValue- }
          { \prg_return_true: }
          { \prg_return_false: }
      }
    \cs_new:Npn \@@_if_value_aux:w #1 QNoValue- { #1 }
  }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Messages}
%
% \subsection{Messages}
%
% Some messages intended as errors.
%    \begin{macrocode}
\__msg_kernel_new:nnnn { xparse } { bad-arg-spec }
  { Bad~argument~specification~'#1'. }
  {
    \c__msg_coding_error_text_tl
    The~argument~specification~provided~was~not~valid:~
    one~or~more~mandatory~pieces~of~information~were~missing. \\ \\
    LaTeX~will~ignore~this~entire~definition.
  }
\__msg_kernel_new:nnnn { xparse } { command-already-defined }
  { Command~'#1'~already~defined! }
  {
    You~have~used~\NewDocumentCommand
    with~a~command~that~already~has~a~definition. \\
    The~existing~definition~of~'#1'~will~not~be~altered.
  }
\__msg_kernel_new:nnnn { xparse } { command-not-yet-defined }
  { Command ~'#1'~not~yet~defined! }
  {
    You~have~used~\RenewDocumentCommand
    with~a~command~that~was~never~defined. \\
    A~new~command~'#1'~will~be~created.
  }
\__msg_kernel_new:nnnn { xparse } { environment-already-defined }
  { Environment~'#1'~already~defined! }
  {
    You~have~used~\NewDocumentEnvironment
    with~an~environment~that~already~has~a~definition. \\
    The~existing~definition~of~'#1'~will~be~overwritten.
  }
\__msg_kernel_new:nnnn { xparse } { environment-mismatch }
  { Mismatch~between~start~and~end~of~environment. }
  {
    The~current~environment~is~called~'#1',~but~you~have~tried~to~
    end~one~called~'#2'.~Environments~have~to~be~properly~nested.
  }
\__msg_kernel_new:nnnn { xparse } { environment-not-yet-defined }
  { Environment~'#1'~not~yet~defined! }
  {
    You~have~used~\RenewDocumentEnvironment
    with~an~environment~that~was~never~defined. \\
    A~new~environment~'#1'~will~be~created.
  }
\__msg_kernel_new:nnnn { xparse } { environment-unknown }
  { Environment~'#1'~undefined. }
  {
    You~have~tried~to~start~an~environment~called~'#1',~
    but~this~has~never~been~defined. \\
    The~command~will~be~ignored.
  }
\__msg_kernel_new:nnnn { xparse } { expandable-ending-optional }
  {
    Argument~specification~for~expandable~command~ends~with~optional~argument.
  }
  {
    \c__msg_coding_error_text_tl
    Expandable~commands~must~have~a~final~mandatory~argument~
    (or~no~arguments~at~all).~You~cannot~have~a~terminal~optional~
    argument~with~expandable~commands.
  }
\__msg_kernel_new:nnnn { xparse } { inconsistent-long }
  { Inconsistent~long~arguments~for~expandable~command. }
  {
    \c__msg_coding_error_text_tl
    The~arguments~for~an~expandable~command~must~either~all~be~
    short~or~all~be~long.~You~have~tried~to~mix~the~two~types.
  }
\__msg_kernel_new:nnnn { xparse } { invalid-expandable-argument-type }
  { Argument~type~'#1'~not~available~for~an~expandable~function. }
  {
    \c__msg_coding_error_text_tl
    The~letter~'#1'~does~not~specify~an~argument~type~which~can~be~used~
    in~an~expandable~function.
    \\ \\
    LaTeX~will~assume~you~want~a~standard~mandatory~argument~(type~'m').
  }
\__msg_kernel_new:nnnn { xparse } { missing-required }
  { Failed~to~find~required~argument~starting~with~'#1'. }
  {
    There~is~supposed~to~be~an~argument~to~the~current~function~starting~with~
    '#1'.~LaTeX~did~not~find~it,~and~will~insert~'#2'~as~the~value~to~be~
    processed.
  }
\__msg_kernel_new:nnnn { xparse } { not-single-token }
  { Argument~delimiter~should~be~a~single~token:~'#1'. }
  {
    \c__msg_coding_error_text_tl
    The~argument~specification~provided~was~not~valid:~
    in~a~place~where~a~single~token~is~required,~LaTeX~found~'#1'. \\ \\
    LaTeX~will~ignore~this~entire~definition.
  }
\__msg_kernel_new:nnnn { xparse } { processor-in-expandable }
  { Argument~processors~cannot~be~used~with~expandable~functions. }
  {
    \c__msg_coding_error_text_tl
    The~argument~specification~for~#1~contains~a~processor~function:~
    this~is~only~supported~for~standard~robust~functions.
  }
\__msg_kernel_new:nnnn { xparse } { split-excess-tokens }
  { Too~many~'#1'~tokens~when~trying~to~split~argument. }
  {
    LaTeX~was~asked~to~split~the~input~'#3'~
    at~each~occurrence~of~the~token~'#1',~up~to~a~maximum~of~#2~parts.~
    There~were~too~many~'#1'~tokens.
  }
\__msg_kernel_new:nnnn { xparse } { unknown-argument-type }
  { Unknown~argument~type~'#1'~replaced~by~'m'. }
  {
    \c__msg_coding_error_text_tl
    The~letter~'#1'~does~not~specify~a~known~argument~type.~
    LaTeX~will~assume~you~want~a~standard~mandatory~argument~(type~'m').
  }
\__msg_kernel_new:nnnn { xparse } { unknown-document-command }
  { Unknown~document~command~'#1'. }
  {
    You~have~asked~for~the~argument~specification~for~a~command~'#1',~
    but~this~is~not~a~document~command.
  }
\__msg_kernel_new:nnnn { xparse } { unknown-document-environment }
  { Unknown~document~environment~'#1'. }
  {
    You~have~asked~for~the~argument~specification~for~a~command~'#1',~
    but~this~is~not~a~document~environment.
  }
\__msg_kernel_new:nnnn { xparse } { verbatim-newline }
  { Verbatim~argument~of~'#1'~ended~by~end~of~line. }
  {
    The~verbatim~argument~of~'#1'~cannot~contain~more~than~one~line,~
    but~the~end~
    of~the~current~line~has~been~reached.~You~have~probably~forgotten~the~
    closing~delimiter.
    \\ \\
    LaTeX~will~ignore~'#2'.
  }
\__msg_kernel_new:nnnn { xparse } { verbatim-tokenized }
  {
    The~verbatim~command~'#1'~cannot~be~used~inside~an~argument.~
  }
  {
    The~command~'#1'~takes~a~verbatim~argument.~
    It~may~not~appear~within~the~argument~of~another~function.~
    It~received~an~illegal~token \tl_if_empty:nF {#3} { ~'#3' } .
    \\ \\
    LaTeX~will~ignore~'#2'.
  }
%    \end{macrocode}
%
% Intended more for information.
%    \begin{macrocode}
\__msg_kernel_new:nnn { xparse } { define-command }
  {
    Defining~command~#1~
    with~sig.~'#2'~\msg_line_context:.
  }
\__msg_kernel_new:nnn { xparse } { define-environment }
  {
    Defining~environment~'#1'~
    with~sig.~'#2'~\msg_line_context:.
  }
\__msg_kernel_new:nnn { xparse } { redefine-command }
  {
    Redefining~command~#1~
    with~sig.~'#2'~\msg_line_context:.
  }
\__msg_kernel_new:nnn { xparse } { redefine-environment }
  {
    Redefining~environment~'#1'~
    with~sig.~'#2'~\msg_line_context:.
  }
%    \end{macrocode}
%
% \subsection{User functions}
%
% The user functions are more or less just the internal functions
% renamed.
%
% \begin{macro}{\BooleanFalse}
% \begin{macro}{\BooleanTrue}
%   Design-space names for the Boolean values.
%    \begin{macrocode}
\cs_new_eq:NN \BooleanFalse \c_false_bool
\cs_new_eq:NN \BooleanTrue  \c_true_bool
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\DeclareDocumentCommand}
% \begin{macro}{\NewDocumentCommand}
% \begin{macro}{\RenewDocumentCommand}
% \begin{macro}{\ProvideDocumentCommand}
%   The user macros are pretty simple wrappers around the internal ones.
%    \begin{macrocode}
\cs_new_protected:Npn \DeclareDocumentCommand #1#2#3
  { \@@_declare_cmd:Nnn #1 {#2} {#3} }
\cs_new_protected:Npn \NewDocumentCommand #1#2#3
  {
    \cs_if_exist:NTF #1
      {
        \__msg_kernel_error:nnx { xparse } { command-already-defined }
          { \token_to_str:N #1 }
      }
      { \@@_declare_cmd:Nnn #1 {#2} {#3} }
  }
\cs_new_protected:Npn \RenewDocumentCommand #1#2#3
  {
    \cs_if_exist:NTF #1
      { \@@_declare_cmd:Nnn #1 {#2} {#3} }
      {
        \__msg_kernel_error:nnx { xparse } { command-not-yet-defined }
          { \token_to_str:N #1 }
      }
  }
\cs_new_protected:Npn \ProvideDocumentCommand #1#2#3
  { \cs_if_exist:NF #1 { \@@_declare_cmd:Nnn #1 {#2} {#3} } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\DeclareDocumentEnvironment}
% \begin{macro}{\NewDocumentEnvironment}
% \begin{macro}{\RenewDocumentEnvironment}
% \begin{macro}{\ProvideDocumentEnvironment}
%   Very similar for environments.
%    \begin{macrocode}
\cs_new_protected:Npn \DeclareDocumentEnvironment #1#2#3#4
  { \@@_declare_env:nnnn {#1} {#2} {#3} {#4} }
\cs_new_protected:Npn \NewDocumentEnvironment #1#2#3#4
  {
    \cs_if_exist:cTF {#1}
      { \__msg_kernel_error:nnx { xparse } { environment-already-defined } {#1} }
      { \@@_declare_env:nnnn {#1} {#2} {#3} {#4} }
}
\cs_new_protected:Npn \RenewDocumentEnvironment #1#2#3#4
  {
    \cs_if_exist:cTF {#1}
      { \@@_declare_env:nnnn {#1} {#2} {#3} {#4} }
      { \__msg_kernel_error:nnx { xparse } { environment-not-yet-defined } {#1} }
  }
\cs_new_protected:Npn \ProvideDocumentEnvironment #1#2#3#4
  { \cs_if_exist:cF { #1 } { \@@_declare_env:nnnn {#1} {#2} {#3} {#4} } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\DeclareExpandableDocumentCommand}
%   The expandable version of the basic function is essentially the same.
%    \begin{macrocode}
\cs_new_protected:Npn \DeclareExpandableDocumentCommand #1#2#3
  { \@@_declare_expandable_cmd:Nnn #1 {#2} {#3} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[TF]{\IfBoolean}
%   The logical \meta{true} and \meta{false} statements are just the
%   normal \cs{c_true_bool} and \cs{c_false_bool}, so testing for them is
%   done with the \cs{bool_if:NTF} functions from \textsf{l3prg}.
%    \begin{macrocode}
\cs_new_eq:NN \IfBooleanTF \bool_if:NTF
\cs_new_eq:NN \IfBooleanT  \bool_if:NT
\cs_new_eq:NN \IfBooleanF  \bool_if:NF
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[TF]{\IfNoValue}
%   Simple re-naming.
%    \begin{macrocode}
\cs_new_eq:NN \IfNoValueF  \@@_if_no_value:nF
\cs_new_eq:NN \IfNoValueT  \@@_if_no_value:nT
\cs_new_eq:NN \IfNoValueTF \@@_if_no_value:nTF
%    \end{macrocode}
% \end{macro}
% \begin{macro}[TF]{\IfValue}
%   Inverted logic.
%    \begin{macrocode}
\cs_set:Npn \IfValueF { \@@_if_no_value:nT }
\cs_set:Npn \IfValueT { \@@_if_no_value:nF }
\cs_set:Npn \IfValueTF #1#2#3 { \@@_if_no_value:nTF {#1} {#3} {#2} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ProcessedArgument}
%   Processed arguments are returned using this name, which is reserved
%   here although the definition will change.
%    \begin{macrocode}
\tl_new:N \ProcessedArgument
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ReverseBoolean, \SplitArgument, \SplitList, \TrimSpaces}
%   Simple copies.
%    \begin{macrocode}
\cs_new_eq:NN \ReverseBoolean \@@_bool_reverse:N
\cs_new_eq:NN \SplitArgument  \@@_split_argument:nnn
\cs_new_eq:NN \SplitList      \@@_split_list:nn
\cs_new_eq:NN \TrimSpaces     \@@_trim_spaces:n
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ProcessList}
%   To support \cs{SplitList}.
%    \begin{macrocode}
\cs_new_eq:NN \ProcessList \tl_map_function:nN
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\GetDocumentCommandArgSpec}
% \begin{macro}{\GetDocumentEnvironmentArgSpec}
% \begin{macro}{\ShowDocumentCommandArgSpec}
% \begin{macro}{\ShowDocumentEnvironmentArgSpec}
%   More simple mappings.
%    \begin{macrocode}
\cs_new_eq:NN \GetDocumentCommandArgSpec      \@@_get_arg_spec:N
\cs_new_eq:NN \GetDocumentEnvironmmentArgSpec \@@_get_arg_spec:n
\cs_new_eq:NN \ShowDocumentCommandArgSpec     \@@_show_arg_spec:N
\cs_new_eq:NN \ShowDocumentEnvironmentArgSpec \@@_show_arg_spec:n
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Package options}
%
% \begin{variable}{\l_@@_options_clist}
% \begin{variable}{\l_@@_log_bool}
%   Key--value option to log information: done by hand to keep dependencies
%   down.
%    \begin{macrocode}
\clist_new:N \l_@@_options_clist
\DeclareOption* { \clist_put_right:NV \l_@@_options_clist \CurrentOption }
\ProcessOptions \relax
\keys_define:nn { xparse }
  {
    log-declarations .bool_set:N = \l_@@_log_bool ,
    log-declarations .initial:n  = true
  }
\keys_set:nV { xparse } \l_@@_options_clist
\bool_if:NF \l_@@_log_bool
  {
    \msg_redirect_module:nnn { LaTeX / xparse } { info }    { none }
    \msg_redirect_module:nnn { LaTeX / xparse } { warning } { none }
  }
%    \end{macrocode}
% \end{variable}
% \end{variable}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
