[latex3-commits] [git/LaTeX3-latex3-latex3] master: Implement token_case_catcode/charcode/meaning (a34439fd5)

Joseph Wright joseph.wright at morningstar2.co.uk
Thu Dec 3 17:40:50 CET 2020


Repository : https://github.com/latex3/latex3
On branch  : master
Link       : https://github.com/latex3/latex3/commit/a34439fd5434efa662743d14802542fcb93acad1

>---------------------------------------------------------------

commit a34439fd5434efa662743d14802542fcb93acad1
Author: Bruno Le Floch <bruno at le-floch.fr>
Date:   Sun Apr 29 23:55:18 2018 -0400

    Implement token_case_catcode/charcode/meaning


>---------------------------------------------------------------

a34439fd5434efa662743d14802542fcb93acad1
 l3kernel/CHANGELOG.md             |  2 +
 l3kernel/l3token.dtx              | 95 ++++++++++++++++++++++++++++++++++++++-
 l3kernel/testfiles/m3quark001.tlg |  1 +
 l3kernel/testfiles/m3token005.lvt | 76 +++++++++++++++++++++++++++++++
 l3kernel/testfiles/m3token005.tlg | 14 ++++++
 5 files changed, 187 insertions(+), 1 deletion(-)

diff --git a/l3kernel/CHANGELOG.md b/l3kernel/CHANGELOG.md
index 2aee70aa1..20133bda3 100644
--- a/l3kernel/CHANGELOG.md
+++ b/l3kernel/CHANGELOG.md
@@ -11,6 +11,8 @@ this project uses date-based 'snapshot' version identifiers.
 - `\peek_analysis_map_inline:n`
 - `\peek_regex:nTF`, `\peek_regex_remove_once:nTF`, and
   `\peek_regex_replace_once:nnTF`
+- `\token_case_catcode:NnTF`, `\token_case_charcode:NnTF`, and
+  `\token_case_meaning:NnTF`
 
 ### Changed
 - Extend `\text_expand:n` to cover `\@protected at testopt`
diff --git a/l3kernel/l3token.dtx b/l3kernel/l3token.dtx
index 798b7b160..dea6ab4d0 100644
--- a/l3kernel/l3token.dtx
+++ b/l3kernel/l3token.dtx
@@ -754,6 +754,32 @@
 %   this includes primitive-like commands defined using |{token.set_lua}|.
 % \end{function}
 %
+% \begin{function}[added = 2020-07-16, EXP, noTF]
+%   {\token_case_catcode:Nn, \token_case_charcode:Nn, \token_case_meaning:Nn}
+%   \begin{syntax}
+%     \cs{token_case_meaning:NnTF} \meta{test token} \\
+%     ~~"{" \\
+%     ~~~~\meta{token case_1} \Arg{code case_1} \\
+%     ~~~~\meta{token case_2} \Arg{code case_2} \\
+%     ~~~~\ldots \\
+%     ~~~~\meta{token case_n} \Arg{code case_n} \\
+%     ~~"}" \\
+%     ~~\Arg{true code}
+%     ~~\Arg{false code}
+%   \end{syntax}
+%   This function compares the \meta{test token} in turn with each of
+%   the \meta{token cases}. If the two are equal (as described for
+%   \cs{token_if_eq_catcode:NNTF}, \cs{token_if_eq_charcode:NNTF} and
+%   \cs{token_if_eq_meaning:NNTF}, respectively) then the associated
+%   \meta{code} is left in the input stream and other cases are
+%   discarded. If any of the cases are matched, the \meta{true code} is
+%   also inserted into the input stream (after the code for the
+%   appropriate case), while if none match then the \meta{false code} is
+%   inserted. The functions \cs{token_case_catcode:Nn},
+%   \cs{token_case_charcode:Nn}, and \cs{token_case_meaning:Nn}, which
+%   do nothing if there is no match, are also available.
+% \end{function}
+%
 % \section{Peeking ahead at the next token}
 %
 % There is often a need to look ahead at the next token in the input
