% \iffalse %% File: l3quark.dtx Copyright (C) 1990-1998 LaTeX3 project % %<*dtx> \ProvidesFile{l3quark.dtx} % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{l3quark} % \ProvidesFile{l3quark.drv} % \fi % \ProvidesFile{l3quark.dtx} [1998/05/20 v1.0e L3 Experimental Quark Commands] % % \iffalse %<*driver> \documentclass{l3doc} \begin{document} \DocInput{l3quark.dtx} \end{document} % % \fi % % % \GetFileInfo{l3quark.dtx} % \title{The \textsf{l3quark} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ % ``Quarks''} % \author{\Team} % \date{\filedate} % \maketitle % % % \section{Quarks} %^^A \label{sec:quarks} % % % A special type of constants in \LaTeX3 are `quarks'. These are control % sequences that expand to themselves and should therefore NEVER be % executed directly in the code. This would result in an endless loop! % % They are meant to be used as delimiter is weird functions (for example % as the stop token (i.e., "\q_stop"). They also permit the following % ingenious trick: when you pick up a token in a temporary, and you want % to know whether you have picked up a particular quark, all you have to % do is compare the temporary to the quark using "\if_meaning:NN". A % set of special quark testing functions is set up below. % % By convention all constants of type quark start out with "\q_". % % \subsection{Functions} % % \begin{function}{% % \quark_new:N | % } % \begin{syntax} % "\quark_new:N" % \end{syntax} % Defines to be a new constant of type "quark". % \end{function} % % \begin{function}{% % \quark_if_no_value:nTF | % \quark_if_no_value:nF | % \quark_if_no_value:nT | % \quark_if_no_value:NTF | % \quark_if_no_value:NF | % } % \begin{syntax} % "\quark_if_no_value:nTF" "{" "}" % " {""}{""}" % "\quark_if_no_value:NTF" % " {""}{""}" % \end{syntax} % This tests whether or not contains only the quark % "\q_no_value". % % If to be tested is stored in a token list pointer use % "\quark_if_no_value:NTF", or "\quark_if_no_value:NF" or check the % value directly with "\if_meaning:NN". All those cases are faster then % "\quark_if_no_value:nTF" so should be preferred. % % \begin{texnote} % But be aware of the fact that "\if_meaning:NN" can result in an % overflow of \TeX{}'s parameter stack since it leaves the corresponding % "\fi:" on the input until the whole replacement text is processed. It % is therefore better in recursions to use "\quark_if_no_value:NTF" as % it will remove the conditional prior to processing the "T" or "F" case % and so allows tail-recursion. % \end{texnote} % \end{function} % % \subsection{Constants} % % \begin{variable}{\q_no_value} The canonical `missing value quark' % that is returned by certain functions to denote that a requested value % is not found in the data structure. % \end{variable} % % \begin{variable}{\q_stop} % This constant is used as a a marker in parameter text. This allows a % scanning function to find the end of some input string. % \end{variable} % % \begin{variable}{\q_nil} % This constant represent the nil pointer in pointer structures. % \end{variable} % % \section{Implementation} % % We start by ensuring that the required packages are loaded. % We check for \texttt{l3expan} since this a basic package that is % essential for use of any higher-level package. % \begin{macrocode} %\RequirePackage{l3expan}\par %<*package> % \end{macrocode} % % \begin{macro}{\quark_new:N} % Allocate a new quark. % \begin{macrocode} \def_new:Npn \quark_new:N #1{\tlp_new:Nn #1{#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\q_stop} % \begin{macro}{\q_no_value} % \begin{macro}{\q_nil} % |\q_stop| is often used as a marker in parameter text, % |\q_no_value| is the canonical missing value, and |\q_nil| % represents a nil pointer in some data structures. % \begin{macrocode} \quark_new:N \q_stop \quark_new:N \q_no_value \quark_new:N \q_nil % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\q_error} % \begin{macro}{\q_mark} % We need two additional quarks. |\q_error| delimits the end of % the computation for purposes of error recovery. |\q_mark| is % used in parameter text when we need a scanning boundary that is % distinct from |\q_stop|. % \begin{macrocode} \quark_new:N\q_error \quark_new:N\q_mark % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\quark_if_no_value:NTF} % \begin{macro}{\quark_if_no_value:NF} % \begin{macro}{\quark_if_no_value:nTF} % \begin{macro}{\quark_if_no_value:nT} % \begin{macro}{\quark_if_no_value:nF} % Here we test if we found a special quark as the first argument. % The argument might contain an arbitrary list of tokens, therefore % we have to wrap it up in a token list pointer. % \begin{macrocode} \def_new:Npn \quark_if_no_value:NTF #1{ % \end{macrocode} % We better start with |\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} \if_meaning:NN\q_no_value#1 \exp_after:NN\use_choice_i:nn \else: \exp_after:NN\use_choice_ii:nn \fi:} % \end{macrocode} % It would be possible to speed up the following commands by % providing individual implementations similar to the one above. % Should perhaps be done if they are used often! % \begin{macrocode} \def_new:Npn \quark_if_no_value:NF #1{\quark_if_no_value:NTF {#1}\use_noop:} \def_new:Npn \quark_if_no_value:nTF #1{\tlp_gset:Nn \g_testa_tlp {#1} \quark_if_no_value:NTF\g_testa_tlp} \def_new:Npn \quark_if_no_value:nF #1{\quark_if_no_value:nTF {#1}\use_noop:} \def_new:Npn \quark_if_no_value:nT #1#2{\quark_if_no_value:nTF {#1} {#2}\use_noop:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\quark_if_nil:NTF} % A function to check for the presence of |\q_nil|. % \begin{macrocode} \def_new:Npn\quark_if_nil:NTF#1{ \if_meaning:NN#1\q_nil \exp_after:NN\use_choice_i:nn \else: \exp_after:NN\use_choice_ii:nn\fi:} % \end{macrocode} % \end{macro} % % Show token usage: % \begin{macrocode} % %<*showmemory> \showMemUsage % % \end{macrocode} % %