% \iffalse meta-comment
%
%% File: l3quark.dtx
%
% Copyright (C) 1990-2026 The LaTeX 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
%
%    https://www.latex-project.org/lppl.txt
%
% This file is part of the "l3kernel bundle" (The Work in LPPL)
% and all files in that bundle must be distributed together.
%
% -----------------------------------------------------------------------
%
% The development version of the bundle can be found at
%
%    https://github.com/latex3/latex3
%
% for those people who are interested.
%
%<*driver>
\documentclass[full,kernel]{l3doc}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \pkg{l3quark} module\\ Quarks and scan marks^^A
% }\ifdefined\thechapter\label{sec:l3quarks}\fi
%
% \author{^^A
%  The \LaTeX{} Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released 2026-02-18}
%
% \maketitle
%
% \begin{documentation}
%
% Two special types of constants in \LaTeX3 are \enquote{quarks} and
% \enquote{scan marks}. By convention all constants of type quark
% start out with |\q_|, and scan marks start with |\s_|.
%
% \section{Quarks}
%
% Quarks are control sequences (and in fact, token lists) that expand
% to themselves and should
% therefore \emph{never} be executed directly in the code.
% This would result in an endless loop!
%
% They are meant to be used as delimiter in weird functions, the most
% common use case being the `stop token' (i.e., \cs{q_stop}).
% For example, when writing a macro to parse a user-defined date
% \begin{verbatim}
%   \date_parse:n {19/June/1981}
% \end{verbatim}
% one might write a command such as
% \begin{verbatim}
%   \cs_new:Npn \date_parse:n #1 { \date_parse_aux:w #1 \q_stop }
%   \cs_new:Npn \date_parse_aux:w #1 / #2 / #3 \q_stop
%     { <do something with the date> }
% \end{verbatim}
%
% Quarks are sometimes also used as error return values for functions
% that receive erroneous input.
% For example, in the function \cs{prop_get:NnN} to retrieve a value stored
% in some key of a property list, if the key does not exist then the return value
% is the quark \cs{q_no_value}.
% As mentioned above, such quarks are extremely fragile and it is imperative
% when using such functions that code is carefully written to check for
% pathological cases to avoid leakage of a quark into an uncontrolled
% environment.
%
% Quarks also permit the
% following ingenious trick when parsing tokens:
% when you pick up a token in a temporary variable
% and you want to know whether you have picked up a particular quark,
% all you have to do is compare the temporary variable to the quark using
% \cs{tl_if_eq:NNTF}. A set of special quark testing functions is set up
% below. All the quark testing functions are expandable although the
% ones testing only single tokens are much faster.
%
% \section{Defining quarks}
%
% \begin{function}{\quark_new:N}
%   \begin{syntax}
%     \cs{quark_new:N} \meta{quark}
%   \end{syntax}
%   Creates a new \meta{quark} which expands only to \meta{quark}.
%   The \meta{quark} is defined globally, and an error message
%   is raised if the name was already taken.
% \end{function}
%
% \begin{variable}{\q_stop}
%   Used as a marker for delimited arguments, such as
%   \begin{verbatim}
%     \cs_set:Npn \tmp:w #1#2 \q_stop {#1}
%   \end{verbatim}
% \end{variable}
%
% \begin{variable}{\q_mark}
%   Used as a marker for delimited arguments when \cs{q_stop} is
%   already in use.
% \end{variable}
%
% \begin{variable}{\q_nil}
%   Quark to mark a null value in structured variables or functions. Used
%   as an end delimiter when this may itself need to be tested
%   (in contrast to \cs{q_stop}, which is only ever used as a delimiter).
% \end{variable}
%
% \begin{variable}{\q_no_value}
%   A canonical value for a missing value, when one is requested from
%   a data structure. This is therefore used as a \enquote{return} value
%   by functions such as \cs{prop_get:NnN} if there is no data to
%   return.
% \end{variable}
%
% \section{Quark tests}
%
% The method used to define quarks means that the single token (\texttt{N})
% tests are faster than the multi-token (\texttt{n}) tests. The latter
% should therefore only be used when the argument can definitely take
% more than a single token.
%
% \begin{function}[EXP,pTF]{\quark_if_nil:N}
%   \begin{syntax}
%     \cs{quark_if_nil_p:N} \meta{token}
%     \cs{quark_if_nil:NTF} \meta{token} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests if the \meta{token} is equal to \cs{q_nil}.
% \end{function}
%
% \begin{function}[EXP,pTF]{\quark_if_nil:n, \quark_if_nil:o, \quark_if_nil:V}
%   \begin{syntax}
%     \cs{quark_if_nil_p:n} \Arg{token list} \\
%     \cs{quark_if_nil:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests if the \meta{token list} contains only \cs{q_nil} (distinct
%   from \meta{token list} being empty or containing \cs{q_nil} plus one
%   or more other tokens).
% \end{function}
%
% \begin{function}[EXP,pTF]{\quark_if_no_value:N, \quark_if_no_value:c}
%   \begin{syntax}
%     \cs{quark_if_no_value_p:N} \meta{token} \\
%     \cs{quark_if_no_value:NTF} \meta{token} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests if the \meta{token} is equal to \cs{q_no_value}.
% \end{function}
%
% \begin{function}[EXP,pTF]{\quark_if_no_value:n}
%   \begin{syntax}
%      \cs{quark_if_no_value_p:n} \Arg{token list} \\
%     \cs{quark_if_no_value:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests if the \meta{token list} contains only \cs{q_no_value}
%   (distinct from \meta{token list} being empty or containing
%   \cs{q_no_value} plus one or more other tokens).
% \end{function}
%
% \section{Recursion}
%
% This module provides a uniform interface to intercepting and
% terminating loops as when one is doing tail recursion. The building
% blocks follow below and an example is shown in
% Section~\ref{sec:l3quark:quark-example}.
%
% \begin{variable}{\q_recursion_tail}
%   This quark is appended to the data structure in question and
%   appears as a real element there. This means it gets any list
%   separators around it.
% \end{variable}
%
% \begin{variable}{\q_recursion_stop}
%   This quark is added \emph{after} the data structure. Its purpose
%   is to make it possible to terminate the recursion at any point
%   easily.
% \end{variable}
%
% \begin{function}[EXP]{\quark_if_recursion_tail_stop:N}
%   \begin{syntax}
%     \cs{quark_if_recursion_tail_stop:N} \meta{token}
%   \end{syntax}
%   Tests if \meta{token} contains only the marker
%   \cs{q_recursion_tail}, and if so uses
%   \cs{use_none_delimit_by_q_recursion_stop:w} to terminate the
%   recursion that this belongs to. The
%   recursion input must include the marker tokens \cs{q_recursion_tail}
%   and \cs{q_recursion_stop} as the last two items.
% \end{function}
%
% \begin{function}[EXP,updated = 2011-09-06]
%   {\quark_if_recursion_tail_stop:n, \quark_if_recursion_tail_stop:o}
%   \begin{syntax}
%     \cs{quark_if_recursion_tail_stop:n} \Arg{token list}
%   \end{syntax}
%   Tests if the \meta{token list} contains only
%   \cs{q_recursion_tail}, and if so uses
%   \cs{use_none_delimit_by_q_recursion_stop:w} to terminate the
%   recursion that this belongs to. The
%   recursion input must include the marker tokens \cs{q_recursion_tail}
%   and \cs{q_recursion_stop} as the last two items.
% \end{function}
%
% \begin{function}[EXP]{\quark_if_recursion_tail_stop_do:Nn}
%   \begin{syntax}
%     \cs{quark_if_recursion_tail_stop_do:Nn} \meta{token} \Arg{insertion}
%   \end{syntax}
%   Tests if \meta{token} contains only the marker
%   \cs{q_recursion_tail}, and if so uses
%   \cs{use_i_delimit_by_q_recursion_stop:w} to terminate the
%   recursion that this belongs to. The
%   recursion input must include the marker tokens \cs{q_recursion_tail}
%   and \cs{q_recursion_stop} as the last two items. The \meta{insertion}
%   code is then added to the input stream after the recursion has
%   ended.
% \end{function}
%
% \begin{function}[EXP,updated = 2011-09-06]
%   {\quark_if_recursion_tail_stop_do:nn, \quark_if_recursion_tail_stop_do:on}
%   \begin{syntax}
%     \cs{quark_if_recursion_tail_stop_do:nn} \Arg{token list} \Arg{insertion}
%   \end{syntax}
%   Tests if the \meta{token list} contains only
%   \cs{q_recursion_tail}, and if so uses
%   \cs{use_i_delimit_by_q_recursion_stop:w} to terminate the
%   recursion that this belongs to. The
%   recursion input must include the marker tokens \cs{q_recursion_tail}
%   and \cs{q_recursion_stop} as the last two items. The \meta{insertion}
%   code is then added to the input stream after the recursion has
%   ended.
% \end{function}
%
%
% \begin{function}[EXP,added = 2018-04-10]
%   {
%     \quark_if_recursion_tail_break:NN,
%     \quark_if_recursion_tail_break:nN
%   }
%   \begin{syntax}
%     \cs{quark_if_recursion_tail_break:nN} \Arg{token list} \cs[no-index]{\meta{type}_map_break:}
%   \end{syntax}
%   Tests if \meta{token list} contains only \cs{q_recursion_tail}, and
%   if so terminates the recursion using \cs[no-index]{\meta{type}_map_break:}.
%   The recursion end should be marked by \cs{prg_break_point:Nn}
%   \cs[no-index]{\meta{type}_map_break:}.
% \end{function}
%
% \subsection{An example of recursion with quarks}
% \label{sec:l3quark:quark-example}
%
% Quarks are mainly used internally in the \pkg{expl3} code to define
% recursion functions such as \cs{tl_map_inline:nn} and so on.
% Here is a small example to demonstrate how to use quarks in this fashion.
% We shall define a command called |\my_map_dbl:nn| which takes a token list
% and applies an operation to every \emph{pair} of tokens.
% For example, |\my_map_dbl:nn {abcd} {[--#1--#2--]~}| would produce
% \enquote{\ttfamily [--a--b--]~[--c--d--]~}.
% Using quarks to define such functions simplifies their logic and ensures
% robustness in many cases.
%
%
% Here's the definition of |\my_map_dbl:nn|.
% First of all, define the function that does the processing based on the
% inline function argument |#2|.
% Then initiate the recursion using an internal function.
% The token list |#1| is terminated using \cs{q_recursion_tail}, with
% delimiters according to the type of recursion (here a pair of
% \cs{q_recursion_tail}), concluding with \cs{q_recursion_stop}.
% These quarks are used to mark the end of the token list being operated upon.
%\begin{verbatim}
% \cs_new:Npn \my_map_dbl:nn #1#2
%  {
%    \cs_set:Npn \__my_map_dbl_fn:nn ##1 ##2 {#2}
%    \__my_map_dbl:nn #1 \q_recursion_tail \q_recursion_tail
%    \q_recursion_stop
%  }
%\end{verbatim}
%
% The definition of the internal recursion function follows.
% First check if either of the input tokens are the termination quarks.
% Then, if not, apply the inline function to the two arguments.
%\begin{verbatim}
% \cs_new:Nn \__my_map_dbl:nn
%  {
%    \quark_if_recursion_tail_stop:n {#1}
%    \quark_if_recursion_tail_stop:n {#2}
%    \__my_map_dbl_fn:nn {#1} {#2}
%\end{verbatim}
% Finally, recurse:
%\begin{verbatim}
%    \__my_map_dbl:nn
%  }
%\end{verbatim}
% Note that contrarily to \LaTeX3 built-in mapping functions, this
% mapping function cannot be nested, since the second map would overwrite
% the definition of |\__my_map_dbl_fn:nn|.
%
% \section{Scan marks}
%
% Scan marks are control sequences set equal to \cs{scan_stop:},
% hence never expand in an expansion context and are (largely)
% invisible if they are encountered in a typesetting context.
%
% Like quarks, they can be used as delimiters in weird functions
% and are often safer to use for this purpose.
% Since they are harmless when executed by \TeX{} in non-expandable
% contexts, they can be used to mark the end of a set of instructions.
% This allows to skip to that point if the end of the instructions
% should not be performed (see \pkg{l3regex}).
%
% \begin{function}[added = 2018-04-01]{\scan_new:N}
%   \begin{syntax}
%     \cs{scan_new:N} \meta{scan mark}
%   \end{syntax}
%   Creates a new \meta{scan mark} which is set equal to \cs{scan_stop:}.
%   The \meta{scan mark} is defined globally, and an error message
%   is raised if the name was already taken by another scan mark.
% \end{function}
%
% \begin{variable}[added = 2018-04-01]{\s_stop}
%   Used at the end of a set of instructions, as a marker
%   that can be jumped to using \cs{use_none_delimit_by_s_stop:w}.
% \end{variable}
%
% \begin{function}[EXP,added = 2018-04-01]{\use_none_delimit_by_s_stop:w}
%   \begin{syntax}
%     \cs{use_none_delimit_by_s_stop:w} \meta{tokens} \cs{s_stop}
%   \end{syntax}
%   Removes the \meta{tokens} and \cs{s_stop} from the input stream.
%   This leads to a low-level \TeX{} error if \cs{s_stop} is absent.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3quark} implementation}
%
% \TestFiles{m3quark001.lvt}
%
%    \begin{macrocode}
%<*code>
%    \end{macrocode}
%
% \subsection{Quarks}
%
%    \begin{macrocode}
%<@@=quark>
%    \end{macrocode}
%
% \begin{macro}{\quark_new:N}
% \UnitTested
%    Allocate a new quark.
%    \begin{macrocode}
\cs_new_protected:Npn \quark_new:N #1
  {
    \__kernel_chk_if_free_cs:N #1
    \cs_gset_nopar:Npn #1 {#1}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{variable}{\q_nil, \q_mark, \q_no_value, \q_stop}
%   Some \enquote{public} quarks. \cs{q_stop} is an \enquote{end of
%   argument} marker, \cs{q_nil} is a empty value and \cs{q_no_value}
%   marks an empty argument.
%    \begin{macrocode}
\quark_new:N \q_nil
\quark_new:N \q_mark
\quark_new:N \q_no_value
\quark_new:N \q_stop
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\q_recursion_tail, \q_recursion_stop}
%   Quarks for ending recursions. Only ever used there!
%   \cs{q_recursion_tail} is appended to whatever list structure we are
%   doing recursion on, meaning it is added as a proper list item with
%   whatever list separator is in use.  \cs{q_recursion_stop} is placed
%   directly after the list.
%    \begin{macrocode}
\quark_new:N \q_recursion_tail
\quark_new:N \q_recursion_stop
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\s_@@}
%   Private scan mark used in \pkg{l3quark}.  We don't have \pkg{l3scan}
%   yet, so we declare the scan mark here and add it to the scan mark pool
%   later.
%    \begin{macrocode}
\cs_new_eq:NN \s_@@ \scan_stop:
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\q_@@_nil}
%   Private quark use for some tests.
%    \begin{macrocode}
\quark_new:N \q_@@_nil
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}[EXP]{\quark_if_recursion_tail_stop:N}
% \UnitTested
% \begin{macro}[EXP]{\quark_if_recursion_tail_stop_do:Nn}
% \UnitTested
%   When doing recursions, it is easy to spend a lot of time testing if the
%   end marker has been found. To avoid this, a dedicated end marker is used
%   each time a recursion is set up. Thus if the marker is found everything
%   can be wrapper up and finished off. The simple case is when the test
%   can guarantee that only a single token is being tested. In this case,
%   there is just a dedicated copy of the standard quark test. Both a gobbling
%   version and one inserting end code are provided.
%    \begin{macrocode}
\cs_new:Npn \quark_if_recursion_tail_stop:N #1
  {
    \if_meaning:w \q_recursion_tail #1
      \exp_after:wN \use_none_delimit_by_q_recursion_stop:w
    \fi:
  }
\cs_new:Npn \quark_if_recursion_tail_stop_do:Nn #1
  {
    \if_meaning:w \q_recursion_tail #1
      \exp_after:wN \use_i_delimit_by_q_recursion_stop:nw
    \else:
      \exp_after:wN \use_none:n
    \fi:
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]
%   {\quark_if_recursion_tail_stop:n, \quark_if_recursion_tail_stop:o}
% \UnitTested
% \begin{macro}[EXP]
%   {\quark_if_recursion_tail_stop_do:nn, \quark_if_recursion_tail_stop_do:on}
% \UnitTested
% \begin{macro}[EXP]{\@@_if_recursion_tail:w}
%   See \cs{quark_if_nil:nTF} for the details.  Expanding
%   \cs{@@_if_recursion_tail:w} once in front of the tokens chosen here
%   gives an empty result if and only if |#1|~is exactly
%   \cs{q_recursion_tail}.
%    \begin{macrocode}
\cs_new:Npn \quark_if_recursion_tail_stop:n #1
  {
    \tl_if_empty:oTF
      { \@@_if_recursion_tail:w {} #1 {} ?! \q_recursion_tail ??! }
      { \use_none_delimit_by_q_recursion_stop:w }
      { }
  }
\cs_new:Npn \quark_if_recursion_tail_stop_do:nn #1
  {
    \tl_if_empty:oTF
      { \@@_if_recursion_tail:w {} #1 {} ?! \q_recursion_tail ??! }
      { \use_i_delimit_by_q_recursion_stop:nw }
      { \use_none:n }
  }
\cs_new:Npn \@@_if_recursion_tail:w
    #1 \q_recursion_tail #2 ? #3 ?! { #1 #2 }
\cs_generate_variant:Nn \quark_if_recursion_tail_stop:n { o }
\cs_generate_variant:Nn \quark_if_recursion_tail_stop_do:nn { o }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\quark_if_recursion_tail_break:NN}
% \begin{macro}[EXP]{\quark_if_recursion_tail_break:nN}
%   Analogues of the \cs[index=quark_if_recursion_tail_stop:n]
%   {quark_if_recursion_tail_stop\ldots{}} functions.
%   Break the mapping using |#2|.
%    \begin{macrocode}
\cs_new:Npn \quark_if_recursion_tail_break:NN #1#2
  {
    \if_meaning:w \q_recursion_tail #1
      \exp_after:wN #2
    \fi:
  }
\cs_new:Npn \quark_if_recursion_tail_break:nN #1#2
  {
    \tl_if_empty:oT
      { \@@_if_recursion_tail:w {} #1 {} ?! \q_recursion_tail ??! }
      {#2}
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[pTF]{\quark_if_nil:N}
% \UnitTested
% \begin{macro}[pTF]{\quark_if_no_value:N, \quark_if_no_value:c}
% \UnitTested
%   Here we test if we found a special quark as the first argument.
%   We better start with \cs{q_no_value} as the first argument since
%   the whole thing may otherwise loop if |#1| is wrongly given
%   a string like |aabc| instead of a single token.\footnote{It may
%   still loop in special circumstances however!}
%    \begin{macrocode}
\prg_new_conditional:Npnn \quark_if_nil:N #1 { p, T , F , TF }
  {
    \if_meaning:w \q_nil #1
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
\prg_new_conditional:Npnn \quark_if_no_value:N #1 { p, T , F , TF }
  {
    \if_meaning:w \q_no_value #1
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
\prg_generate_conditional_variant:Nnn \quark_if_no_value:N
  { c } { p , T , F , TF }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[pTF]{\quark_if_nil:n, \quark_if_nil:V, \quark_if_nil:o}
% \UnitTested
% \begin{macro}[pTF]{\quark_if_no_value:n}
% \UnitTested
% \begin{macro}{\@@_if_nil:w, \@@_if_no_value:w}
% \begin{macro}[EXP]{\@@_if_empty_if:o}
%   Let us explain \cs{quark_if_nil:nTF}.  Expanding \cs{@@_if_nil:w}
%   once is safe thanks to the trailing \cs{q_nil} |??!|.  The result of
%   expanding once is empty if and only if both delimited arguments |#1|
%   and~|#2| are empty and |#3|~is delimited by the last tokens~|?!|.
%   Thanks to the leading~|{}|, the argument~|#1| is empty if and only
%   if the argument of \cs{quark_if_nil:n} starts with \cs{q_nil}.  The
%   argument~|#2| is empty if and only if this \cs{q_nil} is followed
%   immediately by~|?| or by~|{}?|, coming either from the trailing
%   tokens in the definition of \cs{quark_if_nil:n}, or from its
%   argument.  In the first case, \cs{@@_if_nil:w} is followed by
%   |{}\q_nil| |{}?| |!\q_nil|~|??!|, hence |#3|~is delimited by the
%   final~|?!|, and the test returns \texttt{true} as wanted.  In the
%   second case, the result is not empty since the first~|?!| in the
%   definition of \cs{quark_if_nil:n} stop~|#3|. The auxiliary here
%   is the same as \cs{__tl_if_empty_if:o}, with the same comments
%   applying.
%    \begin{macrocode}
\prg_new_conditional:Npnn \quark_if_nil:n #1 { p, T , F , TF }
  {
    \@@_if_empty_if:o
      { \@@_if_nil:w {} #1 {} ? ! \q_nil ? ? ! }
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
\cs_new:Npn \@@_if_nil:w #1 \q_nil #2 ? #3 ? ! { #1 #2 }
\prg_new_conditional:Npnn \quark_if_no_value:n #1 { p, T , F , TF }
  {
    \@@_if_empty_if:o
      { \@@_if_no_value:w {} #1 {} ? ! \q_no_value ? ? ! }
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
\cs_new:Npn \@@_if_no_value:w #1 \q_no_value #2 ? #3 ? ! { #1 #2 }
\prg_generate_conditional_variant:Nnn \quark_if_nil:n
  { V , o } { p , TF , T , F }
\cs_new:Npn \@@_if_empty_if:o #1
  {
    \exp_after:wN \if_meaning:w \exp_after:wN \q_nil
      \__kernel_tl_to_str:w \exp_after:wN {#1} \q_nil
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\__kernel_quark_new_test:N}
%   The function \cs{__kernel_quark_new_test:N} defines |#1| in a
%   similar way as \cs[no-index]{quark_if_recursion_tail_...} functions
%   (as described below), using
%   \cs[no-index]{q__\meta{namespace}_recursion_tail} as the test quark
%   and \cs[no-index]{q__\meta{namespace}_recursion_stop} as the
%   delimiter quark, where the \meta{namespace} is determined as the
%   first |_|-delimited part in~|#1|.
%
%   There are six possible function types which this function can define,
%   and which is defined depends on the signature of the function being
%   defined:
%   \begin{description}
%     \def\makelabel#1{\texttt{:#1}~}
%     \item[n]  gives an analogue of \cs{quark_if_recursion_tail_stop:n}
%     \item[nn] gives an analogue of \cs{quark_if_recursion_tail_stop_do:nn}
%     \item[nN] gives an analogue of \cs{quark_if_recursion_tail_break:nN}
%     \item[N]  gives an analogue of \cs{quark_if_recursion_tail_stop:N}
%     \item[Nn] gives an analogue of \cs{quark_if_recursion_tail_stop_do:Nn}
%     \item[NN] gives an analogue of \cs{quark_if_recursion_tail_break:NN}
%   \end{description}
%   Any other signature causes an error, as does a function without signature.
%
% \begin{macro}{\__kernel_quark_new_conditional:Nn}
%   Similar to \cs{__kernel_quark_new_test:N}, but defines quark
%   branching conditionals like \cs{quark_if_nil:nTF} that test for the
%   quark \cs[no-index]{q__\meta{namespace}_\meta{name}}.
%   The \meta{namespace} and \meta{name} are determined from the
%   conditional~|#1|, which must take the rather rigid form
%   \cs[no-index]{__\meta{namespace}_quark_if_\meta{name}:\meta{arg spec}}.
%   There are only two cases for the \meta{arg spec} here:
%   \begin{description}
%     \def\makelabel#1{\texttt{:#1}~}
%     \item[n] gives an analogue of \cs{quark_if_nil:nTF}
%     \item[N] gives an analogue of \cs{quark_if_nil:NTF}
%   \end{description}
%   Any other signature causes an error, as does a function without signature.
%   We use low-level emptiness tests as \pkg{l3tl} is not available yet when these
%   functions are used; thankfully we only care about whether strings
%   are empty so a simple \cs{if_meaning:w} \cs{q_nil} \meta{string}
%   \cs{q_nil} suffices.
%
% \begin{macro}{\@@_new_test:NNNn, \@@_new_test:Nccn,
%   \@@_new_test_aux:nnNNnnnn}
% \begin{macro}{\@@_new_conditional:Nnnn, \@@_new_conditional:Neen}
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_quark_new_test:N #1
  { \@@_new_test_aux:Ne #1 { \@@_module_name:N #1 } }
\cs_new_protected:Npn \@@_new_test_aux:Nn #1 #2
  {
    \if_meaning:w \q_nil #2 \q_nil
      \msg_error:nne { quark } { invalid-function }
        { \token_to_str:N #1 }
    \else:
      \@@_new_test:Nccn #1
        { q__#2_recursion_tail } { q__#2_recursion_stop } { __#2 }
    \fi:
  }
\cs_generate_variant:Nn \@@_new_test_aux:Nn { Ne }
\cs_new_protected:Npn \@@_new_test:NNNn #1
  {
    \exp_last_unbraced:Nf \@@_new_test_aux:nnNNnnnn
      { \cs_split_function:N #1 }
      #1 { test }
  }
\cs_generate_variant:Nn \@@_new_test:NNNn { Ncc }
\cs_new_protected:Npn \__kernel_quark_new_conditional:Nn #1
  {
    \@@_new_conditional:Neen #1
      { \@@_quark_conditional_name:N #1 }
      { \@@_module_name:N #1 }
  }
\cs_new_protected:Npn \@@_new_conditional:Nnnn #1#2#3#4
  {
    \if_meaning:w \q_nil #2 \q_nil
      \msg_error:nne { quark } { invalid-function }
        { \token_to_str:N #1 }
    \else:
      \if_meaning:w \q_nil #3 \q_nil
        \msg_error:nne { quark } { invalid-function }
          { \token_to_str:N #1 }
      \else:
        \exp_last_unbraced:Nf \@@_new_test_aux:nnNNnnnn
          { \cs_split_function:N #1 }
          #1 { conditional }
          {#2} {#3} {#4}
      \fi:
    \fi:
  }
\cs_generate_variant:Nn \@@_new_conditional:Nnnn { Nee }
\cs_new_protected:Npn \@@_new_test_aux:nnNNnnnn #1 #2 #3 #4 #5
  {
    \cs_if_exist_use:cTF { @@_new_#5_#2:Nnnn } { #4 }
      {
        \msg_error:nnee { quark } { invalid-function }
          { \token_to_str:N #4 } {#2}
        \use_none:nnn
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{
%     \@@_new_test_n:Nnnn, \@@_new_test_nn:Nnnn,
%     \@@_new_test_N:Nnnn, \@@_new_test_Nn:Nnnn,
%     \@@_new_test_NN:Nnnn, \@@_new_test_NN:Nnnn,
%   }
%   These macros implement the six possibilities mentioned above, passing
%   the right arguments to \cs{@@_new_test_aux_do:nNNnnnnNNn},
%   which defines some auxiliaries, and then to
%   \cs{@@_new_test_define_tl:nNnNNn} (|:n(n)| variants) or to
%   \cs{@@_new_test_define_ifx:nNnNNn} (|:N(n)|) which define the
%   main conditionals.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_new_test_n:Nnnn #1 #2 #3 #4
  {
    \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { none } { } { } { }
      \@@_new_test_define_tl:nNnNNn #1 { }
  }
\cs_new_protected:Npn \@@_new_test_nn:Nnnn #1 #2 #3 #4
  {
    \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2}
      \@@_new_test_define_tl:nNnNNn #1 { \use_none:n }
  }
\cs_new_protected:Npn \@@_new_test_nN:Nnnn #1 #2 #3 #4
  {
    \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2}
      \@@_new_test_define_break_tl:nNNNNn #1 { }
  }
\cs_new_protected:Npn \@@_new_test_N:Nnnn #1 #2 #3 #4
  {
    \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { none } { } { } { }
      \@@_new_test_define_ifx:nNnNNn #1 { }
  }
\cs_new_protected:Npn \@@_new_test_Nn:Nnnn #1 #2 #3 #4
  {
    \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2}
      \@@_new_test_define_ifx:nNnNNn #1
      { \else: \exp_after:wN \use_none:n }
  }
\cs_new_protected:Npn \@@_new_test_NN:Nnnn #1 #2 #3 #4
  {
    \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2}
      \@@_new_test_define_break_ifx:nNNNNn #1 { }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{
%     \@@_new_test_aux_do:nNNnnnnNNn,
%     \@@_test_define_aux:NNNNnnNNn
%   }
%   \cs{@@_new_test_aux_do:nNNnnnnNNn} makes the control sequence names
%   which will be used by \cs{@@_test_define_aux:NNNNnnNNn}, and then later
%   by \cs{@@_new_test_define_tl:nNnNNn} or
%   \cs{@@_new_test_define_ifx:nNnNNn}. The control sequences defined
%   here are analogous to \cs{@@_if_recursion_tail:w} and to
%   \cs[no-index]{use_(none|i)_delimit_by_q_recursion_stop:(|n)w}.
%
%   The name is composed by the name-space and the name of the quarks.
%   Suppose \cs{__kernel_quark_new_test:N} was used with:
%   \begin{verbatim}
%     \__kernel_quark_new_test:N \__test_quark_tail:n
%   \end{verbatim}
%   then the first auxiliary will be \cs[no-index]{__test_quark_recursion_tail:w},
%   and the second one will be
%   \cs[no-index]{__test_use_none_delimit_by_q_recursion_stop:w}.
%
%   Note that the actual quarks are \emph{not} defined here. They should
%   be defined separately using \cs{quark_new:N}.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_new_test_aux_do:nNNnnnnNNn #1 #2 #3 #4 #5
  {
    \exp_args:Ncc \@@_test_define_aux:NNNNnnNNn
      { #1 _quark_recursion_tail:w }
      { #1 _use_ #4 _delimit_by_q_recursion_stop: #5 w }
      #2 #3
  }
\cs_new_protected:Npn \@@_test_define_aux:NNNNnnNNn #1 #2 #3 #4 #5 #6 #7
  {
    \cs_gset:Npn #1  ##1 #3 ##2 ? ##3 ?! { ##1 ##2 }
    \cs_gset:Npn #2  ##1 #6 #4 {#5}
    #7 {##1} #1 #2 #3
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{
%     \@@_new_test_define_tl:nNnNNn,
%     \@@_new_test_define_ifx:nNnNNn
%   }
% \begin{macro}{
%     \@@_new_test_define_break_tl:nNNNNn,
%     \@@_new_test_define_break_ifx:nNNNNn
%   }
%   Finally, these two macros define the main conditional function using
%   what's been set up before.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_new_test_define_tl:nNnNNn #1 #2 #3 #4 #5 #6
  {
    \cs_new:Npn #5 #1
      {
        \tl_if_empty:oTF
          { #2 {} ##1 {} ?! #4 ??! }
          {#3} {#6}
      }
  }
\cs_new_protected:Npn \@@_new_test_define_ifx:nNnNNn #1 #2 #3 #4 #5 #6
  {
    \cs_new:Npn #5 #1
      {
        \if_meaning:w #4 ##1
          \exp_after:wN #3
          #6
        \fi:
      }
  }
\cs_new_protected:Npn \@@_new_test_define_break_tl:nNNNNn #1 #2 #3
  { \@@_new_test_define_tl:nNnNNn {##1##2} #2 {##2} }
\cs_new_protected:Npn \@@_new_test_define_break_ifx:nNNNNn #1 #2 #3
  { \@@_new_test_define_ifx:nNnNNn {##1##2} #2 {##2} }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{
%     \@@_new_conditional_n:Nnnn,
%     \@@_new_conditional_N:Nnnn,
%     \@@_new_conditional_n_aux:NNNn,
%     \@@_new_conditional_N_aux:NNNn
%   }
%   These macros implement the two possibilities for branching quark
%   conditionals. To avoid constructing without defining the
%   \cs[no-index]{__\meta{type}_if_quark_\meta{name}:w} helper,
%   \texttt{N}-type function accepts a \cs{prg_do_nothing:} as
%   a placeholder.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_new_conditional_n:Nnnn #1 #2 #3
  {
    \exp_args:Ncc \@@_new_conditional_n_aux:NNNn
      { __ #3 _if_quark_ #2 :w } { q__ #3 _ #2 } #1
  }
\cs_new_protected:Npn \@@_new_conditional_N:Nnnn #1 #2 #3
  {
    \exp_args:NNc \@@_new_conditional_N_aux:NNNn
      \prg_do_nothing: { q__ #3 _ #2 } #1
  }
\cs_new_protected:Npn \@@_new_conditional_n_aux:NNNn #1 #2 #3 #4
  {
    \cs_gset:Npn #1 ##1 #2 ##2 ? ##3 ?! { ##1##2 }
    \prg_new_conditional:Npnn #3 ##1 {#4}
      {
        \@@_if_empty_if:o { #1 {} ##1 {} ?! #2 ??! }
          \prg_return_true:
        \else:
          \prg_return_false:
        \fi:
      }
  }
\cs_new_protected:Npn \@@_new_conditional_N_aux:NNNn #1 #2 #3 #4
  {
    \prg_new_conditional:Npnn #3 ##1 {#4}
      {
        \if_meaning:w #2 ##1
          \prg_return_true:
        \else:
          \prg_return_false:
        \fi:
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\@@_module_name:N}
% \begin{macro}[EXP]{
%     \@@_module_name:w,
%     \@@_module_name_loop:w,
%     \@@_module_name_end:w
%   }
%   \cs{@@_module_name:N} takes a control sequence and returns its
%   \meta{module} name, determined as the first non-empty
%   non-single-character word, separated by |_| or~|:|.  These rules
%   give the correct result for public functions
%   \cs[no-index]{\meta{module}_\ldots{}}, private functions
%   \cs[no-index]{__\meta{module}_\ldots{}}, and variables such as
%   \cs[no-index]{l_\meta{module}_\ldots{}}.  If no valid module is
%   found the result is an empty string.  The approach is to first cut
%   off everything after the (first) |:| if any is present, then
%   repeatedly grab |_|-delimited words until finding one of length at
%   least~$2$ (we use low-level tests as \pkg{l3tl} is not fully
%   available when \cs{__kernel_quark_new_test:N} is first used.
%   If no \meta{module} is found (such as in \cs{::n}) we
%   get the trailing marker \cs{use_none:n} |{}|, which expands to
%   nothing.
%    \begin{macrocode}
\cs_set:Npn \@@_tmp:w #1#2
  {
    \cs_new:Npn \@@_module_name:N ##1
      {
        \exp_last_unbraced:Nf \@@_module_name:w
          { \cs_to_str:N ##1 } #1 \s_@@
      }
    \cs_new:Npn \@@_module_name:w ##1 #1 ##2 \s_@@
      { \@@_module_name_loop:w ##1 #2 \use_none:n { } #2 \s_@@ }
    \cs_new:Npn \@@_module_name_loop:w ##1 #2
      {
        \use_i_ii:nnn \if_meaning:w \prg_do_nothing:
            ##1 \prg_do_nothing: \prg_do_nothing:
          \exp_after:wN \@@_module_name_loop:w
        \else:
          \@@_module_name_end:w ##1
        \fi:
      }
    \cs_new:Npn \@@_module_name_end:w
      ##1 \fi: ##2 \s_@@ { \fi: ##1 }
  }
\exp_after:wN \@@_tmp:w \tl_to_str:n { : _ }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\@@_quark_conditional_name:N, \@@_quark_conditional_name:w}
%   \cs{@@_quark_conditional_name:N} determines the quark name that the quark
%   conditional function~|##1| queries, as the part of the function name
%   between |_quark_if_| and the trailing~|:|.  Again we define it
%   through \cs{@@_tmp:w}, which receives |:| as |#1| and |_quark_if_|
%   as |#2|.  The auxiliary \cs{@@_quark_conditional_name:w} returns the part
%   between the first |_quark_if_| and the next~|:|, and we apply this
%   auxiliary to the function name followed by |:| (in case the function
%   name is lacking a signature), and |_quark_if_:| so that
%   \cs{@@_quark_conditional_name:N} returns an empty string if |_quark_if_| is
%   not present.
%    \begin{macrocode}
\cs_set:Npn \@@_tmp:w #1 #2 \s_@@
  {
    \cs_new:Npn \@@_quark_conditional_name:N ##1
      {
        \exp_last_unbraced:Nf \@@_quark_conditional_name:w
          { \cs_to_str:N ##1 } #1 #2 #1 \s_@@
      }
    \cs_new:Npn \@@_quark_conditional_name:w
      ##1 #2 ##2 #1 ##3 \s_@@ {##2}
  }
\exp_after:wN \@@_tmp:w \tl_to_str:n { : _quark_if_ } \s_@@
%    \end{macrocode}
% \end{macro}
%
% \subsection{Scan marks}
%
%    \begin{macrocode}
%<@@=scan>
%    \end{macrocode}
%
% \begin{macro}{\scan_new:N}
% \UnitTested
%   Check whether the variable is already a scan mark,
%   then declare it to be equal to \cs{scan_stop:} globally.
%    \begin{macrocode}
\cs_new_protected:Npn \scan_new:N #1
  {
    \tl_if_in:NnTF \g_@@_marks_tl { #1 }
      {
        \msg_error:nne { scanmark } { already-defined }
          { \token_to_str:N #1 }
      }
      {
        \tl_gput_right:Nn \g_@@_marks_tl {#1}
        \cs_new_eq:NN #1 \scan_stop:
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{variable}{\s_stop}
% \begin{variable}{\g_@@_marks_tl}
% \UnitTested
%   We only declare one scan mark here, more can be defined
%   by specific modules.
%   Can't use \cs{scan_new:N} yet because \pkg{l3tl} isn't loaded,
%   so define \cs{s_stop} by hand and add it to \cs{g_@@_marks_tl}.
%   We also add the scan marks declared earlier to the pool here.
%   Since they lives in a different namespace, a little \pkg{DocStrip}
%   cheating is necessary.
%    \begin{macrocode}
\cs_new_eq:NN \s_stop \scan_stop:
\cs_gset_nopar:Npn \g_@@_marks_tl
  {
    \s_stop
%<@@=quark>
    \s_@@
%<@@=cs>
    \s_@@_mark
    \s_@@_stop
%<@@=scan>
  }
%    \end{macrocode}
% \end{variable}
% \end{variable}
%
% \begin{macro}[EXP]{\use_none_delimit_by_s_stop:w}
% \UnitTested
%   Similar to \cs{use_none_delimit_by_q_stop:w}.
%    \begin{macrocode}
\cs_new:Npn \use_none_delimit_by_s_stop:w #1 \s_stop { }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%</code>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