@@ -2021,9 +2047,10 @@
 %<@@=token>
 %    \end{macrocode}
 %
-% \begin{variable}{\s_@@_stop}
+% \begin{variable}{\s_@@_mark, \s_@@_stop}
 %   Internal scan marks.
 %    \begin{macrocode}
+\scan_new:N \s_@@_mark
 \scan_new:N \s_@@_stop
 %    \end{macrocode}
 % \end{variable}
@@ -2690,6 +2717,72 @@ end
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}[EXP, noTF]
+%   {\token_case_catcode:Nn, \token_case_charcode:Nn, \token_case_meaning:Nn}
+% \begin{macro}[EXP]{\@@_case:NNnTF, \@@_case:NNw, \@@_case_end:nw}
+%   The aim here is to allow the case statement to be evaluated
+%   using a known number of expansion steps (two), and without
+%   needing to use an explicit \enquote{end of recursion} marker.
+%   That is achieved by using the test input as the final case,
+%   as this is always true. The trick is then to tidy up
+%   the output such that the appropriate case code plus either
+%   the \texttt{true} or \texttt{false} branch code is inserted.
+%    \begin{macrocode}
+\cs_new:Npn \token_case_catcode:Nn #1#2
+  { \exp:w \@@_case:NNnTF \token_if_eq_catcode:NNTF #1 {#2} { } { } }
+\cs_new:Npn \token_case_catcode:NnT #1#2#3
+  { \exp:w \@@_case:NNnTF \token_if_eq_catcode:NNTF #1 {#2} {#3} { } }
+\cs_new:Npn \token_case_catcode:NnF #1#2
+  { \exp:w \@@_case:NNnTF \token_if_eq_catcode:NNTF #1 {#2} { } }
+\cs_new:Npn \token_case_catcode:NnTF
+  { \exp:w \@@_case:NNnTF \token_if_eq_catcode:NNTF }
+\cs_new:Npn \token_case_charcode:Nn #1#2
+  { \exp:w \@@_case:NNnTF \token_if_eq_charcode:NNTF #1 {#2} { } { } }
+\cs_new:Npn \token_case_charcode:NnT #1#2#3
+  { \exp:w \@@_case:NNnTF \token_if_eq_charcode:NNTF #1 {#2} {#3} { } }
+\cs_new:Npn \token_case_charcode:NnF #1#2
+  { \exp:w \@@_case:NNnTF \token_if_eq_charcode:NNTF #1 {#2} { } }
+\cs_new:Npn \token_case_charcode:NnTF
+  { \exp:w \@@_case:NNnTF \token_if_eq_charcode:NNTF }
+\cs_new:Npn \token_case_meaning:Nn #1#2
+  { \exp:w \@@_case:NNnTF \token_if_eq_meaning:NNTF #1 {#2} { } { } }
+\cs_new:Npn \token_case_meaning:NnT #1#2#3
+  { \exp:w \@@_case:NNnTF \token_if_eq_meaning:NNTF #1 {#2} {#3} { } }
+\cs_new:Npn \token_case_meaning:NnF #1#2
+  { \exp:w \@@_case:NNnTF \token_if_eq_meaning:NNTF #1 {#2} { } }
+\cs_new:Npn \token_case_meaning:NnTF
+  { \exp:w \@@_case:NNnTF \token_if_eq_meaning:NNTF }
+\cs_new:Npn \@@_case:NNnTF #1#2#3#4#5
+  {
+    \@@_case:NNw #1 #2 #3 #2 { }
+    \s_@@_mark {#4}
+    \s_@@_mark {#5}
+    \s_@@_stop
+  }
+\cs_new:Npn \@@_case:NNw #1#2#3#4
+  {
+    #1 #2 #3
+      { \@@_case_end:nw {#4} }
+      { \@@_case:NNw #1 #2 }
+  }
+%    \end{macrocode}
+%   To tidy up the recursion, there are two outcomes. If there was a hit to
+%   one of the cases searched for, then |#1| is the code to insert,
+%   |#2| is the \emph{next} case to check on and |#3| is all of
+%   the rest of the cases code. That means that |#4| is the \texttt{true}
+%   branch code, and |#5| tidies up the spare \cs{s_@@_mark} and the
+%   \texttt{false} branch. On the other hand, if none of the cases matched
+%   then we arrive here using the \enquote{termination} case of comparing
+%   the search with itself. That means that |#1| is empty, |#2| is
+%   the first \cs{s_@@_mark} and so |#4| is the \texttt{false} code (the
+%   \texttt{true} code is mopped up by |#3|).
+%    \begin{macrocode}
+\cs_new:Npn \@@_case_end:nw #1#2#3 \s_@@_mark #4#5 \s_@@_stop
+  { \exp_end: #1 #4 }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
 % \subsection{Peeking ahead at the next token}
 %
 %    \begin{macrocode}
diff --git a/l3kernel/testfiles/m3quark001.tlg b/l3kernel/testfiles/m3quark001.tlg
index a86a55bba..10446d7d2 100644
--- a/l3kernel/testfiles/m3quark001.tlg
+++ b/l3kernel/testfiles/m3quark001.tlg
@@ -96,6 +96,7 @@ already been used for a scan mark.
 \s__clist_mark 
 \s__clist_stop 
 \s__char_stop 
+\s__token_mark 
 \s__token_stop 
 \s__peek_mark 
 \s__peek_stop 
diff --git a/l3kernel/testfiles/m3token005.lvt b/l3kernel/testfiles/m3token005.lvt
index 32890f37a..27bf03b0a 100644
--- a/l3kernel/testfiles/m3token005.lvt
+++ b/l3kernel/testfiles/m3token005.lvt
@@ -60,4 +60,80 @@
     \tl_rescan:nn { \char_set_catcode_active:N \D } { \cs_log:N D }
   }
 
+\TEST { Token~case }
+  {
+    \token_case_catcode:Nn \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        & { \ERROR }
+      }
+    \token_case_catcode:NnT \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        & { \ERROR }
+      } { \ERROR }
+    \token_case_catcode:NnF \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        & { \ERROR }
+      } { \FALSE }
+    \token_case_catcode:NnTF \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        & { \ERROR }
+      } { \ERROR } { \FALSE }
+    \token_case_charcode:Nn \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        \scan_stop: { \TRUE }
+      }
+    \token_case_charcode:NnT \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        \scan_stop: { \TRUE }
+      } { \TRUE }
+    \token_case_charcode:NnF \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        \scan_stop: { \TRUE }
+      } { \ERROR }
+    \token_case_charcode:NnTF \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        \scan_stop: { \TRUE }
+      } { \TRUE } { \ERROR }
+    \token_case_meaning:Nn \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        \scan_stop: { \ERROR }
+      }
+    \token_case_meaning:NnT \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        \scan_stop: { \ERROR }
+      } { \ERROR }
+    \token_case_meaning:NnF \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        \scan_stop: { \ERROR }
+      } { \FALSE }
+    \token_case_meaning:NnTF \c_empty_tl
+      {
+        a { \ERROR }
+        + { \ERROR }
+        \scan_stop: { \ERROR }
+      } { \ERROR } { \FALSE }
+  }
+
 \END
diff --git a/l3kernel/testfiles/m3token005.tlg b/l3kernel/testfiles/m3token005.tlg
index 53416c1e8..45b96cf04 100644
--- a/l3kernel/testfiles/m3token005.tlg
+++ b/l3kernel/testfiles/m3token005.tlg
@@ -25,3 +25,17 @@ TEST 3: Char set active (make active rescan)
 > C=undefined.
 > D=\long macro:->Works.
 ============================================================
+============================================================
+TEST 4: Token case
+============================================================
+FALSE
+FALSE
+TRUE
+TRUE
+TRUE
+TRUE
+TRUE
+TRUE
+FALSE
+FALSE
+============================================================





More information about the latex3-commits mailing list.