summaryrefslogtreecommitdiff
path: root/Master
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2011-11-25 00:13:53 +0000
committerKarl Berry <karl@freefriends.org>2011-11-25 00:13:53 +0000
commitffc8e17b8078900ab7932786f99a36a7f3b1166c (patch)
tree4e6b90567c8ee8bff06b06a3868c14b7e9f06eef /Master
parent3c7032087650de924a1aead943de992a2c689248 (diff)
l3experimental 2966 (19nov11)
git-svn-id: svn://tug.org/texlive/trunk@24655 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r--Master/texmf-dist/doc/latex/l3experimental/l3str/l3regex.pdfbin640244 -> 642444 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3experimental/l3str/l3str.pdfbin628821 -> 653010 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3experimental/xcoffins/xcoffins.pdfbin478180 -> 481884 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3experimental/xgalley/l3galley.pdfbin622455 -> 627235 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3experimental/xgalley/xgalley.pdfbin570935 -> 566413 bytes
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3str/l3regex.dtx1909
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx753
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx59
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx178
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx20
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty1053
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty1053
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty305
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty10
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty87
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty7
16 files changed, 3208 insertions, 2226 deletions
diff --git a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3regex.pdf b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3regex.pdf
index 9ee837a7c92..0ddd7169a49 100644
--- a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3regex.pdf
+++ b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3regex.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str.pdf b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str.pdf
index f4b06528802..d82842dca5f 100644
--- a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str.pdf
+++ b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3experimental/xcoffins/xcoffins.pdf b/Master/texmf-dist/doc/latex/l3experimental/xcoffins/xcoffins.pdf
index b20f638d514..796242d76b6 100644
--- a/Master/texmf-dist/doc/latex/l3experimental/xcoffins/xcoffins.pdf
+++ b/Master/texmf-dist/doc/latex/l3experimental/xcoffins/xcoffins.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3experimental/xgalley/l3galley.pdf b/Master/texmf-dist/doc/latex/l3experimental/xgalley/l3galley.pdf
index 3cad13a681f..c238f89d86d 100644
--- a/Master/texmf-dist/doc/latex/l3experimental/xgalley/l3galley.pdf
+++ b/Master/texmf-dist/doc/latex/l3experimental/xgalley/l3galley.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3experimental/xgalley/xgalley.pdf b/Master/texmf-dist/doc/latex/l3experimental/xgalley/xgalley.pdf
index 38d903ad9fb..8e77fd9b96f 100644
--- a/Master/texmf-dist/doc/latex/l3experimental/xgalley/xgalley.pdf
+++ b/Master/texmf-dist/doc/latex/l3experimental/xgalley/xgalley.pdf
Binary files differ
diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3regex.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3regex.dtx
index e2977e2b249..cb0476ac898 100644
--- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3regex.dtx
+++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3regex.dtx
@@ -35,7 +35,7 @@
%
%<*driver|package>
\RequirePackage{expl3}
-\GetIdInfo$Id: l3regex.dtx 2895 2011-10-09 15:58:19Z joseph $
+\GetIdInfo$Id: l3regex.dtx 2943 2011-10-30 15:59:43Z bruno $
{L3 Experimental Regular Expressions}
%</driver|package>
%<*driver>
@@ -68,7 +68,7 @@
%
% \begin{documentation}
% \newenvironment{l3regex-syntax}
-% {\begin{itemize}\def\makelabel##1{\hss\llap{\ttfamily\string##1}}}
+% {\begin{itemize}\def\\{\char`\\}\def\makelabel##1{\hss\llap{\ttfamily##1}}}
% {\end{itemize}}
%
% \section{\pkg{l3regex} documentation}
@@ -91,15 +91,13 @@
% by \enquote{\texttt{is}}. A more complicated example is
% a pattern to add a comma at the end of each word:
% \begin{verbatim}
-% \regex_replace_all:nnN { (\w+) } { \1 , } \l_my_str
+% \regex_replace_all:nnN { \w+ } { \0 , } \l_my_str
% \end{verbatim}
% The |\w| sequence represents any \enquote{word} character,
-% and |*| indicates that the |\w| sequence should be repeated
-% as many times as possible, hence matching a word in the
-% input string. The parentheses \enquote{capture} what their
-% contents matched in the input string, and this can be used
-% in the replacement text as |\1| (and higher numbers if several
-% groups are used in the regular expression).
+% and |+| indicates that the |\w| sequence should be repeated
+% as many times as possible (at least once), hence matching a word in the
+% input string. In the replacement text, |\0| denotes the full match
+% (here, a word).
%
% \subsection{Syntax of regular expressions}
%
@@ -111,13 +109,11 @@
% \begin{itemize}
% \item every alphanumeric character (\texttt{A}--\texttt{Z},
% \texttt{a}--\texttt{z}, \texttt{0}--\texttt{9}) matches
-% exactly itself, none of them should be escaped, because
-% most of those escape sequences have special meanings;
-% \item non-alphanumeric printable ascii characters can always
-% be safely escaped, and for highest portability, they should
-% always be escaped (this avoids problems if some currently
-% \enquote{normal} characters is given a meaning in later
-% releases);
+% exactly itself, and should not be escaped, because
+% |\A|, |\B|, \ldots{} have special meanings;
+% \item non-alphanumeric printable ascii characters can (and should)
+% always be escaped: many of them have special meanings (\emph{e.g.},
+% |(|, |)|, |?|, |.|);
% \item spaces should always be escaped (even in character
% classes);
% \item any other character may be escaped or not, without any
@@ -138,88 +134,97 @@
%
% Characters.
% \begin{l3regex-syntax}
-% \item[\x\{hh\ldots{}\}]
-% Character with hex code \texttt{hh\ldots{}}
-% \item[\xhh]
-% Character with hex code \texttt{hh}.
-% \item[\a] Alarm (hex 07).
-% \item[\e] Escape (hex 1B).
-% \item[\f] Form-feed (hex 0C).
-% \item[\n] New line (hex 0A).
-% \item[\r] Carriage return (hex 0D).
-% \item[\t] Horizontal tab (hex 09).
+% \item[\\x\{hh\ldots{}\}] Character with hex code \texttt{hh\ldots{}}
+% \item[\\xhh] Character with hex code \texttt{hh}.
+% \item[\\a] Alarm (hex 07).
+% \item[\\e] Escape (hex 1B).
+% \item[\\f] Form-feed (hex 0C).
+% \item[\\n] New line (hex 0A).
+% \item[\\r] Carriage return (hex 0D).
+% \item[\\t] Horizontal tab (hex 09).
% \end{l3regex-syntax}
%
% Character types.
% \begin{l3regex-syntax}
-% \item[.] A single period matches any character,
-% including newlines.\footnote{Should that be changed?}
-% \item[\N] A character that is not
-% the |\n| character (hex 0A).\footnote{Is that right?}
-% \item[\d] Any decimal digit.
-% \item[\h] Any horizontal space character,
-% equivalent to |[\^^I\ ]|: space and tab.
-% \item[\s] Any space character,
-% equivalent to |[\^^I\^^J\^^L\^^M\ ]|.
-% \item[\v] Any vertical space character,
-% equivalent to |[\^^I-\^^M]|. Note that |\^^K| is a vertical space,
-% but not a space, for compatibility with perl.
-% \item[\w] Any word character, \emph{i.e.},
-% alpha-numerics and underscore, equivalent to |[A-Za-z0-9\_]|.
-% \item[\D] Any character not matched by |\d|.
-% \item[\H] Any character not matched by |\h|.
-% \item[\S] Any character not matched by |\s|.
-% \item[\V] Any character not matched by |\v|.
-% \item[\W] Any character not matched by |\w|.
+% \item[.] A single period matches any character, including newlines.
+% \item[\\d] Any decimal digit.
+% \item[\\h] Any horizontal space character,
+% equivalent to |[\ \^^I]|: space and tab.
+% \item[\\s] Any space character,
+% equivalent to |[\ \^^I\^^J\^^L\^^M]|.
+% \item[\\v] Any vertical space character,
+% equivalent to |[\^^J\^^K\^^L\^^M]|. Note that |\^^K| is a vertical space,
+% but not a space, for compatibility with Perl.
+% \item[\\w] Any word character, \emph{i.e.},
+% alpha-numerics and underscore, equivalent to |[A-Za-z0-9\_]|.
+% \item[\\D] Any character not matched by |\d|.
+% \item[\\H] Any character not matched by |\h|.
+% \item[\\N] Any character other than the |\n| character (hex 0A).
+% \item[\\S] Any character not matched by |\s|.
+% \item[\\V] Any character not matched by |\v|.
+% \item[\\W] Any character not matched by |\w|.
% \end{l3regex-syntax}
%
% Character classes match exactly one character in the subject string.
% \begin{l3regex-syntax}
-% \item[{[...]}] Positive character class.
-% \item[{[\string^...]}] Negative character class.
-% \item[{[x-y]}] Range (can be used with escaped characters).
+% \item[{[\ldots{}]}] Positive character class.
+% Matches any of the specified characters.
+% \item[{[\char`\^\ldots{}]}] Negative character class.
+% Matches any character other than the specified characters.
+% \item[{[x-y]}] Range (can be used with escaped characters).
% \end{l3regex-syntax}
%
-% Quantifiers.
+% Quantifiers (repetition).
% \begin{l3regex-syntax}
-% \item[?] $0$ or $1$, greedy.
-% \item[??] $0$ or $1$, lazy.
-% \item[*] $0$ or more, greedy.
-% \item[*?] $0$ or more, lazy.
-% \item[+] $1$ or more, greedy.
-% \item[+?] $1$ or more, lazy.
-% \end{l3regex-syntax}
-% Not implemented yet: ^^A !
-% \begin{l3regex-syntax}\def\makelabel#1{\hss\llap{\ttfamily#1}}
-% \item[\{$n$\}] Exactly $n$.
-% \item[\{$n,$\}] $n$ or more, greedy.
-% \item[\{$n,$\}?] $n$ or more, lazy.
-% \item[\{$n,m$\}] At least $n$, no more than $m$, greedy.
-% \item[\{$n,m$\}?] At least $n$, no more than $m$, lazy.
+% \item[?] $0$ or $1$, greedy.
+% \item[??] $0$ or $1$, lazy.
+% \item[*] $0$ or more, greedy.
+% \item[*?] $0$ or more, lazy.
+% \item[+] $1$ or more, greedy.
+% \item[+?] $1$ or more, lazy.
+% \item[\{$n$\}] Exactly $n$.
+% \item[\{$n,$\}] $n$ or more, greedy.
+% \item[\{$n,$\}?] $n$ or more, lazy.
+% \item[\{$n,m$\}] At least $n$, no more than $m$, greedy.
+% \item[\{$n,m$\}?] At least $n$, no more than $m$, lazy.
% \end{l3regex-syntax}
%
% Anchors and simple assertions.
% \begin{l3regex-syntax}
-% \item[\b] Word boundary.
-% \item[\B] Not a word boundary.
-% \item[^\string\A] Start of the subject string.\footnote{The
-% multiline mode is not implemented yet, so those are currently
-% identical.}
-% \item[$\string\Z\string\z] End of the subject
-% string.\footnotemark[\thefootnote]
-% \item[\G] Start of the current match. This is only different from |^|
-% in the case of multiple matches: for instance
-% |\regex_count:nnN { \G a } { aaba } \l_tmpa_int| yields $2$, but
-% replacing |\G| by |^| would result in \cs{l_tmpa_int} holding the
-% value $1$.
+% \item[\\b] Word boundary.
+% \item[\\B] Not a word boundary.
+% \item[\char`^ \textrm{or} \\A]
+% Start of the subject string.
+% \item[\char`$\textrm{,} \\Z \textrm{or} \\z]
+% End of the subject string.
+% \item[\\G] Start of the current match. This is only different from |^|
+% in the case of multiple matches: for instance
+% |\regex_count:nnN { \G a } { aaba } \l_tmpa_int| yields $2$, but
+% replacing |\G| by |^| would result in \cs{l_tmpa_int} holding the
+% value $1$.
% \end{l3regex-syntax}
%
% Alternation and capturing groups.
% \begin{l3regex-syntax}
-% \item[A\string|B\string|C] Either one of \texttt{A}, \texttt{B},
-% or \texttt{C}.
-% \item[(\ldots{})] Capturing group.
-% \item[(?:\ldots{})] Non-capturing group.
+% \item[A\char`|B\char`|C] Either one of \texttt{A}, \texttt{B},
+% or \texttt{C}.
+% \item[(\ldots{})] Capturing group.
+% \item[(?:\ldots{})] Non-capturing group.
+% \end{l3regex-syntax}
+%
+% Options can be set with |(?|\meta{option}|)| and
+% unset with |(?-|\meta{option}|)|. Options are local
+% to the group in which they are set, and revert to their
+% previous setting upon reaching the closing parenthesis.
+% For instance, in \verb"(?i)a(b(?-i)c|d)e", the |i| option
+% applies to the letters |a|, |b| and |e|.
+% \begin{l3regex-syntax}
+% \item[(?i) \textrm{and} (?-i)] Toggle to a case
+% insensitive/sensitive mode. This only applies to ascii letters
+% (mapping \texttt{A}--\texttt{Z} to \texttt{a}--\texttt{z}).
+% For instance, |(?i)[Y-\\]| matches the characters |Y|, |Z|, |[|,
+% |\|, and the lower case letters |y| and |z|, while |(?i)[^aeiou]|
+% matches any character which is not a vowel.
% \end{l3regex-syntax}
%
% In character classes, only |^|, |-|, |]|, |\| and spaces are special,
@@ -235,29 +240,23 @@
% opening parenthesis, starting at $1$. The contents of those groups
% corresponding to the \enquote{best} match (leftmost longest)
% can be extracted and stored in a sequence of strings using for
-% instance \cs{regex_extract:nnNTF}.
+% instance \cs{regex_extract_once:nnNTF}.
%
% \subsection{Syntax of in the replacement text}
%
% Most of the features described in regular expressions do not make sense
% within the replacement text. Escaped characters are supported as inside
-% regular expressions. The various submatches are accessed with |\1|, |\2|,
-% \emph{etc.}, and the whole match is accessed using |\0|.
+% regular expressions. The whole match is accessed as |\0|, and the first
+% $9$ submatches are accessed as |\1|, \ldots{}, |\9|. Submatches with
+% numbers higher than $9$ are accessed as |\g{|\meta{number}|}| instead.
%
% For instance,
% \begin{verbatim}
-% \str_set:Nn \l_my_str { Hello,~world! }
-% \regex_replace_all:nnN { ([er]?l|o) . } { \(\0\-\-\1\) } \l_my_str
+% \str_set:Nn \l_my_str { Hello,~world! }
+% \regex_replace_all:nnN { ([er]?l|o) . } { \(\0\-\-\1\) } \l_my_str
% \end{verbatim}
% results in \cs{l_my_str} holding |H(ell--el)(o,--o) w(or--o)(ld--l)!|
%
-% Submatches with numbers higher than $10$ are accessed in the same way,
-% namely |\10|, |\11|, \emph{etc}. To insert in the replacement text
-% a submatch followed by a digit, the digit must be entered using the
-% |\x| escape sequence: for instance, to get the first submatch followed
-% by the digit $7$, use |\1\x37|, because $7$ has character code |37|
-% (in hexadecimal).
-%
% \subsection{Precompiling regular expressions}
%
% If a regular expression is to be used several times,
@@ -268,8 +267,7 @@
% regular expression argument either as an explicit string
% or as a precompiled regular expression.
%
-% \begin{function}{\regex_set:Nn}
-% \begin{function}{\regex_gset:Nn}
+% \begin{function}{\regex_set:Nn, \regex_gset:Nn}
% \begin{syntax}
% \cs{regex_set:Nn} \meta{tl var} \Arg{regex}
% \end{syntax}
@@ -280,20 +278,23 @@
% \tl_new:N \l_my_regex_tl
% \regex_set:Nn \l_my_regex_tl { my\ (simple\ )? reg(ex|ular\ expression) }
% \end{verbatim}
-% The assignment is local for \cs{regex_set:Nn}
-% and global for \cs{regex_gset:Nn}.
+% The assignment is local for \cs{regex_set:Nn} and global for
+% \cs{regex_gset:Nn}.
% \begin{texnote}
% Precompiled regular expressions can be safely written to a file
% and read when the \LaTeX3 syntax is active (as triggered by
% \cs{ExplSyntaxOn}).
% \end{texnote}
% \end{function}
-% \end{function}
%
% \subsection{String matching}
%
-% \begin{function}[TF]{\regex_match:nn}
-% \begin{function}[TF]{\regex_match:Nn}
+% All regular expression functions are available in both |:n| and |:N|
+% variants. The former require a \enquote{standard} regular expression,
+% while the later require a precompiled expression as generated by
+% \cs{regex_(g)set:Nn}.
+%
+% \begin{function}[TF]{\regex_match:nn, \regex_match:Nn}
% \begin{syntax}
% \cs{regex_match:nnTF} \Arg{regex} \Arg{string} \Arg{true code} \Arg{false code}
% \end{syntax}
@@ -303,16 +304,15 @@
% \regex_match:nnTF { b [cde]* } { abecdcx } { TRUE } { FALSE }
% \regex_match:nnTF { [b-dq-w] } { example } { TRUE } { FALSE }
% \end{verbatim}
-% leaves \texttt{TRUE FALSE} in the input stream.
-% \end{function}
+% leaves \texttt{TRUE} then \texttt{FALSE} in the input stream.
% \end{function}
%
-% \begin{function}{\regex_count:nnN}
-% \begin{function}{\regex_count:NnN}
+% \begin{function}{\regex_count:nnN, \regex_count:NnN}
% \begin{syntax}
% \cs{regex_count:nnN} \Arg{regex} \Arg{string} \meta{int var}
% \end{syntax}
-% Sets \meta{int var} equal to the number of times
+% Sets \meta{int var} within the current \TeX{} group level
+% equal to the number of times
% \meta{regular expression} appears in \meta{string}.
% The search starts by finding the left-most longest match,
% respecting greedy and ungreedy operators. Then the search
@@ -325,29 +325,26 @@
% \end{verbatim}
% results in \cs{l_foo_int} taking the value $5$.
% \end{function}
-% \end{function}
%
% \subsection{Submatch extraction}
%
-% \begin{function}{\regex_extract:nnN}
-% \begin{function}{\regex_extract:NnN}
-% \begin{function}[TF]{\regex_extract:nnN}
-% \begin{function}[TF]{\regex_extract:NnN}
+% \begin{function}[TF]{\regex_extract_once:nnN, \regex_extract_once:NnN}
% \begin{syntax}
-% \cs{regex_extract:nnNTF} \Arg{regex} \Arg{string} \meta{seq~var} \Arg{true code} \Arg{false code}
+% \cs{regex_extract_once:nnN} \Arg{regex} \Arg{string} \meta{seq~var}
+% \cs{regex_extract_once:nnNTF} \Arg{regex} \Arg{string} \meta{seq~var} \Arg{true code} \Arg{false code}
% \end{syntax}
% Finds the first match of the \meta{regular expression}
% in the \meta{string}. If it exists, the match is stored
% as the zeroeth item of the \meta{seq~var}, and further
% items are the contents of capturing groups, in the order
-% of their opening left parenthesis. The \meta{seq~var}
+% of their opening parenthesis. The \meta{seq~var}
% is assigned locally. If there is no match,
% the \meta{seq~var} is not altered.
-% The testing versions return \meta{true} if a match was found,
-% and \meta{false} otherwise.
+% The testing versions insert the \meta{true code} into the input
+% stream if a match was found, and the \meta{false code} otherwise.
% For instance, assume that you type
% \begin{verbatim}
-% \regex_extract:nnNTF { ^(La)?TeX(!*)$ } { LaTeX!!! }
+% \regex_extract_once:nnNTF { ^(La)?TeX(!*)$ } { LaTeX!!! }
% \l_foo_seq { true } { false }
% \end{verbatim}
% Then the regular expression (anchored at the start with |^| and
@@ -357,14 +354,26 @@
% the items |{LaTeX!!!}|, |{La}|, and |{!!!}|, and the \texttt{true}
% branch is left in the input stream.
% \end{function}
-% \end{function}
-% \end{function}
+%
+% \begin{function}[TF]{\regex_extract_all:nnN, \regex_extract_all:NnN}
+% \begin{syntax}
+% \cs{regex_extract_all:nnNTF} \Arg{regex} \Arg{string} \meta{seq~var} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Finds all matches of the \meta{regular expression}
+% in the \meta{string}, and stores all the submatch information
+% in a single sequence (concatenating the results of
+% multiple \cs{regex_extract_once:nnN} calls).
+% For instance, assume that you type
+% \begin{verbatim}
+% \regex_extract_all:nnN { \w+ } { Hello,~world! } \l_foo_seq
+% \end{verbatim}
+% Then the regular expression will match twice, and the resulting
+% sequence contains the two items \texttt{Hello} and \texttt{world}.
% \end{function}
%
% \subsection{String splitting}
%
-% \begin{function}{\regex_split:nnN}
-% \begin{function}{\regex_split:NnN}
+% \begin{function}{\regex_split:nnN, \regex_split:NnN}
% \begin{syntax}
% \cs{regex_split:nnN} \Arg{regular expression} \meta{string} \meta{seq~var}
% \end{syntax}
@@ -375,15 +384,18 @@
% If no match is found the resulting \meta{seq~var} has the \meta{string} as
% its sole item. If the \meta{regular expression} matches the empty string,
% then the \meta{string} is split into single character substrings.
-% \end{function}
+% For example, after
+% \begin{verbatim}
+% \seq_new:N \l_path_seq
+% \regex_split:nnN { / } { the/path/for/this/file.tex } \l_path_seq
+% \end{verbatim}
+% the sequence |\l_path_seq| contains the items |{the}|, |{path}|,
+% |{for}|, |{this}|, and |{file.tex}|.
% \end{function}
%
% \subsection{String replacement}
%
-% \begin{function}{\regex_replace_once:nnN}
-% \begin{function}{\regex_replace_once:NnN}
-% \begin{function}[TF]{\regex_replace_once:nnN}
-% \begin{function}[TF]{\regex_replace_once:NnN}
+% \begin{function}[TF]{\regex_replace_once:nnN,\regex_replace_once:NnN}
% \begin{syntax}
% \cs{regex_replace_once:nnN} \Arg{regular expression} \Arg{replacement} \meta{str~var}
% \end{syntax}
@@ -393,12 +405,8 @@
% |\0| represents the full match, |\1| represent the contents
% of the first capturing group, |\2| of the second, \emph{etc.}
% \end{function}
-% \end{function}
-% \end{function}
-% \end{function}
%
-% \begin{function}{\regex_replace_all:nnN}
-% \begin{function}{\regex_replace_all:NnN}
+% \begin{function}{\regex_replace_all:nnN, \regex_replace_all:NnN}
% \begin{syntax}
% \cs{regex_replace_all:nnN} \Arg{regular expression} \Arg{replacement} \meta{str~var}
% \end{syntax}
@@ -407,53 +415,42 @@
% |\0| represents the full match, |\1|
% represent the contents of the first capturing group,
% |\2| of the second, \emph{etc.} Every match
-% is treated independently. The result is assigned
-% locally to \meta{str~var}.
-% \end{function}
+% is treated independently, and matches cannot overlap.
+% The result is assigned locally to \meta{str~var}.
% \end{function}
%
% \subsection{Bugs, misfeatures, future work, and other possibilities}
%
-% The \texttt{\{\}} quantifiers are not implemented.
-%
-% The following need discussion.
+% The following need to be done now.
% \begin{itemize}
+% \item The \texttt{\{\}} quantifiers are only partially implemented.
+% \item Space's catcode wrong in the result of a replacement!
% \item Newline conventions are not done.
% In particular, |.| should not match newlines.
% Also, |\A| should differ from |^|, and |\Z|, |\z| and |$| should
% differ.
-% \item Caseless matching and more generally
-% |(*..)| and |(?..)| sequences to set some options.
-% \item General look-ahead/behind assertions.
-% \item Idea of |#| as a synonym of |.*?|.
-% \item Do we need a facility for balanced groups? (That's non-regular.)
% \end{itemize}
%
% The following features are likely to be implemented at some point
% in the future.
% \begin{itemize}
+% \item General look-ahead/behind assertions.
+% \item Regex matching on external files.
+% \item Conditional subpatterns with look ahead/behind: \enquote{if
+% what follows is [\ldots{}], then [\ldots{}]}.
+% \item \verb"(?|..|..)" to reset the capturing group number at the start
+% of each alternative.
+% \item |(*..)| and |(?..)| sequences to set some options.
+% \item Reduce the number of epsilon-transitions in alternatives.
% \item Optimize simple strings: use less states
% (|abcade| should give two states, for |abc| and |ade|).
% \item Optimize groups with no alternative.
% \item Optimize the use of \cs{prg_stepwise_...} functions.
-% \item Implement regex matching on external files.
-% \item Conditional subpatterns with look ahead/behind: \enquote{if
-% what follows is [\ldots{}], then [\ldots{}]}.
-% \item "(?|..|..)" to reset the capturing group number at the start
-% of each alternative.
-% \item Todo: check space's catcode in the result of a replacement.
+% \item |\K| for resetting the beginning of the match.
+% \item UTF-8 mode for pdf\TeX{}.
% \end{itemize}
%
-% The following features not present in PCRE nor perl (because they can
-% be done in other ways in those languages) might be added.
-% \begin{itemize}
-% \item |#| as a synonym of |.*?|, in a way similar to macro parameters.
-% \item Facility to match balanced groups: this is non-regular, but quite
-% useful, and it can be implemented without too much performance loss.
-% (\emph{cf.} callout?)
-% \end{itemize}
-%
-% The following features of PCRE or perl will probably not be implemented.
+% The following features of PCRE or Perl will probably not be implemented.
% \begin{itemize}
% \item Other forms of escapes, and character classes.
% |\cx|$\simeq$|\^^x|, |\ddd| (octal \texttt{ddd}).
@@ -465,7 +462,7 @@
% or look-behind condition): this is non-regular, isn't it?
% \end{itemize}
%
-% The following features of PCRE or perl will not be implemented.
+% The following features of PCRE or perl will definitely not be implemented.
% \begin{itemize}
% \item Comments: \TeX{} already has its own system for comments.
% \item Named subpatterns: \TeX{} programmers have lived so far without
@@ -482,9 +479,9 @@
% \item Back-references: non-regular feature, this requires backtracking,
% which is prohibitively slow.
% \item Backtracking control verbs: intrinsically tied to backtracking.
-% \item |\K| for resetting the beginning of the match: tied to backtracking.
-% \item |\C| single byte in UTF-8 mode: well, UTF-8 mode is not
-% implemented, and that seems like a very rarely useful feature anyways.
+% \item |\C| single byte in UTF-8 mode: Xe\TeX{} and Lua\TeX{} serve
+% us characters directly, and splitting those into bytes is tricky,
+% encoding dependent, and most likely not useful anyways.
% \end{itemize}
%
% \end{documentation}
@@ -521,9 +518,28 @@
%
% \subsection{Constants and variables}
%
+% \begin{variable}
+% {
+% \c_forty_eight, \c_fifty_eight, \c_sixty_five, \c_ninety_one,
+% \c_ninety_seven, \c_one_hundred_twenty_three,
+% \c_one_hundred_twenty_seven
+% }
+% We declare here some integer values which delimit ranges of
+% ASCII characters of various types.
+% \begin{macrocode}
+\int_const:Nn \c_forty_eight { 48 }
+\int_const:Nn \c_fifty_eight { 58 }
+\int_const:Nn \c_sixty_five { 65 }
+\int_const:Nn \c_ninety_one { 91 }
+\int_const:Nn \c_ninety_seven { 97 }
+\int_const:Nn \c_one_hundred_twenty_three { 123 }
+\int_const:Nn \c_one_hundred_twenty_seven { 127 }
+% \end{macrocode}
+% \end{variable}
+%
% \begin{macro}{\regex_tmp:w}
-% \begin{variable}{\g_regex_tmpa_tl,\l_regex_tmpa_tl,\l_regex_tmpb_tl}
-% \begin{variable}{\l_regex_tmpa_int}
+% \begin{variable}{\g_regex_tmpa_tl, \l_regex_tmpa_tl, \l_regex_tmpb_tl}
+% \begin{variable}{\l_regex_tmpa_int, \l_regex_tmpb_int}
% Temporary variables.
% \begin{macrocode}
\cs_new:Npn \regex_tmp:w { }
@@ -531,6 +547,7 @@
\tl_new:N \l_regex_tmpa_tl
\tl_new:N \l_regex_tmpb_tl
\int_new:N \l_regex_tmpa_int
+\int_new:N \l_regex_tmpb_int
% \end{macrocode}
% \end{variable}
% \end{variable}
@@ -538,16 +555,8 @@
%
% \subsubsection{Variables used while building}
%
-% \begin{variable}{\l_regex_pattern_str}
-% The \meta{pattern} is stored in a string variable.
-% \begin{macrocode}
-\tl_new:N \l_regex_pattern_str
-% \end{macrocode}
-% \end{variable}
-%
% \begin{variable}{\l_regex_max_state_int}
-% \begin{variable}{\l_regex_left_state_int,\l_regex_right_state_int}
-% \begin{variable}{\l_regex_left_state_seq,\l_regex_right_state_seq}
+% \begin{variable}{\l_regex_left_state_int, \l_regex_right_state_int}
% The last state that was allocated is stored in \cs{l_regex_max_state_int},
% and \cs{l_regex_left/right_state_int} point to both end-points of the
% last group (which any quantifier would repeat). For simple strings of
@@ -556,21 +565,29 @@
\int_new:N \l_regex_max_state_int
\int_new:N \l_regex_left_state_int
\int_new:N \l_regex_right_state_int
-\seq_new:N \l_regex_left_state_seq
-\seq_new:N \l_regex_right_state_seq
% \end{macrocode}
% \end{variable}
% \end{variable}
+%
+% \begin{variable}{\l_regex_group_begin_seq, \l_regex_group_end_seq}
+% Alternatives are implemented by branching from a state into the
+% various choices, then merging those into another state. We store
+% information about those states in two sequences (several can be
+% active at the same time when nesting groups).
+% \begin{macrocode}
+\seq_new:N \l_regex_group_begin_seq
+\seq_new:N \l_regex_group_end_seq
+% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_regex_capturing_group_int}
% \begin{variable}{\l_regex_capturing_group_seq}
-% \cs{l_regex_capturing_group_int} is the id number of the current
+% \cs{l_regex_capturing_group_int} is the ID number of the current
% capturing group, starting at $0$ for a group enclosing the full
% regular expression, and counting in the order of their left parenthesis.
% This number is used when a branch of the alternation ends.
% Capturing groups can be arbitrarily nested, and we keep track of
-% the stack of id numbers in \cs{l_regex_capturing_group_seq}.
+% the stack of ID numbers in \cs{l_regex_capturing_group_seq}.
% \begin{macrocode}
\int_new:N \l_regex_capturing_group_int
\seq_new:N \l_regex_capturing_group_seq
@@ -588,33 +605,17 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{l_regex_repetition_int}
-% Used when to distinguish threads at the same state but with
-% different repetitions of some quantifiers.
-% \begin{macrocode}
-\int_new:N \l_regex_repetition_int
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_regex_look_behind_bool}
-% \begin{variable}{\l_regex_look_behind_str}
-% The boolean \cs{l_regex_look_behind_bool} indicates whether
-% a look-behind assertion appears within the regular expression
-% (currently only |\b| or |\B|). When matching, we will keep
-% track of the part of the string before the current character
-% in \cs{l_regex_look_behind_str}, stored backwards.
-% \begin{macrocode}
-\bool_new:N \l_regex_look_behind_bool
-\tl_new:N \l_regex_look_behind_str
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-%
% \subsubsection{Character classes}
%
% \begin{macro}{\regex_build_tmp_class:n}
% \begin{variable}{\l_regex_class_bool,\l_regex_class_tl}
-% Used when building character classes.
+% \cs{l_regex_class_bool} is false for negative character classes.
+% \cs{l_regex_class_tl} holds the tests which should be performed
+% to decide whether the \cs{l_regex_current_char_int} matches that
+% character class. Once the class is read completely, the full
+% instructions are stored in \cs{regex_build_tmp_class:n}, whose
+% argument is the target state if the test succeeds. It is also used
+% for all other single-character situations (\emph{e.g.}, |\d|, or |.|).
% \begin{macrocode}
\cs_new_eq:NN \regex_build_tmp_class:n \use_none:n
\bool_new:N \l_regex_class_bool
@@ -633,73 +634,73 @@
% are recognized by |\d|, |\D|, |\w|, \emph{etc.}
% in regular expressions. Namely, |\d=[0-9]|,
% |\w=[0-9A-Z_a-z]|, |\s=[\ \^^I\^^J\^^L\^^M]|,
-% |\h=[\ \^^I]|, |\v=[\^^J-\^^M]|, and the upper-case
-% counterparts match anything that the lowercase
+% |\h=[\ \^^I]|, |\v=[\^^J-\^^M]|, and the upper case
+% counterparts match anything that the lower case
% does not match.
% The order in which the various ranges appear is
-% optimized for usual mostly lowercase letter text.
+% optimized for usual mostly lower case letter text.
% \begin{macrocode}
\tl_const:Nn \c_regex_d_tl
{
- \regex_item_range:nn {48} {57} % 0--9
+ \regex_item_range:nn { \c_forty_eight } { 57 } % 0--9
}
\tl_const:Nn \c_regex_D_tl
{
- \regex_item_more:n {57} % 9
- \regex_item_range:nn {0} {47} % 0
+ \regex_item_geq:n { \c_fifty_eight } % > `9
+ \regex_item_range:nn { \c_zero } { 47 } % 0
}
\tl_const:Nn \c_regex_h_tl
{
- \regex_item_equal:n {32} % space
- \regex_item_equal:n {9} % tab
+ \regex_item_equal:n { \c_thirty_two } % space
+ \regex_item_equal:n { \c_nine } % tab
}
\tl_const:Nn \c_regex_H_tl
{
- \regex_item_neq:n {32} % space
- \regex_item_neq:n {9} % tab
- \regex_break_true:w
+ \regex_item_geq:n { 33 } % > space
+ \regex_item_range:nn { \c_ten } { 31 } % tab < ... < space
+ \regex_item_range:nn { \c_zero } { \c_eight } % < tab
}
\tl_const:Nn \c_regex_s_tl
{
- \regex_item_equal:n {32} % space
- \regex_item_neq:n {11} % vtab
- \regex_item_range:nn {9} {13} % tab, lf, vtab, ff, cr
+ \regex_item_equal:n { \c_thirty_two } % space
+ \regex_item_range:nn { \c_nine } { \c_ten } % tab, lf
+ \regex_item_range:nn { \c_twelve } { \c_thirteen } % ff, cr
}
\tl_const:Nn \c_regex_S_tl
{
- \regex_item_more:n {32} % > space
- \regex_item_range:nn {14} {31} % tab < ... < space
- \regex_item_range:nn {0} {8} % < tab
- \regex_item_equal:n {11} % vtab
+ \regex_item_geq:n { 33 } % > space
+ \regex_item_range:nn { \c_fourteen } { 31 } % tab < ... < space
+ \regex_item_range:nn { \c_zero } { \c_eight } % < tab
+ \regex_item_equal:n { \c_eleven } % vtab
}
\tl_const:Nn \c_regex_v_tl
{
- \regex_item_range:nn {10} {13} % lf, vtab, ff, cr
+ \regex_item_range:nn { \c_ten } { \c_thirteen } % lf, vtab, ff, cr
}
\tl_const:Nn \c_regex_V_tl
{
- \regex_item_more:n {13} % cr
- \regex_item_range:nn {0} {9} % < lf
+ \regex_item_geq:n { \c_fourteen } % >cr
+ \regex_item_range:nn { \c_zero } { \c_nine } % < lf
}
\tl_const:Nn \c_regex_w_tl
{
- \regex_item_range:nn {97} {122} % a--z
- \regex_item_range:nn {65} {90} % A--Z
- \regex_item_range:nn {48} {57} % 0--9
- \regex_item_equal:n {95} % _
+ \regex_item_range:nn { \c_ninety_seven } { 122 } % a--z
+ \regex_item_range:nn { \c_sixty_five } { 90 } % A--Z
+ \regex_item_range:nn { \c_forty_eight } { 57 } % 0--9
+ \regex_item_equal:n { 95 } % _
}
\tl_const:Nn \c_regex_W_tl
{
- \regex_item_range:nn {0} {47} % <`0
- \regex_item_range:nn {58} {64} % (`9+1)--(`A-1)
- \regex_item_range:nn {91} {94} % (`Z+1)--(`_-1)
- \regex_item_equal:n {96} % `
- \regex_item_more:n {122} % z
+ \regex_item_range:nn { \c_zero } { 47 } % <`0
+ \regex_item_range:nn { \c_fifty_eight } { 64 } % (`9+1)--(`A-1)
+ \regex_item_range:nn { \c_ninety_one } { 94 } % (`Z+1)--(`_-1)
+ \regex_item_equal:n { 96 } % `
+ \regex_item_geq:n { \c_one_hundred_twenty_three } % z
}
\tl_const:Nn \c_regex_N_tl
{
- \regex_item_neq:n {10} % lf
- \regex_break_true:w
+ \regex_item_geq:n { \c_eleven } % > lf
+ \regex_item_range:nn { \c_zero } { \c_nine } % < lf
}
% \end{macrocode}
% \end{variable}
@@ -711,43 +712,69 @@
%
% \subsubsection{Variables used when matching}
%
-% \begin{variable}{\l_regex_query_str}
+% \begin{variable}{\l_regex_query_other_str}
% The string that is being matched.
+% In that string, spaces have category code \enquote{other}.
% \begin{macrocode}
-\tl_new:N \l_regex_query_str
+\tl_new:N \l_regex_query_other_str
% \end{macrocode}
% \end{variable}
%
+% \begin{variable}{\l_regex_current_step_int}
% \begin{variable}{\l_regex_start_step_int}
-% In the case of multiple matches, \cs{l_regex_start_step_int}
-% is equal to the position where the current match
-% attempt began.
+% \begin{variable}{\l_regex_success_step_int}
+% While reading through the query string, \cs{l_regex_current_step_int}
+% is the position in the string. Each match begins at the position
+% given by \cs{l_regex_start_step_int}. Whenever an execution thread
+% succeeds, the corresponding step is stored into
+% \cs{l_regex_success_step_int}, which will be the next starting step
+% (except in the case of empty matches).
% \begin{macrocode}
+\int_new:N \l_regex_current_step_int
\int_new:N \l_regex_start_step_int
+\int_new:N \l_regex_success_step_int
+% \end{macrocode}
+% \end{variable}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}{\l_regex_unique_step_int}
+% In the case of repeated matches, \cs{l_regex_current_step_int}
+% is reset to the end-position of the previous match. In contrast,
+% \cs{l_regex_unique_step_int} is simply incremented to provide
+% a unique number for each iteration of the matching loop. This
+% is handy to attach each set of submatch information to a given
+% iteration (and automatically discard it when it corresponds to
+% a past iteration).
+% \begin{macrocode}
+\int_new:N \l_regex_unique_step_int
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_regex_current_char_int}
-% \begin{variable}{\l_regex_current_step_int}
-% The character at the current position in the string,
-% and the current position.
+% \begin{variable}{\l_regex_last_char_int}
+% \begin{variable}{\l_regex_case_changed_char_int}
+% The character codes of the character at the current position
+% in the string, and at the previous position, and the current
+% character with its case changed (|A-Z|$\leftrightarrow$|a-z|).
+% The \cs{l_regex_last_char_int} is used to test for word boundaries
+% (|\b| and |\B|). The \cs{l_regex_case_changed_char_int} is
+% only computed if the \enquote{case insensitive} option |(?i)|
+% is used in the regex.
% \begin{macrocode}
\int_new:N \l_regex_current_char_int
-\int_new:N \l_regex_current_step_int
+\int_new:N \l_regex_last_char_int
+\int_new:N \l_regex_case_changed_char_int
% \end{macrocode}
% \end{variable}
% \end{variable}
+% \end{variable}
%
-% \begin{variable}{\l_regex_unique_step_int}
-% This gives a unique identifier to every step in the loop over
-% characters in the string. In the case of a single match, it is
-% equal to \cs{l_regex_current_step_int}, but for multiple matches,
-% it is not reset to the start of the next match, but incremented.
-% A unique identifier is handy when considering whether a state of
-% the automaton has been visited at that step or not, and when
-% tracking submatch information.
+% \begin{variable}{\l_regex_caseless_bool}
+% True if caseless matching is used within the regular expression.
+% This controls whether \cs{l_regex_case_changed_char_int} is computed.
% \begin{macrocode}
-\int_new:N \l_regex_unique_step_int
+\bool_new:N \l_regex_caseless_bool
% \end{macrocode}
% \end{variable}
%
@@ -755,17 +782,37 @@
% For every character in the string, each of the active states is
% considered in turn.
% The variable \cs{l_regex_current_state_int} holds the state
-% of the NFA which is currently considered.
+% of the NFA which is currently considered: transitions are then
+% given as shifts relative to the current state.
+% In the case of groups with quantifiers,
+% \cs{l_regex_current_state_int} is shifted to a fake value for
+% transitions to point to the correct states.
% \begin{macrocode}
\int_new:N \l_regex_current_state_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_regex_current_submatches_prop}
+% \begin{variable}{\l_regex_success_submatches_prop}
+% The submatches for the thread which lies at the
+% \cs{l_regex_current_state_int} are stored in a property
+% list variable. This property list is stored by
+% \cs{regex_action_cost:n} into the \tn{toks} register
+% for the target state of the transition. When a thread
+% succeeds, this property list is copied to
+% \cs{l_regex_success_submatches_prop} and only the last
+% sucessful thread will remain there.
+% \begin{macrocode}
\prop_new:N \l_regex_current_submatches_prop
+\prop_new:N \l_regex_success_submatches_prop
% \end{macrocode}
% \end{variable}
+% \end{variable}
%
% \begin{variable}{\l_regex_max_index_int}
% All the currently active states are kept in order of precedence
% in the \tn{skip} registers, which for our purpose serve as an array:
-% the $i$-th item of the array is \tn{skip}$i$. The largest index used
+% the $i$th item of the array is \tn{skip}$i$. The largest index used
% after treating the previous character is \cs{l_regex_max_index_int}.
% At the start of every step, the whole array is unpacked, so that the
% space can immediately be reused, and \cs{l_regex_max_index_int} reset
@@ -785,11 +832,25 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{variable}{\l_regex_success_bool}
+% The boolean \cs{l_regex_success_bool} is true if the current match
+% attempt was successful.
+% \begin{macrocode}
+\bool_new:N \l_regex_success_bool
+% \end{macrocode}
+% \end{variable}
+%
% \begin{macro}{\regex_last_match_empty:F}
-% This function is most often \cs{use:n}, unless the current
-% regular expression can match an empty string at the current
-% position, and has already done so at the previous match attempt.
-% The goal is to break infinite loops.
+% \begin{macro}[aux]{\regex_last_match_empty_no:F}
+% \begin{macro}[aux]{\regex_last_match_empty_yes:F}
+% When doing multiple matches, we need to avoid infinite loops where
+% each iteration matches the same empty string. When we detect such
+% a situation, the next match attempt is shifted by one character.
+% Namely, an empty match is discarded if it follows an empty match
+% at the same position. If the previous match was non-empty,
+% \cs{regex_last_match_empty:F} is simply \cs{use:n}, and keeps
+% the match. If it was empty, then we test whether the new match
+% has moved or not: if it has not, then the success is discarded.
% \begin{macrocode}
\cs_new_protected:Npn \regex_last_match_empty_no:F #1 {#1}
\cs_new_protected:Npn \regex_last_match_empty_yes:F
@@ -797,37 +858,25 @@
\cs_new_eq:NN \regex_last_match_empty:F \regex_last_match_empty_no:F
% \end{macrocode}
% \end{macro}
+% \end{macro}
+% \end{macro}
%
-% \begin{variable}{\l_regex_success_bool}
-% \begin{variable}{\l_regex_success_step_int}
-% \begin{variable}{\l_regex_success_submatches_prop}
% \begin{variable}{\l_regex_success_empty_bool}
-% The booleans \cs{l_regex_success_bool} and
-% \cs{l_regex_success_empty_bool} are true if the current match
-% attempt was successful, and if the match was empty, respectively.
-% The other two variables hold the step number at which the match
-% was successful and a property list of submatches.
-% \begin{macrocode}
-\bool_new:N \l_regex_success_bool
-\bool_new:N \l_regex_success_empty_bool
-\int_new:N \l_regex_success_step_int
-\prop_new:N \l_regex_success_submatches_prop
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
% \begin{variable}{\l_regex_fresh_thread_bool}
-% This boolean marks when the current thread has started from
-% the beginning of the regular expression at this character,
-% in other words, it is true if the current thread has matched
-% an empty string so far (and we only care about this boolean
-% when a thread succeeds, hence matching an empty string overall).
+% When a match succeeds, \cs{l_regex_success_empty_bool}
+% records whether it is empty. This information is used
+% to initialize \cs{regex_last_match_empty:F} before
+% starting the next match attempt.
+% The boolean \cs{l_regex_fresh_thread_bool} is true
+% when the current thread has started from the beginning of the
+% regular expression at this character.
+% This is probably suboptimal. Improvements welcome.
% \begin{macrocode}
+\bool_new:N \l_regex_success_empty_bool
\bool_new:N \l_regex_fresh_thread_bool
% \end{macrocode}
% \end{variable}
+% \end{variable}
%
% \subsubsection{Variables used for user functions}
%
@@ -848,6 +897,15 @@
% \end{macrocode}
% \end{variable}
%
+% \begin{variable}{\g_regex_extract_all_seq}
+% The \cs{regex_extract_all:nnN} function stores its result
+% in that sequence variable before assigning it to the
+% variable provided by the user.
+% \begin{macrocode}
+\seq_new:N \g_regex_extract_all_seq
+% \end{macrocode}
+% \end{variable}
+%
% \begin{variable}{\g_regex_split_seq}
% The \cs{regex_split:nnN} function stores its result
% in that sequence variable before assigning it to the
@@ -909,59 +967,66 @@
% \end{macro}
% \end{macro}
%
-% \subsubsection{Interrupting recursions}
+% \subsubsection{Unsafe substring extraction}
%
-% \begin{macro}[int]{\regex_if_tail_stop:N}
-% \begin{macro}[int]{\regex_if_tail_error:Nn}
-% Test for the end of the \meta{string}, and either stop
-% or cause an error if it is reached.
+% \begin{macro}[int]{\regex_query_substr:NN}
+% \begin{macro}[aux]{\regex_query_substr_aux:nnn}
+% Extracting submatches from the query string is done
+% in a way similar to \cs{str_substr:Nnn}, but omitting
+% most checks, hence faster.
% \begin{macrocode}
-\cs_new_eq:NN \regex_if_tail_stop:N \quark_if_recursion_tail_stop:N
-\cs_new_protected_nopar:Npn \regex_if_tail_error:Nn #1#2
- { \quark_if_recursion_tail_stop_do:Nn #1 { \regex_build_error:n {#2} } }
+\cs_new_nopar:Npn \regex_query_substr:NN #1#2
+ {
+ \exp_after:wN \regex_query_substr_aux:NN
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \l_regex_query_other_str
+ \q_stop
+ }
+\cs_new:Npn \regex_query_substr_aux:NN #1#2
+ {
+ \str_skip_do:nn {#1}
+ { \str_collect_do:nn { #2 - #1 } { \use_i_delimit_by_q_stop:nw } }
+ }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\regex_build_error:n}
-% This macro is called if anything goes wrong when building
-% the NFA corresponding to a given regular expression
-% Negative codes are specific to the \LaTeX3 implementation.
-% Other error codes match with the PCRE codes (not all of
-% the PCRE errors can occur, since some constructions are
-% not supported).
+% \subsubsection{Sequences}
+%
+% \begin{macro}[int]{\regex_seq_pop:N}
+% \begin{macro}[int]{\regex_seq_get:N}
+% When building the regular expression, some settings are kept
+% local to capturing groups without any help from \TeX{}'s grouping.
+% This is done \enquote{by hand}, in sequences whose items contain
+% instructions such as |\int_set:Nn| \meta{int~var} \Arg{value},
+% which should be run immediately.
% \begin{macrocode}
-\cs_new_protected_nopar:Npn \regex_build_error:n #1
+\cs_new_protected_nopar:Npn \regex_seq_pop:N #1
{
- \msg_error:nnxx { regex } { build-error } {\int_eval:n{#1}}
- {
- \prg_case_int:nnn {#1}
- {
- {-999} {File~not~found}
- {-998} {Unsupported~construct}
- {-997} {The~regular~expression~is~too~large~(32768~states).}
- {1} {\iow_char:N\\~at~end~of~pattern }
-% {2} {\iow_char:N\\c~at~end~of~pattern }
- {4} {Numbers~out~of~order~in~\iow_char:N\{\iow_char\}~quantifier.}
- {6} {Missing~terminating~\iow_char:N\]~for~character~class }
- {7} {Invalid~escape~sequence~in~character~class}
- {8} {Range~out~of~order~in~character~class}
- {22} {Mismatched~parentheses}
- {34} {Character~value~in~\iow_char:N\\x{...}~sequence~is~too~large}
-% {44} {Invalid~UTF-8~string}
-% {46} {Malformed~\iow_char:N\\P~or\iow_char:N\\p~sequence}
-% {47} {Unknown~property~after~\iow_char:N\\P~or\iow_char:N\\p}
-% {68} {\iow_char:N\\c~must~be~followed~by~an~ASCII~character}
- }
- { Internal~bug. }
- }
+ \seq_pop:NN #1 \l_regex_tmpa_tl
+ \l_regex_tmpa_tl
+ }
+\cs_new_protected_nopar:Npn \regex_seq_get:N #1
+ {
+ \seq_get:NN #1 \l_regex_tmpa_tl
+ \l_regex_tmpa_tl
}
-\msg_new:nnn { regex } { build-error } { (error~#1): ~ #2 }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \subsubsection{Testing characters}
%
+% \begin{macro}{\regex_item_dot:T}
+% The dot meta-character matches any character,
+% except the end-of-string marker.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \regex_item_dot:T
+ { \int_compare:nNnF \l_regex_current_char_int = \c_minus_one }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[int]{\regex_break_point:TF}
% \begin{macro}[int]{\regex_break_true:w,\regex_break_false:w}
% When testing whether a character of the query string matches
@@ -977,25 +1042,27 @@
% Otherwise, \cs{regex_break_point:TF} leaves the \meta{false code}
% in the input stream.
% \begin{macrocode}
-\cs_new_nopar:Npn \regex_break_true:w #1 \regex_break_point:TF #2 #3 {#2}
-\cs_new_nopar:Npn \regex_break_false:w #1 \regex_break_point:TF #2 #3 {#3}
-\cs_new_eq:NN \regex_break_point:TF \use_ii:nn
+\cs_new_protected_nopar:Npn \regex_break_true:w
+ #1 \regex_break_point:TF #2 #3 {#2}
+\cs_new_protected_nopar:Npn \regex_break_false:w
+ #1 \regex_break_point:TF #2 #3 {#3}
+\cs_new_protected_nopar:Npn \regex_break_point:TF #1 #2 { #2 }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\regex_item_equal:n,\regex_item_range:nn}
-% \begin{macro}[int]{\regex_item_less:n,\regex_item_more:n}
-% \begin{macro}[int]{\regex_item_neq:n}
+% \begin{macro}[int]{\regex_item_caseful_equal:n}
+% \begin{macro}[int]{\regex_item_caseful_range:nn}
+% \begin{macro}[int]{\regex_item_caseful_geq:n}
% Simple comparisons triggering \cs{regex_break_true:w} when true.
% \begin{macrocode}
-\cs_new_nopar:Npn \regex_item_equal:n #1
+\cs_new_protected_nopar:Npn \regex_item_caseful_equal:n #1
{
\if_num:w #1 = \l_regex_current_char_int
\exp_after:wN \regex_break_true:w
\fi:
}
-\cs_new_nopar:Npn \regex_item_range:nn #1 #2
+\cs_new_protected_nopar:Npn \regex_item_caseful_range:nn #1 #2
{
\reverse_if:N \if_num:w #1 > \l_regex_current_char_int
\reverse_if:N \if_num:w #2 < \l_regex_current_char_int
@@ -1003,29 +1070,97 @@
\fi:
\fi:
}
-\cs_new_nopar:Npn \regex_item_less:n #1
+\cs_new_protected_nopar:Npn \regex_item_caseful_geq:n #1
{
- \if_num:w #1 > \l_regex_current_char_int
+ \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
\exp_after:wN \regex_break_true:w
\fi:
}
-\cs_new_nopar:Npn \regex_item_more:n #1
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int]{\regex_item_caseless_equal:n}
+% \begin{macro}[int]{\regex_item_caseless_range:nn}
+% \begin{macro}[int]{\regex_item_caseless_geq:n}
+% For caseless matching, we perform the test both on
+% \cs{l_regex_current_char_int} and on
+% \cs{l_regex_case_changed_char_int}.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \regex_item_caseless_equal:n #1
{
- \if_num:w #1 < \l_regex_current_char_int
+ \if_num:w #1 = \l_regex_current_char_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ \if_num:w #1 = \l_regex_case_changed_char_int
\exp_after:wN \regex_break_true:w
\fi:
}
-\cs_new_nopar:Npn \regex_item_neq:n #1
+\cs_new_protected_nopar:Npn \regex_item_caseless_range:nn #1 #2
{
- \if_num:w #1 = \l_regex_current_char_int
- \exp_after:wN \regex_break_false:w
+ \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
+ \reverse_if:N \if_num:w #2 < \l_regex_current_char_int
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
+ \fi:
+ \fi:
+ \reverse_if:N \if_num:w #1 > \l_regex_case_changed_char_int
+ \reverse_if:N \if_num:w #2 < \l_regex_case_changed_char_int
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
+ \fi:
\fi:
}
+\cs_new_protected_nopar:Npn \regex_item_caseless_geq:n #1
+ {
+ \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ \reverse_if:N \if_num:w #1 > \l_regex_case_changed_char_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int]{\regex_item_equal:n}
+% \begin{macro}[int]{\regex_item_range:nn}
+% \begin{macro}[int]{\regex_item_geq:n}
+% By default, matching takes the letter case into account.
+% Note that those functions are not protected:
+% they will expand at the building step, hard-coding which
+% states take care of caseless versus caseful matching.
+% \begin{macrocode}
+\cs_new:Npn \regex_item_equal:n { \regex_item_caseful_equal:n }
+\cs_new:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
+\cs_new:Npn \regex_item_geq:n { \regex_item_caseful_geq:n }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
+% \begin{macro}[int]{\regex_build_caseless:,\regex_build_caseful:}
+% Switch between caseful and caseless matching.
+% This is only done during the building step.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \regex_build_caseless:
+ {
+ \bool_set_true:N \l_regex_caseless_bool
+ \cs_set:Npn \regex_item_equal:n { \regex_item_caseless_equal:n }
+ \cs_set:Npn \regex_item_range:nn { \regex_item_caseless_range:nn }
+ \cs_set:Npn \regex_item_geq:n { \regex_item_caseless_geq:n }
+ }
+\cs_new_protected_nopar:Npn \regex_build_caseful:
+ {
+ \bool_set_false:N \l_regex_caseless_bool
+ \cs_set:Npn \regex_item_equal:n { \regex_item_caseful_equal:n }
+ \cs_set:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
+ \cs_set:Npn \regex_item_geq:n { \regex_item_caseful_geq:n }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \subsubsection{Grabbing digits}
%
% \begin{macro}[int]{\regex_get_digits:nw}
@@ -1042,23 +1177,27 @@
{
\exp_not:n {#1}
{ \if_false: } } \fi:
- \regex_get_digits_aux:N
+ \regex_get_digits_aux:NN
}
-\cs_new_nopar:Npn \regex_get_digits_aux:N #1
+\cs_new_nopar:Npn \regex_get_digits_aux:NN #1#2
{
- \if_num:w 9 < 1 \exp_not:N #1 \exp_stop_f:
- \else:
- \if_charcode:w \c_space_token \exp_not:N #1
+ \if_meaning:w \regex_build_raw:N #1
+ \if_charcode:w \c_space_token \exp_not:N #2
\else:
- \regex_get_digits_end:w
+ \if_num:w 9 < 1 \exp_not:N #2 \exp_stop_f:
+ #2
+ \else:
+ \regex_get_digits_end:w #1 #2
+ \fi:
\fi:
+ \else:
+ \regex_get_digits_end:w #1 #2
\fi:
- #1 \regex_get_digits_aux:N
+ \regex_get_digits_aux:NN
}
-\cs_new_nopar:Npn \regex_get_digits_end:w
- \fi: \fi: #1 \regex_get_digits_aux:N
+\cs_new_nopar:Npn \regex_get_digits_end:w #1 \fi: #2 \regex_get_digits_aux:NN
{
- \fi: \fi:
+ \fi: #2
\if_false: { { \fi: } }
#1
}
@@ -1066,7 +1205,20 @@
% \end{macro}
% \end{macro}
%
-% \subsubsection{More char testing}
+% \subsubsection{More character testing}
+%
+% \begin{macro}[EXP,pTF]{\regex_token_if_other_digit:N}
+% In the replacement text, |\g{|\meta{int}|}| denotes the \meta{int}-th
+% submatch. Parsing this construction robustly requires a test of whether
+% a token is a digit or not.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \regex_token_if_other_digit:N #1 { TF }
+ {
+ \if_num:w \c_nine < 1 \exp_not:N #1 \exp_stop_f:
+ \prg_return_true: \else: \prg_return_false: \fi:
+ }
+% \end{macrocode}
+% \end{macro}
%
% \begin{macro}[EXP,aux]{\regex_aux_char_if_alphanumeric:NTF}
% \begin{macro}[EXP,aux]{\regex_aux_char_if_special:NTF}
@@ -1076,11 +1228,11 @@
% ones have special meanings and which should be interpreted
% as \enquote{raw} characters. Namely,
% \begin{itemize}
-% \item alphanumerics are \enquote{raw} if they are not escaped,
-% and may have a special meaning when escaped;
-% \item non-alphanumeric printable ascii characters are \enquote{raw}
-% if they are escaped, and may have a special meaning when not escaped;
-% \item characters other than printable ascii are always \enquote{raw}.
+% \item alphanumerics are \enquote{raw} if they are not escaped,
+% and may have a special meaning when escaped;
+% \item non-alphanumeric printable ascii characters are \enquote{raw}
+% if they are escaped, and may have a special meaning when not escaped;
+% \item characters other than printable ascii are always \enquote{raw}.
% \end{itemize}
% The code is ugly, and highly based on magic numbers and the ascii
% codes of characters. This is mostly unavoidable for performance
@@ -1095,43 +1247,40 @@
% \begin{macrocode}
\prg_new_conditional:Npnn \regex_aux_char_if_special:N #1 { TF }
{
- \if_num:w `#1 < 97 \exp_stop_f:
- \if_num:w `#1 < 58 \exp_stop_f:
- \if_num:w \int_eval:w (`#1 - \c_eight)/\c_sixteen = \c_two
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
+ \if_num:w `#1 < \c_ninety_one
+ \if_num:w `#1 < \c_fifty_eight
+ \if_num:w `#1 < \c_forty_eight
+ \if_num:w `#1 < \c_thirty_two
+ \prg_return_false: \else: \prg_return_true: \fi:
+ \else: \prg_return_false: \fi:
\else:
- \if_num:w \int_eval:w `#1 / 26 = \c_three
- \prg_return_false:
- \else:
- \prg_return_true:
- \fi:
+ \if_num:w `#1 < \c_sixty_five
+ \prg_return_true: \else: \prg_return_false: \fi:
\fi:
\else:
- \if_num:w \int_eval:w `#1 / \c_five = 25 \exp_stop_f:
- \prg_return_true:
+ \if_num:w `#1 < \c_one_hundred_twenty_three
+ \if_num:w `#1 < \c_ninety_seven
+ \prg_return_true: \else: \prg_return_false: \fi:
\else:
- \prg_return_false:
+ \if_num:w `#1 < \c_one_hundred_twenty_seven
+ \prg_return_true: \else: \prg_return_false: \fi:
\fi:
\fi:
}
\prg_new_conditional:Npnn \regex_aux_char_if_alphanumeric:N #1 { TF }
{
- \if_num:w `#1 < 91 \exp_stop_f:
- \if_num:w `#1 < 65 \exp_stop_f:
- \if_num:w \c_nine < 1 #1 \exp_stop_f:
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
+ \if_num:w `#1 < \c_ninety_one
+ \if_num:w `#1 < \c_fifty_eight
+ \if_num:w `#1 < \c_forty_eight
+ \prg_return_false: \else: \prg_return_true: \fi:
\else:
- \prg_return_true:
+ \if_num:w `#1 < \c_sixty_five
+ \prg_return_false: \else: \prg_return_true: \fi:
\fi:
\else:
- \if_num:w \int_eval:w (`#1-\c_six)/26 = \c_four
- \prg_return_true:
+ \if_num:w `#1 < \c_one_hundred_twenty_three
+ \if_num:w `#1 < \c_ninety_seven
+ \prg_return_false: \else: \prg_return_true: \fi:
\else:
\prg_return_false:
\fi:
@@ -1153,8 +1302,8 @@
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_build_new_state:
{
- \int_compare:nNnTF \l_regex_max_state_int > {32766}
- { \regex_build_error:n {-997} }
+ \int_compare:nNnTF \l_regex_max_state_int > { 32766 }
+ { \msg_error:nn { regex } { -997 } }
{
\int_incr:N \l_regex_max_state_int
\tex_toks:D \l_regex_max_state_int { \s_regex_toks }
@@ -1174,15 +1323,15 @@
{
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
- { #1 { \int_use:N #2 } }
+ { #1 { \int_eval:n { #2 - \l_regex_left_state_int } } }
}
\cs_new_protected_nopar:Npn \regex_build_transitions_aux:NNNN #1#2#3#4
{
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
{
- #1 { \int_use:N #2 }
- #3 { \int_use:N #4 }
+ #1 { \int_eval:n { #2 - \l_regex_left_state_int } }
+ #3 { \int_eval:n { #4 - \l_regex_left_state_int } }
}
}
% \end{macrocode}
@@ -1191,8 +1340,10 @@
%
% \subsubsection{From regex to NFA: framework}
%
-% In order for the construction \texttt{ab\string|cd} to work, we enclose
-% the whole pattern within parentheses. These have the added benefit
+% In order for the construction \verb"ab|cd" to work, we enclose
+% the whole pattern within parentheses (in the code below,
+% \cs{regex_build_open_aux:} and \cs{regex_build_close_aux:}).
+% These have the added benefit
% to form a capturing group: hence we get the data of the whole match
% for free.
%
@@ -1270,28 +1421,20 @@
%
% \begin{macro}[int]{\regex_build_setup:}
% Hopefully, we didn't forget to initialize anything here.
-% The search is not anchored: to acheive that, we insert state(s)
+% The search is not anchored: to achieve that, we insert state(s)
% responsible for repeating the match attempt on every character
-% of the string: the first state has a free transition to the second
-% state, where the regular expression really begins, and a costly
-% transition to itself, to try again at the next character.
+% of the string.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_build_setup:
{
\cs_set_eq:NN \regex_build_control:N \regex_build_default_control:N
\cs_set_eq:NN \regex_build_raw:N \regex_build_default_raw:N
\int_set_eq:NN \l_regex_capturing_group_int \c_zero
- \int_zero:N \l_regex_left_state_int
- \int_zero:N \l_regex_right_state_int
\int_zero:N \l_regex_max_state_int
\regex_build_new_state:
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
- {
- \regex_action_start_wildcard:nn
- { \int_use:N \l_regex_left_state_int }
- { \int_use:N \l_regex_right_state_int }
- }
+ { \regex_action_start_wildcard:nn {0} {1} }
}
% \end{macrocode}
% \end{macro}
@@ -1305,9 +1448,9 @@
{
\seq_if_empty:NF \l_regex_capturing_group_seq
{
- \regex_build_error:n {22}
+ \msg_error:nn { regex } {22}
\prg_replicate:nn
- { \seq_length:N \l_regex_capturing_group_seq } % (
+ { \seq_length:N \l_regex_capturing_group_seq }
{ \regex_build_close_aux: \regex_build_group_: }
}
\regex_toks_put_right:Nx \l_regex_right_state_int
@@ -1339,7 +1482,13 @@
\regex_toks_put_right:Nx \l_regex_left_state_int
{
\exp_not:N \int_compare:nNnT {#1} = \l_regex_current_step_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
}
% \end{macrocode}
@@ -1360,7 +1509,13 @@
{
\exp_not:N \int_compare:nNnT
\c_minus_one = \l_regex_current_char_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
}
\cs_new_eq:Nc \regex_build_Z: { regex_build_$: } %$
@@ -1374,52 +1529,50 @@
% \begin{macro}[int]{\regex_build_B:}
% \begin{macro}[aux]{\regex_if_word_boundary:TF}
% Contrarily to |^| and |$|, which could be implemented without
-% really knowing what preceeds in the string, this requires
-% more information. We request it by setting
-% \cs{l_regex_look_behind_bool}. Then the matching code will
-% keep store the characters that were already read, backwards,
-% in \cs{l_regex_look_behind_str}, and we can analyse the first
-% character of that string.
+% really knowing what precedes in the string, this requires
+% more information, namely, the knowledge of the last character
+% code. Case sensitivity does not change word boundaries.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_build_b:
{
- \bool_set_true:N \l_regex_look_behind_bool
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
{
\exp_not:N \regex_if_word_boundary:TF
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
{ }
}
}
\cs_new_protected_nopar:Npn \regex_build_B:
{
- \bool_set_true:N \l_regex_look_behind_bool
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
{
\exp_not:N \regex_if_word_boundary:TF
{ }
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
}
\cs_new_protected_nopar:Npn \regex_if_word_boundary:TF
{
- \tl_if_empty:NTF \l_regex_look_behind_str
- { \c_regex_w_tl }
- {
- \group_begin:
- \cs_set_nopar:Npx \regex_tmp:w
- {
- \int_set:Nn \l_regex_current_char_int
- { ` \str_head:N \l_regex_look_behind_str }
- }
- \regex_tmp:w
- \c_regex_w_tl
- \regex_break_point:TF
- { \group_end: \c_regex_W_tl }
- { \group_end: \c_regex_w_tl }
- }
+ \group_begin:
+ \int_set_eq:NN \l_regex_current_char_int \l_regex_last_char_int
+ \c_regex_w_tl
+ \regex_break_point:TF
+ { \group_end: \c_regex_W_tl \regex_item_equal:n { -1 } }
+ { \group_end: \c_regex_w_tl }
\regex_break_point:TF
}
% \end{macrocode}
@@ -1434,18 +1587,16 @@
% (actually, any unknown combination) will match itself
% and the thread will fail otherwise. We prepare
% \cs{regex_build_tmp_class:n} with the relevant test and
-% commands. The program steps to be inserted in those
-% commands will come as |##1| and |##2|: we don't know
-% yet what those will be before checking for quantifiers.
+% commands. The state shift to be inserted in those
+% commands will come as |##1|: we don't know
+% yet what this will be before checking for quantifiers.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_build_default_raw:N #1
{
\cs_set:Npx \regex_build_tmp_class:n ##1
{
- \exp_not:n { \exp_not:N \if_num:w }
- \int_value:w `#1 = \l_regex_current_char_int
- \regex_action_cost:n { ##1 }
- \exp_not:n { \exp_not:N \fi: }
+ \regex_item_equal:n { \int_value:w `#1 }
+ \regex_break_point:TF { \regex_action_cost:n { ##1 } } { }
}
\regex_build_one_quantifier:
}
@@ -1459,11 +1610,7 @@
\cs_new_protected_nopar:cpn { regex_build_.: }
{
\cs_set:Npn \regex_build_tmp_class:n ##1
- {
- \exp_not:N \if_num:w \c_minus_one < \l_regex_current_char_int
- \regex_action_cost:n {##1}
- \exp_not:N \fi:
- }
+ { \regex_item_dot:T { \regex_action_cost:n {##1} } }
\regex_build_one_quantifier:
}
% \end{macrocode}
@@ -1486,9 +1633,7 @@
\cs_set:Npn \regex_build_tmp_class:n ##1
{
\exp_not:N #1
- \exp_not:N \regex_break_point:TF
- { \regex_action_cost:n {##1} }
- { }
+ \regex_break_point:TF { \regex_action_cost:n {##1} } { }
}
\regex_build_one_quantifier:
}
@@ -1557,16 +1702,8 @@
{
\exp_not:o \l_regex_class_tl
\bool_if:NTF \l_regex_class_bool
- {
- \exp_not:N \regex_break_point:TF
- { \regex_action_cost:n {##1} }
- { }
- }
- {
- \exp_not:N \regex_break_point:TF
- { }
- { \regex_action_cost:n {##1} }
- }
+ { \regex_break_point:TF { \regex_action_cost:n {##1} } { } }
+ { \regex_break_point:TF { } { \regex_action_cost:n {##1} } }
}
\regex_build_one_quantifier:
}
@@ -1607,7 +1744,7 @@
\cs_new_protected_nopar:Npn \regex_class_single:N #1
{
\tl_put_right:Nx \l_regex_class_tl
- { \exp_not:N \regex_item_equal:n { \int_value:w `#1 } }
+ { \regex_item_equal:n { \int_value:w `#1 } }
}
% \end{macrocode}
% \end{macro}
@@ -1641,14 +1778,14 @@
\cs_new_protected_nopar:Npn \regex_class_range_put:NN #1#2
{
\if_num:w `#1 > `#2 \exp_stop_f:
- \regex_build_error:n {8}
+ \msg_error:nn { regex } {8}
\else:
\tl_put_right:Nx \l_regex_class_tl
{
\if_num:w `#1 = `#2 \exp_stop_f:
- \exp_not:N \regex_item_equal:n
+ \regex_item_equal:n
\else:
- \exp_not:N \regex_item_range:nn { \int_value:w `#1 }
+ \regex_item_range:nn { \int_value:w `#1 }
\fi:
{ \int_value:w `#2 }
}
@@ -1781,26 +1918,29 @@
\exp_not:N \regex_build_raw:N \c_lbrace_str #1#2
}
}
-\cs_new_protected_nopar:Npn \regex_build_quantifier_lbrace:nnw #1#2#3
+\cs_new_protected_nopar:Npn \regex_build_quantifier_lbrace:nnw #1#2#3#4
{
- \str_if_eq:xxTF { \exp_not:N #3 } { \c_rbrace_str }
+ \str_if_eq:xxTF
+ { \exp_not:n {#3#4} }
+ { \exp_not:N \regex_build_control:N \c_rbrace_str }
{
\tl_if_empty:nTF {#2}
- { \regex_build_quantifier_aux:nnN { {#1} {\c_max_int} } {nn} }
+ { \regex_build_quantifier_aux:nnNN { {#1} } { n* } }
{
\int_compare:nNnT {#1} > {#2}
- { \regex_build_error:n {4} }
- \regex_build_quantifier_aux:nnN { {#1} {#2} } {nn}
+ { \msg_error:nn { regex } {4} }
+ \regex_build_quantifier_aux:nnNN { {#1} {#2} } { nn }
}
}
{
\regex_build_quantifier_end:n { }
\use:x
{
- \exp_not:n { \exp_args:No \tl_map_function:nN }
- { \c_lbrace_str #1 #2 , }
- \regex_build_raw:N
+ \exp_args:No \tl_map_function:nN
+ { \c_lbrace_str #1 , #2 }
+ \regex_build_raw:N
}
+ #3 #4
}
}
% \end{macrocode}
@@ -1923,83 +2063,49 @@
% This function is called in case the syntax is
% \texttt{\{\meta{int}\}}. Greedy and lazy operators
% are identical, since the number of repetitions is fixed.
+% Simply repeat |#1| times the effect of \cs{regex_build_one_:}.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_build_one_n: #1
- {
- \int_set_eq:NN \l_regex_tmpa_int \l_regex_right_state_int
- \regex_build_new_state:
- \regex_build_new_state:
- \regex_toks_put_right:Nx \l_regex_tmpa_int
- { %^^A safe \if nesting?
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \regex_action_repeat_move:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \else:
- \regex_action_no_repeat_move:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \fi:
- }
- \regex_toks_put_right:Nx \l_regex_left_state_int
- {
- \regex_build_tmp_class:n
- { \int_use:N \l_regex_tmpa_int }
- }
- }
+ { \prg_replicate:nn {#1} { \regex_build_one_: } }
\cs_new_eq:cN { regex_build_one_n?: } \regex_build_one_n:
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[aux]{\regex_build_one_nn:}
-% \begin{macro}[aux]{\regex_build_one_nn?:}
-% \begin{macro}[aux]{\regex_build_one_nn_aux:nn}
-% This function is called when the syntax is either
-% \texttt{\{\meta{int},\}} or \texttt{\{\meta{int},\meta{int}\}}.
+% \begin{macro}[aux]{\regex_build_one_n*:}
+% \begin{macro}[aux]{\regex_build_one_n*?:}
+% This function is called in case the syntax is
+% \texttt{\{\meta{int},\}}.
% \begin{macrocode}
-\cs_new_protected_nopar:Npn \regex_build_one_nn: #1#2
+\cs_new_protected_nopar:cpx { regex_build_one_n*: } #1
{
- \regex_build_one_nn_aux:nn {#1}
- {
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \regex_action_repeat_copy:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \fi:
- \regex_action_no_repeat_move:n
- { \int_use:N \l_regex_right_state_int }
- }
+ \exp_not:N \prg_replicate:nn {#1} { \exp_not:N \regex_build_one_: }
+ \exp_not:c { regex_build_one_*: }
}
-\cs_new_protected_nopar:cpn { regex_build_one_nn?: } #1#2
+\cs_new_protected_nopar:cpx { regex_build_one_n*?: } #1
{
- \regex_build_one_nn_aux:nn {#1}
- {
- \regex_action_no_repeat_copy:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \regex_action_repeat_move:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \fi:
- }
+ \exp_not:N \prg_replicate:nn {#1} { \exp_not:N \regex_build_one_: }
+ \exp_not:c { regex_build_one_*?: }
}
-\cs_new_protected_nopar:Npn \regex_build_one_nn_aux:nn #1#2
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[aux]{\regex_build_one_nn:}
+% \begin{macro}[aux]{\regex_build_one_nn?:}
+% \begin{macro}[aux]{\regex_build_one_nn_aux:Nnn}
+% This function is called when the syntax is
+% \texttt{\{\meta{int},\meta{int}\}}.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \regex_build_one_nn_aux:Nnn #1#2#3
{
- \int_set_eq:NN \l_regex_tmpa_int \l_regex_right_state_int
- \regex_build_new_state:
- \regex_build_new_state:
- \regex_toks_put_right:Nx \l_regex_tmpa_int
- {
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \regex_action_repeat_move:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \else:
- #2
- \exp_not:N \fi:
- }
- \regex_toks_put_right:Nx \l_regex_left_state_int
- {
- \regex_build_tmp_class:n
- { \int_use:N \l_regex_tmpa_int }
- }
+ \prg_replicate:nn {#2} { \regex_build_one_: }
+ \prg_replicate:nn {#3-#2} {#1}
}
+\cs_new_protected_nopar:Npx \regex_build_one_nn:
+ { \regex_build_one_nn_aux:Nnn \exp_not:c { regex_build_one_?: } }
+\cs_new_protected_nopar:cpx { regex_build_one_nn?: }
+ { \regex_build_one_nn_aux:Nnn \exp_not:c { regex_build_one_??: } }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -2007,8 +2113,8 @@
%
% \subsubsection{Groups and alternation}
%
-% We support the syntax \texttt{(\meta{expr1}|\ldots{}%^^A
-% |\meta{expr$\sb{n}$})\meta{quantifier}} for alternations.
+% We support the syntax \texttt{\meta{expr1}|\ldots{}%^^A
+% |\meta{expr$\sb{n}$}} for alternations.
%
% \begin{macro}[aux]{\regex_build_(:, \regex_build_):}
% \begin{macro}[aux]{\regex_build_open_aux:}
@@ -2017,14 +2123,14 @@
% \regex_build_end_alternation:}
% Grouping and alternation go together.
% \begin{itemize}
-% \item Allocate the next available number for the end vertex
-% of the alternation/group and store it on a stack (so that nested
-% alternations work).
-% \item Put free transitions to separate all cases of the alternation.
-% \item Build each branch separately, and merge them to the common
-% end-node.
-% \item Test for a quantifier, and if needed, transfer the initial
-% vertex to a new vertex.
+% \item Allocate the next available number for the end vertex
+% of the alternation/group and store it on a stack (so that nested
+% alternations work).
+% \item Put free transitions to separate all cases of the alternation.
+% \item Build each branch separately, and merge them to the common
+% end-node.
+% \item Test for a quantifier, and if needed, transfer the initial
+% vertex to a new vertex.
% \end{itemize}
% \begin{macrocode}
\cs_new_protected_nopar:cpn { regex_build_(: } #1#2
@@ -2042,10 +2148,19 @@
\cs_new_protected_nopar:Npn \regex_build_open_aux:
{
\regex_build_new_state:
- \seq_push:Nx \l_regex_left_state_seq
- { \int_use:N \l_regex_left_state_int }
- \seq_push:Nx \l_regex_right_state_seq
- { \int_use:N \l_regex_right_state_int }
+ \seq_push:Nx \l_regex_group_begin_seq
+ {
+ \int_set:Nn \l_regex_left_state_int
+ { \int_use:N \l_regex_left_state_int }
+ }
+ \bool_if:NTF \l_regex_caseless_bool
+ { \seq_push:Nn \l_regex_group_end_seq { \regex_build_caseless: } }
+ { \seq_push:Nn \l_regex_group_end_seq { \regex_build_caseful: } }
+ \seq_push:Nx \l_regex_group_end_seq
+ {
+ \int_set:Nn \l_regex_right_state_int
+ { \int_use:N \l_regex_right_state_int }
+ }
\regex_build_begin_alternation:
}
\cs_new_protected_nopar:cpn { regex_build_|: }
@@ -2056,7 +2171,7 @@
\cs_new_protected_nopar:cpn { regex_build_): }
{
\seq_if_empty:NTF \l_regex_capturing_group_seq
- { \regex_build_error:n {22} }
+ { \msg_error:nn { regex } { 22 } }
{
\regex_build_close_aux:
\regex_build_group_quantifier:
@@ -2065,10 +2180,9 @@
\cs_new_protected_nopar:Npn \regex_build_close_aux:
{
\regex_build_end_alternation:
- \seq_pop:NN \l_regex_left_state_seq \l_regex_tmpa_tl
- \int_set:Nn \l_regex_left_state_int \l_regex_tmpa_tl
- \seq_pop:NN \l_regex_right_state_seq \l_regex_tmpa_tl
- \int_set:Nn \l_regex_right_state_int \l_regex_tmpa_tl
+ \regex_seq_pop:N \l_regex_group_begin_seq
+ \regex_seq_pop:N \l_regex_group_end_seq
+ \regex_seq_pop:N \l_regex_group_end_seq
}
% \end{macrocode}
% Building each branch.
@@ -2076,16 +2190,28 @@
\cs_new_protected_nopar:Npn \regex_build_begin_alternation:
{
\regex_build_new_state:
- \seq_get:NN \l_regex_left_state_seq \l_regex_tmpa_tl
- \int_set:Nn \l_regex_left_state_int \l_regex_tmpa_tl
+ \regex_seq_get:N \l_regex_group_begin_seq
\regex_toks_put_right:Nx \l_regex_left_state_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
\cs_new_protected_nopar:Npn \regex_build_end_alternation:
{
- \seq_get:NN \l_regex_right_state_seq \l_regex_tmpa_tl
- \regex_toks_put_right:Nx \l_regex_right_state_int
- { \regex_action_free:n { \l_regex_tmpa_tl } }
+ \int_set_eq:NN \l_regex_left_state_int \l_regex_right_state_int
+ \regex_seq_get:N \l_regex_group_end_seq
+ \regex_toks_put_right:Nx \l_regex_left_state_int
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
% \end{macrocode}
% \end{macro}
@@ -2102,7 +2228,7 @@
{
\cs_if_exist_use:cF { regex_build_special_group_\token_to_str:N #2 : }
{
- \regex_build_error:n { -998 }
+ \msg_error:nn { regex } { -998 }
\regex_build_control:N ( % )
\regex_build_raw:N ?
#1 #2
@@ -2125,6 +2251,55 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\regex_build_special_group_i:}
+% \begin{macro}{\regex_build_special_group_-:}
+% \begin{macro}[aux]{\regex_build_options:NNN}
+% \begin{macro}[aux]{\regex_build_option_+i:}
+% \begin{macro}[aux]{\regex_build_option_-i:}
+% The match can be made case-insensitive by setting the option
+% with \texttt{(?i)}.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \regex_build_special_group_i:
+ {
+ \regex_build_options:NNN +
+ \regex_build_raw:N i
+ }
+\cs_new_protected_nopar:cpn { regex_build_special_group_-: }
+ {
+ \regex_build_options:NNN -
+ }
+\cs_new_protected_nopar:Npn \regex_build_options:NNN #1#2#3
+ {
+ \token_if_eq_meaning:NNTF \regex_build_raw:N #2
+ {
+ \cs_if_exist_use:cF { regex_build_option_#1#3: }
+ { \msg_error:nnx { regex } { unknown-option } { #3 } }
+ \regex_build_options:NNN #1
+ }
+ {
+ \prg_case_str:nnn { #3 }
+ { % (
+ { ) } { }
+ { - } { \regex_build_options:NNN - }
+ }
+ { \msg_error:nnx { regex } { invalid-in-option } { #3 } }
+ }
+ }
+\cs_new_protected_nopar:cpn { regex_build_option_+i: }
+ {
+ \regex_build_caseless:
+ \cs_set_eq:NN \regex_match_loop_case_hook:
+ \regex_match_loop_caseless_hook:
+ }
+\cs_new_protected_nopar:cpn { regex_build_option_-i: }
+ { \regex_build_caseful: }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \subsubsection{Quantifiers for groups}
%
% \begin{macro}[aux]{\regex_build_group_quantifier:}
@@ -2162,7 +2337,7 @@
%
% \begin{macro}[aux]{\regex_build_group_:}
% When there is no quantifier, the group is simply inserted as is,
-% and we only need to track submatches.
+% and we only need to track submatches, and move to a new state.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_build_group_:
{
@@ -2184,14 +2359,22 @@
\int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int
\regex_build_new_state:
\tex_toks:D \l_regex_right_state_int = \tex_toks:D \l_regex_tmpa_int
- \use:x
+ \regex_toks_put_left:Nx \l_regex_right_state_int
+ {
+ \int_set:Nn \l_regex_current_state_int
+ { \int_use:N \l_regex_tmpa_int } % ^^A here we lie!
+ }
+ \cs_set:Npx \regex_tmp:w
{
\tex_toks:D \l_regex_tmpa_int
- { \s_regex_toks #1 { \int_use:N \l_regex_right_state_int } }
+ {
+ \s_regex_toks
+ #1 { \int_eval:n { \l_regex_right_state_int - \l_regex_tmpa_int } }
+ }
}
+ \regex_tmp:w
\regex_build_group_submatches:NN
\l_regex_right_state_int \l_regex_left_state_int
- \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
}
% \end{macrocode}
% \end{macro}
@@ -2216,9 +2399,13 @@
\cs_new_protected_nopar:Npn \regex_build_group_qs_aux:NN #1#2
{
\regex_build_group_shift:N \regex_action_free:n
+ \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
\regex_build_transition_aux:NN \regex_action_free:n #1
#2 \l_regex_tmpa_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ { \int_eval:n { \l_regex_right_state_int - \l_regex_tmpa_int } }
+ }
}
\cs_new_protected_nopar:cpn { regex_build_group_?: }
{
@@ -2275,84 +2462,108 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}[aux]{\regex_build_group_n_aux:n}
+% The braced quantifiers rely on replicating the states
+% corresponding to the group that has just been built,
+% and joining the right state of each copy to the left state
+% of the next copy. Once this function has been run,
+% \cs{l_regex_tmpa_int} points to the last copy of the initial
+% left-most state, \cs{l_regex_left_state_int} has its initial
+% value, and \cs{l_regex_right_state_int} points to the last
+% copy of the initial right-most state. Furthermore,
+% \cs{l_regex_max_state_int} is set appropriately to the largest
+% allocated \tn{toks} register.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \regex_build_group_n_aux:n #1
+ {
+ \regex_toks_put_right:Nx \l_regex_right_state_int
+ {
+ \regex_action_free:n
+ { \int_eval:n { \l_regex_max_state_int - \l_regex_left_state_int } }
+ }
+ \int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int
+ \int_set:Nn \l_regex_tmpb_int { \l_regex_max_state_int + \c_one }
+ \int_set:Nn \l_regex_max_state_int
+ {
+ \l_regex_left_state_int - \c_one
+ + #1 * ( \l_regex_max_state_int - \l_regex_left_state_int + \c_one )
+ }
+ \int_until_do:nNnn \l_regex_tmpb_int > \l_regex_max_state_int
+ {
+ \tex_toks:D \l_regex_tmpb_int = \tex_toks:D \l_regex_tmpa_int
+ \int_incr:N \l_regex_tmpa_int
+ \int_incr:N \l_regex_tmpb_int
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[aux]{\regex_build_group_n:}
% \begin{macro}[aux]{\regex_build_group_n?:}
% These functions are called in case the syntax is
% \texttt{\{\meta{int}\}}. Greedy and lazy operators
% are identical, since the number of repetitions is fixed.
+% We only record the submatch information at the last repetition.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_build_group_n: #1
- {
- \regex_build_group_shift:N \regex_action_repeat_move:n
+ { % ^^A todo: catch case #1 <= 0.
+ \regex_build_group_n_aux:n {#1}
\regex_build_transition_aux:NN
- \regex_action_free:n \l_regex_tmpa_int
- \use:x
- {
- \tex_toks:D \l_regex_tmpa_int
- {
- \s_regex_toks
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \else:
- \regex_action_no_repeat_move:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \fi:
- }
- }
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_build_group_submatches:NN
+ \l_regex_tmpa_int \l_regex_left_state_int
}
\cs_new_eq:cN { regex_build_group_n?: } \regex_build_group_n:
% \end{macrocode}
% \end{macro}
% \end{macro}
%
+% \begin{macro}[aux]{\regex_build_group_n*:}
+% \begin{macro}[aux]{\regex_build_group_n*?:}
+% These functions are called in case the syntax is
+% \texttt{\{\meta{int},\}}. They are somewhat hybrid between
+% the \texttt{\{\meta{int}\}} and the \texttt{*} quantifiers.
+% Contrarily to the \texttt{*} quantifier, for which we had
+% to be careful not to overwrite the submatch information in
+% case no iteration was made, here, we know that the submatch
+% information is overwritten in any case.
+% \begin{macrocode}
+\cs_new_protected_nopar:cpn { regex_build_group_n*: } #1
+ { % ^^A todo: catch case #1 <= 0.
+ \regex_build_group_n_aux:n {#1}
+ \regex_build_transitions_aux:NNNN
+ \regex_action_free:n \l_regex_tmpa_int
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_build_group_submatches:NN
+ \l_regex_tmpa_int \l_regex_left_state_int
+ }
+\cs_new_protected_nopar:cpn { regex_build_group_n*?: } #1
+ { % ^^A todo: catch case #1 <= 0.
+ \regex_build_group_n_aux:n {#1}
+ \regex_build_transitions_aux:NNNN
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_action_free:n \l_regex_tmpa_int
+ \regex_build_group_submatches:NN
+ \l_regex_tmpa_int \l_regex_left_state_int
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \begin{macro}[aux]{\regex_build_group_nn:}
% \begin{macro}[aux]{\regex_build_group_nn?:}
% These functions are called when the syntax is either
% \texttt{\{\meta{int},\}} or \texttt{\{\meta{int},\meta{int}\}}.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_build_group_nn: #1#2
- {
- \regex_build_group_shift:N \regex_action_repeat_move:n
- \regex_build_transition_aux:NN
- \regex_action_free:n \l_regex_tmpa_int
- \use:x
- {
- \tex_toks:D \l_regex_tmpa_int
- {
- \s_regex_toks
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \else:
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \fi:
- \regex_action_no_repeat_copy:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \fi:
- }
- }
+ { % ^^A Not Implemented Yet!
+ \msg_expandable_error:n { Quantifier~{m,n}~not~implemented~yet }
+ \use:c { regex_build_group_n*: } {#1}
}
\cs_new_protected_nopar:cpn { regex_build_group_nn?: } #1#2
- {
- \regex_build_group_shift:N \regex_action_repeat_move:n
- \regex_build_transition_aux:NN
- \regex_action_free:n \l_regex_tmpa_int
- \use:x
- {
- \tex_toks:D \l_regex_tmpa_int
- {
- \s_regex_toks
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \else:
- \regex_action_no_repeat_copy:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \fi:
- \exp_not:N \fi:
- }
- }
+ { % ^^A Not Implemented Yet!
+ \msg_expandable_error:n { Quantifier~{m,n}~not~implemented~yet }
+ \use:c { regex_build_group_n*?: } {#1}
}
% \end{macrocode}
% \end{macro}
@@ -2435,22 +2646,6 @@
%
% \subsubsection{Helpers for running the NFA}
%
-% \begin{macro}[aux]{\regex_if_state_free:nT}
-% A state is free if it is not marker as taken, namely
-% if the corresponding \tn{dimen} register is $0\mathtt{sp}$
-% rather than $1\mathtt{sp}$.
-% \begin{macrocode}
-\cs_new_protected:Npn \regex_if_state_free:nT #1
- {
- \if_num:w \tex_dimen:D #1 = \l_regex_unique_step_int
- \exp_after:wN \use_none:n
- \else:
- \exp_after:wN \use:n
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}[aux]{\regex_store_state:n}
% Put the given state in the array of \tn{skip} registers.
% This is done by increasing the pointer
@@ -2468,27 +2663,33 @@
% \end{macro}
%
% \begin{macro}[int]{\regex_state_use:}
-% \begin{macro}[int]{\regex_state_use_submatches:}
-% \begin{macro}[aux]{\regex_state_use_aux:n}
+% \begin{macro}[int]{\regex_state_use_with_submatches:}
% \begin{macro}[aux]{\regex_state_use_aux_ii:w}
+% \begin{macro}[aux]{\regex_state_use_aux:n}
% Use a given program instruction, unless it has already been
% executed at this step. The \tn{toks} registers begin with
% some submatch information, ignored by \cs{regex_state_use:},
-% but not by \cs{regex_state_use_submatches:}.
+% but not by \cs{regex_state_use_with_submatches:}.
+% A state is free if it is not marker as taken, namely
+% if the corresponding \tn{dimen} register is not
+% \cs{l_regex_unique_step_int} in \texttt{sp}.
+% The primitive conditional is ended before unpacking
+% the \tn{toks} register.
% \begin{macrocode}
-\cs_new_protected_nopar:Npn \regex_state_use_submatches:
+\cs_new_protected_nopar:Npn \regex_state_use_with_submatches:
{ \regex_state_use_aux:n { } }
\cs_new_protected_nopar:Npn \regex_state_use:
{ \regex_state_use_aux:n { \exp_after:wN \regex_state_use_aux_ii:w } }
-\cs_new:Npn \regex_state_use_aux_ii:w #1 \s_regex_toks { }
-\cs_new_protected:Npn \regex_state_use_aux:n #1
- {
- \regex_if_state_free:nT { \l_regex_current_state_int }
- {
- \tex_dimen:D \l_regex_current_state_int
- = \l_regex_unique_step_int sp \scan_stop:
- #1 \tex_the:D \tex_toks:D \l_regex_current_state_int \scan_stop:
- }
+\cs_new_nopar:Npn \regex_state_use_aux_ii:w #1 \s_regex_toks { }
+\cs_new_protected_nopar:Npn \regex_state_use_aux:n #1
+ {
+ \if_num:w \tex_dimen:D \l_regex_current_state_int
+ < \l_regex_unique_step_int
+ \tex_dimen:D \l_regex_current_state_int
+ = \l_regex_unique_step_int sp \scan_stop:
+ #1 \tex_the:D \tex_toks:D \exp_after:wN \l_regex_current_state_int
+ \fi:
+ \scan_stop:
}
% \end{macrocode}
% \end{macro}
@@ -2506,7 +2707,7 @@
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_disable_submatches:
{
- \cs_set_eq:NN \regex_state_use_submatches: \regex_state_use:
+ \cs_set_eq:NN \regex_state_use_with_submatches: \regex_state_use:
\cs_set_eq:NN \regex_store_submatches:n
\regex_protected_use_none:n
\cs_set_eq:NN \regex_action_submatches:n
@@ -2517,37 +2718,42 @@
% \end{macro}
%
% \begin{macro}[int]{\regex_store_submatches:n}
-% \begin{macro}[aux]{\regex_store_submatches_aux:Nw}
-% \begin{macro}[aux]{\regex_store_submatches_aux_ii:wnnwwn}
+% \begin{macro}[aux]{\regex_store_submatches_aux:w}
+% \begin{macro}[aux]{\regex_store_submatches_aux_ii:Nnnw}
% The submatch information pertaining to one given thread is moved
% from state to state as we execute the NFA.
+% We make sure that most of the \tn{toks} register is not read
+% before being assigned again to that same register.
% \begin{macrocode}
\cs_new_protected:Npn \regex_store_submatches:n #1
{
- \exp_after:wN \regex_store_submatches_aux:Nw
- \exp_after:wN \l_regex_current_submatches_prop
- \tex_the:D \tex_toks:D #1 \scan_stop: \q_stop
- { #1 }
+ \tex_toks:D #1 \exp_after:wN
+ {
+ \tex_romannumeral:D
+ \exp_after:wN \regex_store_submatches_aux:w
+ \tex_the:D \tex_toks:D #1
+ }
}
-\cs_new_protected:Npn \regex_store_submatches_aux:Nw #1 #2 \s_regex_toks
+\cs_new_protected:Npn \regex_store_submatches_aux:w #1 \s_regex_toks
{
- \exp_args:No \regex_store_submatches_aux_ii:wnnwwn { #1 }
- #2
- \regex_state_submatches:nn { \c_minus_one } { \q_prop }
+ \regex_store_submatches_aux_ii:Nnnw
+ #1
+ \regex_state_submatches:nn \c_minus_one \q_prop
\s_regex_toks
}
-\cs_new_protected:Npn \regex_store_submatches_aux_ii:wnnwwn
- #1 \regex_state_submatches:nn #2#3 #4 \s_regex_toks #5 \q_stop #6
+\cs_new_protected:Npn \regex_store_submatches_aux_ii:Nnnw
+ \regex_state_submatches:nn #1 #2 #3 \s_regex_toks
{
- \tex_toks:D #6 \exp_after:wN
+ \exp_after:wN \c_zero
+ \exp_after:wN \regex_state_submatches:nn \exp_after:wN
{
- \exp_after:wN \regex_state_submatches:nn \exp_after:wN
- { \int_value:w \int_eval:w \l_regex_unique_step_int + \c_one }
- { #1 }
- \regex_state_submatches:nn {#2} {#3}
- \s_regex_toks
- #5
+ \int_value:w \int_eval:w
+ \l_regex_unique_step_int + \c_one
+ \exp_after:wN
}
+ \exp_after:wN { \l_regex_current_submatches_prop }
+ \regex_state_submatches:nn {#1} {#2}
+ \s_regex_toks
}
% \end{macrocode}
% \end{macro}
@@ -2562,7 +2768,7 @@
\cs_new_protected:Npn \regex_state_submatches:nn #1#2
{
\if_num:w #1 = \l_regex_unique_step_int
- \tl_set:Nn \l_regex_current_submatches_prop {#2}
+ \tl_set:Nn \l_regex_current_submatches_prop { #2 }
\fi:
}
% \end{macrocode}
@@ -2571,7 +2777,7 @@
% \subsubsection{Matching: framework}
%
% \begin{macro}[int]{\regex_match:n}
-% Store the query string in \cs{l_regex_query_str}.
+% Store the query string in \cs{l_regex_query_other_str}.
% Then reset a few variables which should be set only once,
% before the first match, even in the case of multiple matches.
% Then run the NFA (\cs{regex_match_once:} matches multiple times
@@ -2579,7 +2785,7 @@
% \begin{macrocode}
\cs_new_protected:Npn \regex_match:n #1
{
- \tl_set:Nx \l_regex_query_str { \tl_to_other_str:n {#1} }
+ \tl_set:Nx \l_regex_query_other_str { \tl_to_other_str:n {#1} }
\regex_match_initial_setup:
\regex_match_once:
}
@@ -2588,6 +2794,7 @@
%
% \begin{macro}[int]{\regex_match_once:}
% \begin{macro}[aux]{\regex_match_once_aux:}
+% \begin{macro}[aux]{\regex_match_once_aux_ii:N}
% After setting up more variables in \cs{regex_match_setup:},
% skip the \cs{l_regex_start_step_int} first characters of the
% query string, and loop over it.
@@ -2597,15 +2804,32 @@
\cs_new_protected_nopar:Npn \regex_match_once:
{
\regex_match_setup:
- \exp_after:wN \regex_match_once_aux: \l_regex_query_str
+ \exp_after:wN \regex_match_once_aux: \l_regex_query_other_str
\q_recursion_tail \q_recursion_stop
\bool_if:NT \l_regex_success_bool { \l_regex_every_match_tl }
}
\cs_new_protected_nopar:Npn \regex_match_once_aux:
- { \str_skip_do:nn { \l_regex_start_step_int } { \regex_match_loop:N } }
+ {
+ \int_compare:nNnTF \l_regex_start_step_int = \c_zero
+ {
+ \int_set_eq:NN \l_regex_current_char_int \c_minus_one
+ \regex_match_loop:N
+ }
+ {
+ \str_skip_do:nn
+ { \l_regex_start_step_int - \c_one }
+ { \regex_match_once_aux_ii:N }
+ }
+ }
+\cs_new_protected_nopar:Npn \regex_match_once_aux_ii:N #1
+ {
+ \int_set:Nn \l_regex_current_char_int { `#1 }
+ \regex_match_loop:N
+ }
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% \begin{macro}[aux]{\regex_match_initial_setup:}
% This function holds the setup that should be done
@@ -2613,12 +2837,11 @@
% string. It is called only once for the whole string.
% On the other hand, \cs{regex_match_setup:}
% is called for every match in the string in case of
-% repeated matches, and \cs{regex_match_loop_setup:}
+% repeated matches, and \cs{regex_match_loop_setup:N}
% is called at every step.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_match_initial_setup:
{
- \tl_clear:N \l_regex_look_behind_str
\prg_stepwise_inline:nnnn {1} {1} { \l_regex_max_state_int }
{ \tex_dimen:D ##1 \c_minus_one sp \scan_stop: }
\int_set_eq:NN \l_regex_unique_step_int \c_minus_one
@@ -2650,18 +2873,6 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\regex_match_loop_setup:}
-% This is called for every character in the string.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \regex_match_loop_setup:
- {
- \int_incr:N \l_regex_current_step_int
- \int_incr:N \l_regex_unique_step_int
- \bool_set_false:N \l_regex_fresh_thread_bool
- }
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}[int]{\s_regex_step}
% \begin{macro}[aux]{\regex_break_step:w}
% When a thread succeeds, all threads with lower precedence
@@ -2677,7 +2888,7 @@
%
% \begin{macro}[aux]{\regex_match_loop:N}
% \begin{macro}[aux]{\regex_match_one_index:n}
-% \begin{macro}[aux]{\regex_match_one_index_aux:nn}
+% \begin{macro}[aux]{\regex_match_one_index_aux:n}
% Setup what needs to be reset at every character,
% then set \cs{l_regex_current_char_int} to the
% character code of the character that is read
@@ -2688,10 +2899,7 @@
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_match_loop:N #1
{
- \regex_match_loop_setup:
- \token_if_eq_meaning:NNTF #1 \q_recursion_tail
- { \int_set_eq:NN \l_regex_current_char_int \c_minus_one }
- { \int_set:Nn \l_regex_current_char_int {`#1} }
+ \regex_match_loop_setup:N #1
\cs_set_nopar:Npx \regex_tmp:w
{
\int_zero:N \l_regex_max_index_int
@@ -2705,28 +2913,80 @@
\exp_after:wN \use_none_delimit_by_q_recursion_stop:w
\fi:
\quark_if_recursion_tail_stop:N #1
- \bool_if:NT \l_regex_look_behind_bool
- { \tl_put_left:Nx \l_regex_look_behind_str {#1} }
\regex_match_loop:N
}
\cs_new_nopar:Npn \regex_match_one_index:n #1
{
- \regex_match_one_index_aux:n { \int_value:w \tex_skip:D #1 }
+ \regex_match_one_index_aux:n
+ { \int_value:w \tex_skip:D #1 }
}
\cs_new_protected_nopar:Npn \regex_match_one_index_aux:n #1
{
\int_set:Nn \l_regex_current_state_int {#1}
\prop_clear:N \l_regex_current_submatches_prop
- \regex_state_use_submatches:
+ \regex_state_use_with_submatches:
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
+% \begin{macro}[aux]{\regex_match_loop_setup:N}
+% This is called for every character in the string.
+% At every step in reading the query string, we store the character
+% code of the current character in \cs{l_regex_current_char_int},
+% unless the end was reached: then we store $-1$.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \regex_match_loop_setup:N #1
+ {
+ \int_incr:N \l_regex_current_step_int
+ \int_incr:N \l_regex_unique_step_int
+ \bool_set_false:N \l_regex_fresh_thread_bool
+ \int_set_eq:NN \l_regex_last_char_int \l_regex_current_char_int
+ \if_meaning:w #1 \q_recursion_tail
+ \int_set_eq:NN \l_regex_current_char_int \c_minus_one
+ \else:
+ \int_set:Nn \l_regex_current_char_int {`#1}
+ \fi:
+ \regex_match_loop_case_hook:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\regex_match_loop_case_hook:}
+% \begin{macro}{\regex_match_loop_caseless_hook:}
+% In the case where the regular expression contains caseless matching,
+% the \cs{regex_match_loop_case_hook:} (normally empty) is redefined
+% to set \cs{l_regex_case_changed_char_int} properly.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \regex_match_loop_case_hook: { }
+\cs_new_protected_nopar:Npn \regex_match_loop_caseless_hook:
+ {
+ \int_set_eq:NN \l_regex_case_changed_char_int \l_regex_current_char_int
+ \if_num:w \l_regex_current_char_int < \c_ninety_one
+ \if_num:w \l_regex_current_char_int < \c_sixty_five
+ \else:
+ \int_add:Nn \l_regex_case_changed_char_int { \c_thirty_two }
+ \fi:
+ \else:
+ \if_num:w \l_regex_current_char_int < \c_one_hundred_twenty_three
+ \if_num:w \l_regex_current_char_int < \c_ninety_seven
+ \else:
+ \int_sub:Nn \l_regex_case_changed_char_int { \c_thirty_two }
+ \fi:
+ \fi:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \subsubsection{Actions when matching}
%
% \begin{macro}[aux]{\regex_action_start_wildcard:nn}
+%: the first state has a free transition to the second
+% state, where the regular expression really begins, and a costly
+% transition to itself, to try again at the next character. ^^A ??
% The search is made unanchored at the start by putting
% a free transition to the real start of the NFA, and a
% costly transition to the same state, waiting for the
@@ -2751,7 +3011,10 @@
% to state |#1|.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_action_cost:n #1
- { \regex_store_state:n {#1} }
+ {
+ \exp_args:Nf \regex_store_state:n %^^A optimize!
+ { \int_eval:n { \l_regex_current_state_int + #1 } }
+ }
% \end{macrocode}
% \end{macro}
%
@@ -2790,41 +3053,32 @@
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_action_free:n #1
{
- \regex_if_state_free:nT {#1}
+ \cs_set_nopar:Npx \regex_tmp:w
{
- \use:x
- {
- \int_set:Nn \l_regex_current_state_int {#1}
- \regex_store_submatches:n { \l_regex_current_state_int }
- \regex_state_use:
- \int_set:Nn \l_regex_current_state_int
- { \int_use:N \l_regex_current_state_int }
- \tl_set:Nn \exp_not:N \l_regex_current_submatches_prop
- { \exp_not:o \l_regex_current_submatches_prop }
- }
+ \int_add:Nn \l_regex_current_state_int {#1}
+ \regex_state_use:
+ \int_set:Nn \l_regex_current_state_int
+ { \int_use:N \l_regex_current_state_int }
+ \tl_set:Nn \exp_not:N \l_regex_current_submatches_prop
+ { \exp_not:o \l_regex_current_submatches_prop }
}
+ \regex_tmp:w
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\regex_action_submatch:n}
+% Update the current submatches with the information
+% from the current step.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_action_submatch:n #1
{
\prop_put:Nno \l_regex_current_submatches_prop {#1}
{ \int_use:N \l_regex_current_step_int }
- \regex_store_submatches:n { \l_regex_current_state_int }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \regex_action_repeat_copy:n { \ERROR }
-\cs_new_protected_nopar:Npn \regex_action_repeat_move:n { \ERROR }
-\cs_new_protected_nopar:Npn \regex_action_no_repeat_copy:n { \ERROR }
-\cs_new_protected_nopar:Npn \regex_action_no_repeat_move:n { \ERROR }
-% \end{macrocode}
-%
% \subsection{Submatches, once the correct match is found}
%
% \begin{macro}[int]{\regex_extract:}
@@ -2839,11 +3093,7 @@
\regex_extract_aux:nTF { ##1 }
{
\seq_gput_right:Nx \g_regex_submatches_seq
- {
- \str_from_to:Nnn \l_regex_query_str
- { \l_regex_tmpa_tl }
- { \l_regex_tmpb_tl }
- }
+ { \regex_query_substr:NN \l_regex_tmpa_tl \l_regex_tmpb_tl }
}
{ \seq_gput_right:Nn \g_regex_submatches_seq { } }
}
@@ -2918,9 +3168,13 @@
= \int_use:N \l_regex_max_state_int
\l_regex_capturing_group_int
= \int_use:N \l_regex_capturing_group_int
- \bool_if:NTF \l_regex_look_behind_bool
- { \bool_set_true:N \l_regex_look_behind_bool }
- { \bool_set_false:N \l_regex_look_behind_bool }
+ \token_if_eq_meaning:NNT
+ \regex_match_loop_case_hook:
+ \regex_match_loop_caseless_hook:
+ {
+ \cs_set_eq:NN \regex_match_loop_case_hook:
+ \regex_match_loop_caseless_hook:
+ }
\prg_stepwise_function:nnnN
{1} {1} {\l_regex_max_state_int}
\regex_set_aux:n
@@ -2946,7 +3200,7 @@
% If a token list variable starts with \cs{regex_nfa:Nw},
% then it most likely holds the data for a precompiled pattern.
% \begin{macrocode}
-\prg_new_protected_conditional:Npnn \regex_check_nfa:N #1 { TF }
+\prg_new_protected_conditional:Npnn \regex_check_nfa:N #1 { T , TF }
{ \exp_after:wN \regex_check_nfa_aux:Nw #1 \q_stop }
\cs_new:Npn \regex_check_nfa_aux:Nw #1 #2 \q_stop
{
@@ -2957,11 +3211,6 @@
\prg_return_false:
\fi:
}
-\msg_new:nnn { regex } { not-nfa }
- {
- I~was~expecting~a~regular~expression~variable.\\
- Instead,~I~got~#1.
- }
% \end{macrocode}
% \end{macro}
%
@@ -3001,7 +3250,7 @@
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_return_after_group:
{
- \if_bool:N \l_regex_success_bool
+ \if_meaning:w \c_true_bool \l_regex_success_bool
\group_insert_after:N \prg_return_true:
\else:
\group_insert_after:N \prg_return_false:
@@ -3016,7 +3265,7 @@
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_extract_after_group:N #1
{
- \if_bool:N \l_regex_success_bool
+ \if_meaning:w \c_true_bool \l_regex_success_bool
\regex_extract:
\group_insert_after:N \seq_set_eq:NN
\group_insert_after:N #1
@@ -3100,7 +3349,7 @@
}
\cs_new_protected:Npn \regex_count:NnN #1#2#3
{
- \regex_check_nfa:NTF #1
+ \regex_check_nfa:NT #1
{
\regex_user_aux:n
{
@@ -3116,7 +3365,6 @@
\regex_count_after_group:N #3
}
}
- { }
}
% \end{macrocode}
% \end{macro}
@@ -3124,12 +3372,12 @@
%
% \subsubsection{Submatch extraction}
%
-% \begin{macro}{\regex_extract:nnN}
-% \begin{macro}{\regex_extract:NnN}
-% \begin{macro}[TF]{\regex_extract:nnN}
-% \begin{macro}[TF]{\regex_extract:NnN}
+% \begin{macro}{\regex_extract_once:nnN}
+% \begin{macro}{\regex_extract_once:NnN}
+% \begin{macro}[TF]{\regex_extract_once:nnN}
+% \begin{macro}[TF]{\regex_extract_once:NnN}
% \begin{macrocode}
-\cs_new_protected:Npn \regex_extract:nnN #1#2#3
+\cs_new_protected:Npn \regex_extract_once:nnN #1#2#3
{
\regex_user_aux:n
{
@@ -3138,7 +3386,8 @@
\regex_extract_after_group:N #3
}
}
-\prg_new_protected_conditional:Npnn \regex_extract:nnN #1#2#3 { T , F , TF }
+\prg_new_protected_conditional:Npnn \regex_extract_once:nnN #1#2#3
+ { T , F , TF }
{
\regex_user_aux:n
{
@@ -3148,9 +3397,9 @@
\regex_return_after_group:
}
}
-\cs_new_protected:Npn \regex_extract:NnN #1#2#3
+\cs_new_protected:Npn \regex_extract_once:NnN #1#2#3
{
- \regex_check_nfa:NTF #1
+ \regex_check_nfa:NT #1
{
\regex_user_aux:n
{
@@ -3159,9 +3408,9 @@
\regex_extract_after_group:N #3
}
}
- { }
}
-\prg_new_protected_conditional:Npnn \regex_extract:NnN #1#2#3 { T , F , TF }
+\prg_new_protected_conditional:Npnn \regex_extract_once:NnN #1#2#3
+ { T , F , TF }
{
\regex_check_nfa:NTF #1
{
@@ -3181,6 +3430,66 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\regex_extract_all:nnN}
+% \begin{macro}{\regex_extract_all:NnN}
+% \begin{macro}[aux]{\regex_extract_all_aux:}
+% \begin{macro}[aux]{\regex_extract_all_after_group:N}
+% Similarly to \cs{regex_count:nnN} functions,
+% recurse through matches of the pattern. Then we do
+% something slightly different, extracting submatches.
+% Submatches are not extracted if the pattern matched
+% an empty string at the start of the match attempt
+% (to avoid adding spurious empty items to the resulting
+% sequence).
+% \begin{macrocode}
+\cs_new_protected:Npn \regex_extract_all:nnN #1#2#3
+ {
+ \regex_user_aux:n
+ {
+ \seq_gclear:N \g_regex_extract_all_seq
+ \tl_set:Nn \l_regex_every_match_tl { \regex_extract_all_aux: }
+ \regex_build:n {#1}
+ \regex_match:n {#2}
+ \regex_extract_all_after_group:N #3
+ }
+ }
+\cs_new_protected:Npn \regex_extract_all:NnN #1#2#3
+ {
+ \regex_check_nfa:NT #1
+ {
+ \regex_user_aux:n
+ {
+ \seq_gclear:N \g_regex_extract_all_seq
+ \tl_set:Nn \l_regex_every_match_tl { \regex_extract_all_aux: }
+ \regex_use:N #1
+ \regex_match:n {#2}
+ \regex_extract_all_after_group:N #3
+ }
+ }
+ }
+\cs_new_protected_nopar:Npn \regex_extract_all_aux:
+ {
+ \regex_extract:
+ \seq_gconcat:NNN \g_regex_extract_all_seq
+ \g_regex_extract_all_seq \g_regex_submatches_seq
+ \regex_match_once:
+ }
+\cs_new_protected_nopar:Npn \regex_extract_all_after_group:N #1
+ {
+ \seq_if_empty:NF \g_regex_extract_all_seq
+ {
+ \regex_extract:
+ \group_insert_after:N \seq_set_eq:NN
+ \group_insert_after:N #1
+ \group_insert_after:N \g_regex_extract_all_seq
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \subsubsection{Splitting a string by matches of a regex}
%
% \begin{macro}{\regex_split:nnN}
@@ -3208,7 +3517,7 @@
}
\cs_new_protected:Npn \regex_split:NnN #1#2#3
{
- \regex_check_nfa:NTF #1
+ \regex_check_nfa:NT #1
{
\regex_user_aux:n
{
@@ -3219,7 +3528,6 @@
\regex_split_after_group:N #3
}
}
- { }
}
\cs_new_protected_nopar:Npn \regex_split_aux:
{
@@ -3231,9 +3539,8 @@
{
\seq_gput_left:Nx \g_regex_submatches_seq
{
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \l_regex_tmpa_tl }
+ \regex_query_substr:NN
+ \l_regex_start_step_int \l_regex_tmpa_tl
}
}
{ \msg_error:nn { regex } { internal } }
@@ -3252,9 +3559,8 @@
{
\seq_gput_right:Nx \g_regex_split_seq
{
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \int_use:N \l_regex_current_step_int }
+ \regex_query_substr:NN
+ \l_regex_start_step_int \l_regex_current_step_int
}
}
\group_insert_after:N \seq_set_eq:NN
@@ -3270,55 +3576,77 @@
% \subsubsection{String replacement}
%
% \begin{macro}[int]{\regex_replacement:n}
-% \begin{macro}[aux]{\regex_replacement_loop:N}
-% \begin{macro}[aux]{\regex_replacement_normal:N}
+% \begin{macro}[aux]{\regex_replacement_escaped:N}
+% \begin{macro}[aux]{\regex_replacement_submatch:w}
+% \begin{macro}[aux]{\regex_replacement_submatch_aux:nN}
% \begin{macrocode}
\cs_new_protected:Npn \regex_replacement:n #1
{
\str_aux_escape:NNNn
\prg_do_nothing:
\regex_replacement_escaped:N
- \regex_replacement_raw:N
+ \prg_do_nothing:
{#1}
\tl_set_eq:NN \l_regex_replacement_tl \g_str_result_tl
\tl_set:Nx \l_regex_replacement_tl
{ \l_regex_replacement_tl \prg_do_nothing: }
}
-\cs_new_nopar:Npn \regex_replacement_raw:N { \exp_not:N \prg_do_nothing: }
\cs_new_nopar:Npn \regex_replacement_escaped:N #1
{
- \if_num:w 9 < 1 #1 \exp_stop_f:
- \exp_not:N \regex_replacement_escaped_ii:nN {#1}
- \else:
- #1
- \fi:
+ \regex_token_if_other_digit:NTF #1
+ {
+ \exp_not:n
+ { \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } } {#1}
+ }
+ {
+ \token_if_eq_charcode:NNTF g #1
+ { \exp_not:N \regex_replacement_submatch:w }
+ { #1 }
+ }
}
-\cs_new_nopar:Npn \regex_replacement_escaped_ii:nN #1#2
+\cs_new_nopar:Npn \regex_replacement_submatch:w #1
{
- \regex_token_if_other_digit:NTF #2
- { \regex_replacement_escaped_ii:nN {#1#2} }
- { \exp_not:N \seq_item:Nn \exp_not:N \g_regex_submatches_seq {#1} #2 }
+ \exp_after:wN \token_if_eq_meaning:NNTF \c_lbrace_str #1
+ { \regex_replacement_submatch_aux:nN { } }
+ {
+ \regex_token_if_other_digit:NTF #1
+ { \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } }
+ { \msg_expandable_error:n { \g misused~in~replacement~text. } }
+ #1
+ }
}
-\prg_new_conditional:Npnn \regex_token_if_other_digit:N #1 { TF }
+\cs_new_nopar:Npn \regex_replacement_submatch_aux:nN #1 #2
{
- \if_num:w 9 < 1 \exp_not:N #1 \exp_stop_f:
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
+ \regex_token_if_other_digit:NTF #2
+ { \regex_replacement_submatch_aux:nN {#1#2} }
+ {
+ \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } {#1}
+ \exp_after:wN \token_if_eq_meaning:NNF \c_rbrace_str #2
+ {
+ \msg_expandable_error:n { \g misused~in~replacement~text. }
+ #2
+ }
+ }
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% \begin{macro}[aux]{\regex_replace_after_group:N}
+% I wonder why I implemented things with \tn{aftergroup}
+% rather than simply placing that code after the explicit
+% \cs{group_end:} that I have. (General remark.)
% \begin{macrocode}
\cs_new_protected_nopar:Npn \regex_replace_after_group:N #1
{
- \group_insert_after:N \tl_set_eq:NN
+ \group_insert_after:N \tl_set:Nx
\group_insert_after:N #1
- \group_insert_after:N \g_regex_replaced_str
+ \group_insert_after:N {
+ \group_insert_after:N \tl_to_str:N
+ \group_insert_after:N \g_regex_replaced_str
+ \group_insert_after:N }
}
% \end{macrocode}
% \end{macro}
@@ -3339,15 +3667,16 @@
\regex_extract:
\regex_extract_aux:nTF {0}
{
+ \cs_set_nopar:Npn \regex_tmp:w
+ { \str_skip_do:nn { \l_regex_tmpb_tl } { } }
\tl_gset:Nx \g_regex_replaced_str
{
- \str_from_to:Nnn \l_regex_query_str {0} { \l_regex_tmpa_tl }
+ \regex_query_substr:NN \c_zero \l_regex_tmpa_tl
\l_regex_replacement_tl
- \str_from_to:Nnn \l_regex_query_str
- { \l_regex_tmpb_tl } { \c_max_int }
+ \exp_after:wN \regex_tmp:w \l_regex_query_other_str
}
}
- { \tl_gset_eq:NN \g_regex_replaced_str \l_regex_query_str }
+ { \tl_gset_eq:NN \g_regex_replaced_str \l_regex_query_other_str }
\group_end:
}
\cs_new_protected:Npn \regex_replace_once:nnN #1#2#3
@@ -3404,12 +3733,10 @@
\tl_gclear:N \g_regex_replaced_str
#2
\exp_args:No \regex_match:n {#1}
+ \cs_set_nopar:Npn \regex_tmp:w
+ { \str_skip_do:nn { \l_regex_start_step_int } { } }
\tl_gput_right:Nx \g_regex_replaced_str
- {
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \c_max_int }
- }
+ { \exp_after:wN \regex_tmp:w \l_regex_query_other_str }
\group_end:
}
\cs_new_protected_nopar:Npn \regex_replace_all_aux:
@@ -3419,9 +3746,8 @@
{
\tl_gput_right:Nx \g_regex_replaced_str
{
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \l_regex_tmpa_tl }
+ \regex_query_substr:NN
+ \l_regex_start_step_int \l_regex_tmpa_tl
\l_regex_replacement_tl
}
}
@@ -3450,6 +3776,47 @@
% \end{macro}
% \end{macro}
%
+% \subsection{Messages}
+%
+% Negative codes are specific to the \LaTeX3 implementation.
+% Other error codes match with the PCRE codes (not all of
+% the PCRE errors can occur, since many constructions are
+% not supported).
+% \begin{macrocode}
+% \msg_new:nnn { regex } { -999 } { File~not~found }
+\msg_new:nnn { regex } { -998 } { Unsupported~construct }
+\msg_new:nnn { regex } { -997 }
+ { The~regular~expression~is~too~large~(32768~states). }
+\msg_new:nnn { regex } { 1 } { \iow_char:N\\~at~end~of~pattern }
+% \msg_new:nnn { regex } { 2 } { \iow_char:N\\c~at~end~of~pattern }
+\msg_new:nnn { regex } { 4 }
+ { Numbers~out~of~order~in~\iow_char:N\{\iow_char\}~quantifier. }
+\msg_new:nnn { regex } { 6 }
+ { Missing~terminating~\iow_char:N\]~for~character~class }
+\msg_new:nnn { regex } { 7 }
+ { Invalid~escape~sequence~in~character~class }
+\msg_new:nnn { regex } { 8 }
+ { Range~out~of~order~in~character~class }
+\msg_new:nnn { regex } { 22 } { Mismatched~parentheses }
+\msg_new:nnn { regex } { 34 }
+ { Character~value~in~\iow_char:N\\x{...}~sequence~is~too~large }
+% \msg_new:nnn { regex } { 44 } { Invalid~UTF-8~string }
+% \msg_new:nnn { regex } { 46 }
+% { Malformed~\iow_char:N\\P~or\iow_char:N\\p~sequence }
+% \msg_new:nnn { regex } { 47 }
+% { Unknown~property~after~\iow_char:N\\P~or\iow_char:N\\p }
+% \msg_new:nnn { regex } { 68 }
+% { \iow_char:N\\c~must~be~followed~by~an~ASCII~character }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\msg_new:nnn { regex } { not-nfa }
+ {
+ LaTeX~was~expecting~a~regular~expression~variable.\\
+ Instead,~LaTeX~found~'#1'.
+ }
+% \end{macrocode}
+%
% \begin{macrocode}
%</package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx
index a718f986ce7..b3648c57ede 100644
--- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx
+++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx
@@ -35,7 +35,7 @@
%
%<*driver|package>
\RequirePackage{expl3}
-\GetIdInfo$Id: l3str.dtx 2895 2011-10-09 15:58:19Z joseph $
+\GetIdInfo$Id: l3str.dtx 2921 2011-10-17 13:23:36Z bruno $
{L3 Experimental Strings}
%</driver|package>
%<*driver>
@@ -72,25 +72,23 @@
% \LaTeX3 provides a set of functions to manipulate token lists
% as strings of characters, ignoring the category codes of those
% characters.
-%
-% There is no separate string data type: string variables are simply
-% specialized token lists, conventionally made out only of characters
-% with category code $12$ (other), except spaces, which have category
-% code $10$ (blank space). All the \enquote{safe} functions in this
-% module first convert their argument to a string for internal processing,
+%
+% String variables are simply specialised token lists, but by convention
+% should be named with the suffix \texttt{\ldots str}. Such variables should
+% contain characters with category code $12$ (other), except spaces, which
+% have category code $10$ (blank space). All the \enquote{safe} functions in
+% this module first convert their argument to a string for internal processing,
% and will not treat a token list or the corresponding string representation
-% differently. However, it is often better to name token list variables
-% meant to contain string data with a name such as \cs{l_\ldots{}_str}.
-% Those are then manipulated mostly with tools from \pkg{l3tl}.
+% differently.
%
% Most functions in this module come in three flavours:
% \begin{itemize}
-% \item \cs{str_...:N...}, which expect a token list
-% variable as their argument;
-% \item \cs{str_...:n...}, taking any token list (or string) as an argument;
-% \item \cs{str_..._ignore_spaces:n...}, which ignores any space encountered
-% during the operation: these functions are slightly faster than those
-% which take care of escaping spaces appropriately;
+% \item \cs{str_...:N...}, which expect a token list
+% variable as their argument;
+% \item \cs{str_...:n...}, taking any token list (or string) as an argument;
+% \item \cs{str_..._ignore_spaces:n...}, which ignores any space encountered
+% during the operation: these functions are slightly faster than those
+% which take care of escaping spaces appropriately;
% \end{itemize}
% When performance is important, the internal \cs{str_..._unsafe:n...}
% functions, which expect a \enquote{safe} string in which spaces
@@ -98,66 +96,119 @@
%
% \subsection{Conversion and input of strings}
%
-% \begin{variable}{\c_backslash_str,
-% \c_lbrace_str,\c_rbrace_str,\c_hash_str,\c_percent_str}
+% \begin{variable}
+% {
+% \c_backslash_str,
+% \c_lbrace_str,
+% \c_rbrace_str,
+% \c_hash_str,
+% \c_percent_str
+% }
% Constant strings, containing a single character, with category code $12$.
% \end{variable}
%
-% \begin{function}[EXP]{\tl_to_str:N,\tl_to_str:n}
+% \begin{function}[EXP]{\tl_to_str:N, \tl_to_str:n}
% \begin{syntax}
% \cs{tl_to_str:N} \meta{tl var}
% \cs{tl_to_str:n} \Arg{token list}
% \end{syntax}
-% Converts the \meta{token list} to a \meta{string}.
+% Converts the \meta{token list} to a \meta{string}, leaving the resulting
+% tokens in the input stream.
+% \end{function}
+%
+% \begin{function}{\str_set:Nn, \str_set:Nx, \str_set:cn, \str_set:cx}
+% \begin{syntax}
+% \cs{str_set:Nn} \meta{str var} \Arg{token list}
+% \end{syntax}
+% Converts the \meta{token list} to a \meta{string},
+% and saves the result in \meta{str var}.
+% \end{function}
+%
+% \begin{function}{\str_gset:Nn, \str_gset:Nx, \str_gset:cn, \str_gset:cx}
+% \begin{syntax}
+% \cs{str_gset:Nn} \meta{str var} \Arg{token list}
+% \end{syntax}
+% Converts the \meta{token list} to a \meta{string},
+% and saves the result in \meta{str var} globally.
% \end{function}
%
% \begin{function}
% {
-% \str_set:Nn, \str_set:Nx,
-% \str_set:cn, \str_set:cx,
-% \str_gset:Nn, \str_gset:Nx,
-% \str_gset:cn, \str_gset:cx,
+% \str_put_left:Nn, \str_put_left:Nx,
+% \str_put_left:cn, \str_put_left:cx
% }
+% \begin{syntax}
+% \cs{str_put_left:Nn} \meta{str var} \Arg{token list}
+% \end{syntax}
+% Converts the \meta{token list} to a \meta{string},
+% and prepends the result to \meta{str var}.
+% The current contents of the \meta{str var} are not
+% automatically converted to a string.
+% \end{function}
+%
% \begin{function}
% {
-% \str_put_left:Nn, \str_put_left:Nx,
-% \str_put_left:cn, \str_put_left:cx,
% \str_gput_left:Nn, \str_gput_left:Nx,
-% \str_gput_left:cn, \str_gput_left:cx,
+% \str_gput_left:cn, \str_gput_left:cx
% }
+% \begin{syntax}
+% \cs{str_gput_left:Nn} \meta{str var} \Arg{token list}
+% \end{syntax}
+% Converts the \meta{token list} to a \meta{string},
+% and prepends the result to \meta{str var}, globally.
+% The current contents of the \meta{str var} are not
+% automatically converted to a string.
+% \end{function}
+%
% \begin{function}
% {
% \str_put_right:Nn, \str_put_right:Nx,
-% \str_put_right:cn, \str_put_right:cx,
-% \str_gput_right:Nn, \str_gput_right:Nx,
-% \str_gput_right:cn, \str_gput_right:cx,
+% \str_put_right:cn, \str_put_right:cx
% }
% \begin{syntax}
-% \cs{str_set:Nn} \meta{str var} \Arg{token list}
+% \cs{str_put_right:Nn} \meta{str var} \Arg{token list}
% \end{syntax}
% Converts the \meta{token list} to a \meta{string},
-% and saves the result in \meta{str var}.
-% \end{function}
+% and appends the result to \meta{str var}.
+% The current contents of the \meta{str var} are not
+% automatically converted to a string.
% \end{function}
+%
+% \begin{function}
+% {
+% \str_gput_right:Nn, \str_gput_right:Nx,
+% \str_gput_right:cn, \str_gput_right:cx
+% }
+% \begin{syntax}
+% \cs{str_gput_right:Nn} \meta{str var} \Arg{token list}
+% \end{syntax}
+% Converts the \meta{token list} to a \meta{string},
+% and appends the result to \meta{str var}, globally.
+% The current contents of the \meta{str var} are not
+% automatically converted to a string.
% \end{function}
%
-% \begin{function}{\str_input:Nn,\str_ginput:Nn}
+% \begin{function}{\str_input:Nn, \str_ginput:Nn}
% \begin{syntax}
% \cs{str_input:Nn} \meta{str var} \Arg{token list}
% \end{syntax}
% Converts the \meta{token list} into a \meta{string}, and stores
-% it in the \meta{str var}. Special characters can be input by
+% it in the \meta{str var}, within the current \TeX{} group level
+% for the \texttt{input} variant and globally for the \texttt{ginput}
+% version.
+% Special characters can be input by
% escaping them with a backslash.
% \begin{itemize}
-% \item Spaces are ignored unless escaped with a backslash.
-% \item |\xhh| produces the character with code \texttt{hh}
-% in hexadecimal: when |\x| is encountered, up to two hexadecimal digits
-% (\texttt{0}--\texttt{9}, \texttt{a}--\texttt{f}, \texttt{A}--\texttt{F})
-% are read to give a number between $0$ and $255$.
-% \item |\x{hh...}| produces the character with code \texttt{hh...}
-% (an aribtrary number of hexadecimal digits are read):
-% this is mostly useful for Lua\TeX{} and Xe\TeX{}.
-% \item |\a|, |\e|, |\f|, |\n|, |\r|, |\t| stand for specific characters:
+% \item Spaces are ignored unless escaped with a backslash.
+% \item |\xhh| produces the character with code \texttt{hh}
+% in hexadecimal: when |\x| is encountered, up to two hexadecimal digits
+% (\texttt{0}--\texttt{9}, \texttt{a}--\texttt{f},
+% \texttt{A}--\texttt{F})
+% are read to give a number between $0$ and $255$.
+% \item |\x{hh...}| produces the character with code \texttt{hh...}
+% (an arbitrary number of hexadecimal digits are read):
+% this is mostly useful for \LuaTeX{} and \XeTeX{}.
+% \item |\a|, |\e|, |\f|, |\n|, |\r|, |\t| stand for specific characters:
% \begin{center}
% \begin{tabular}{cccc}
% |\a| & |\^^G| & alarm & hex \texttt{07} \\
@@ -172,26 +223,27 @@
% For instance,
% \begin{quote}
% \cs{tl_new:N} \cs{l_my_str} \\
-% \cs{str_input:Nn} \cs{l_my_str} |{\x3C \\ \# abc\ def\^}|
+% \cs{str_input:Nn} \cs{l_my_str} |{\x3C \\ \# abc\ def\^\n}|
% \end{quote}
-% results in \cs{l_my_str} containing the characters |\<#abc def^|,
-% since |<| has ascii code \texttt{3C} (in hexadecimal).
+% results in \cs{l_my_str} containing the characters |<\#abc def^|,
+% followed by a newline character (hex \texttt{0A})
+% since |<| has \textsc{ascii} code \texttt{3C} (in hexadecimal).
% \end{function}
%
% \subsection{Characters given by their position}
%
-% \begin{function}[EXP]{\str_length:N}
-% \begin{function}[EXP]{\str_length:n}
-% \begin{function}[EXP]{\str_length_ignore_spaces:n}
+% \begin{function}[EXP]
+% {\str_length:N, \str_length:n, \str_length_ignore_spaces:n}
% \begin{syntax}
% \cs{str_length:n} \Arg{token list}
% \end{syntax}
% Leaves the length of the string representation of \meta{token list}
-% in the input stream. The functions differ in their treatment of spaces.
+% in the input stream as an integer denotation. The functions differ in
+% their treatment of spaces.
% In the case of \cs{str_length:N} and \cs{str_length:n},
% all characters including spaces are counted.
-% The \cs{str_length_ignore_spaces:n} returns the number of non-space
-% characters.
+% The \cs{str_length_ignore_spaces:n} leaves the number of non-space
+% characters in the input stream.
% \begin{texnote}
% The \cs{str_length:n} of a given token list may depend
% on the category codes in effect when it is measured,
@@ -200,12 +252,8 @@
% on the escape character, and the category code of \texttt{a}.
% \end{texnote}
% \end{function}
-% \end{function}
-% \end{function}
%
-% \begin{function}[EXP]{\str_head:N}
-% \begin{function}[EXP]{\str_head:n}
-% \begin{function}[EXP]{\str_head_ignore_spaces:n}
+% \begin{function}[EXP]{\str_head:N, \str_head:n, \str_head_ignore_spaces:n}
% \begin{syntax}
% \cs{str_head:n} \Arg{token list}
% \end{syntax}
@@ -215,18 +263,14 @@
% The functions differ in their treatment of spaces.
% In the case of \cs{str_head:N} and \cs{str_head:n},
% a leading space is returned with category code $10$ (blank space).
-% The \cs{str_head_ignore_spaces:n} function returns the first
-% non-space character.
+% The \cs{str_head_ignore_spaces:n} function leaves the first
+% non-space character in the input stream.
% If the \meta{token list} is empty (or blank in the case of the
% \texttt{_ignore_spaces} variant), then nothing is left on the
% input stream.
% \end{function}
-% \end{function}
-% \end{function}
%
-% \begin{function}[EXP]{\str_tail:N}
-% \begin{function}[EXP]{\str_tail:n}
-% \begin{function}[EXP]{\str_tail_ignore_spaces:n}
+% \begin{function}[EXP]{\str_tail:N, \str_tail:n, \str_tail_ignore_spaces:n}
% \begin{syntax}
% \cs{str_tail:n} \Arg{token list}
% \end{syntax}
@@ -239,12 +283,8 @@
% only that space, while \cs{str_tail_ignore_spaces:n} trims
% the first non-space character.
% \end{function}
-% \end{function}
-% \end{function}
%
-% \begin{function}[EXP]{\str_item:Nn}
-% \begin{function}[EXP]{\str_item:nn}
-% \begin{function}[EXP]{\str_item_ignore_spaces:nn}
+% \begin{function}[EXP]{\str_item:Nn, \str_item:nn, \str_item_ignore_spaces:nn}
% \begin{syntax}
% \cs{str_item:nn} \Arg{token list} \Arg{integer expression}
% \end{syntax}
@@ -260,29 +300,25 @@
% the right-most character, \emph{etc.}, while $0$ is the first
% (left-most) character.
% \end{function}
-% \end{function}
-% \end{function}
%
-% \begin{function}[EXP]{\str_from_to:Nnn}
-% \begin{function}[EXP]{\str_from_to:nnn}
-% \begin{function}[EXP]{\str_from_to_ignore_spaces:nnn}
+% \begin{function}[EXP]
+% {\str_substr:Nnn, \str_substr:nnn, \str_substr_ignore_spaces:nnn}
% \begin{syntax}
-% \cs{str_from_to:nnn} \Arg{token list} \Arg{start index} \Arg{end index}
+% \cs{str_substr:nnn} \Arg{token list} \Arg{start index} \Arg{end index}
% \end{syntax}
% Converts the \meta{token list} to a \meta{string},
% and leaves in the input stream the characters
% between \meta{start index} (inclusive) and \meta{end index} (exclusive).
% If either of \meta{start index} or \meta{end index} is negative,
-% the it is incremented by the length of the list.
-% \end{function}
-% \end{function}
+% the it is incremented by the length of the list. Both \meta{start index}
+% and \meta{end index} count from $0$ for the first (left most) character.
% \end{function}
%
% \subsection{String conditionals}
%
-% \begin{function}[EXP,pTF]{\str_if_eq:NN}
-% \begin{function}[EXP,pTF]
+% \begin{function}[EXP, pTF]
% {
+% \str_if_eq:NN,
% \str_if_eq:nn, \str_if_eq:Vn, \str_if_eq:on, \str_if_eq:no,
% \str_if_eq:nV, \str_if_eq:VV, \str_if_eq:xx
% }
@@ -300,10 +336,9 @@
% expandable (including those involving an \texttt{x}-type
% expansion).
% \end{function}
-% \end{function}
%
-% \begin{function}[EXP,pTF]{\str_if_contains_char:NN}
-% \begin{function}[EXP,pTF]{\str_if_contains_char:nN}
+% \begin{function}[EXP, pTF]
+% {\str_if_contains_char:NN, \str_if_contains_char:nN}
% \begin{syntax}
% \cs{str_if_contains_char:nN} \Arg{token list} \meta{char}
% \end{syntax}
@@ -312,43 +347,43 @@
% The \meta{char} can be given either directly, or as a one
% letter control sequence.
% \end{function}
-% \end{function}
%
-% \subsection{Bytes and encoding}
+% \subsection{Byte conditionals}
%
-% \subsubsection{Conditionals}
-%
-% \begin{function}[EXP,pTF]{\str_if_bytes:N}
+% \begin{function}[EXP, pTF]{\str_if_bytes:N}
% \begin{syntax}
% \cs{str_if_bytes:NTF} \meta{str var} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests whether the \meta{str var} only contains characters
-% in the range $0$--$255$.
-% \end{function}
-%
-% \begin{function}[EXP,pTF]{\str_if_UTF_viii:N}
-% \begin{syntax}
-% \cs{str_if_UTF_viii:N} \meta{str var} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Tests whether the \meta{str var} only contains characters
-% in the range $0$--$255$, and forms a valid \texttt{UTF8} string.
-% \textbf{Missing!} ^^A Missing.
+% in the range $0$ to $255$.
% \end{function}
%
-% \subsubsection{Conversion}
+% ^^A\begin{function}[EXP, pTF]{\str_if_UTF_viii:N}
+% ^^A \begin{syntax}
+% ^^A \cs{str_if_UTF_viii:N} \meta{str var} \Arg{true code} \Arg{false code}
+% ^^A \end{syntax}
+% ^^A Tests whether the \meta{str var} only contains characters
+% ^^A in the range $0$--$255$, and forms a valid \texttt{UTF8} string.
+% ^^A \textbf{Missing!} ^^A Missing.
+% ^^A\end{function}
+%
+% \subsection{Byte conversion}
+%
+% Byte conversions are necessary where strings are to be used in PDF
+% string objects or within URLs. In both cases, only a restricted subset
+% of characters are permitted.
%
% \begin{function}{\str_native_from_UTF_viii:NN}
% \begin{syntax}
% \cs{str_native_from_UTF_viii:NN} \meta{str~var1} \meta{str~var2}
% \end{syntax}
-% Reads the contents of the \meta{str~var2} as an \texttt{UTF8}-encoded
+% Reads the contents of the \meta{str~var2} as an \textsc{utf8}-encoded
% sequence of bytes, and stores the resulting characters (which can
% now have any character code) into \meta{str~var1}.
% This function raises an error if the \meta{str~var2} is not
-% a valid sequence of bytes in the \texttt{UTF8} encoding.
+% a valid sequence of bytes in the \textsc{utf8} encoding.
% In the \pdfTeX{} engine, this function raises an error if any of the
-% resulting characters is outside the range $0$--$255$ (in other words,
-% don't use this function with \pdfTeX{}).
+% resulting characters is outside the range $0$ to $255$.
% \end{function}
%
% \begin{function}{\str_UTF_viii_from_native:NN}
@@ -356,58 +391,123 @@
% \cs{str_UTF_viii_from_native:NN} \meta{str~var1} \meta{str~var2}
% \end{syntax}
% Converts each character of the \meta{str~var2} into
-% a sequence of bytes, as defined by the \texttt{UTF8}
+% a sequence of bytes, as defined by the \textsc{utf8}
% encoding, and stores the result in \meta{str~var1}.
% In the \pdfTeX{} engine, this function is of course
% of very little use, but can be used without harm:
-% characters in the range $0$--$127$ are left unchanged,
-% and characters in the range $128$--$255$ become two-byte
+% characters in the range $0$ to $127$ are left unchanged,
+% and characters in the range $128$ to $255$ become two-byte
% sequences, as per the definition of \texttt{UTF8}.
% \end{function}
%
-% \begin{function}{\str_bytes_escape_hexadecimal:NN}
-% \begin{function}{\str_bytes_unescape_hexadecimal:NN}
+% \begin{function}
+% {\str_bytes_escape_hexadecimal:NN, \str_bytes_unescape_hexadecimal:NN}
% \begin{syntax}
% \cs{str_bytes_escape_hexadecimal:NN} \meta{str var1} \meta{str var2}
% \cs{str_bytes_unescape_hexadecimal:NN} \meta{str var1} \meta{str var2}
% \end{syntax}
-% See \tn{pdfescapehex}. ^^A missing doc
-% \end{function}
+% The \texttt{escape} variant takes each character in \meta{str var1}
+% and converts it into the hexadecimal representation. The resulting
+% string is stored in \meta{str var2} within the current \TeX{} group
+% level. The \texttt{unescape} variant reverses this process.
+% Thus for example
+% \begin{verbatim}
+% \str_set:Nn \l_mya_str { Hello ( ) }
+% \str_bytes_escape_hexadecimal:NN \l_mya_str \l_myb_str
+% \end{verbatim}
+% will result in \cs{l_myb_str} containing the string |48656C6C6F2829|,
+% while
+% \begin{verbatim}
+% \str_set:Nn \l_mya_str { 48656C6C6F2829 }
+% \str_bytes_unescape_hexadecimal:NN \l_mya_str \l_myb_str
+% \end{verbatim}
+% will result in \cs{l_myb_str} containing the string |Hello()|.
+% See also \tn{pdfescapehex}.
% \end{function}
%
-% \begin{function}{\str_bytes_escape_name:NN}
-% \begin{function}{\str_bytes_unescape_name:NN}
+% \begin{function}
+% {\str_bytes_escape_name:NN, \str_bytes_unescape_name:NN}
% \begin{syntax}
% \cs{str_bytes_escape_name:NN} \meta{str var1} \meta{str var2}
% \cs{str_bytes_unescape_name:NN} \meta{str var1} \meta{str var2}
% \end{syntax}
-% See \tn{pdfescapename}. ^^A missing doc
-% \end{function}
+% The \texttt{escape} variant takes each character in \meta{str var1}
+% and replaces any which cannot be used directly in a PDF string object
+% with the appropriate hexadecimal representation preceded by the |#|
+% character. The resulting
+% string is stored in \meta{str var2} within the current \TeX{} group
+% level. The \texttt{unescape} variant reverses this process. Thus for
+% example
+% \begin{verbatim}
+% \str_set:Nn \l_mya_str { Hello ( ) }
+% \str_bytes_escape_name:NN \l_mya_str \l_myb_str
+% \end{verbatim}
+% will result in \cs{l_myb_str} containing the string |Hello#28#29|,
+% while
+% \begin{verbatim}
+% \char_set_catcode_other:N \#
+% \str_set:Nn \l_mya_str { Hello#28#29 }
+% \str_bytes_unescape_name:NN \l_mya_str \l_myb_str
+% \end{verbatim}
+% will result in \cs{l_myb_str} containing the string |Hello()|.
+% See also \tn{pdfescapename}.
% \end{function}
%
-% \begin{function}{\str_bytes_escape_string:NN}
-% \begin{function}{\str_bytes_unescape_string:NN}
+% \begin{function}{\str_bytes_escape_string:NN, \str_bytes_unescape_string:NN}
% \begin{syntax}
% \cs{str_bytes_escape_string:NN} \meta{str var1} \meta{str var2}
% \cs{str_bytes_unescape_string:NN} \meta{str var1} \meta{str var2}
% \end{syntax}
-% See \tn{pdfescapestring}. ^^A missing doc
-% \end{function}
+% The \texttt{escape} variant takes each character in \meta{str var1}
+% and prepends a |\| to any which cannot be used directly in a PDF string
+% object. The resulting string is stored in \meta{str var2} within the
+% current \TeX{} group level. The \texttt{unescape} variant reverses this
+% process. Thus for example
+% \begin{verbatim}
+% \str_set:Nn \l_mya_str { Hello [ ] }
+% \str_bytes_escape_string:NN \l_mya_str \l_myb_str
+% \end{verbatim}
+% will result in \cs{l_myb_str} containing the string |Hello\(\)|,
+% while
+% \begin{verbatim}
+% \str_set:Nn \l_mya_str { Hello\(\) }
+% \str_bytes_unescape_string:NN \l_mya_str \l_myb_str
+% \end{verbatim}
+% will result in \cs{l_myb_str} containing the string |Hello()|.
+% Some characters (for example a space) are converted to a three-digit
+% octal representation, so for example a space gives |\040|.
+% See also \tn{pdfescapename}.
% \end{function}
%
-% \begin{function}{\str_bytes_percent_encode:NN}
-% \begin{function}{\str_bytes_percent_decode:NN}
+% \begin{function}{\str_bytes_percent_encode:NN, \str_bytes_percent_decode:NN}
% \begin{syntax}
% \cs{str_bytes_percent_encode:NN} meta{str var1} \meta{str var2}
% \cs{str_bytes_percent_decode:NN} meta{str var1} \meta{str var2}
% \end{syntax}
-% Used for urls. ^^A missing doc
-% \end{function}
+% The \texttt{escape} variant takes each character in \meta{str var1}
+% and replaces any which cannot be used directly in a URL
+% with the appropriate hexadecimal representation preceded by the |%|
+% character. The resulting
+% string is stored in \meta{str var2} within the current \TeX{} group
+% level. The \texttt{unescape} variant reverses this process. Thus for
+% example
+% \begin{verbatim}
+% \str_set:Nn \l_mya_str { Hello ( ) }
+% \str_bytes_precent_encode:NN \l_mya_str \l_myb_str
+% \end{verbatim}
+% will result in \cs{l_myb_str} containing the string |Hello%28%29|,
+% while
+% \begin{verbatim}
+% \char_set_catcode_other:N \%
+% \str_set:Nn \l_mya_str { Hello%28%29 }
+% \str_bytes_unescape_name:NN \l_mya_str \l_myb_str
+% \end{verbatim}
+% will result in \cs{l_myb_str} containing the string |Hello()|.
% \end{function}
%
% \subsection{Internal string functions}
%
-% \begin{function}[EXP]{\tl_to_other_str:N,\tl_to_other_str:n}
+% \begin{function}[EXP]{\tl_to_other_str:N, \tl_to_other_str:n}
% \begin{syntax}
% \cs{tl_to_other_str:n} \Arg{token list}
% \end{syntax}
@@ -421,7 +521,7 @@
% \end{texnote}
% \end{function}
%
-% \begin{function}[EXP]{\str_sanitize_args:Nn,\str_sanitize_args:Nnn}
+% \begin{function}[EXP]{\str_sanitize_args:Nn, \str_sanitize_args:Nnn}
% \begin{syntax}
% \cs{str_sanitize_args:Nnn} \meta{function}
% ~~\Arg{token list1} \Arg{token list2}
@@ -473,7 +573,6 @@
% Some functionalities of \pkg{stringstrings} and \pkg{xstring} as well.
%
%^^A Should "str_item" be "str_char"?
-%^^A Should "str_from_to" be "str_substr"?
%
% \end{documentation}
%
@@ -482,7 +581,7 @@
% \section{\pkg{l3str} implementation}
%
% \begin{macrocode}
-%<*package>
+%<*initex|package>
% \end{macrocode}
%
% \begin{macrocode}
@@ -492,31 +591,18 @@
%
% Those string-related functions are defined in \pkg{l3kernel}.
% \begin{itemize}
-% \item \cs{str_if_eq:nn}[pTF] and variants,
-% \item \cs{str_if_eq_return:on},
-% \item \cs{tl_to_str:n}, \cs{tl_to_str:N}, \cs{tl_to_str:c},
-% \item \cs{token_to_str:N}, \cs{cs_to_str:N}
-% \item \cs{str_head:n}, \cs{str_head_aux:w}, (changed behaviour slightly)
-% \item \cs{str_tail:n}, \cs{str_tail_aux:w}, (changed behaviour slightly)
-% \item \cs{str_length_skip_spaces} (deprecated)
-% \item \cs{str_length_loop:NNNNNNNNN} (unchanged)
+% \item \cs{str_if_eq:nn}[pTF] and variants,
+% \item \cs{str_if_eq_return:on},
+% \item \cs{tl_to_str:n}, \cs{tl_to_str:N}, \cs{tl_to_str:c},
+% \item \cs{token_to_str:N}, \cs{cs_to_str:N}
+% \item \cs{str_head:n}, \cs{str_head_aux:w}, (copied here)
+% \item \cs{str_tail:n}, \cs{str_tail_aux:w}, (copied here)
+% \item \cs{str_length_skip_spaces} (deprecated)
+% \item \cs{str_length_loop:NNNNNNNNN} (unchanged)
% \end{itemize}
%
% \subsection{General functions}
%
-% \begin{macro}[EXP,aux]{\cs_if_exist_use:cF}
-% This function could be moved to a different module in \pkg{l3kernel}.
-% If the control sequence exists, use it,
-% otherwise fall back to a default behaviour.
-% \begin{macrocode}
-\cs_if_exist:NF \cs_if_exist_use:cF
- {
- \cs_new:Npn \cs_if_exist_use:cF #1
- { \cs_if_exist:cTF {#1} { \use:c {#1} } }
- }
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}[EXP,aux]{\use_i:nnnnnnnn}
% A function which may already be defined elsewhere.
% \begin{macrocode}
@@ -542,18 +628,20 @@
% }
% Simply convert the token list inputs to \meta{strings}.
% \begin{macrocode}
-\cs_set:Npn \str_tmp:w #1
- {
- \cs_new_protected:cpx { str_#1:Nn } ##1##2
- { \exp_not:c { tl_#1:Nx } ##1 { \exp_not:N \tl_to_str:n {##2} } }
- \exp_args:Nc \cs_generate_variant:Nn { str_#1:Nn } { Nx , cn , cx }
- }
-\str_tmp:w {set}
-\str_tmp:w {gset}
-\str_tmp:w {put_left}
-\str_tmp:w {gput_left}
-\str_tmp:w {put_right}
-\str_tmp:w {gput_right}
+\group_begin:
+ \cs_set_protected_nopar:Npn \str_tmp:w #1
+ {
+ \cs_new_protected:cpx { str_ #1 :Nn } ##1##2
+ { \exp_not:c { tl_ #1 :Nx } ##1 { \exp_not:N \tl_to_str:n {##2} } }
+ \exp_args:Nc \cs_generate_variant:Nn { str_ #1 :Nn } { Nx , cn , cx }
+ }
+ \str_tmp:w { set }
+ \str_tmp:w { gset }
+ \str_tmp:w { put_left }
+ \str_tmp:w { gput_left }
+ \str_tmp:w { put_right }
+ \str_tmp:w { gput_right }
+\group_end:
% \end{macrocode}
% \end{macro}
%
@@ -563,7 +651,7 @@
% \begin{variable}{\g_str_tmpa_tl}
% Internal scratch space for some functions.
% \begin{macrocode}
-\cs_set_protected_nopar:Npn \str_tmp:w { }
+\cs_new_protected_nopar:Npn \str_tmp:w { }
\tl_new:N \g_str_tmpa_tl
% \end{macrocode}
% \end{variable}
@@ -579,11 +667,11 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_str_char_int,\l_str_bytes_int}
+% \begin{variable}{\l_str_char_int, \l_str_bytes_int}
% When converting from various escaped forms to raw characters,
% we often need to read several digits (hexadecimal or octal depending
% on the case) and keep track of the corresponding character code
-% in \cs{l_str_char_int}. For UTF-8 support, the number of bytes
+% in \cs{l_str_char_int}. For \textsc{utf8} support, the number of bytes
% of for the current character is stored in \cs{l_str_bytes_int}.
% \begin{macrocode}
\int_new:N \l_str_char_int
@@ -591,8 +679,14 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\c_backslash_str,
-% \c_lbrace_str,\c_rbrace_str,\c_hash_str,\c_percent_str}
+% \begin{variable}
+% {
+% \c_backslash_str,
+% \c_lbrace_str,
+% \c_rbrace_str,
+% \c_hash_str,
+% \c_percent_str
+% }
% For all of those strings, \cs{cs_to_str:N} produce characters
% with the correct category code.
% \begin{macrocode}
@@ -606,48 +700,45 @@
%
% \subsection{Escaping spaces}
%
-% \begin{macro}[EXP]{\tl_to_other_str:N,\tl_to_other_str:n}
-% \begin{macro}[EXP,aux]{\tl_to_other_str_loop:w,\tl_to_other_str_end:w}
+% \begin{macro}[EXP]{\tl_to_other_str:N, \tl_to_other_str:n}
+% \begin{macro}[EXP,aux]{\tl_to_other_str_loop:w, \tl_to_other_str_end:w}
% Replaces all spaces by \enquote{other} spaces, after converting
% the token list to a string via \cs{tl_to_str:n}.
% \begin{macrocode}
\group_begin:
-\char_set_lccode:nn {`\*}{`\ }
-\char_set_lccode:nn {`\A}{`\A}
-\tl_to_lowercase:n {
- \group_end:
- \cs_new:Npn \tl_to_other_str:n #1
- {
- \exp_after:wN \tl_to_other_str_loop:w \tl_to_str:n {#1} ~ %
- A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_mark \q_stop
- }
- \cs_new_nopar:Npn \tl_to_other_str_loop:w
+\char_set_lccode:nn { `\* } { `\ }
+\char_set_lccode:nn { `\A } { `\A }
+\tl_to_lowercase:n
+ {
+ \group_end:
+ \cs_new:Npn \tl_to_other_str:n #1
+ {
+ \exp_after:wN \tl_to_other_str_loop:w \tl_to_str:n {#1} ~ %
+ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_mark \q_stop
+ }
+ \cs_new_nopar:Npn \tl_to_other_str_loop:w
#1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 \q_stop
- {
- \if_meaning:w A #8
- \tl_to_other_str_end:w
- \fi:
- \tl_to_other_str_loop:w
- #9 #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * \q_stop
- }
- \cs_new_nopar:Npn \tl_to_other_str_end:w \fi: #1 \q_mark #2 * A #3 \q_stop
- { \fi: #2 }
-}
-\cs_new_nopar:Npn \tl_to_other_str:N
- { \exp_args:No \tl_to_other_str:n }
+ {
+ \if_meaning:w A #8
+ \tl_to_other_str_end:w
+ \fi:
+ \tl_to_other_str_loop:w
+ #9 #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * \q_stop
+ }
+ \cs_new_nopar:Npn \tl_to_other_str_end:w \fi: #1 \q_mark #2 * A #3 \q_stop
+ { \fi: #2 }
+ }
+\cs_new_nopar:Npn \tl_to_other_str:N { \exp_args:No \tl_to_other_str:n }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[EXP]{\str_sanitize_args:Nn,\str_sanitize_args:Nnn}
+% \begin{macro}[EXP]{\str_sanitize_args:Nn, \str_sanitize_args:Nnn}
% Here, \texttt{f}-expansion does not lose leading spaces,
% since they have catcode \enquote{other} after \cs{str_sanitize:n}.
% \begin{macrocode}
-\cs_new:Npn \str_sanitize_args:Nn #1 #2
- {
- \exp_args:Nf #1
- { \tl_to_other_str:n {#2} }
- }
+\cs_new:Npn \str_sanitize_args:Nn #1#2
+ { \exp_args:Nf #1 { \tl_to_other_str:n {#2} } }
\cs_new:Npn \str_sanitize_args:Nnn #1#2#3
{
\exp_args:Nff #1
@@ -726,15 +817,15 @@
% gives an empty result after passing through
% \cs{use_i_delimit_by_q_stop:nw}.
% \begin{macrocode}
-\cs_set_nopar:Npn \str_head:N { \exp_args:No \str_head:n }
+\cs_new_nopar:Npn \str_head:N { \exp_args:No \str_head:n }
\cs_set:Npn \str_head:n #1
{
\exp_after:wN \str_head_aux:w
\tl_to_str:n {#1}
{ { } } ~ \q_stop
}
-\cs_set_nopar:Npx \str_head_aux:w #1 ~ %
- { \exp_not:N \use_i_delimit_by_q_stop:nw #1 { ~ } }
+\cs_set_nopar:Npn \str_head_aux:w #1 ~ %
+ { \use_i_delimit_by_q_stop:nw #1 { ~ } }
\cs_new:Npn \str_head_ignore_spaces:n #1
{ \exp_after:wN \use_i_delimit_by_q_stop:nw \tl_to_str:n {#1} { } \q_stop }
\cs_new_nopar:Npn \str_head_unsafe:n #1
@@ -779,7 +870,7 @@
}
\cs_new_nopar:Npn \str_tail_unsafe:n #1
{ \str_tail_aux_ii:w #1 X { } X \q_stop }
-\cs_set_nopar:Npn \str_tail_aux_ii:w #1 #2 X #3 \q_stop { #2 }
+\cs_new_nopar:Npn \str_tail_aux_ii:w #1 #2 X #3 \q_stop { #2 }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -800,12 +891,14 @@
% \begin{macrocode}
\cs_new:Npn \str_skip_do:nn #1
{
- \int_compare:nNnTF {#1} > \c_seven
- { \str_skip_aux:nnnnnnnnn }
- { \str_skip_end:n }
+ \if_num:w \int_eval:w #1 > \c_seven
+ \exp_after:wN \str_skip_aux:nnnnnnnnn
+ \else:
+ \exp_after:wN \str_skip_end:n
+ \fi:
{#1}
}
-\cs_new:Npn \str_skip_aux:nnnnnnnnn #1#2 #3#4#5#6#7#8#9
+\cs_new:Npn \str_skip_aux:nnnnnnnnn #1#2#3#4#5#6#7#8#9
{ \exp_args:Nf \str_skip_do:nn { \int_eval:n { #1 - \c_seven } } {#2} }
\cs_new:Npn \str_skip_end:n #1
{
@@ -821,7 +914,7 @@
\else: \str_skip_end_ii:nwn { XXXXXXX }
\fi:
}
-\cs_new:Npn \str_skip_end_ii:nwn #1 #2 \fi: #3
+\cs_new:Npn \str_skip_end_ii:nwn #1#2 \fi: #3
{ \fi: \use_i:nnnnnnnn {#3} #1 }
% \end{macrocode}
% \end{macro}
@@ -861,18 +954,18 @@
\cs_new:Npn \str_collect_end:n #1
{
\if_case:w \int_eval:w #1 \int_eval_end:
- \str_collect_end_ii:nwn { {}{}{}{}{}{}{} }
- \or: \str_collect_end_ii:nwn { {}{}{}{}{}{} }
- \or: \str_collect_end_ii:nwn { {}{}{}{}{} }
- \or: \str_collect_end_ii:nwn { {}{}{}{} }
- \or: \str_collect_end_ii:nwn { {}{}{} }
- \or: \str_collect_end_ii:nwn { {}{} }
- \or: \str_collect_end_ii:nwn { {} }
+ \str_collect_end_ii:nwn { { } { } { } { } { } { } { } }
+ \or: \str_collect_end_ii:nwn { { } { } { } { } { } { } }
+ \or: \str_collect_end_ii:nwn { { } { } { } { } { } }
+ \or: \str_collect_end_ii:nwn { { } { } { } { } }
+ \or: \str_collect_end_ii:nwn { { } { } { } }
+ \or: \str_collect_end_ii:nwn { { } { } }
+ \or: \str_collect_end_ii:nwn { { } }
\or: \str_collect_end_ii:nwn { }
- \else: \str_collect_end_ii:nwn { {}{}{}{}{}{}{} }
+ \else: \str_collect_end_ii:nwn { { } { } { } { } { } { } { } }
\fi:
}
-\cs_new:Npn \str_collect_end_ii:nwn #1 #2 \fi: #3
+\cs_new:Npn \str_collect_end_ii:nwn #1#2 \fi: #3
{ \fi: #3 \q_stop #1 }
\cs_new:Npn \str_collect_end_iii:nwNNNNNNN #1 #2 \q_stop #3#4#5#6#7#8#9
{ #1 {#2#3#4#5#6#7#8#9} }
@@ -938,12 +1031,12 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[EXP]{\str_from_to:Nnn}
-% \begin{macro}[EXP]{\str_from_to:nnn}
-% \begin{macro}[EXP]{\str_from_to_ignore_spaces:nnn}
-% \begin{macro}[EXP]{\str_from_to_unsafe:nnn}
-% \begin{macro}[EXP,aux]{\str_from_to_aux:nnnw}
-% \begin{macro}[EXP,aux]{\str_from_to_aux_ii:nnw}
+% \begin{macro}[EXP]{\str_substr:Nnn}
+% \begin{macro}[EXP]{\str_substr:nnn}
+% \begin{macro}[EXP]{\str_substr_ignore_spaces:nnn}
+% \begin{macro}[EXP]{\str_substr_unsafe:nnn}
+% \begin{macro}[EXP,aux]{\str_substr_aux:nnnw}
+% \begin{macro}[EXP,aux]{\str_substr_aux_ii:nnw}
% \begin{macro}[EXP,aux]{\str_aux_eval_args:Nnnn}
% \begin{macro}[EXP,aux]{\str_aux_normalize_range:nn}
% Sanitize the string, then limit the second and third arguments
@@ -952,30 +1045,30 @@
% Afterwards, skip characters, then keep some more, and finally
% drop the end of the string.
% \begin{macrocode}
-\cs_new_nopar:Npn \str_from_to:Nnn { \exp_args:No \str_from_to:nnn }
-\cs_new:Npn \str_from_to:nnn #1#2#3
+\cs_new_nopar:Npn \str_substr:Nnn { \exp_args:No \str_substr:nnn }
+\cs_new:Npn \str_substr:nnn #1#2#3
{
\exp_args:Nf \tl_to_str:n
- { \str_sanitize_args:Nn \str_from_to_unsafe:nnn {#1}{#2}{#3} }
+ { \str_sanitize_args:Nn \str_substr_unsafe:nnn {#1} {#2} {#3} }
}
-\cs_new:Npn \str_from_to_ignore_spaces:nnn #1
- { \exp_args:No \str_from_to_unsafe:nnn { \tl_to_str:n {#1} } }
-\cs_new:Npn \str_from_to_unsafe:nnn #1#2#3 % <string> <from> <to>
+\cs_new:Npn \str_substr_ignore_spaces:nnn #1
+ { \exp_args:No \str_substr_unsafe:nnn { \tl_to_str:n {#1} } }
+\cs_new:Npn \str_substr_unsafe:nnn #1#2#3
{
- \str_aux_eval_args:Nnnn \str_from_to_aux:nnnw
+ \str_aux_eval_args:Nnnn \str_substr_aux:nnnw
{ \str_length_unsafe:n {#1} }
{#2}
{#3}
#1
\q_stop
}
-\cs_new:Npn \str_from_to_aux:nnnw #1#2#3 % <len> <from> <to>
+\cs_new:Npn \str_substr_aux:nnnw #1#2#3
{
- \exp_args:Nf \str_from_to_aux_ii:nnw
+ \exp_args:Nf \str_substr_aux_ii:nnw
{ \str_aux_normalize_range:nn {#2} {#1} }
{ \str_aux_normalize_range:nn {#3} {#1} }
}
-\cs_new:Npn \str_from_to_aux_ii:nnw #1#2
+\cs_new:Npn \str_substr_aux_ii:nnw #1#2
{
\str_skip_do:nn {#1}
{
@@ -1127,7 +1220,7 @@
%
% \subsection{Internal conditionals}
%
-% \begin{macro}[aux]{\str_aux_hexadecimal_test:N}
+% \begin{macro}[aux]{\str_aux_hexadecimal_test:NTF}
% This test is used when reading hexadecimal digits, for the |\x| escape
% sequence, and some conversion functions. It returns \meta{true} if the
% token is a hexadecimal digit, and \meta{false} otherwise. It has the
@@ -1137,7 +1230,7 @@
% \begin{macrocode}
\prg_new_protected_conditional:Npnn \str_aux_hexadecimal_test:N #1 { TF }
{
- \tl_if_in:onTF { \tl_to_str:n {abcdef} } {#1}
+ \tl_if_in:onTF { \tl_to_str:n { abcdef } } {#1}
{
\int_set:Nn \l_str_char_int
{ \c_sixteen * \l_str_char_int + `#1 - 87 }
@@ -1156,7 +1249,7 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\str_aux_octal_test:N}
+% \begin{macro}[aux]{\str_aux_octal_test:NTF}
% This test is used when reading octal digits, for
% some conversion functions. It returns \meta{true} if the
% token is an octal digit, and \meta{false} otherwise.
@@ -1193,7 +1286,8 @@
% and in the regular expression module to go through the regular expression
% once before actually parsing it. The goal in that case is to turn any
% character with a meaning in regular expressions (\texttt{*}, \texttt{?},
-% \texttt{\{}, etc.) into a marker indicating that this was a special character,
+% \texttt{\{}, etc.) into a marker indicating that this was a special
+% character,
% and replace any escaped character by the corresponding unescaped character,
% so that the \pkg{l3regex} code can avoid caring about escaping issues
% (those can become quite complex to handle in combination with ranges
@@ -1201,7 +1295,7 @@
%
% The idea is to feed unescaped characters to one function,
% escaped characters to another, and feed |\a|, |\e|, |\f|,
-% |\n|, |\r|, |\t| and |\x| converted to the approriate
+% |\n|, |\r|, |\t| and |\x| converted to the appropriate
% character to a third function. Spaces are ignored unless
% escaped.
% For the \cs{str_(g)input:Nn} application, all the functions are simply
@@ -1245,7 +1339,7 @@
\cs_set_nopar:Npn \str_aux_escape_unescaped:N { #1 }
\cs_set_nopar:Npn \str_aux_escape_escaped:N { #2 }
\cs_set_nopar:Npn \str_aux_escape_raw:N { #3 }
- \int_set:Nn \tex_escapechar:D {92}
+ \int_set:Nn \tex_escapechar:D { 92 }
\tl_gset:Nx \g_str_result_tl { \tl_to_other_str:n {#4} }
\tl_gset:Nx \g_str_result_tl
{
@@ -1278,9 +1372,11 @@
% \begin{macro}[aux]+\str_aux_escape_\q_recursion_tail:w+
% \begin{macro}[aux]+\str_aux_escape_/\q_recursion_tail:w+
% \begin{macro}[aux]+\str_aux_escape_ :w+
-% \begin{macro}[aux]{
+% \begin{macro}[aux]
+% {
% \str_aux_escape_/a:w, \str_aux_escape_/e:w, \str_aux_escape_/f:w,
-% \str_aux_escape_/n:w, \str_aux_escape_/r:w, \str_aux_escape_/t:w}
+% \str_aux_escape_/n:w, \str_aux_escape_/r:w, \str_aux_escape_/t:w
+% }
% The loop is ended upon seeing \cs{q_recursion_tail}.
% Spaces are ignored, and |\a|, |\e|, |\f|, |\n|, |\r|, |\t| take
% their meaning here.
@@ -1396,12 +1492,6 @@
}
}
\group_end:
-\msg_new:nnn { str } { x-missing-brace }
- {
- You~wrote~something~like~
- `\iow_char:N\\x\{ \int_to_hexadecimal:n { \l_str_char_int }'.~
- The~closing~brace~is~missing.
- }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1411,21 +1501,21 @@
% \end{macro}
% \end{macro}
%
-% \subsubsection{Escape and unescape strings for pdf use}
+% \subsubsection{Escape and unescape strings for PDF use}
%
% \begin{macro}{\str_aux_convert_store:}
% \begin{macro}{\str_aux_convert_store:NNn}
% \begin{macrocode}
\group_begin:
- \char_set_catcode_other:n {`\^^@}
+ \char_set_catcode_other:n { `\^^@ }
\cs_new_protected_nopar:Npn \str_aux_convert_store:
{
- \char_set_lccode:nn {\c_zero} {\l_str_char_int}
+ \char_set_lccode:nn { \c_zero } { \l_str_char_int }
\tl_to_lowercase:n { \tl_gput_right:Nx \g_str_result_tl {^^@} }
}
\cs_new_protected_nopar:Npn \str_aux_convert_store:NNn #1#2#3
{
- \char_set_lccode:nn {\c_zero} {#3}
+ \char_set_lccode:nn { \c_zero } {#3}
\tl_to_lowercase:n { #1 #2 {^^@} }
}
\group_end:
@@ -1438,7 +1528,7 @@
% \begin{macrocode}
\cs_new_nopar:Npn \str_aux_byte_to_hexadecimal:N #1
{
- \int_compare:nNnTF {`#1} < {256}
+ \int_compare:nNnTF {`#1} < { 256 }
{
\int_to_letter:n { \int_div_truncate:nn {`#1} \c_sixteen }
\int_to_letter:n { \int_mod:nn {`#1} \c_sixteen }
@@ -1447,14 +1537,14 @@
}
\cs_new_nopar:Npn \str_aux_byte_to_octal:N #1
{
- \int_compare:nNnTF {`#1} < {64}
+ \int_compare:nNnTF {`#1} < { 64 }
{
0
\int_to_letter:n { \int_div_truncate:nn {`#1} \c_eight }
\int_to_letter:n { \int_mod:nn {`#1} \c_eight }
}
{
- \int_compare:nNnTF {`#1} < {256}
+ \int_compare:nNnTF {`#1} < { 256 }
{ \int_to_octal:n {`#1} }
{ \msg_expandable_error:n { Invalid~byte~`#1'. } }
}
@@ -1476,7 +1566,7 @@
% \begin{macro}{\str_bytes_escape_name:NN}
% \begin{macrocode}
\tl_const:Nx \c_str_bytes_escape_name_str
- { \c_hash_str \c_percent_str \c_lbrace_str \c_rbrace_str () /<>[] }
+ { \c_hash_str \c_percent_str \c_lbrace_str \c_rbrace_str ()/<>[] }
\cs_new_protected_nopar:Npn \str_bytes_escape_name:NN #1#2
{
\str_set:Nx #1
@@ -1484,10 +1574,10 @@
}
\cs_new_nopar:Npn \str_bytes_escape_name_aux:N #1
{
- \int_compare:nNnTF {`#1} < {"21}
+ \int_compare:nNnTF {`#1} < { "21 }
{ \c_hash_str \str_aux_byte_to_hexadecimal:N #1 }
{
- \int_compare:nNnTF {`#1} > {"7E}
+ \int_compare:nNnTF {`#1} > { "7E }
{ \c_hash_str \str_aux_byte_to_hexadecimal:N #1 }
{
\str_if_contains_char:NNTF \c_str_bytes_escape_name_str #1
@@ -1501,7 +1591,7 @@
%
% \begin{macro}{\str_bytes_escape_string:NN}
% Any character below (and including) space, and any character
-% above (anc including) \texttt{del}, are converted to octal.
+% above (and including) \texttt{del}, are converted to octal.
% One backslash is added before each parenthesis and backslash.
% \begin{macrocode}
\tl_const:Nx \c_str_bytes_escape_string_str { \c_backslash_str ( ) }
@@ -1512,10 +1602,10 @@
}
\cs_new_nopar:Npn \str_bytes_escape_string_aux:N #1
{
- \int_compare:nNnTF {`#1} < {"21}
+ \int_compare:nNnTF {`#1} < { "21 }
{ \c_backslash_str \str_aux_byte_to_octal:N #1 }
{
- \int_compare:nNnTF {`#1} > {"7E}
+ \int_compare:nNnTF {`#1} > { "7E }
{ \c_backslash_str \str_aux_byte_to_octal:N #1 }
{
\str_if_contains_char:NNT \c_str_bytes_escape_string_str #1
@@ -1639,7 +1729,7 @@
% If followed by an end-of-line character, the backslash and
% the end-of-line are ignored. If followed by anything else,
% the backslash is ignored.
-% The pdf specification indicates that LF, CR, and CRLF should be
+% The PDF specification indicates that LF, CR, and CRLF should be
% converted to LF: \emph{this is not implemented here}.
% \begin{macrocode}
\group_begin:
@@ -1671,16 +1761,16 @@
{
\prg_case_str:xxn {#2}
{
- {n} {10}
- {r} {13}
- {t} {9}
- {b} {8}
- {f} {12}
- {(} {40}
- {)} {41}
- {\c_backslash_str} {92}
- {^^J} {-1}
- {^^M} {-1}
+ { n } { 10 }
+ { r } { 13 }
+ { t } { 9 }
+ { b } { 8 }
+ { f } { 12 }
+ { ( } { 40 }
+ { ) } { 41 }
+ { \c_backslash_str } { 92 }
+ { ^^J } { -1 }
+ { ^^M } { -1 }
}
{`#2}
}
@@ -1727,14 +1817,14 @@
}
\cs_new_nopar:Npn \str_bytes_percent_encode_aux:N #1
{
- \int_compare:nNnTF {`#1} < {"41}
+ \int_compare:nNnTF {`#1} < { "41 }
{
\str_if_contains_char:NNTF \c_str_bytes_percent_encode_not_str #1
{ #1 }
{ \c_percent_str \str_aux_byte_to_hexadecimal:N #1 }
}
{
- \int_compare:nNnTF {`#1} > {"7E}
+ \int_compare:nNnTF {`#1} > { "7E }
{ \c_percent_str \str_aux_byte_to_hexadecimal:N #1 }
{
\str_if_contains_char:NNTF \c_str_bytes_percent_encode_str #1
@@ -1798,6 +1888,14 @@
% \subsubsection{UTF-8 support}
%
% \begin{macro}{\str_native_from_UTF_viii:NN}
+% \begin{macro}[aux]
+% {
+% \str_native_from_UTF_viii_aux_i:N,
+% \str_native_from_UTF_viii_aux_ii:nN,
+% \str_native_from_UTF_viii_aux_iii:N,
+% \str_native_from_UTF_viii_aux_iv:,
+% \str_native_from_UTF_viii_aux_v:
+% }
% \begin{macrocode}
\cs_new_protected_nopar:Npn \str_native_from_UTF_viii:NN #1#2
{
@@ -1812,19 +1910,18 @@
\cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_i:N #1
{
\quark_if_recursion_tail_stop:N #1
- \int_set:Nn \l_str_char_int { `#1 }
- \str_native_from_UTF_viii_aux_ii:nN {128} \c_one
- \str_native_from_UTF_viii_aux_ii:nN {64} \c_zero
- \str_native_from_UTF_viii_aux_ii:nN {32} \c_two
- \str_native_from_UTF_viii_aux_ii:nN {16} \c_three
- \str_native_from_UTF_viii_aux_ii:nN {8} \c_four
+ \int_set:Nn \l_str_char_int {`#1}
+ \str_native_from_UTF_viii_aux_ii:nN { 128 } \c_one
+ \str_native_from_UTF_viii_aux_ii:nN { 64 } \c_zero
+ \str_native_from_UTF_viii_aux_ii:nN { 32 } \c_two
+ \str_native_from_UTF_viii_aux_ii:nN { 16 } \c_three
+ \str_native_from_UTF_viii_aux_ii:nN { 8 } \c_four
\msg_error:nnx { str } { utf8-invalid-byte } {#1}
\use_i:nnn \str_native_from_UTF_viii_aux_i:N
\q_stop
\str_native_from_UTF_viii_aux_iii:N
}
-\cs_new_protected_nopar:Npn
- \str_native_from_UTF_viii_aux_ii:nN #1#2
+\cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_ii:nN #1#2
{
\int_compare:nNnTF \l_str_char_int < {#1}
{
@@ -1833,8 +1930,7 @@
}
{ \int_sub:Nn \l_str_char_int {#1} }
}
-\cs_new_protected_nopar:Npn
- \str_native_from_UTF_viii_aux_iii:N #1
+\cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_iii:N #1
{
\int_compare:nNnTF \l_str_bytes_int < \c_two
{ \str_native_from_UTF_viii_aux_iv: #1 }
@@ -1844,11 +1940,11 @@
\exp_after:wN \use_none_delimit_by_q_recursion_stop:w
\fi:
\quark_if_recursion_tail_stop:N #1
- \tex_multiply:D \l_str_char_int by 64 \scan_stop: % no interface??
+ \tex_multiply:D \l_str_char_int by 64 \scan_stop:
\int_decr:N \l_str_bytes_int
- \int_compare:nNnTF {`#1} < {128}
+ \int_compare:nNnTF {`#1} < { 128 }
{ \use_ii:nn }
- { \int_compare:nNnTF {`#1} < {192} }
+ { \int_compare:nNnTF {`#1} < { 192 } }
{
\int_add:Nn \l_str_char_int { `#1 - 128 }
\str_native_from_UTF_viii_aux_iii:N
@@ -1859,49 +1955,35 @@
}
}
}
-\cs_new_protected_nopar:Npn
- \str_native_from_UTF_viii_aux_iv:
+\cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_iv:
{
\int_compare:nNnTF \l_str_bytes_int = \c_zero
{
\msg_error:nnx { str } { utf8-extra-byte }
{ \int_eval:n { \l_str_char_int + 128 } }
}
+ { \str_native_from_UTF_viii_aux_v: }
+ \str_native_from_UTF_viii_aux_i:N
+ }
+\pdftex_if_engine:TF
+ {
+ \cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_v:
{
- \pdftex_if_engine:TF
+ \int_compare:nNnTF { \l_str_char_int } < { 256 }
+ { \str_aux_convert_store: }
{
- \int_compare:nNnTF { \l_str_char_int } < { 256 }
- { \str_aux_convert_store: }
- {
- \msg_error:nnx { str } { utf8-pdftex-overflow }
- { \int_use:N \l_str_char_int }
- }
+ \msg_error:nnx { str } { utf8-pdftex-overflow }
+ { \int_use:N \l_str_char_int }
}
- { \str_aux_convert_store: }
}
- \str_native_from_UTF_viii_aux_i:N
- }
-\msg_new:nnn { str } { utf8-invalid-byte }
- {
- \int_compare:nNnTF {`#1} < {256}
- { Byte~number~\int_eval:n {`#1}~invalid~in~utf-8~encoding. }
- { The~character~number~\int_eval:n {`#1}~is~not~a~byte. }
}
-\msg_new:nnn { str } { utf8-missing-byte }
- { The~byte~number~\int_eval:n {`#1}~is~not~a~valid~continuation~byte. }
-\msg_new:nnn { str } { utf8-extra-byte }
- { The~byte~number~\int_eval:n {`#1}~is~only~valid~as~a~continuation~byte. }
-\msg_new:nnnn { str } { utf8-premature-end }
- { Incomplete~last~utf8~character. }
{
- The~sequence~of~byte~that~I~need~to~convert~to~utf8 \
- ended~before~the~last~character~was~complete.~Perhaps \
- it~was~mistakenly~truncated?
+ \cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_v:
+ { \str_aux_convert_store: }
}
-\msg_new:nnn { str } { utf8-pdftex-overflow }
- { The~character~number~#1~is~too~big~for~pdfTeX. }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\str_UTF_viii_from_native:NN}
% \begin{macrocode}
@@ -1916,14 +1998,14 @@
\cs_new_protected_nopar:Npn \str_UTF_viii_from_native_aux_i:N #1
{
\int_set:Nn \l_str_char_int {`#1}
- \int_compare:nNnTF \l_str_char_int < {128}
+ \int_compare:nNnTF \l_str_char_int < { 128 }
{ \tl_gput_right:Nx \g_str_result_tl {#1} }
{
\tl_gclear:N \g_str_tmpa_tl
\int_set:Nn \l_str_bytes_int { 64 }
- \str_UTF_viii_from_native_aux_ii:n {32}
- \str_UTF_viii_from_native_aux_ii:n {16}
- \str_UTF_viii_from_native_aux_ii:n {8}
+ \str_UTF_viii_from_native_aux_ii:n { 32 }
+ \str_UTF_viii_from_native_aux_ii:n { 16 }
+ \str_UTF_viii_from_native_aux_ii:n { 8 }
\ERROR % somehow the unicode char was > "1FFFFF > "10FFFF
\tl_gclear:N \g_str_tmpa_tl
\use_none:n \q_stop
@@ -1936,29 +2018,60 @@
{
\str_aux_convert_store:NNn
\tl_gput_left:Nx \g_str_tmpa_tl
- { 128 + \int_mod:nn { \l_str_char_int } {64} }
- \tex_divide:D \l_str_char_int by 64 \scan_stop: % no interface??
+ { 128 + \int_mod:nn { \l_str_char_int } { 64 } }
+ \tex_divide:D \l_str_char_int by 64 \scan_stop:
\int_add:Nn \l_str_bytes_int {#1}
\int_compare:nNnT \l_str_char_int < {#1}
{ \use_none_delimit_by_q_stop:w }
}
% \end{macrocode}
% \end{macro}
+%
+% \subsection{Messages}
+%
+% \begin{macrocode}
+\msg_new:nnnn { str } { x-missing-brace }
+ { Missing~closing~brace~in~ \token_to_str:N \x ~byte~sequence. }
+ {
+ You~wrote~something~like~
+ `\iow_char:N\\x\{ \int_to_hexadecimal:n { \l_str_char_int }'.~
+ The~closing~brace~is~missing.
+ }
+\msg_new:nnn { str } { utf8-invalid-byte }
+ {
+ \int_compare:nNnTF {`#1} < { 256 }
+ { Byte~number~ \int_eval:n {`#1} ~invalid~in~utf-8~encoding. }
+ { The~character~number~ \int_eval:n {`#1} ~is~not~a~byte. }
+ }
+\msg_new:nnn { str } { utf8-missing-byte }
+ { The~byte~number~ \int_eval:n {`#1} ~is~not~a~valid~continuation~byte. }
+\msg_new:nnn { str } { utf8-extra-byte }
+ { The~byte~number~ \int_eval:n {`#1} ~is~only~valid~as~a~continuation~byte. }
+\msg_new:nnnn { str } { utf8-premature-end }
+ { Incomplete~last~UTF8~character. }
+ {
+ The~sequence~of~byte~that~to~be~converted~to~UTF8~
+ ended~before~the~last~character~was~complete.~Perhaps~
+ it~was~mistakenly~truncated?
+ }
+\msg_new:nnn { str } { utf8-pdftex-overflow }
+ { The~character~number~#1~is~too~big~for~pdfTeX. }
+% \end{macrocode}
%
% \subsection{Deprecated string functions}
%
-% \begin{macro}{\str_length_skip_spaces:N,\str_length_skip_spaces:n}
+% \begin{macro}{\str_length_skip_spaces:N, \str_length_skip_spaces:n}
% The naming scheme is a little bit more consistent
% with \enquote{ignore_spaces} instead of \enquote{skip_spaces}.
% \begin{macrocode}
-\cs_gset:Npn \str_length_skip_spaces:N
+\cs_set:Npn \str_length_skip_spaces:N
{ \exp_args:No \str_length_skip_spaces:n }
-\cs_gset_eq:NN \str_length_skip_spaces:n \str_length_ignore_spaces:n
+\cs_set_eq:NN \str_length_skip_spaces:n \str_length_ignore_spaces:n
% \end{macrocode}
% \end{macro}
%
% \begin{macrocode}
-%</package>
+%</initex|package>
% \end{macrocode}
%
% \end{implementation}
diff --git a/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx b/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx
index 103934d5fe8..30a58c18817 100644
--- a/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx
+++ b/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx
@@ -36,7 +36,7 @@
%
%<*driver|package>
\RequirePackage{xparse}
-\GetIdInfo$Id: xcoffins.dtx 2895 2011-10-09 15:58:19Z joseph $
+\GetIdInfo$Id: xcoffins.dtx 2963 2011-11-15 22:06:41Z joseph $
{L3 Experimental design-level coffins}
%</driver|package>
%<*driver>
@@ -583,6 +583,47 @@
% coffin is therefore analogous to carrying out an alignment where the
% \enquote{parent} coffin is the current insertion point.
% \end{function}
+%
+% \section{Measuring coffins}
+%
+% There are places in the design process where it is useful to be able to
+% measure coffins outside of pole-setting procedures.
+%
+% \begin{function}{\CoffinDepth}
+% \begin{syntax}
+% \cs{CoffinDepth} \meta{coffin}
+% \end{syntax}
+% Calculates the depth (below the baseline) of the \meta{coffin}
+% in a form suitable for use in a \meta{dimension expression}, for example
+% |\setlength{\mylength}{\CoffinDepth\ExampleCoffin}|.
+% \end{function}
+%
+% \begin{function}{\CoffinHeight}
+% \begin{syntax}
+% \cs{CoffinHeight} \meta{coffin}
+% \end{syntax}
+% Calculates the height (above the baseline) of the \meta{coffin}
+% in a form suitable for use in a \meta{dimension expression}, for example
+% |\setlength{\mylength}{\CoffinHeight\ExampleCoffin}|.
+% \end{function}
+%
+% \begin{function}{\CoffinTotalHeight}
+% \begin{syntax}
+% \cs{CoffinTotalHeight} \meta{coffin}
+% \end{syntax}
+% Calculates the total height of the \meta{coffin}
+% in a form suitable for use in a \meta{dimension expression}, for example
+% |\setlength{\mylength}{\CoffinTotalHeight\ExampleCoffin}|.
+% \end{function}
+%
+% \begin{function}{\CoffinWidth}
+% \begin{syntax}
+% \cs{CoffinHeight} \meta{coffin}
+% \end{syntax}
+% Calculates the width of the \meta{coffin} in a form
+% suitable for use in a \meta{dimension expression}, for example
+% |\setlength{\mylength}{\CoffinWidth\ExampleCoffin}|.
+% \end{function}
%
% \section{Diagnostic functions}
%
@@ -839,6 +880,22 @@
% \end{macro}
% \end{macro}
% \end{macro}
+%
+% \begin{macro}{\CoffinDepth, \CoffinHeight, \CoffinTotalHeigth, \CoffinWidth}
+% Nothing too complex, except that the total height is set up as an
+% expression so that it will act correctly if prefixed with a negative
+% sign, \emph{etc.}
+% \begin{macrocode}
+\NewDocumentCommand \CoffinDepth { m }
+ { \coffin_dp:N #1 }
+\NewDocumentCommand \CoffinHeight { m }
+ { \coffin_ht:N #1 }
+\NewDocumentCommand \CoffinTotalHeight { m }
+ { \dim_eval:w \coffin_ht:N #1 + \coffin_dp:N #1 \dim_eval_end: }
+\NewDocumentCommand \CoffinWidth { m }
+ { \coffin_wd:N #1 }
+% \end{macrocode}
+% \end{macro}
%
% \begin{macro}{\DisplayCoffinHandles}
% Displaying all of the handles is a bit easier, as there is no need
diff --git a/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx b/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx
index fa54ac37e59..57fbb9ecca4 100644
--- a/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx
+++ b/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx
@@ -37,7 +37,7 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3galley.dtx 2899 2011-10-09 21:22:06Z joseph $
+\GetIdInfo$Id: l3galley.dtx 2938 2011-10-25 18:41:20Z joseph $
{L3 Experimental galley code}
%</driver|package>
%<*driver>
@@ -535,10 +535,22 @@
% paragraph started.
% \end{variable}
%
-% \begin{variable}{\g_galley_whatsit_previous_hook_tl}
+% \begin{variable}{\g_galley_whatsit_previous_tl}
% Token list for whatsits to be inserted at the very end of the last
% paragraph started.
% \end{variable}
+%
+% \section{Additional effects}
+%
+% \begin{function}{\galley_end_par:n}
+% \begin{syntax}
+% \cs{galley_end_par:n} \Arg{tokens}
+% \end{syntax}
+% Adds the \meta{tokens} to the material collected for the last paragraph
+% before finalising the last paragraph in the usual way. This function should
+% therefore be the \emph{first} non-expandable entry used when a function
+% needs to add tokens to the preceding paragraph.
+% \end{function}
%
% \section{Internal variables}
%
@@ -641,6 +653,17 @@
\package_check_loaded_expl:
%</package>
% \end{macrocode}
+%
+% \subsection{TO BE MOVED}
+%
+% \begin{macro}{\scan_marker_new:N, \scan_marker_new:c}
+% Temporary: needs to go somewhere else if this concept is retained.
+% \begin{macrocode}
+\cs_new_protected:Npn \scan_marker_new:N #1
+ { \cs_new_eq:NN #1 \scan_stop: }
+\cs_generate_variant:Nn \scan_marker_new:N { c }
+% \end{macrocode}
+% \end{macro}
%
% \subsection{Support items}
%
@@ -755,11 +778,11 @@
% \begin{macrocode}
\bool_new:N \g_galley_begin_level_bool
\bool_new:N \l_galley_begin_level_bool
-\bool_gset_true:N \g_galley_begin_level_bool
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\g_galley_omit_next_indent_bool, \l_galley_omit_next_indent_bool}
+% \begin{variable}
+% {\g_galley_omit_next_indent_bool, \l_galley_omit_next_indent_bool}
% A global flag is needed for suppressing indentation of the next
% paragraph. This does not need a \enquote{running} version since that
% should be handled using the \texttt{justification} object: the two
@@ -907,9 +930,10 @@
\bool_gset_false:N \g_galley_parshape_set_bool
\int_gzero:N \g_galley_previous_par_lines_int
\tl_gclear:N \g_galley_restore_running_tl
- \tl_gclear:N \g_galley_whatsits_previous_tl
- \tl_gclear:N \g_galley_whatsits_next_tl
+ \tl_gclear:N \g_galley_whatsit_previous_tl
+ \tl_gclear:N \g_galley_whatsit_next_tl
}
+\galley_initialise_variables:
% \end{macrocode}
% \end{macro}
%
@@ -955,10 +979,10 @@
\g_galley_previous_par_lines_int
\tl_set_eq:NN \l_galley_restore_running_tl
\g_galley_restore_running_tl
- \tl_set_eq:NN \l_galley_whatsits_previous_tl
- \g_galley_whatsits_previous_tl
- \tl_set_eq:NN \l_galley_whatsits_next_tl
- \g_galley_whatsits_next_tl
+ \tl_set_eq:NN \l_galley_whatsit_previous_tl
+ \g_galley_whatsit_previous_tl
+ \tl_set_eq:NN \l_galley_whatsit_next_tl
+ \g_galley_whatsit_next_tl
}
\cs_new_protected_nopar:Npn \galley_restore_parameters:
{
@@ -984,10 +1008,10 @@
\l_galley_previous_par_lines_int
\tl_gset_eq:NN \g_galley_restore_running_tl
\l_galley_restore_running_tl
- \tl_gset_eq:NN \g_galley_whatsits_previous_tl
- \l_galley_whatsits_previous_tl
- \tl_gset_eq:NN \g_galley_whatsits_next_tl
- \l_galley_whatsits_next_tl
+ \tl_gset_eq:NN \g_galley_whatsit_previous_tl
+ \l_galley_whatsit_previous_tl
+ \tl_gset_eq:NN \g_galley_whatsit_next_tl
+ \l_galley_whatsit_next_tl
}
% \end{macrocode}
% \end{macro}
@@ -1025,13 +1049,46 @@
% \end{macro}
%
% \subsection{The \cs{par} token}
+%
+% \begin{variable}{\s_par_omit}
+% Used to indicate that a paragraph should be omitted.
+% \begin{macrocode}
+\scan_marker_new:N \s_par_omit
+% \end{macrocode}
+% \end{variable}
%
% \begin{macro}{\galley_std_par:}
-% In vertical mode, the standard paragraph insert is just the primitive
-% \cs{tex_par:D}.
+% \begin{macro}[aux]{\galley_std_par_aux_i:, \galley_std_par_aux_ii:}
+% \begin{macro}[aux]{\galley_std_par_aux:N}
+% The idea here is to expand the next token in exactly the same way as \TeX{}
+% would do anyway. The \texttt{f}-type expansion will ignore any protection,
+% but will stop at a scan marker. Thus the code can test for an
+% \enquote{omit paragraph} marker.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \galley_std_par:
{
+ \s_par_omit
+ \exp_after:wN \galley_std_par_aux_i: \tex_romannumeral:D - `0
+ }
+\cs_new_protected:Npn \galley_std_par_aux_i:
+ {
+ \peek_meaning:NTF \s_par_omit
+ { \galley_std_par_aux:N }
+ { \galley_std_par_aux_ii: }
+ }
+\cs_new_protected:Npn \galley_std_par_aux:N #1
+ {
+ \str_if_eq:xxF {#1} { \s_par_omit }
+ {
+ \galley_std_par_aux_ii:
+ #1
+ }
+ }
+% \end{macrocode}
+% No marker, so really insert a paragraph. In vertical mode,
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \galley_std_par_aux_ii:
+ {
\mode_if_vertical:TF
{ \tex_par:D }
% \end{macrocode}
@@ -1064,6 +1121,24 @@
}
% \end{macrocode}
% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\galley_end_par:n}
+% Inserts tokens such that they are appended to the end of the last
+% paragraph, using the paragraph-omitting system.
+% \begin{macrocode}
+\cs_new_protected:Npn \galley_end_par:n #1
+ {
+ \s_par_omit
+ \bool_if:nF \g_galley_begin_level_bool
+ {
+ #1
+ \galley_std_par:
+ }
+ }
+% \end{macrocode}
+% \end{macro}
%
% \begin{macro}{\par}
% The meaning of the token \cs{par} itself starts off as a standard
@@ -1375,14 +1450,14 @@
{
\g_galley_whatsit_next_tl
\tl_gclear:N \g_galley_whatsit_next_tl
- \bool_if:NT \g_galley_omit_next_indent_bool
+ \bool_if:NF \g_galley_omit_next_indent_bool
{
- \box_if_empty:NF \g_galley_last_box
+ \box_if_empty:NF \g_galley_last_box
{ \hbox_to_wd:nn \l_galley_par_indent_dim { } }
}
\skip_horizontal:N \l_galley_par_begin_skip
\g_galley_par_begin_hook_tl
- \bool_gset_true:N \g_galley_omit_next_indent_bool
+ \bool_gset_false:N \g_galley_omit_next_indent_bool
}
% \end{macrocode}
% \end{macro}
@@ -2066,16 +2141,57 @@
% \end{macro}
% \end{macro}
% \end{macro}
+%
%
-% \subsection{\LaTeXe{} fixes}
-%
+% \subsection{\LaTeXe{} functions}
+%
% \begin{macrocode}
%<*package>
% \end{macrocode}
%
+% \begin{macro}{\nobreak}
+% \begin{macro}{\noindent}
+% \begin{macro}{\vspace}
+% In package mode, some of \LaTeXe{}'s functions are re-implemented using
+% the galley system. Not all of the optional arguments currently work!
+% \begin{macrocode}
+\cs_set_protected_nopar:Npn \nobreak
+ { \bool_gset_true:N \g_galley_no_break_next_bool }
+% \end{macrocode}
+% The \tn{noindent} primitive will causes problems, as it is used by
+% \LaTeXe{} documents to implicitly leave vertical mode as well as to
+% prevent indentation. Rather than patch \emph{every} place where we
+% need leave vertical mode, at the moment we stick with the primitive as
+% well as setting the galley flag.
+% \begin{macrocode}
+\cs_set_protected_nopar:Npn \noindent
+ {
+ \tex_noindent:D
+ \bool_gset_false:N \g_galley_omit_next_indent_bool
+ }
+\cs_set_protected_nopar:Npn \vspace #1
+ {
+ \@ifstar
+ { \galley_set_user_vspace:n {#1} }
+ { \galley_set_user_vspace:n {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{\LaTeXe{} fixes}
+%
% Purely for testing, some internal \LaTeXe{} functions are altered to work
% with the mechanism here. This material is not comprehensive: additions are
% made as-needed for test purposes.
+%
+% \begin{macro}{\@@par}
+% The primitive is moved as otherwise the clever skipping code will fail.
+% \begin{macrocode}
+\cs_set_eq:NN \@@par \galley_std_par:
+% \end{macrocode}
+% \end{macro}
%
% \begin{macro}{\@afterheading}
% Set some flags and hope for the best!
@@ -2098,6 +2214,8 @@
% \begin{macrocode}
\cs_set_protected:Npn \@hangfrom #1
{
+ \bool_gset_true:N \g_galley_omit_next_indent_bool
+ \leavevmode
\setbox \@tempboxa = \hbox { {#1} }
\galley_parshape_single_par:nnnN
\c_one
@@ -2105,28 +2223,12 @@
\c_zero_dim
\c_false_bool
\bool_gset_true:N \g_galley_no_break_next_bool
- \bool_gset_true:N \galley_omit_next_indent_bool
+ \bool_gset_true:N \g_galley_omit_next_indent_bool
\box \@tempboxa
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\@makefntext}
-% Here, the paragraph indent is set up using the template system, and
-% as in other places the code ensures that the label is set in horizontal
-% mode. The flag used for omitting the indent is once again the galley
-% one.
-% \begin{macrocode}
-\cs_set_protected:Npn \@makefntext #1
- {
- \UseTemplate { justification } { std } { indent-width = 1 em }
- \bool_gset_true:N \galley_omit_next_indent_bool
- \galley_leave_vmode:
- \hb@xt@ 1.8em { \hss \@makefnmark } #1
- }
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macrocode}
%</package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx b/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx
index 0dc1c85b610..f573668fde8 100644
--- a/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx
+++ b/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx
@@ -37,7 +37,7 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: xgalley.dtx 2895 2011-10-09 15:58:19Z joseph $
+\GetIdInfo$Id: xgalley.dtx 2922 2011-10-17 19:01:04Z joseph $
{L3 Experimental galley}
%</driver|package>
%<*driver>
@@ -1575,24 +1575,6 @@
}
% \end{macrocode}
%
-% \subsection{\LaTeXe{} functions}
-%
-% \begin{macro}{\nobreak}
-% \begin{macro}{\noindent}
-% \begin{macro}{\vspace}
-% In package mode, some of \LaTeXe{}'s functions are re-implemented using
-% the galley system. Not all of the optional arguments currently work!
-% \begin{macrocode}
-\RenewDocumentCommand \nobreak { }
- { \bool_gset_true:N \g_galley_no_break_next_bool }
-\RenewDocumentCommand \noindent { }
- { \bool_gset_false:N \g_galley_omit_next_indent_bool }
-\RenewDocumentCommand \vspace { s m } { \galley_set_vspace_user:n {#2} }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
% \begin{macrocode}
%</package>
% \end{macrocode}
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty
index 29045fcdea9..07d568d94e9 100644
--- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty
+++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty
@@ -46,113 +46,121 @@
%%
%% -----------------------------------------------------------------------
\RequirePackage{expl3}
-\GetIdInfo$Id: l3regex.dtx 2895 2011-10-09 15:58:19Z joseph $
+\GetIdInfo$Id: l3regex.dtx 2943 2011-10-30 15:59:43Z bruno $
{L3 Experimental Regular Expressions}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
\RequirePackage{l3str}
+\int_const:Nn \c_forty_eight { 48 }
+\int_const:Nn \c_fifty_eight { 58 }
+\int_const:Nn \c_sixty_five { 65 }
+\int_const:Nn \c_ninety_one { 91 }
+\int_const:Nn \c_ninety_seven { 97 }
+\int_const:Nn \c_one_hundred_twenty_three { 123 }
+\int_const:Nn \c_one_hundred_twenty_seven { 127 }
\cs_new:Npn \regex_tmp:w { }
\tl_new:N \g_regex_tmpa_tl
\tl_new:N \l_regex_tmpa_tl
\tl_new:N \l_regex_tmpb_tl
\int_new:N \l_regex_tmpa_int
-\tl_new:N \l_regex_pattern_str
+\int_new:N \l_regex_tmpb_int
\int_new:N \l_regex_max_state_int
\int_new:N \l_regex_left_state_int
\int_new:N \l_regex_right_state_int
-\seq_new:N \l_regex_left_state_seq
-\seq_new:N \l_regex_right_state_seq
+\seq_new:N \l_regex_group_begin_seq
+\seq_new:N \l_regex_group_end_seq
\int_new:N \l_regex_capturing_group_int
\seq_new:N \l_regex_capturing_group_seq
\tl_new:N \l_regex_one_or_group_tl
-\int_new:N \l_regex_repetition_int
-\bool_new:N \l_regex_look_behind_bool
-\tl_new:N \l_regex_look_behind_str
\cs_new_eq:NN \regex_build_tmp_class:n \use_none:n
\bool_new:N \l_regex_class_bool
\tl_new:N \l_regex_class_tl
\tl_const:Nn \c_regex_d_tl
{
- \regex_item_range:nn {48} {57} % 0--9
+ \regex_item_range:nn { \c_forty_eight } { 57 } % 0--9
}
\tl_const:Nn \c_regex_D_tl
{
- \regex_item_more:n {57} % 9
- \regex_item_range:nn {0} {47} % 0
+ \regex_item_geq:n { \c_fifty_eight } % > `9
+ \regex_item_range:nn { \c_zero } { 47 } % 0
}
\tl_const:Nn \c_regex_h_tl
{
- \regex_item_equal:n {32} % space
- \regex_item_equal:n {9} % tab
+ \regex_item_equal:n { \c_thirty_two } % space
+ \regex_item_equal:n { \c_nine } % tab
}
\tl_const:Nn \c_regex_H_tl
{
- \regex_item_neq:n {32} % space
- \regex_item_neq:n {9} % tab
- \regex_break_true:w
+ \regex_item_geq:n { 33 } % > space
+ \regex_item_range:nn { \c_ten } { 31 } % tab < ... < space
+ \regex_item_range:nn { \c_zero } { \c_eight } % < tab
}
\tl_const:Nn \c_regex_s_tl
{
- \regex_item_equal:n {32} % space
- \regex_item_neq:n {11} % vtab
- \regex_item_range:nn {9} {13} % tab, lf, vtab, ff, cr
+ \regex_item_equal:n { \c_thirty_two } % space
+ \regex_item_range:nn { \c_nine } { \c_ten } % tab, lf
+ \regex_item_range:nn { \c_twelve } { \c_thirteen } % ff, cr
}
\tl_const:Nn \c_regex_S_tl
{
- \regex_item_more:n {32} % > space
- \regex_item_range:nn {14} {31} % tab < ... < space
- \regex_item_range:nn {0} {8} % < tab
- \regex_item_equal:n {11} % vtab
+ \regex_item_geq:n { 33 } % > space
+ \regex_item_range:nn { \c_fourteen } { 31 } % tab < ... < space
+ \regex_item_range:nn { \c_zero } { \c_eight } % < tab
+ \regex_item_equal:n { \c_eleven } % vtab
}
\tl_const:Nn \c_regex_v_tl
{
- \regex_item_range:nn {10} {13} % lf, vtab, ff, cr
+ \regex_item_range:nn { \c_ten } { \c_thirteen } % lf, vtab, ff, cr
}
\tl_const:Nn \c_regex_V_tl
{
- \regex_item_more:n {13} % cr
- \regex_item_range:nn {0} {9} % < lf
+ \regex_item_geq:n { \c_fourteen } % >cr
+ \regex_item_range:nn { \c_zero } { \c_nine } % < lf
}
\tl_const:Nn \c_regex_w_tl
{
- \regex_item_range:nn {97} {122} % a--z
- \regex_item_range:nn {65} {90} % A--Z
- \regex_item_range:nn {48} {57} % 0--9
- \regex_item_equal:n {95} % _
+ \regex_item_range:nn { \c_ninety_seven } { 122 } % a--z
+ \regex_item_range:nn { \c_sixty_five } { 90 } % A--Z
+ \regex_item_range:nn { \c_forty_eight } { 57 } % 0--9
+ \regex_item_equal:n { 95 } % _
}
\tl_const:Nn \c_regex_W_tl
{
- \regex_item_range:nn {0} {47} % <`0
- \regex_item_range:nn {58} {64} % (`9+1)--(`A-1)
- \regex_item_range:nn {91} {94} % (`Z+1)--(`_-1)
- \regex_item_equal:n {96} % `
- \regex_item_more:n {122} % z
+ \regex_item_range:nn { \c_zero } { 47 } % <`0
+ \regex_item_range:nn { \c_fifty_eight } { 64 } % (`9+1)--(`A-1)
+ \regex_item_range:nn { \c_ninety_one } { 94 } % (`Z+1)--(`_-1)
+ \regex_item_equal:n { 96 } % `
+ \regex_item_geq:n { \c_one_hundred_twenty_three } % z
}
\tl_const:Nn \c_regex_N_tl
{
- \regex_item_neq:n {10} % lf
- \regex_break_true:w
+ \regex_item_geq:n { \c_eleven } % > lf
+ \regex_item_range:nn { \c_zero } { \c_nine } % < lf
}
-\tl_new:N \l_regex_query_str
-\int_new:N \l_regex_start_step_int
-\int_new:N \l_regex_current_char_int
+\tl_new:N \l_regex_query_other_str
\int_new:N \l_regex_current_step_int
+\int_new:N \l_regex_start_step_int
+\int_new:N \l_regex_success_step_int
\int_new:N \l_regex_unique_step_int
+\int_new:N \l_regex_current_char_int
+\int_new:N \l_regex_last_char_int
+\int_new:N \l_regex_case_changed_char_int
+\bool_new:N \l_regex_caseless_bool
\int_new:N \l_regex_current_state_int
\prop_new:N \l_regex_current_submatches_prop
+\prop_new:N \l_regex_success_submatches_prop
\int_new:N \l_regex_max_index_int
\tl_new:N \l_regex_every_match_tl
+\bool_new:N \l_regex_success_bool
\cs_new_protected:Npn \regex_last_match_empty_no:F #1 {#1}
\cs_new_protected:Npn \regex_last_match_empty_yes:F
{ \int_compare:nNnF \l_regex_start_step_int = \l_regex_current_step_int }
\cs_new_eq:NN \regex_last_match_empty:F \regex_last_match_empty_no:F
-\bool_new:N \l_regex_success_bool
\bool_new:N \l_regex_success_empty_bool
-\int_new:N \l_regex_success_step_int
-\prop_new:N \l_regex_success_submatches_prop
\bool_new:N \l_regex_fresh_thread_bool
\seq_new:N \g_regex_submatches_seq
\int_new:N \g_regex_match_count_int
+\seq_new:N \g_regex_extract_all_seq
\seq_new:N \g_regex_split_seq
\tl_new:N \l_regex_replacement_tl
\tl_new:N \g_regex_replaced_str
@@ -169,40 +177,43 @@
\tex_toks:D #1 \exp_after:wN
{ \tex_the:D \tex_toks:D \exp_after:wN #1 \regex_tmp:w }
}
-\cs_new_eq:NN \regex_if_tail_stop:N \quark_if_recursion_tail_stop:N
-\cs_new_protected_nopar:Npn \regex_if_tail_error:Nn #1#2
- { \quark_if_recursion_tail_stop_do:Nn #1 { \regex_build_error:n {#2} } }
-\cs_new_protected_nopar:Npn \regex_build_error:n #1
+\cs_new_nopar:Npn \regex_query_substr:NN #1#2
{
- \msg_error:nnxx { regex } { build-error } {\int_eval:n{#1}}
- {
- \prg_case_int:nnn {#1}
- {
- {-999} {File~not~found}
- {-998} {Unsupported~construct}
- {-997} {The~regular~expression~is~too~large~(32768~states).}
- {1} {\iow_char:N\\~at~end~of~pattern }
- {4} {Numbers~out~of~order~in~\iow_char:N\{\iow_char\}~quantifier.}
- {6} {Missing~terminating~\iow_char:N\]~for~character~class }
- {7} {Invalid~escape~sequence~in~character~class}
- {8} {Range~out~of~order~in~character~class}
- {22} {Mismatched~parentheses}
- {34} {Character~value~in~\iow_char:N\\x{...}~sequence~is~too~large}
- }
- { Internal~bug. }
- }
+ \exp_after:wN \regex_query_substr_aux:NN
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \l_regex_query_other_str
+ \q_stop
+ }
+\cs_new:Npn \regex_query_substr_aux:NN #1#2
+ {
+ \str_skip_do:nn {#1}
+ { \str_collect_do:nn { #2 - #1 } { \use_i_delimit_by_q_stop:nw } }
+ }
+\cs_new_protected_nopar:Npn \regex_seq_pop:N #1
+ {
+ \seq_pop:NN #1 \l_regex_tmpa_tl
+ \l_regex_tmpa_tl
+ }
+\cs_new_protected_nopar:Npn \regex_seq_get:N #1
+ {
+ \seq_get:NN #1 \l_regex_tmpa_tl
+ \l_regex_tmpa_tl
}
-\msg_new:nnn { regex } { build-error } { (error~#1): ~ #2 }
-\cs_new_nopar:Npn \regex_break_true:w #1 \regex_break_point:TF #2 #3 {#2}
-\cs_new_nopar:Npn \regex_break_false:w #1 \regex_break_point:TF #2 #3 {#3}
-\cs_new_eq:NN \regex_break_point:TF \use_ii:nn
-\cs_new_nopar:Npn \regex_item_equal:n #1
+\cs_new_protected_nopar:Npn \regex_item_dot:T
+ { \int_compare:nNnF \l_regex_current_char_int = \c_minus_one }
+\cs_new_protected_nopar:Npn \regex_break_true:w
+ #1 \regex_break_point:TF #2 #3 {#2}
+\cs_new_protected_nopar:Npn \regex_break_false:w
+ #1 \regex_break_point:TF #2 #3 {#3}
+\cs_new_protected_nopar:Npn \regex_break_point:TF #1 #2 { #2 }
+\cs_new_protected_nopar:Npn \regex_item_caseful_equal:n #1
{
\if_num:w #1 = \l_regex_current_char_int
\exp_after:wN \regex_break_true:w
\fi:
}
-\cs_new_nopar:Npn \regex_item_range:nn #1 #2
+\cs_new_protected_nopar:Npn \regex_item_caseful_range:nn #1 #2
{
\reverse_if:N \if_num:w #1 > \l_regex_current_char_int
\reverse_if:N \if_num:w #2 < \l_regex_current_char_int
@@ -210,24 +221,60 @@
\fi:
\fi:
}
-\cs_new_nopar:Npn \regex_item_less:n #1
+\cs_new_protected_nopar:Npn \regex_item_caseful_geq:n #1
{
- \if_num:w #1 > \l_regex_current_char_int
+ \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
\exp_after:wN \regex_break_true:w
\fi:
}
-\cs_new_nopar:Npn \regex_item_more:n #1
+\cs_new_protected_nopar:Npn \regex_item_caseless_equal:n #1
{
- \if_num:w #1 < \l_regex_current_char_int
+ \if_num:w #1 = \l_regex_current_char_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ \if_num:w #1 = \l_regex_case_changed_char_int
\exp_after:wN \regex_break_true:w
\fi:
}
-\cs_new_nopar:Npn \regex_item_neq:n #1
+\cs_new_protected_nopar:Npn \regex_item_caseless_range:nn #1 #2
{
- \if_num:w #1 = \l_regex_current_char_int
- \exp_after:wN \regex_break_false:w
+ \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
+ \reverse_if:N \if_num:w #2 < \l_regex_current_char_int
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
+ \fi:
+ \fi:
+ \reverse_if:N \if_num:w #1 > \l_regex_case_changed_char_int
+ \reverse_if:N \if_num:w #2 < \l_regex_case_changed_char_int
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
+ \fi:
\fi:
}
+\cs_new_protected_nopar:Npn \regex_item_caseless_geq:n #1
+ {
+ \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ \reverse_if:N \if_num:w #1 > \l_regex_case_changed_char_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ }
+\cs_new:Npn \regex_item_equal:n { \regex_item_caseful_equal:n }
+\cs_new:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
+\cs_new:Npn \regex_item_geq:n { \regex_item_caseful_geq:n }
+\cs_new_protected_nopar:Npn \regex_build_caseless:
+ {
+ \bool_set_true:N \l_regex_caseless_bool
+ \cs_set:Npn \regex_item_equal:n { \regex_item_caseless_equal:n }
+ \cs_set:Npn \regex_item_range:nn { \regex_item_caseless_range:nn }
+ \cs_set:Npn \regex_item_geq:n { \regex_item_caseless_geq:n }
+ }
+\cs_new_protected_nopar:Npn \regex_build_caseful:
+ {
+ \bool_set_false:N \l_regex_caseless_bool
+ \cs_set:Npn \regex_item_equal:n { \regex_item_caseful_equal:n }
+ \cs_set:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
+ \cs_set:Npn \regex_item_geq:n { \regex_item_caseful_geq:n }
+ }
\cs_new_protected:Npn \regex_get_digits:nw #1
{
\tex_afterassignment:D \regex_tmp:w
@@ -235,65 +282,71 @@
{
\exp_not:n {#1}
{ \if_false: } } \fi:
- \regex_get_digits_aux:N
+ \regex_get_digits_aux:NN
}
-\cs_new_nopar:Npn \regex_get_digits_aux:N #1
+\cs_new_nopar:Npn \regex_get_digits_aux:NN #1#2
{
- \if_num:w 9 < 1 \exp_not:N #1 \exp_stop_f:
- \else:
- \if_charcode:w \c_space_token \exp_not:N #1
+ \if_meaning:w \regex_build_raw:N #1
+ \if_charcode:w \c_space_token \exp_not:N #2
\else:
- \regex_get_digits_end:w
+ \if_num:w 9 < 1 \exp_not:N #2 \exp_stop_f:
+ #2
+ \else:
+ \regex_get_digits_end:w #1 #2
+ \fi:
\fi:
+ \else:
+ \regex_get_digits_end:w #1 #2
\fi:
- #1 \regex_get_digits_aux:N
+ \regex_get_digits_aux:NN
}
-\cs_new_nopar:Npn \regex_get_digits_end:w
- \fi: \fi: #1 \regex_get_digits_aux:N
+\cs_new_nopar:Npn \regex_get_digits_end:w #1 \fi: #2 \regex_get_digits_aux:NN
{
- \fi: \fi:
+ \fi: #2
\if_false: { { \fi: } }
#1
}
+\prg_new_conditional:Npnn \regex_token_if_other_digit:N #1 { TF }
+ {
+ \if_num:w \c_nine < 1 \exp_not:N #1 \exp_stop_f:
+ \prg_return_true: \else: \prg_return_false: \fi:
+ }
\prg_new_conditional:Npnn \regex_aux_char_if_special:N #1 { TF }
{
- \if_num:w `#1 < 97 \exp_stop_f:
- \if_num:w `#1 < 58 \exp_stop_f:
- \if_num:w \int_eval:w (`#1 - \c_eight)/\c_sixteen = \c_two
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
+ \if_num:w `#1 < \c_ninety_one
+ \if_num:w `#1 < \c_fifty_eight
+ \if_num:w `#1 < \c_forty_eight
+ \if_num:w `#1 < \c_thirty_two
+ \prg_return_false: \else: \prg_return_true: \fi:
+ \else: \prg_return_false: \fi:
\else:
- \if_num:w \int_eval:w `#1 / 26 = \c_three
- \prg_return_false:
- \else:
- \prg_return_true:
- \fi:
+ \if_num:w `#1 < \c_sixty_five
+ \prg_return_true: \else: \prg_return_false: \fi:
\fi:
\else:
- \if_num:w \int_eval:w `#1 / \c_five = 25 \exp_stop_f:
- \prg_return_true:
+ \if_num:w `#1 < \c_one_hundred_twenty_three
+ \if_num:w `#1 < \c_ninety_seven
+ \prg_return_true: \else: \prg_return_false: \fi:
\else:
- \prg_return_false:
+ \if_num:w `#1 < \c_one_hundred_twenty_seven
+ \prg_return_true: \else: \prg_return_false: \fi:
\fi:
\fi:
}
\prg_new_conditional:Npnn \regex_aux_char_if_alphanumeric:N #1 { TF }
{
- \if_num:w `#1 < 91 \exp_stop_f:
- \if_num:w `#1 < 65 \exp_stop_f:
- \if_num:w \c_nine < 1 #1 \exp_stop_f:
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
+ \if_num:w `#1 < \c_ninety_one
+ \if_num:w `#1 < \c_fifty_eight
+ \if_num:w `#1 < \c_forty_eight
+ \prg_return_false: \else: \prg_return_true: \fi:
\else:
- \prg_return_true:
+ \if_num:w `#1 < \c_sixty_five
+ \prg_return_false: \else: \prg_return_true: \fi:
\fi:
\else:
- \if_num:w \int_eval:w (`#1-\c_six)/26 = \c_four
- \prg_return_true:
+ \if_num:w `#1 < \c_one_hundred_twenty_three
+ \if_num:w `#1 < \c_ninety_seven
+ \prg_return_false: \else: \prg_return_true: \fi:
\else:
\prg_return_false:
\fi:
@@ -301,8 +354,8 @@
}
\cs_new_protected_nopar:Npn \regex_build_new_state:
{
- \int_compare:nNnTF \l_regex_max_state_int > {32766}
- { \regex_build_error:n {-997} }
+ \int_compare:nNnTF \l_regex_max_state_int > { 32766 }
+ { \msg_error:nn { regex } { -997 } }
{
\int_incr:N \l_regex_max_state_int
\tex_toks:D \l_regex_max_state_int { \s_regex_toks }
@@ -314,15 +367,15 @@
{
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
- { #1 { \int_use:N #2 } }
+ { #1 { \int_eval:n { #2 - \l_regex_left_state_int } } }
}
\cs_new_protected_nopar:Npn \regex_build_transitions_aux:NNNN #1#2#3#4
{
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
{
- #1 { \int_use:N #2 }
- #3 { \int_use:N #4 }
+ #1 { \int_eval:n { #2 - \l_regex_left_state_int } }
+ #3 { \int_eval:n { #4 - \l_regex_left_state_int } }
}
}
\cs_new_protected:Npn \regex_build:n #1
@@ -363,25 +416,19 @@
\cs_set_eq:NN \regex_build_control:N \regex_build_default_control:N
\cs_set_eq:NN \regex_build_raw:N \regex_build_default_raw:N
\int_set_eq:NN \l_regex_capturing_group_int \c_zero
- \int_zero:N \l_regex_left_state_int
- \int_zero:N \l_regex_right_state_int
\int_zero:N \l_regex_max_state_int
\regex_build_new_state:
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
- {
- \regex_action_start_wildcard:nn
- { \int_use:N \l_regex_left_state_int }
- { \int_use:N \l_regex_right_state_int }
- }
+ { \regex_action_start_wildcard:nn {0} {1} }
}
\cs_new_protected_nopar:Npn \regex_build_end:
{
\seq_if_empty:NF \l_regex_capturing_group_seq
{
- \regex_build_error:n {22}
+ \msg_error:nn { regex } {22}
\prg_replicate:nn
- { \seq_length:N \l_regex_capturing_group_seq } % (
+ { \seq_length:N \l_regex_capturing_group_seq }
{ \regex_build_close_aux: \regex_build_group_: }
}
\regex_toks_put_right:Nx \l_regex_right_state_int
@@ -399,7 +446,13 @@
\regex_toks_put_right:Nx \l_regex_left_state_int
{
\exp_not:N \int_compare:nNnT {#1} = \l_regex_current_step_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
}
\cs_new_protected_nopar:cpn { regex_build_$: } % $
@@ -409,71 +462,72 @@
{
\exp_not:N \int_compare:nNnT
\c_minus_one = \l_regex_current_char_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
}
\cs_new_eq:Nc \regex_build_Z: { regex_build_$: } %$
\cs_new_eq:Nc \regex_build_z: { regex_build_$: } %$
\cs_new_protected_nopar:Npn \regex_build_b:
{
- \bool_set_true:N \l_regex_look_behind_bool
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
{
\exp_not:N \regex_if_word_boundary:TF
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
{ }
}
}
\cs_new_protected_nopar:Npn \regex_build_B:
{
- \bool_set_true:N \l_regex_look_behind_bool
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
{
\exp_not:N \regex_if_word_boundary:TF
{ }
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
}
\cs_new_protected_nopar:Npn \regex_if_word_boundary:TF
{
- \tl_if_empty:NTF \l_regex_look_behind_str
- { \c_regex_w_tl }
- {
- \group_begin:
- \cs_set_nopar:Npx \regex_tmp:w
- {
- \int_set:Nn \l_regex_current_char_int
- { ` \str_head:N \l_regex_look_behind_str }
- }
- \regex_tmp:w
- \c_regex_w_tl
- \regex_break_point:TF
- { \group_end: \c_regex_W_tl }
- { \group_end: \c_regex_w_tl }
- }
+ \group_begin:
+ \int_set_eq:NN \l_regex_current_char_int \l_regex_last_char_int
+ \c_regex_w_tl
+ \regex_break_point:TF
+ { \group_end: \c_regex_W_tl \regex_item_equal:n { -1 } }
+ { \group_end: \c_regex_w_tl }
\regex_break_point:TF
}
\cs_new_protected_nopar:Npn \regex_build_default_raw:N #1
{
\cs_set:Npx \regex_build_tmp_class:n ##1
{
- \exp_not:n { \exp_not:N \if_num:w }
- \int_value:w `#1 = \l_regex_current_char_int
- \regex_action_cost:n { ##1 }
- \exp_not:n { \exp_not:N \fi: }
+ \regex_item_equal:n { \int_value:w `#1 }
+ \regex_break_point:TF { \regex_action_cost:n { ##1 } } { }
}
\regex_build_one_quantifier:
}
\cs_new_protected_nopar:cpn { regex_build_.: }
{
\cs_set:Npn \regex_build_tmp_class:n ##1
- {
- \exp_not:N \if_num:w \c_minus_one < \l_regex_current_char_int
- \regex_action_cost:n {##1}
- \exp_not:N \fi:
- }
+ { \regex_item_dot:T { \regex_action_cost:n {##1} } }
\regex_build_one_quantifier:
}
\cs_new_protected_nopar:Npn \regex_build_char_type:N #1
@@ -481,9 +535,7 @@
\cs_set:Npn \regex_build_tmp_class:n ##1
{
\exp_not:N #1
- \exp_not:N \regex_break_point:TF
- { \regex_action_cost:n {##1} }
- { }
+ \regex_break_point:TF { \regex_action_cost:n {##1} } { }
}
\regex_build_one_quantifier:
}
@@ -518,16 +570,8 @@
{
\exp_not:o \l_regex_class_tl
\bool_if:NTF \l_regex_class_bool
- {
- \exp_not:N \regex_break_point:TF
- { \regex_action_cost:n {##1} }
- { }
- }
- {
- \exp_not:N \regex_break_point:TF
- { }
- { \regex_action_cost:n {##1} }
- }
+ { \regex_break_point:TF { \regex_action_cost:n {##1} } { } }
+ { \regex_break_point:TF { } { \regex_action_cost:n {##1} } }
}
\regex_build_one_quantifier:
}
@@ -553,7 +597,7 @@
\cs_new_protected_nopar:Npn \regex_class_single:N #1
{
\tl_put_right:Nx \l_regex_class_tl
- { \exp_not:N \regex_item_equal:n { \int_value:w `#1 } }
+ { \regex_item_equal:n { \int_value:w `#1 } }
}
\cs_new_protected_nopar:Npn \regex_class_range:Nw #1#2#3
{
@@ -572,14 +616,14 @@
\cs_new_protected_nopar:Npn \regex_class_range_put:NN #1#2
{
\if_num:w `#1 > `#2 \exp_stop_f:
- \regex_build_error:n {8}
+ \msg_error:nn { regex } {8}
\else:
\tl_put_right:Nx \l_regex_class_tl
{
\if_num:w `#1 = `#2 \exp_stop_f:
- \exp_not:N \regex_item_equal:n
+ \regex_item_equal:n
\else:
- \exp_not:N \regex_item_range:nn { \int_value:w `#1 }
+ \regex_item_range:nn { \int_value:w `#1 }
\fi:
{ \int_value:w `#2 }
}
@@ -651,26 +695,29 @@
\exp_not:N \regex_build_raw:N \c_lbrace_str #1#2
}
}
-\cs_new_protected_nopar:Npn \regex_build_quantifier_lbrace:nnw #1#2#3
+\cs_new_protected_nopar:Npn \regex_build_quantifier_lbrace:nnw #1#2#3#4
{
- \str_if_eq:xxTF { \exp_not:N #3 } { \c_rbrace_str }
+ \str_if_eq:xxTF
+ { \exp_not:n {#3#4} }
+ { \exp_not:N \regex_build_control:N \c_rbrace_str }
{
\tl_if_empty:nTF {#2}
- { \regex_build_quantifier_aux:nnN { {#1} {\c_max_int} } {nn} }
+ { \regex_build_quantifier_aux:nnNN { {#1} } { n* } }
{
\int_compare:nNnT {#1} > {#2}
- { \regex_build_error:n {4} }
- \regex_build_quantifier_aux:nnN { {#1} {#2} } {nn}
+ { \msg_error:nn { regex } {4} }
+ \regex_build_quantifier_aux:nnNN { {#1} {#2} } { nn }
}
}
{
\regex_build_quantifier_end:n { }
\use:x
{
- \exp_not:n { \exp_args:No \tl_map_function:nN }
- { \c_lbrace_str #1 #2 , }
- \regex_build_raw:N
+ \exp_args:No \tl_map_function:nN
+ { \c_lbrace_str #1 , #2 }
+ \regex_build_raw:N
}
+ #3 #4
}
}
\cs_new_protected_nopar:Npn \regex_build_quantifier_end:n #1
@@ -726,71 +773,27 @@
\regex_action_free:n \l_regex_tmpa_int
}
\cs_new_protected_nopar:Npn \regex_build_one_n: #1
- {
- \int_set_eq:NN \l_regex_tmpa_int \l_regex_right_state_int
- \regex_build_new_state:
- \regex_build_new_state:
- \regex_toks_put_right:Nx \l_regex_tmpa_int
- { %^^A safe \if nesting?
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \regex_action_repeat_move:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \else:
- \regex_action_no_repeat_move:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \fi:
- }
- \regex_toks_put_right:Nx \l_regex_left_state_int
- {
- \regex_build_tmp_class:n
- { \int_use:N \l_regex_tmpa_int }
- }
- }
+ { \prg_replicate:nn {#1} { \regex_build_one_: } }
\cs_new_eq:cN { regex_build_one_n?: } \regex_build_one_n:
-\cs_new_protected_nopar:Npn \regex_build_one_nn: #1#2
+\cs_new_protected_nopar:cpx { regex_build_one_n*: } #1
{
- \regex_build_one_nn_aux:nn {#1}
- {
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \regex_action_repeat_copy:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \fi:
- \regex_action_no_repeat_move:n
- { \int_use:N \l_regex_right_state_int }
- }
+ \exp_not:N \prg_replicate:nn {#1} { \exp_not:N \regex_build_one_: }
+ \exp_not:c { regex_build_one_*: }
}
-\cs_new_protected_nopar:cpn { regex_build_one_nn?: } #1#2
+\cs_new_protected_nopar:cpx { regex_build_one_n*?: } #1
{
- \regex_build_one_nn_aux:nn {#1}
- {
- \regex_action_no_repeat_copy:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \regex_action_repeat_move:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \fi:
- }
+ \exp_not:N \prg_replicate:nn {#1} { \exp_not:N \regex_build_one_: }
+ \exp_not:c { regex_build_one_*?: }
}
-\cs_new_protected_nopar:Npn \regex_build_one_nn_aux:nn #1#2
+\cs_new_protected_nopar:Npn \regex_build_one_nn_aux:Nnn #1#2#3
{
- \int_set_eq:NN \l_regex_tmpa_int \l_regex_right_state_int
- \regex_build_new_state:
- \regex_build_new_state:
- \regex_toks_put_right:Nx \l_regex_tmpa_int
- {
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \regex_action_repeat_move:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \else:
- #2
- \exp_not:N \fi:
- }
- \regex_toks_put_right:Nx \l_regex_left_state_int
- {
- \regex_build_tmp_class:n
- { \int_use:N \l_regex_tmpa_int }
- }
+ \prg_replicate:nn {#2} { \regex_build_one_: }
+ \prg_replicate:nn {#3-#2} {#1}
}
+\cs_new_protected_nopar:Npx \regex_build_one_nn:
+ { \regex_build_one_nn_aux:Nnn \exp_not:c { regex_build_one_?: } }
+\cs_new_protected_nopar:cpx { regex_build_one_nn?: }
+ { \regex_build_one_nn_aux:Nnn \exp_not:c { regex_build_one_??: } }
\cs_new_protected_nopar:cpn { regex_build_(: } #1#2
{
\str_if_eq:nnTF { #1 #2 } { \regex_build_control:N ? }
@@ -806,10 +809,19 @@
\cs_new_protected_nopar:Npn \regex_build_open_aux:
{
\regex_build_new_state:
- \seq_push:Nx \l_regex_left_state_seq
- { \int_use:N \l_regex_left_state_int }
- \seq_push:Nx \l_regex_right_state_seq
- { \int_use:N \l_regex_right_state_int }
+ \seq_push:Nx \l_regex_group_begin_seq
+ {
+ \int_set:Nn \l_regex_left_state_int
+ { \int_use:N \l_regex_left_state_int }
+ }
+ \bool_if:NTF \l_regex_caseless_bool
+ { \seq_push:Nn \l_regex_group_end_seq { \regex_build_caseless: } }
+ { \seq_push:Nn \l_regex_group_end_seq { \regex_build_caseful: } }
+ \seq_push:Nx \l_regex_group_end_seq
+ {
+ \int_set:Nn \l_regex_right_state_int
+ { \int_use:N \l_regex_right_state_int }
+ }
\regex_build_begin_alternation:
}
\cs_new_protected_nopar:cpn { regex_build_|: }
@@ -820,7 +832,7 @@
\cs_new_protected_nopar:cpn { regex_build_): }
{
\seq_if_empty:NTF \l_regex_capturing_group_seq
- { \regex_build_error:n {22} }
+ { \msg_error:nn { regex } { 22 } }
{
\regex_build_close_aux:
\regex_build_group_quantifier:
@@ -829,30 +841,41 @@
\cs_new_protected_nopar:Npn \regex_build_close_aux:
{
\regex_build_end_alternation:
- \seq_pop:NN \l_regex_left_state_seq \l_regex_tmpa_tl
- \int_set:Nn \l_regex_left_state_int \l_regex_tmpa_tl
- \seq_pop:NN \l_regex_right_state_seq \l_regex_tmpa_tl
- \int_set:Nn \l_regex_right_state_int \l_regex_tmpa_tl
+ \regex_seq_pop:N \l_regex_group_begin_seq
+ \regex_seq_pop:N \l_regex_group_end_seq
+ \regex_seq_pop:N \l_regex_group_end_seq
}
\cs_new_protected_nopar:Npn \regex_build_begin_alternation:
{
\regex_build_new_state:
- \seq_get:NN \l_regex_left_state_seq \l_regex_tmpa_tl
- \int_set:Nn \l_regex_left_state_int \l_regex_tmpa_tl
+ \regex_seq_get:N \l_regex_group_begin_seq
\regex_toks_put_right:Nx \l_regex_left_state_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
\cs_new_protected_nopar:Npn \regex_build_end_alternation:
{
- \seq_get:NN \l_regex_right_state_seq \l_regex_tmpa_tl
- \regex_toks_put_right:Nx \l_regex_right_state_int
- { \regex_action_free:n { \l_regex_tmpa_tl } }
+ \int_set_eq:NN \l_regex_left_state_int \l_regex_right_state_int
+ \regex_seq_get:N \l_regex_group_end_seq
+ \regex_toks_put_right:Nx \l_regex_left_state_int
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
\cs_new_protected_nopar:Npn \regex_build_special_group:NN #1#2
{
\cs_if_exist_use:cF { regex_build_special_group_\token_to_str:N #2 : }
{
- \regex_build_error:n { -998 }
+ \msg_error:nn { regex } { -998 }
\regex_build_control:N ( % )
\regex_build_raw:N ?
#1 #2
@@ -863,6 +886,40 @@
\seq_push:Nx \l_regex_capturing_group_seq { * }
\regex_build_open_aux:
}
+\cs_new_protected_nopar:Npn \regex_build_special_group_i:
+ {
+ \regex_build_options:NNN +
+ \regex_build_raw:N i
+ }
+\cs_new_protected_nopar:cpn { regex_build_special_group_-: }
+ {
+ \regex_build_options:NNN -
+ }
+\cs_new_protected_nopar:Npn \regex_build_options:NNN #1#2#3
+ {
+ \token_if_eq_meaning:NNTF \regex_build_raw:N #2
+ {
+ \cs_if_exist_use:cF { regex_build_option_#1#3: }
+ { \msg_error:nnx { regex } { unknown-option } { #3 } }
+ \regex_build_options:NNN #1
+ }
+ {
+ \prg_case_str:nnn { #3 }
+ { % (
+ { ) } { }
+ { - } { \regex_build_options:NNN - }
+ }
+ { \msg_error:nnx { regex } { invalid-in-option } { #3 } }
+ }
+ }
+\cs_new_protected_nopar:cpn { regex_build_option_+i: }
+ {
+ \regex_build_caseless:
+ \cs_set_eq:NN \regex_match_loop_case_hook:
+ \regex_match_loop_caseless_hook:
+ }
+\cs_new_protected_nopar:cpn { regex_build_option_-i: }
+ { \regex_build_caseful: }
\cs_new_protected_nopar:Npn \regex_build_group_quantifier:
{
\tl_set:Nn \l_regex_one_or_group_tl { group }
@@ -891,21 +948,33 @@
\int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int
\regex_build_new_state:
\tex_toks:D \l_regex_right_state_int = \tex_toks:D \l_regex_tmpa_int
- \use:x
+ \regex_toks_put_left:Nx \l_regex_right_state_int
+ {
+ \int_set:Nn \l_regex_current_state_int
+ { \int_use:N \l_regex_tmpa_int } % ^^A here we lie!
+ }
+ \cs_set:Npx \regex_tmp:w
{
\tex_toks:D \l_regex_tmpa_int
- { \s_regex_toks #1 { \int_use:N \l_regex_right_state_int } }
+ {
+ \s_regex_toks
+ #1 { \int_eval:n { \l_regex_right_state_int - \l_regex_tmpa_int } }
+ }
}
+ \regex_tmp:w
\regex_build_group_submatches:NN
\l_regex_right_state_int \l_regex_left_state_int
- \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
}
\cs_new_protected_nopar:Npn \regex_build_group_qs_aux:NN #1#2
{
\regex_build_group_shift:N \regex_action_free:n
+ \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
\regex_build_transition_aux:NN \regex_action_free:n #1
#2 \l_regex_tmpa_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ { \int_eval:n { \l_regex_right_state_int - \l_regex_tmpa_int } }
+ }
}
\cs_new_protected_nopar:cpn { regex_build_group_?: }
{
@@ -945,77 +1014,63 @@
\regex_action_free:n \l_regex_right_state_int
\regex_action_free:n \l_regex_tmpa_int
}
-\cs_new_protected_nopar:Npn \regex_build_group_n: #1
+\cs_new_protected_nopar:Npn \regex_build_group_n_aux:n #1
{
- \regex_build_group_shift:N \regex_action_repeat_move:n
- \regex_build_transition_aux:NN
- \regex_action_free:n \l_regex_tmpa_int
- \use:x
+ \regex_toks_put_right:Nx \l_regex_right_state_int
{
- \tex_toks:D \l_regex_tmpa_int
- {
- \s_regex_toks
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \else:
- \regex_action_no_repeat_move:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \fi:
- }
+ \regex_action_free:n
+ { \int_eval:n { \l_regex_max_state_int - \l_regex_left_state_int } }
}
- }
-\cs_new_eq:cN { regex_build_group_n?: } \regex_build_group_n:
-\cs_new_protected_nopar:Npn \regex_build_group_nn: #1#2
- {
- \regex_build_group_shift:N \regex_action_repeat_move:n
- \regex_build_transition_aux:NN
- \regex_action_free:n \l_regex_tmpa_int
- \use:x
+ \int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int
+ \int_set:Nn \l_regex_tmpb_int { \l_regex_max_state_int + \c_one }
+ \int_set:Nn \l_regex_max_state_int
{
- \tex_toks:D \l_regex_tmpa_int
- {
- \s_regex_toks
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \else:
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \fi:
- \regex_action_no_repeat_copy:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \fi:
- }
+ \l_regex_left_state_int - \c_one
+ + #1 * ( \l_regex_max_state_int - \l_regex_left_state_int + \c_one )
+ }
+ \int_until_do:nNnn \l_regex_tmpb_int > \l_regex_max_state_int
+ {
+ \tex_toks:D \l_regex_tmpb_int = \tex_toks:D \l_regex_tmpa_int
+ \int_incr:N \l_regex_tmpa_int
+ \int_incr:N \l_regex_tmpb_int
}
}
-\cs_new_protected_nopar:cpn { regex_build_group_nn?: } #1#2
- {
- \regex_build_group_shift:N \regex_action_repeat_move:n
+\cs_new_protected_nopar:Npn \regex_build_group_n: #1
+ { % ^^A todo: catch case #1 <= 0.
+ \regex_build_group_n_aux:n {#1}
\regex_build_transition_aux:NN
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_build_group_submatches:NN
+ \l_regex_tmpa_int \l_regex_left_state_int
+ }
+\cs_new_eq:cN { regex_build_group_n?: } \regex_build_group_n:
+\cs_new_protected_nopar:cpn { regex_build_group_n*: } #1
+ { % ^^A todo: catch case #1 <= 0.
+ \regex_build_group_n_aux:n {#1}
+ \regex_build_transitions_aux:NNNN
\regex_action_free:n \l_regex_tmpa_int
- \use:x
- {
- \tex_toks:D \l_regex_tmpa_int
- {
- \s_regex_toks
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \else:
- \regex_action_no_repeat_copy:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \fi:
- \exp_not:N \fi:
- }
- }
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_build_group_submatches:NN
+ \l_regex_tmpa_int \l_regex_left_state_int
}
-\cs_new_protected:Npn \regex_if_state_free:nT #1
- {
- \if_num:w \tex_dimen:D #1 = \l_regex_unique_step_int
- \exp_after:wN \use_none:n
- \else:
- \exp_after:wN \use:n
- \fi:
+\cs_new_protected_nopar:cpn { regex_build_group_n*?: } #1
+ { % ^^A todo: catch case #1 <= 0.
+ \regex_build_group_n_aux:n {#1}
+ \regex_build_transitions_aux:NNNN
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_action_free:n \l_regex_tmpa_int
+ \regex_build_group_submatches:NN
+ \l_regex_tmpa_int \l_regex_left_state_int
+ }
+\cs_new_protected_nopar:Npn \regex_build_group_nn: #1#2
+ { % ^^A Not Implemented Yet!
+ \msg_expandable_error:n { Quantifier~{m,n}~not~implemented~yet }
+ \use:c { regex_build_group_n*: } {#1}
+ }
+\cs_new_protected_nopar:cpn { regex_build_group_nn?: } #1#2
+ { % ^^A Not Implemented Yet!
+ \msg_expandable_error:n { Quantifier~{m,n}~not~implemented~yet }
+ \use:c { regex_build_group_n*?: } {#1}
}
\cs_new_protected:Npn \regex_store_state:n #1
{
@@ -1023,23 +1078,24 @@
\tex_skip:D \l_regex_max_index_int #1 sp \scan_stop:
\regex_store_submatches:n {#1}
}
-\cs_new_protected_nopar:Npn \regex_state_use_submatches:
+\cs_new_protected_nopar:Npn \regex_state_use_with_submatches:
{ \regex_state_use_aux:n { } }
\cs_new_protected_nopar:Npn \regex_state_use:
{ \regex_state_use_aux:n { \exp_after:wN \regex_state_use_aux_ii:w } }
-\cs_new:Npn \regex_state_use_aux_ii:w #1 \s_regex_toks { }
-\cs_new_protected:Npn \regex_state_use_aux:n #1
- {
- \regex_if_state_free:nT { \l_regex_current_state_int }
- {
- \tex_dimen:D \l_regex_current_state_int
- = \l_regex_unique_step_int sp \scan_stop:
- #1 \tex_the:D \tex_toks:D \l_regex_current_state_int \scan_stop:
- }
+\cs_new_nopar:Npn \regex_state_use_aux_ii:w #1 \s_regex_toks { }
+\cs_new_protected_nopar:Npn \regex_state_use_aux:n #1
+ {
+ \if_num:w \tex_dimen:D \l_regex_current_state_int
+ < \l_regex_unique_step_int
+ \tex_dimen:D \l_regex_current_state_int
+ = \l_regex_unique_step_int sp \scan_stop:
+ #1 \tex_the:D \tex_toks:D \exp_after:wN \l_regex_current_state_int
+ \fi:
+ \scan_stop:
}
\cs_new_protected_nopar:Npn \regex_disable_submatches:
{
- \cs_set_eq:NN \regex_state_use_submatches: \regex_state_use:
+ \cs_set_eq:NN \regex_state_use_with_submatches: \regex_state_use:
\cs_set_eq:NN \regex_store_submatches:n
\regex_protected_use_none:n
\cs_set_eq:NN \regex_action_submatches:n
@@ -1048,55 +1104,73 @@
\cs_new_protected:Npn \regex_protected_use_none:n #1 { }
\cs_new_protected:Npn \regex_store_submatches:n #1
{
- \exp_after:wN \regex_store_submatches_aux:Nw
- \exp_after:wN \l_regex_current_submatches_prop
- \tex_the:D \tex_toks:D #1 \scan_stop: \q_stop
- { #1 }
+ \tex_toks:D #1 \exp_after:wN
+ {
+ \tex_romannumeral:D
+ \exp_after:wN \regex_store_submatches_aux:w
+ \tex_the:D \tex_toks:D #1
+ }
}
-\cs_new_protected:Npn \regex_store_submatches_aux:Nw #1 #2 \s_regex_toks
+\cs_new_protected:Npn \regex_store_submatches_aux:w #1 \s_regex_toks
{
- \exp_args:No \regex_store_submatches_aux_ii:wnnwwn { #1 }
- #2
- \regex_state_submatches:nn { \c_minus_one } { \q_prop }
+ \regex_store_submatches_aux_ii:Nnnw
+ #1
+ \regex_state_submatches:nn \c_minus_one \q_prop
\s_regex_toks
}
-\cs_new_protected:Npn \regex_store_submatches_aux_ii:wnnwwn
- #1 \regex_state_submatches:nn #2#3 #4 \s_regex_toks #5 \q_stop #6
+\cs_new_protected:Npn \regex_store_submatches_aux_ii:Nnnw
+ \regex_state_submatches:nn #1 #2 #3 \s_regex_toks
{
- \tex_toks:D #6 \exp_after:wN
+ \exp_after:wN \c_zero
+ \exp_after:wN \regex_state_submatches:nn \exp_after:wN
{
- \exp_after:wN \regex_state_submatches:nn \exp_after:wN
- { \int_value:w \int_eval:w \l_regex_unique_step_int + \c_one }
- { #1 }
- \regex_state_submatches:nn {#2} {#3}
- \s_regex_toks
- #5
+ \int_value:w \int_eval:w
+ \l_regex_unique_step_int + \c_one
+ \exp_after:wN
}
+ \exp_after:wN { \l_regex_current_submatches_prop }
+ \regex_state_submatches:nn {#1} {#2}
+ \s_regex_toks
}
\cs_new_protected:Npn \regex_state_submatches:nn #1#2
{
\if_num:w #1 = \l_regex_unique_step_int
- \tl_set:Nn \l_regex_current_submatches_prop {#2}
+ \tl_set:Nn \l_regex_current_submatches_prop { #2 }
\fi:
}
\cs_new_protected:Npn \regex_match:n #1
{
- \tl_set:Nx \l_regex_query_str { \tl_to_other_str:n {#1} }
+ \tl_set:Nx \l_regex_query_other_str { \tl_to_other_str:n {#1} }
\regex_match_initial_setup:
\regex_match_once:
}
\cs_new_protected_nopar:Npn \regex_match_once:
{
\regex_match_setup:
- \exp_after:wN \regex_match_once_aux: \l_regex_query_str
+ \exp_after:wN \regex_match_once_aux: \l_regex_query_other_str
\q_recursion_tail \q_recursion_stop
\bool_if:NT \l_regex_success_bool { \l_regex_every_match_tl }
}
\cs_new_protected_nopar:Npn \regex_match_once_aux:
- { \str_skip_do:nn { \l_regex_start_step_int } { \regex_match_loop:N } }
+ {
+ \int_compare:nNnTF \l_regex_start_step_int = \c_zero
+ {
+ \int_set_eq:NN \l_regex_current_char_int \c_minus_one
+ \regex_match_loop:N
+ }
+ {
+ \str_skip_do:nn
+ { \l_regex_start_step_int - \c_one }
+ { \regex_match_once_aux_ii:N }
+ }
+ }
+\cs_new_protected_nopar:Npn \regex_match_once_aux_ii:N #1
+ {
+ \int_set:Nn \l_regex_current_char_int { `#1 }
+ \regex_match_loop:N
+ }
\cs_new_protected_nopar:Npn \regex_match_initial_setup:
{
- \tl_clear:N \l_regex_look_behind_str
\prg_stepwise_inline:nnnn {1} {1} { \l_regex_max_state_int }
{ \tex_dimen:D ##1 \c_minus_one sp \scan_stop: }
\int_set_eq:NN \l_regex_unique_step_int \c_minus_one
@@ -1118,20 +1192,11 @@
\int_zero:N \l_regex_max_index_int
\regex_store_state:n {1}
}
-\cs_new_protected_nopar:Npn \regex_match_loop_setup:
- {
- \int_incr:N \l_regex_current_step_int
- \int_incr:N \l_regex_unique_step_int
- \bool_set_false:N \l_regex_fresh_thread_bool
- }
\cs_new_eq:NN \s_regex_step \scan_stop:
\cs_new:Npn \regex_break_step:w #1 \s_regex_step { }
\cs_new_protected_nopar:Npn \regex_match_loop:N #1
{
- \regex_match_loop_setup:
- \token_if_eq_meaning:NNTF #1 \q_recursion_tail
- { \int_set_eq:NN \l_regex_current_char_int \c_minus_one }
- { \int_set:Nn \l_regex_current_char_int {`#1} }
+ \regex_match_loop_setup:N #1
\cs_set_nopar:Npx \regex_tmp:w
{
\int_zero:N \l_regex_max_index_int
@@ -1145,19 +1210,49 @@
\exp_after:wN \use_none_delimit_by_q_recursion_stop:w
\fi:
\quark_if_recursion_tail_stop:N #1
- \bool_if:NT \l_regex_look_behind_bool
- { \tl_put_left:Nx \l_regex_look_behind_str {#1} }
\regex_match_loop:N
}
\cs_new_nopar:Npn \regex_match_one_index:n #1
{
- \regex_match_one_index_aux:n { \int_value:w \tex_skip:D #1 }
+ \regex_match_one_index_aux:n
+ { \int_value:w \tex_skip:D #1 }
}
\cs_new_protected_nopar:Npn \regex_match_one_index_aux:n #1
{
\int_set:Nn \l_regex_current_state_int {#1}
\prop_clear:N \l_regex_current_submatches_prop
- \regex_state_use_submatches:
+ \regex_state_use_with_submatches:
+ }
+\cs_new_protected_nopar:Npn \regex_match_loop_setup:N #1
+ {
+ \int_incr:N \l_regex_current_step_int
+ \int_incr:N \l_regex_unique_step_int
+ \bool_set_false:N \l_regex_fresh_thread_bool
+ \int_set_eq:NN \l_regex_last_char_int \l_regex_current_char_int
+ \if_meaning:w #1 \q_recursion_tail
+ \int_set_eq:NN \l_regex_current_char_int \c_minus_one
+ \else:
+ \int_set:Nn \l_regex_current_char_int {`#1}
+ \fi:
+ \regex_match_loop_case_hook:
+ }
+\cs_new_protected_nopar:Npn \regex_match_loop_case_hook: { }
+\cs_new_protected_nopar:Npn \regex_match_loop_caseless_hook:
+ {
+ \int_set_eq:NN \l_regex_case_changed_char_int \l_regex_current_char_int
+ \if_num:w \l_regex_current_char_int < \c_ninety_one
+ \if_num:w \l_regex_current_char_int < \c_sixty_five
+ \else:
+ \int_add:Nn \l_regex_case_changed_char_int { \c_thirty_two }
+ \fi:
+ \else:
+ \if_num:w \l_regex_current_char_int < \c_one_hundred_twenty_three
+ \if_num:w \l_regex_current_char_int < \c_ninety_seven
+ \else:
+ \int_sub:Nn \l_regex_case_changed_char_int { \c_thirty_two }
+ \fi:
+ \fi:
+ \fi:
}
\cs_new_protected_nopar:Npn \regex_action_start_wildcard:nn #1#2
{
@@ -1167,7 +1262,10 @@
\regex_action_cost:n {#1}
}
\cs_new_protected_nopar:Npn \regex_action_cost:n #1
- { \regex_store_state:n {#1} }
+ {
+ \exp_args:Nf \regex_store_state:n %^^A optimize!
+ { \int_eval:n { \l_regex_current_state_int + #1 } }
+ }
\cs_new_protected_nopar:Npn \regex_action_success:
{
\regex_last_match_empty:F
@@ -1184,30 +1282,22 @@
}
\cs_new_protected_nopar:Npn \regex_action_free:n #1
{
- \regex_if_state_free:nT {#1}
+ \cs_set_nopar:Npx \regex_tmp:w
{
- \use:x
- {
- \int_set:Nn \l_regex_current_state_int {#1}
- \regex_store_submatches:n { \l_regex_current_state_int }
- \regex_state_use:
- \int_set:Nn \l_regex_current_state_int
- { \int_use:N \l_regex_current_state_int }
- \tl_set:Nn \exp_not:N \l_regex_current_submatches_prop
- { \exp_not:o \l_regex_current_submatches_prop }
- }
+ \int_add:Nn \l_regex_current_state_int {#1}
+ \regex_state_use:
+ \int_set:Nn \l_regex_current_state_int
+ { \int_use:N \l_regex_current_state_int }
+ \tl_set:Nn \exp_not:N \l_regex_current_submatches_prop
+ { \exp_not:o \l_regex_current_submatches_prop }
}
+ \regex_tmp:w
}
\cs_new_protected_nopar:Npn \regex_action_submatch:n #1
{
\prop_put:Nno \l_regex_current_submatches_prop {#1}
{ \int_use:N \l_regex_current_step_int }
- \regex_store_submatches:n { \l_regex_current_state_int }
}
-\cs_new_protected_nopar:Npn \regex_action_repeat_copy:n { \ERROR }
-\cs_new_protected_nopar:Npn \regex_action_repeat_move:n { \ERROR }
-\cs_new_protected_nopar:Npn \regex_action_no_repeat_copy:n { \ERROR }
-\cs_new_protected_nopar:Npn \regex_action_no_repeat_move:n { \ERROR }
\cs_new_protected_nopar:Npn \regex_extract:
{
\seq_gclear:N \g_regex_submatches_seq
@@ -1217,11 +1307,7 @@
\regex_extract_aux:nTF { ##1 }
{
\seq_gput_right:Nx \g_regex_submatches_seq
- {
- \str_from_to:Nnn \l_regex_query_str
- { \l_regex_tmpa_tl }
- { \l_regex_tmpb_tl }
- }
+ { \regex_query_substr:NN \l_regex_tmpa_tl \l_regex_tmpb_tl }
}
{ \seq_gput_right:Nn \g_regex_submatches_seq { } }
}
@@ -1253,9 +1339,13 @@
= \int_use:N \l_regex_max_state_int
\l_regex_capturing_group_int
= \int_use:N \l_regex_capturing_group_int
- \bool_if:NTF \l_regex_look_behind_bool
- { \bool_set_true:N \l_regex_look_behind_bool }
- { \bool_set_false:N \l_regex_look_behind_bool }
+ \token_if_eq_meaning:NNT
+ \regex_match_loop_case_hook:
+ \regex_match_loop_caseless_hook:
+ {
+ \cs_set_eq:NN \regex_match_loop_case_hook:
+ \regex_match_loop_caseless_hook:
+ }
\prg_stepwise_function:nnnN
{1} {1} {\l_regex_max_state_int}
\regex_set_aux:n
@@ -1269,7 +1359,7 @@
\cs_new:Npn \regex_nfa:Nw #1 #2 \regex_nfa_end:
{ \msg_expandable_error:n { Automaton~#1 used~incorrectly. } }
\cs_new_eq:NN \regex_nfa_end: \scan_stop:
-\prg_new_protected_conditional:Npnn \regex_check_nfa:N #1 { TF }
+\prg_new_protected_conditional:Npnn \regex_check_nfa:N #1 { T , TF }
{ \exp_after:wN \regex_check_nfa_aux:Nw #1 \q_stop }
\cs_new:Npn \regex_check_nfa_aux:Nw #1 #2 \q_stop
{
@@ -1280,11 +1370,6 @@
\prg_return_false:
\fi:
}
-\msg_new:nnn { regex } { not-nfa }
- {
- I~was~expecting~a~regular~expression~variable.\\
- Instead,~I~got~#1.
- }
\cs_new_protected_nopar:Npn \regex_use:N #1
{ \exp_after:wN \use_none:nn #1 }
\cs_new_protected:Npn \regex_user_aux:n #1
@@ -1296,7 +1381,7 @@
}
\cs_new_protected_nopar:Npn \regex_return_after_group:
{
- \if_bool:N \l_regex_success_bool
+ \if_meaning:w \c_true_bool \l_regex_success_bool
\group_insert_after:N \prg_return_true:
\else:
\group_insert_after:N \prg_return_false:
@@ -1304,7 +1389,7 @@
}
\cs_new_protected_nopar:Npn \regex_extract_after_group:N #1
{
- \if_bool:N \l_regex_success_bool
+ \if_meaning:w \c_true_bool \l_regex_success_bool
\regex_extract:
\group_insert_after:N \seq_set_eq:NN
\group_insert_after:N #1
@@ -1359,7 +1444,7 @@
}
\cs_new_protected:Npn \regex_count:NnN #1#2#3
{
- \regex_check_nfa:NTF #1
+ \regex_check_nfa:NT #1
{
\regex_user_aux:n
{
@@ -1375,9 +1460,8 @@
\regex_count_after_group:N #3
}
}
- { }
}
-\cs_new_protected:Npn \regex_extract:nnN #1#2#3
+\cs_new_protected:Npn \regex_extract_once:nnN #1#2#3
{
\regex_user_aux:n
{
@@ -1386,7 +1470,8 @@
\regex_extract_after_group:N #3
}
}
-\prg_new_protected_conditional:Npnn \regex_extract:nnN #1#2#3 { T , F , TF }
+\prg_new_protected_conditional:Npnn \regex_extract_once:nnN #1#2#3
+ { T , F , TF }
{
\regex_user_aux:n
{
@@ -1396,9 +1481,9 @@
\regex_return_after_group:
}
}
-\cs_new_protected:Npn \regex_extract:NnN #1#2#3
+\cs_new_protected:Npn \regex_extract_once:NnN #1#2#3
{
- \regex_check_nfa:NTF #1
+ \regex_check_nfa:NT #1
{
\regex_user_aux:n
{
@@ -1407,9 +1492,9 @@
\regex_extract_after_group:N #3
}
}
- { }
}
-\prg_new_protected_conditional:Npnn \regex_extract:NnN #1#2#3 { T , F , TF }
+\prg_new_protected_conditional:Npnn \regex_extract_once:NnN #1#2#3
+ { T , F , TF }
{
\regex_check_nfa:NTF #1
{
@@ -1423,6 +1508,48 @@
}
{ \prg_return_false: }
}
+\cs_new_protected:Npn \regex_extract_all:nnN #1#2#3
+ {
+ \regex_user_aux:n
+ {
+ \seq_gclear:N \g_regex_extract_all_seq
+ \tl_set:Nn \l_regex_every_match_tl { \regex_extract_all_aux: }
+ \regex_build:n {#1}
+ \regex_match:n {#2}
+ \regex_extract_all_after_group:N #3
+ }
+ }
+\cs_new_protected:Npn \regex_extract_all:NnN #1#2#3
+ {
+ \regex_check_nfa:NT #1
+ {
+ \regex_user_aux:n
+ {
+ \seq_gclear:N \g_regex_extract_all_seq
+ \tl_set:Nn \l_regex_every_match_tl { \regex_extract_all_aux: }
+ \regex_use:N #1
+ \regex_match:n {#2}
+ \regex_extract_all_after_group:N #3
+ }
+ }
+ }
+\cs_new_protected_nopar:Npn \regex_extract_all_aux:
+ {
+ \regex_extract:
+ \seq_gconcat:NNN \g_regex_extract_all_seq
+ \g_regex_extract_all_seq \g_regex_submatches_seq
+ \regex_match_once:
+ }
+\cs_new_protected_nopar:Npn \regex_extract_all_after_group:N #1
+ {
+ \seq_if_empty:NF \g_regex_extract_all_seq
+ {
+ \regex_extract:
+ \group_insert_after:N \seq_set_eq:NN
+ \group_insert_after:N #1
+ \group_insert_after:N \g_regex_extract_all_seq
+ }
+ }
\cs_new_protected:Npn \regex_split:nnN #1#2#3
{
\regex_user_aux:n
@@ -1436,7 +1563,7 @@
}
\cs_new_protected:Npn \regex_split:NnN #1#2#3
{
- \regex_check_nfa:NTF #1
+ \regex_check_nfa:NT #1
{
\regex_user_aux:n
{
@@ -1447,7 +1574,6 @@
\regex_split_after_group:N #3
}
}
- { }
}
\cs_new_protected_nopar:Npn \regex_split_aux:
{
@@ -1459,9 +1585,8 @@
{
\seq_gput_left:Nx \g_regex_submatches_seq
{
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \l_regex_tmpa_tl }
+ \regex_query_substr:NN
+ \l_regex_start_step_int \l_regex_tmpa_tl
}
}
{ \msg_error:nn { regex } { internal } }
@@ -1480,9 +1605,8 @@
{
\seq_gput_right:Nx \g_regex_split_seq
{
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \int_use:N \l_regex_current_step_int }
+ \regex_query_substr:NN
+ \l_regex_start_step_int \l_regex_current_step_int
}
}
\group_insert_after:N \seq_set_eq:NN
@@ -1494,40 +1618,57 @@
\str_aux_escape:NNNn
\prg_do_nothing:
\regex_replacement_escaped:N
- \regex_replacement_raw:N
+ \prg_do_nothing:
{#1}
\tl_set_eq:NN \l_regex_replacement_tl \g_str_result_tl
\tl_set:Nx \l_regex_replacement_tl
{ \l_regex_replacement_tl \prg_do_nothing: }
}
-\cs_new_nopar:Npn \regex_replacement_raw:N { \exp_not:N \prg_do_nothing: }
\cs_new_nopar:Npn \regex_replacement_escaped:N #1
{
- \if_num:w 9 < 1 #1 \exp_stop_f:
- \exp_not:N \regex_replacement_escaped_ii:nN {#1}
- \else:
- #1
- \fi:
+ \regex_token_if_other_digit:NTF #1
+ {
+ \exp_not:n
+ { \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } } {#1}
+ }
+ {
+ \token_if_eq_charcode:NNTF g #1
+ { \exp_not:N \regex_replacement_submatch:w }
+ { #1 }
+ }
}
-\cs_new_nopar:Npn \regex_replacement_escaped_ii:nN #1#2
+\cs_new_nopar:Npn \regex_replacement_submatch:w #1
{
- \regex_token_if_other_digit:NTF #2
- { \regex_replacement_escaped_ii:nN {#1#2} }
- { \exp_not:N \seq_item:Nn \exp_not:N \g_regex_submatches_seq {#1} #2 }
+ \exp_after:wN \token_if_eq_meaning:NNTF \c_lbrace_str #1
+ { \regex_replacement_submatch_aux:nN { } }
+ {
+ \regex_token_if_other_digit:NTF #1
+ { \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } }
+ { \msg_expandable_error:n { \g misused~in~replacement~text. } }
+ #1
+ }
}
-\prg_new_conditional:Npnn \regex_token_if_other_digit:N #1 { TF }
+\cs_new_nopar:Npn \regex_replacement_submatch_aux:nN #1 #2
{
- \if_num:w 9 < 1 \exp_not:N #1 \exp_stop_f:
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
+ \regex_token_if_other_digit:NTF #2
+ { \regex_replacement_submatch_aux:nN {#1#2} }
+ {
+ \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } {#1}
+ \exp_after:wN \token_if_eq_meaning:NNF \c_rbrace_str #2
+ {
+ \msg_expandable_error:n { \g misused~in~replacement~text. }
+ #2
+ }
+ }
}
\cs_new_protected_nopar:Npn \regex_replace_after_group:N #1
{
- \group_insert_after:N \tl_set_eq:NN
+ \group_insert_after:N \tl_set:Nx
\group_insert_after:N #1
- \group_insert_after:N \g_regex_replaced_str
+ \group_insert_after:N {
+ \group_insert_after:N \tl_to_str:N
+ \group_insert_after:N \g_regex_replaced_str
+ \group_insert_after:N }
}
\cs_new_protected:Npn \regex_replace_once_aux:Nn #1#2
{
@@ -1539,15 +1680,16 @@
\regex_extract:
\regex_extract_aux:nTF {0}
{
+ \cs_set_nopar:Npn \regex_tmp:w
+ { \str_skip_do:nn { \l_regex_tmpb_tl } { } }
\tl_gset:Nx \g_regex_replaced_str
{
- \str_from_to:Nnn \l_regex_query_str {0} { \l_regex_tmpa_tl }
+ \regex_query_substr:NN \c_zero \l_regex_tmpa_tl
\l_regex_replacement_tl
- \str_from_to:Nnn \l_regex_query_str
- { \l_regex_tmpb_tl } { \c_max_int }
+ \exp_after:wN \regex_tmp:w \l_regex_query_other_str
}
}
- { \tl_gset_eq:NN \g_regex_replaced_str \l_regex_query_str }
+ { \tl_gset_eq:NN \g_regex_replaced_str \l_regex_query_other_str }
\group_end:
}
\cs_new_protected:Npn \regex_replace_once:nnN #1#2#3
@@ -1592,12 +1734,10 @@
\tl_gclear:N \g_regex_replaced_str
#2
\exp_args:No \regex_match:n {#1}
+ \cs_set_nopar:Npn \regex_tmp:w
+ { \str_skip_do:nn { \l_regex_start_step_int } { } }
\tl_gput_right:Nx \g_regex_replaced_str
- {
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \c_max_int }
- }
+ { \exp_after:wN \regex_tmp:w \l_regex_query_other_str }
\group_end:
}
\cs_new_protected_nopar:Npn \regex_replace_all_aux:
@@ -1607,9 +1747,8 @@
{
\tl_gput_right:Nx \g_regex_replaced_str
{
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \l_regex_tmpa_tl }
+ \regex_query_substr:NN
+ \l_regex_start_step_int \l_regex_tmpa_tl
\l_regex_replacement_tl
}
}
@@ -1632,6 +1771,26 @@
\regex_replacement:n {#2}
}
}
+\msg_new:nnn { regex } { -998 } { Unsupported~construct }
+\msg_new:nnn { regex } { -997 }
+ { The~regular~expression~is~too~large~(32768~states). }
+\msg_new:nnn { regex } { 1 } { \iow_char:N\\~at~end~of~pattern }
+\msg_new:nnn { regex } { 4 }
+ { Numbers~out~of~order~in~\iow_char:N\{\iow_char\}~quantifier. }
+\msg_new:nnn { regex } { 6 }
+ { Missing~terminating~\iow_char:N\]~for~character~class }
+\msg_new:nnn { regex } { 7 }
+ { Invalid~escape~sequence~in~character~class }
+\msg_new:nnn { regex } { 8 }
+ { Range~out~of~order~in~character~class }
+\msg_new:nnn { regex } { 22 } { Mismatched~parentheses }
+\msg_new:nnn { regex } { 34 }
+ { Character~value~in~\iow_char:N\\x{...}~sequence~is~too~large }
+\msg_new:nnn { regex } { not-nfa }
+ {
+ LaTeX~was~expecting~a~regular~expression~variable.\\
+ Instead,~LaTeX~found~'#1'.
+ }
%%
%%
%% End of file `l3regex-trace.sty'.
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty
index 5da00fdd3d0..c57f415bc47 100644
--- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty
+++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty
@@ -46,113 +46,121 @@
%%
%% -----------------------------------------------------------------------
\RequirePackage{expl3}
-\GetIdInfo$Id: l3regex.dtx 2895 2011-10-09 15:58:19Z joseph $
+\GetIdInfo$Id: l3regex.dtx 2943 2011-10-30 15:59:43Z bruno $
{L3 Experimental Regular Expressions}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
\RequirePackage{l3str}
+\int_const:Nn \c_forty_eight { 48 }
+\int_const:Nn \c_fifty_eight { 58 }
+\int_const:Nn \c_sixty_five { 65 }
+\int_const:Nn \c_ninety_one { 91 }
+\int_const:Nn \c_ninety_seven { 97 }
+\int_const:Nn \c_one_hundred_twenty_three { 123 }
+\int_const:Nn \c_one_hundred_twenty_seven { 127 }
\cs_new:Npn \regex_tmp:w { }
\tl_new:N \g_regex_tmpa_tl
\tl_new:N \l_regex_tmpa_tl
\tl_new:N \l_regex_tmpb_tl
\int_new:N \l_regex_tmpa_int
-\tl_new:N \l_regex_pattern_str
+\int_new:N \l_regex_tmpb_int
\int_new:N \l_regex_max_state_int
\int_new:N \l_regex_left_state_int
\int_new:N \l_regex_right_state_int
-\seq_new:N \l_regex_left_state_seq
-\seq_new:N \l_regex_right_state_seq
+\seq_new:N \l_regex_group_begin_seq
+\seq_new:N \l_regex_group_end_seq
\int_new:N \l_regex_capturing_group_int
\seq_new:N \l_regex_capturing_group_seq
\tl_new:N \l_regex_one_or_group_tl
-\int_new:N \l_regex_repetition_int
-\bool_new:N \l_regex_look_behind_bool
-\tl_new:N \l_regex_look_behind_str
\cs_new_eq:NN \regex_build_tmp_class:n \use_none:n
\bool_new:N \l_regex_class_bool
\tl_new:N \l_regex_class_tl
\tl_const:Nn \c_regex_d_tl
{
- \regex_item_range:nn {48} {57} % 0--9
+ \regex_item_range:nn { \c_forty_eight } { 57 } % 0--9
}
\tl_const:Nn \c_regex_D_tl
{
- \regex_item_more:n {57} % 9
- \regex_item_range:nn {0} {47} % 0
+ \regex_item_geq:n { \c_fifty_eight } % > `9
+ \regex_item_range:nn { \c_zero } { 47 } % 0
}
\tl_const:Nn \c_regex_h_tl
{
- \regex_item_equal:n {32} % space
- \regex_item_equal:n {9} % tab
+ \regex_item_equal:n { \c_thirty_two } % space
+ \regex_item_equal:n { \c_nine } % tab
}
\tl_const:Nn \c_regex_H_tl
{
- \regex_item_neq:n {32} % space
- \regex_item_neq:n {9} % tab
- \regex_break_true:w
+ \regex_item_geq:n { 33 } % > space
+ \regex_item_range:nn { \c_ten } { 31 } % tab < ... < space
+ \regex_item_range:nn { \c_zero } { \c_eight } % < tab
}
\tl_const:Nn \c_regex_s_tl
{
- \regex_item_equal:n {32} % space
- \regex_item_neq:n {11} % vtab
- \regex_item_range:nn {9} {13} % tab, lf, vtab, ff, cr
+ \regex_item_equal:n { \c_thirty_two } % space
+ \regex_item_range:nn { \c_nine } { \c_ten } % tab, lf
+ \regex_item_range:nn { \c_twelve } { \c_thirteen } % ff, cr
}
\tl_const:Nn \c_regex_S_tl
{
- \regex_item_more:n {32} % > space
- \regex_item_range:nn {14} {31} % tab < ... < space
- \regex_item_range:nn {0} {8} % < tab
- \regex_item_equal:n {11} % vtab
+ \regex_item_geq:n { 33 } % > space
+ \regex_item_range:nn { \c_fourteen } { 31 } % tab < ... < space
+ \regex_item_range:nn { \c_zero } { \c_eight } % < tab
+ \regex_item_equal:n { \c_eleven } % vtab
}
\tl_const:Nn \c_regex_v_tl
{
- \regex_item_range:nn {10} {13} % lf, vtab, ff, cr
+ \regex_item_range:nn { \c_ten } { \c_thirteen } % lf, vtab, ff, cr
}
\tl_const:Nn \c_regex_V_tl
{
- \regex_item_more:n {13} % cr
- \regex_item_range:nn {0} {9} % < lf
+ \regex_item_geq:n { \c_fourteen } % >cr
+ \regex_item_range:nn { \c_zero } { \c_nine } % < lf
}
\tl_const:Nn \c_regex_w_tl
{
- \regex_item_range:nn {97} {122} % a--z
- \regex_item_range:nn {65} {90} % A--Z
- \regex_item_range:nn {48} {57} % 0--9
- \regex_item_equal:n {95} % _
+ \regex_item_range:nn { \c_ninety_seven } { 122 } % a--z
+ \regex_item_range:nn { \c_sixty_five } { 90 } % A--Z
+ \regex_item_range:nn { \c_forty_eight } { 57 } % 0--9
+ \regex_item_equal:n { 95 } % _
}
\tl_const:Nn \c_regex_W_tl
{
- \regex_item_range:nn {0} {47} % <`0
- \regex_item_range:nn {58} {64} % (`9+1)--(`A-1)
- \regex_item_range:nn {91} {94} % (`Z+1)--(`_-1)
- \regex_item_equal:n {96} % `
- \regex_item_more:n {122} % z
+ \regex_item_range:nn { \c_zero } { 47 } % <`0
+ \regex_item_range:nn { \c_fifty_eight } { 64 } % (`9+1)--(`A-1)
+ \regex_item_range:nn { \c_ninety_one } { 94 } % (`Z+1)--(`_-1)
+ \regex_item_equal:n { 96 } % `
+ \regex_item_geq:n { \c_one_hundred_twenty_three } % z
}
\tl_const:Nn \c_regex_N_tl
{
- \regex_item_neq:n {10} % lf
- \regex_break_true:w
+ \regex_item_geq:n { \c_eleven } % > lf
+ \regex_item_range:nn { \c_zero } { \c_nine } % < lf
}
-\tl_new:N \l_regex_query_str
-\int_new:N \l_regex_start_step_int
-\int_new:N \l_regex_current_char_int
+\tl_new:N \l_regex_query_other_str
\int_new:N \l_regex_current_step_int
+\int_new:N \l_regex_start_step_int
+\int_new:N \l_regex_success_step_int
\int_new:N \l_regex_unique_step_int
+\int_new:N \l_regex_current_char_int
+\int_new:N \l_regex_last_char_int
+\int_new:N \l_regex_case_changed_char_int
+\bool_new:N \l_regex_caseless_bool
\int_new:N \l_regex_current_state_int
\prop_new:N \l_regex_current_submatches_prop
+\prop_new:N \l_regex_success_submatches_prop
\int_new:N \l_regex_max_index_int
\tl_new:N \l_regex_every_match_tl
+\bool_new:N \l_regex_success_bool
\cs_new_protected:Npn \regex_last_match_empty_no:F #1 {#1}
\cs_new_protected:Npn \regex_last_match_empty_yes:F
{ \int_compare:nNnF \l_regex_start_step_int = \l_regex_current_step_int }
\cs_new_eq:NN \regex_last_match_empty:F \regex_last_match_empty_no:F
-\bool_new:N \l_regex_success_bool
\bool_new:N \l_regex_success_empty_bool
-\int_new:N \l_regex_success_step_int
-\prop_new:N \l_regex_success_submatches_prop
\bool_new:N \l_regex_fresh_thread_bool
\seq_new:N \g_regex_submatches_seq
\int_new:N \g_regex_match_count_int
+\seq_new:N \g_regex_extract_all_seq
\seq_new:N \g_regex_split_seq
\tl_new:N \l_regex_replacement_tl
\tl_new:N \g_regex_replaced_str
@@ -169,40 +177,43 @@
\tex_toks:D #1 \exp_after:wN
{ \tex_the:D \tex_toks:D \exp_after:wN #1 \regex_tmp:w }
}
-\cs_new_eq:NN \regex_if_tail_stop:N \quark_if_recursion_tail_stop:N
-\cs_new_protected_nopar:Npn \regex_if_tail_error:Nn #1#2
- { \quark_if_recursion_tail_stop_do:Nn #1 { \regex_build_error:n {#2} } }
-\cs_new_protected_nopar:Npn \regex_build_error:n #1
+\cs_new_nopar:Npn \regex_query_substr:NN #1#2
{
- \msg_error:nnxx { regex } { build-error } {\int_eval:n{#1}}
- {
- \prg_case_int:nnn {#1}
- {
- {-999} {File~not~found}
- {-998} {Unsupported~construct}
- {-997} {The~regular~expression~is~too~large~(32768~states).}
- {1} {\iow_char:N\\~at~end~of~pattern }
- {4} {Numbers~out~of~order~in~\iow_char:N\{\iow_char\}~quantifier.}
- {6} {Missing~terminating~\iow_char:N\]~for~character~class }
- {7} {Invalid~escape~sequence~in~character~class}
- {8} {Range~out~of~order~in~character~class}
- {22} {Mismatched~parentheses}
- {34} {Character~value~in~\iow_char:N\\x{...}~sequence~is~too~large}
- }
- { Internal~bug. }
- }
+ \exp_after:wN \regex_query_substr_aux:NN
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \l_regex_query_other_str
+ \q_stop
+ }
+\cs_new:Npn \regex_query_substr_aux:NN #1#2
+ {
+ \str_skip_do:nn {#1}
+ { \str_collect_do:nn { #2 - #1 } { \use_i_delimit_by_q_stop:nw } }
+ }
+\cs_new_protected_nopar:Npn \regex_seq_pop:N #1
+ {
+ \seq_pop:NN #1 \l_regex_tmpa_tl
+ \l_regex_tmpa_tl
+ }
+\cs_new_protected_nopar:Npn \regex_seq_get:N #1
+ {
+ \seq_get:NN #1 \l_regex_tmpa_tl
+ \l_regex_tmpa_tl
}
-\msg_new:nnn { regex } { build-error } { (error~#1): ~ #2 }
-\cs_new_nopar:Npn \regex_break_true:w #1 \regex_break_point:TF #2 #3 {#2}
-\cs_new_nopar:Npn \regex_break_false:w #1 \regex_break_point:TF #2 #3 {#3}
-\cs_new_eq:NN \regex_break_point:TF \use_ii:nn
-\cs_new_nopar:Npn \regex_item_equal:n #1
+\cs_new_protected_nopar:Npn \regex_item_dot:T
+ { \int_compare:nNnF \l_regex_current_char_int = \c_minus_one }
+\cs_new_protected_nopar:Npn \regex_break_true:w
+ #1 \regex_break_point:TF #2 #3 {#2}
+\cs_new_protected_nopar:Npn \regex_break_false:w
+ #1 \regex_break_point:TF #2 #3 {#3}
+\cs_new_protected_nopar:Npn \regex_break_point:TF #1 #2 { #2 }
+\cs_new_protected_nopar:Npn \regex_item_caseful_equal:n #1
{
\if_num:w #1 = \l_regex_current_char_int
\exp_after:wN \regex_break_true:w
\fi:
}
-\cs_new_nopar:Npn \regex_item_range:nn #1 #2
+\cs_new_protected_nopar:Npn \regex_item_caseful_range:nn #1 #2
{
\reverse_if:N \if_num:w #1 > \l_regex_current_char_int
\reverse_if:N \if_num:w #2 < \l_regex_current_char_int
@@ -210,24 +221,60 @@
\fi:
\fi:
}
-\cs_new_nopar:Npn \regex_item_less:n #1
+\cs_new_protected_nopar:Npn \regex_item_caseful_geq:n #1
{
- \if_num:w #1 > \l_regex_current_char_int
+ \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
\exp_after:wN \regex_break_true:w
\fi:
}
-\cs_new_nopar:Npn \regex_item_more:n #1
+\cs_new_protected_nopar:Npn \regex_item_caseless_equal:n #1
{
- \if_num:w #1 < \l_regex_current_char_int
+ \if_num:w #1 = \l_regex_current_char_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ \if_num:w #1 = \l_regex_case_changed_char_int
\exp_after:wN \regex_break_true:w
\fi:
}
-\cs_new_nopar:Npn \regex_item_neq:n #1
+\cs_new_protected_nopar:Npn \regex_item_caseless_range:nn #1 #2
{
- \if_num:w #1 = \l_regex_current_char_int
- \exp_after:wN \regex_break_false:w
+ \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
+ \reverse_if:N \if_num:w #2 < \l_regex_current_char_int
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
+ \fi:
+ \fi:
+ \reverse_if:N \if_num:w #1 > \l_regex_case_changed_char_int
+ \reverse_if:N \if_num:w #2 < \l_regex_case_changed_char_int
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
+ \fi:
\fi:
}
+\cs_new_protected_nopar:Npn \regex_item_caseless_geq:n #1
+ {
+ \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ \reverse_if:N \if_num:w #1 > \l_regex_case_changed_char_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ }
+\cs_new:Npn \regex_item_equal:n { \regex_item_caseful_equal:n }
+\cs_new:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
+\cs_new:Npn \regex_item_geq:n { \regex_item_caseful_geq:n }
+\cs_new_protected_nopar:Npn \regex_build_caseless:
+ {
+ \bool_set_true:N \l_regex_caseless_bool
+ \cs_set:Npn \regex_item_equal:n { \regex_item_caseless_equal:n }
+ \cs_set:Npn \regex_item_range:nn { \regex_item_caseless_range:nn }
+ \cs_set:Npn \regex_item_geq:n { \regex_item_caseless_geq:n }
+ }
+\cs_new_protected_nopar:Npn \regex_build_caseful:
+ {
+ \bool_set_false:N \l_regex_caseless_bool
+ \cs_set:Npn \regex_item_equal:n { \regex_item_caseful_equal:n }
+ \cs_set:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
+ \cs_set:Npn \regex_item_geq:n { \regex_item_caseful_geq:n }
+ }
\cs_new_protected:Npn \regex_get_digits:nw #1
{
\tex_afterassignment:D \regex_tmp:w
@@ -235,65 +282,71 @@
{
\exp_not:n {#1}
{ \if_false: } } \fi:
- \regex_get_digits_aux:N
+ \regex_get_digits_aux:NN
}
-\cs_new_nopar:Npn \regex_get_digits_aux:N #1
+\cs_new_nopar:Npn \regex_get_digits_aux:NN #1#2
{
- \if_num:w 9 < 1 \exp_not:N #1 \exp_stop_f:
- \else:
- \if_charcode:w \c_space_token \exp_not:N #1
+ \if_meaning:w \regex_build_raw:N #1
+ \if_charcode:w \c_space_token \exp_not:N #2
\else:
- \regex_get_digits_end:w
+ \if_num:w 9 < 1 \exp_not:N #2 \exp_stop_f:
+ #2
+ \else:
+ \regex_get_digits_end:w #1 #2
+ \fi:
\fi:
+ \else:
+ \regex_get_digits_end:w #1 #2
\fi:
- #1 \regex_get_digits_aux:N
+ \regex_get_digits_aux:NN
}
-\cs_new_nopar:Npn \regex_get_digits_end:w
- \fi: \fi: #1 \regex_get_digits_aux:N
+\cs_new_nopar:Npn \regex_get_digits_end:w #1 \fi: #2 \regex_get_digits_aux:NN
{
- \fi: \fi:
+ \fi: #2
\if_false: { { \fi: } }
#1
}
+\prg_new_conditional:Npnn \regex_token_if_other_digit:N #1 { TF }
+ {
+ \if_num:w \c_nine < 1 \exp_not:N #1 \exp_stop_f:
+ \prg_return_true: \else: \prg_return_false: \fi:
+ }
\prg_new_conditional:Npnn \regex_aux_char_if_special:N #1 { TF }
{
- \if_num:w `#1 < 97 \exp_stop_f:
- \if_num:w `#1 < 58 \exp_stop_f:
- \if_num:w \int_eval:w (`#1 - \c_eight)/\c_sixteen = \c_two
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
+ \if_num:w `#1 < \c_ninety_one
+ \if_num:w `#1 < \c_fifty_eight
+ \if_num:w `#1 < \c_forty_eight
+ \if_num:w `#1 < \c_thirty_two
+ \prg_return_false: \else: \prg_return_true: \fi:
+ \else: \prg_return_false: \fi:
\else:
- \if_num:w \int_eval:w `#1 / 26 = \c_three
- \prg_return_false:
- \else:
- \prg_return_true:
- \fi:
+ \if_num:w `#1 < \c_sixty_five
+ \prg_return_true: \else: \prg_return_false: \fi:
\fi:
\else:
- \if_num:w \int_eval:w `#1 / \c_five = 25 \exp_stop_f:
- \prg_return_true:
+ \if_num:w `#1 < \c_one_hundred_twenty_three
+ \if_num:w `#1 < \c_ninety_seven
+ \prg_return_true: \else: \prg_return_false: \fi:
\else:
- \prg_return_false:
+ \if_num:w `#1 < \c_one_hundred_twenty_seven
+ \prg_return_true: \else: \prg_return_false: \fi:
\fi:
\fi:
}
\prg_new_conditional:Npnn \regex_aux_char_if_alphanumeric:N #1 { TF }
{
- \if_num:w `#1 < 91 \exp_stop_f:
- \if_num:w `#1 < 65 \exp_stop_f:
- \if_num:w \c_nine < 1 #1 \exp_stop_f:
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
+ \if_num:w `#1 < \c_ninety_one
+ \if_num:w `#1 < \c_fifty_eight
+ \if_num:w `#1 < \c_forty_eight
+ \prg_return_false: \else: \prg_return_true: \fi:
\else:
- \prg_return_true:
+ \if_num:w `#1 < \c_sixty_five
+ \prg_return_false: \else: \prg_return_true: \fi:
\fi:
\else:
- \if_num:w \int_eval:w (`#1-\c_six)/26 = \c_four
- \prg_return_true:
+ \if_num:w `#1 < \c_one_hundred_twenty_three
+ \if_num:w `#1 < \c_ninety_seven
+ \prg_return_false: \else: \prg_return_true: \fi:
\else:
\prg_return_false:
\fi:
@@ -301,8 +354,8 @@
}
\cs_new_protected_nopar:Npn \regex_build_new_state:
{
- \int_compare:nNnTF \l_regex_max_state_int > {32766}
- { \regex_build_error:n {-997} }
+ \int_compare:nNnTF \l_regex_max_state_int > { 32766 }
+ { \msg_error:nn { regex } { -997 } }
{
\int_incr:N \l_regex_max_state_int
\tex_toks:D \l_regex_max_state_int { \s_regex_toks }
@@ -314,15 +367,15 @@
{
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
- { #1 { \int_use:N #2 } }
+ { #1 { \int_eval:n { #2 - \l_regex_left_state_int } } }
}
\cs_new_protected_nopar:Npn \regex_build_transitions_aux:NNNN #1#2#3#4
{
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
{
- #1 { \int_use:N #2 }
- #3 { \int_use:N #4 }
+ #1 { \int_eval:n { #2 - \l_regex_left_state_int } }
+ #3 { \int_eval:n { #4 - \l_regex_left_state_int } }
}
}
\cs_new_protected:Npn \regex_build:n #1
@@ -363,25 +416,19 @@
\cs_set_eq:NN \regex_build_control:N \regex_build_default_control:N
\cs_set_eq:NN \regex_build_raw:N \regex_build_default_raw:N
\int_set_eq:NN \l_regex_capturing_group_int \c_zero
- \int_zero:N \l_regex_left_state_int
- \int_zero:N \l_regex_right_state_int
\int_zero:N \l_regex_max_state_int
\regex_build_new_state:
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
- {
- \regex_action_start_wildcard:nn
- { \int_use:N \l_regex_left_state_int }
- { \int_use:N \l_regex_right_state_int }
- }
+ { \regex_action_start_wildcard:nn {0} {1} }
}
\cs_new_protected_nopar:Npn \regex_build_end:
{
\seq_if_empty:NF \l_regex_capturing_group_seq
{
- \regex_build_error:n {22}
+ \msg_error:nn { regex } {22}
\prg_replicate:nn
- { \seq_length:N \l_regex_capturing_group_seq } % (
+ { \seq_length:N \l_regex_capturing_group_seq }
{ \regex_build_close_aux: \regex_build_group_: }
}
\regex_toks_put_right:Nx \l_regex_right_state_int
@@ -399,7 +446,13 @@
\regex_toks_put_right:Nx \l_regex_left_state_int
{
\exp_not:N \int_compare:nNnT {#1} = \l_regex_current_step_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
}
\cs_new_protected_nopar:cpn { regex_build_$: } % $
@@ -409,71 +462,72 @@
{
\exp_not:N \int_compare:nNnT
\c_minus_one = \l_regex_current_char_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
}
\cs_new_eq:Nc \regex_build_Z: { regex_build_$: } %$
\cs_new_eq:Nc \regex_build_z: { regex_build_$: } %$
\cs_new_protected_nopar:Npn \regex_build_b:
{
- \bool_set_true:N \l_regex_look_behind_bool
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
{
\exp_not:N \regex_if_word_boundary:TF
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
{ }
}
}
\cs_new_protected_nopar:Npn \regex_build_B:
{
- \bool_set_true:N \l_regex_look_behind_bool
\regex_build_new_state:
\regex_toks_put_right:Nx \l_regex_left_state_int
{
\exp_not:N \regex_if_word_boundary:TF
{ }
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
}
\cs_new_protected_nopar:Npn \regex_if_word_boundary:TF
{
- \tl_if_empty:NTF \l_regex_look_behind_str
- { \c_regex_w_tl }
- {
- \group_begin:
- \cs_set_nopar:Npx \regex_tmp:w
- {
- \int_set:Nn \l_regex_current_char_int
- { ` \str_head:N \l_regex_look_behind_str }
- }
- \regex_tmp:w
- \c_regex_w_tl
- \regex_break_point:TF
- { \group_end: \c_regex_W_tl }
- { \group_end: \c_regex_w_tl }
- }
+ \group_begin:
+ \int_set_eq:NN \l_regex_current_char_int \l_regex_last_char_int
+ \c_regex_w_tl
+ \regex_break_point:TF
+ { \group_end: \c_regex_W_tl \regex_item_equal:n { -1 } }
+ { \group_end: \c_regex_w_tl }
\regex_break_point:TF
}
\cs_new_protected_nopar:Npn \regex_build_default_raw:N #1
{
\cs_set:Npx \regex_build_tmp_class:n ##1
{
- \exp_not:n { \exp_not:N \if_num:w }
- \int_value:w `#1 = \l_regex_current_char_int
- \regex_action_cost:n { ##1 }
- \exp_not:n { \exp_not:N \fi: }
+ \regex_item_equal:n { \int_value:w `#1 }
+ \regex_break_point:TF { \regex_action_cost:n { ##1 } } { }
}
\regex_build_one_quantifier:
}
\cs_new_protected_nopar:cpn { regex_build_.: }
{
\cs_set:Npn \regex_build_tmp_class:n ##1
- {
- \exp_not:N \if_num:w \c_minus_one < \l_regex_current_char_int
- \regex_action_cost:n {##1}
- \exp_not:N \fi:
- }
+ { \regex_item_dot:T { \regex_action_cost:n {##1} } }
\regex_build_one_quantifier:
}
\cs_new_protected_nopar:Npn \regex_build_char_type:N #1
@@ -481,9 +535,7 @@
\cs_set:Npn \regex_build_tmp_class:n ##1
{
\exp_not:N #1
- \exp_not:N \regex_break_point:TF
- { \regex_action_cost:n {##1} }
- { }
+ \regex_break_point:TF { \regex_action_cost:n {##1} } { }
}
\regex_build_one_quantifier:
}
@@ -518,16 +570,8 @@
{
\exp_not:o \l_regex_class_tl
\bool_if:NTF \l_regex_class_bool
- {
- \exp_not:N \regex_break_point:TF
- { \regex_action_cost:n {##1} }
- { }
- }
- {
- \exp_not:N \regex_break_point:TF
- { }
- { \regex_action_cost:n {##1} }
- }
+ { \regex_break_point:TF { \regex_action_cost:n {##1} } { } }
+ { \regex_break_point:TF { } { \regex_action_cost:n {##1} } }
}
\regex_build_one_quantifier:
}
@@ -553,7 +597,7 @@
\cs_new_protected_nopar:Npn \regex_class_single:N #1
{
\tl_put_right:Nx \l_regex_class_tl
- { \exp_not:N \regex_item_equal:n { \int_value:w `#1 } }
+ { \regex_item_equal:n { \int_value:w `#1 } }
}
\cs_new_protected_nopar:Npn \regex_class_range:Nw #1#2#3
{
@@ -572,14 +616,14 @@
\cs_new_protected_nopar:Npn \regex_class_range_put:NN #1#2
{
\if_num:w `#1 > `#2 \exp_stop_f:
- \regex_build_error:n {8}
+ \msg_error:nn { regex } {8}
\else:
\tl_put_right:Nx \l_regex_class_tl
{
\if_num:w `#1 = `#2 \exp_stop_f:
- \exp_not:N \regex_item_equal:n
+ \regex_item_equal:n
\else:
- \exp_not:N \regex_item_range:nn { \int_value:w `#1 }
+ \regex_item_range:nn { \int_value:w `#1 }
\fi:
{ \int_value:w `#2 }
}
@@ -651,26 +695,29 @@
\exp_not:N \regex_build_raw:N \c_lbrace_str #1#2
}
}
-\cs_new_protected_nopar:Npn \regex_build_quantifier_lbrace:nnw #1#2#3
+\cs_new_protected_nopar:Npn \regex_build_quantifier_lbrace:nnw #1#2#3#4
{
- \str_if_eq:xxTF { \exp_not:N #3 } { \c_rbrace_str }
+ \str_if_eq:xxTF
+ { \exp_not:n {#3#4} }
+ { \exp_not:N \regex_build_control:N \c_rbrace_str }
{
\tl_if_empty:nTF {#2}
- { \regex_build_quantifier_aux:nnN { {#1} {\c_max_int} } {nn} }
+ { \regex_build_quantifier_aux:nnNN { {#1} } { n* } }
{
\int_compare:nNnT {#1} > {#2}
- { \regex_build_error:n {4} }
- \regex_build_quantifier_aux:nnN { {#1} {#2} } {nn}
+ { \msg_error:nn { regex } {4} }
+ \regex_build_quantifier_aux:nnNN { {#1} {#2} } { nn }
}
}
{
\regex_build_quantifier_end:n { }
\use:x
{
- \exp_not:n { \exp_args:No \tl_map_function:nN }
- { \c_lbrace_str #1 #2 , }
- \regex_build_raw:N
+ \exp_args:No \tl_map_function:nN
+ { \c_lbrace_str #1 , #2 }
+ \regex_build_raw:N
}
+ #3 #4
}
}
\cs_new_protected_nopar:Npn \regex_build_quantifier_end:n #1
@@ -726,71 +773,27 @@
\regex_action_free:n \l_regex_tmpa_int
}
\cs_new_protected_nopar:Npn \regex_build_one_n: #1
- {
- \int_set_eq:NN \l_regex_tmpa_int \l_regex_right_state_int
- \regex_build_new_state:
- \regex_build_new_state:
- \regex_toks_put_right:Nx \l_regex_tmpa_int
- { %^^A safe \if nesting?
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \regex_action_repeat_move:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \else:
- \regex_action_no_repeat_move:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \fi:
- }
- \regex_toks_put_right:Nx \l_regex_left_state_int
- {
- \regex_build_tmp_class:n
- { \int_use:N \l_regex_tmpa_int }
- }
- }
+ { \prg_replicate:nn {#1} { \regex_build_one_: } }
\cs_new_eq:cN { regex_build_one_n?: } \regex_build_one_n:
-\cs_new_protected_nopar:Npn \regex_build_one_nn: #1#2
+\cs_new_protected_nopar:cpx { regex_build_one_n*: } #1
{
- \regex_build_one_nn_aux:nn {#1}
- {
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \regex_action_repeat_copy:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \fi:
- \regex_action_no_repeat_move:n
- { \int_use:N \l_regex_right_state_int }
- }
+ \exp_not:N \prg_replicate:nn {#1} { \exp_not:N \regex_build_one_: }
+ \exp_not:c { regex_build_one_*: }
}
-\cs_new_protected_nopar:cpn { regex_build_one_nn?: } #1#2
+\cs_new_protected_nopar:cpx { regex_build_one_n*?: } #1
{
- \regex_build_one_nn_aux:nn {#1}
- {
- \regex_action_no_repeat_copy:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \regex_action_repeat_move:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \fi:
- }
+ \exp_not:N \prg_replicate:nn {#1} { \exp_not:N \regex_build_one_: }
+ \exp_not:c { regex_build_one_*?: }
}
-\cs_new_protected_nopar:Npn \regex_build_one_nn_aux:nn #1#2
+\cs_new_protected_nopar:Npn \regex_build_one_nn_aux:Nnn #1#2#3
{
- \int_set_eq:NN \l_regex_tmpa_int \l_regex_right_state_int
- \regex_build_new_state:
- \regex_build_new_state:
- \regex_toks_put_right:Nx \l_regex_tmpa_int
- {
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \regex_action_repeat_move:n
- { \int_use:N \l_regex_left_state_int }
- \exp_not:N \else:
- #2
- \exp_not:N \fi:
- }
- \regex_toks_put_right:Nx \l_regex_left_state_int
- {
- \regex_build_tmp_class:n
- { \int_use:N \l_regex_tmpa_int }
- }
+ \prg_replicate:nn {#2} { \regex_build_one_: }
+ \prg_replicate:nn {#3-#2} {#1}
}
+\cs_new_protected_nopar:Npx \regex_build_one_nn:
+ { \regex_build_one_nn_aux:Nnn \exp_not:c { regex_build_one_?: } }
+\cs_new_protected_nopar:cpx { regex_build_one_nn?: }
+ { \regex_build_one_nn_aux:Nnn \exp_not:c { regex_build_one_??: } }
\cs_new_protected_nopar:cpn { regex_build_(: } #1#2
{
\str_if_eq:nnTF { #1 #2 } { \regex_build_control:N ? }
@@ -806,10 +809,19 @@
\cs_new_protected_nopar:Npn \regex_build_open_aux:
{
\regex_build_new_state:
- \seq_push:Nx \l_regex_left_state_seq
- { \int_use:N \l_regex_left_state_int }
- \seq_push:Nx \l_regex_right_state_seq
- { \int_use:N \l_regex_right_state_int }
+ \seq_push:Nx \l_regex_group_begin_seq
+ {
+ \int_set:Nn \l_regex_left_state_int
+ { \int_use:N \l_regex_left_state_int }
+ }
+ \bool_if:NTF \l_regex_caseless_bool
+ { \seq_push:Nn \l_regex_group_end_seq { \regex_build_caseless: } }
+ { \seq_push:Nn \l_regex_group_end_seq { \regex_build_caseful: } }
+ \seq_push:Nx \l_regex_group_end_seq
+ {
+ \int_set:Nn \l_regex_right_state_int
+ { \int_use:N \l_regex_right_state_int }
+ }
\regex_build_begin_alternation:
}
\cs_new_protected_nopar:cpn { regex_build_|: }
@@ -820,7 +832,7 @@
\cs_new_protected_nopar:cpn { regex_build_): }
{
\seq_if_empty:NTF \l_regex_capturing_group_seq
- { \regex_build_error:n {22} }
+ { \msg_error:nn { regex } { 22 } }
{
\regex_build_close_aux:
\regex_build_group_quantifier:
@@ -829,30 +841,41 @@
\cs_new_protected_nopar:Npn \regex_build_close_aux:
{
\regex_build_end_alternation:
- \seq_pop:NN \l_regex_left_state_seq \l_regex_tmpa_tl
- \int_set:Nn \l_regex_left_state_int \l_regex_tmpa_tl
- \seq_pop:NN \l_regex_right_state_seq \l_regex_tmpa_tl
- \int_set:Nn \l_regex_right_state_int \l_regex_tmpa_tl
+ \regex_seq_pop:N \l_regex_group_begin_seq
+ \regex_seq_pop:N \l_regex_group_end_seq
+ \regex_seq_pop:N \l_regex_group_end_seq
}
\cs_new_protected_nopar:Npn \regex_build_begin_alternation:
{
\regex_build_new_state:
- \seq_get:NN \l_regex_left_state_seq \l_regex_tmpa_tl
- \int_set:Nn \l_regex_left_state_int \l_regex_tmpa_tl
+ \regex_seq_get:N \l_regex_group_begin_seq
\regex_toks_put_right:Nx \l_regex_left_state_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
\cs_new_protected_nopar:Npn \regex_build_end_alternation:
{
- \seq_get:NN \l_regex_right_state_seq \l_regex_tmpa_tl
- \regex_toks_put_right:Nx \l_regex_right_state_int
- { \regex_action_free:n { \l_regex_tmpa_tl } }
+ \int_set_eq:NN \l_regex_left_state_int \l_regex_right_state_int
+ \regex_seq_get:N \l_regex_group_end_seq
+ \regex_toks_put_right:Nx \l_regex_left_state_int
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
}
\cs_new_protected_nopar:Npn \regex_build_special_group:NN #1#2
{
\cs_if_exist_use:cF { regex_build_special_group_\token_to_str:N #2 : }
{
- \regex_build_error:n { -998 }
+ \msg_error:nn { regex } { -998 }
\regex_build_control:N ( % )
\regex_build_raw:N ?
#1 #2
@@ -863,6 +886,40 @@
\seq_push:Nx \l_regex_capturing_group_seq { * }
\regex_build_open_aux:
}
+\cs_new_protected_nopar:Npn \regex_build_special_group_i:
+ {
+ \regex_build_options:NNN +
+ \regex_build_raw:N i
+ }
+\cs_new_protected_nopar:cpn { regex_build_special_group_-: }
+ {
+ \regex_build_options:NNN -
+ }
+\cs_new_protected_nopar:Npn \regex_build_options:NNN #1#2#3
+ {
+ \token_if_eq_meaning:NNTF \regex_build_raw:N #2
+ {
+ \cs_if_exist_use:cF { regex_build_option_#1#3: }
+ { \msg_error:nnx { regex } { unknown-option } { #3 } }
+ \regex_build_options:NNN #1
+ }
+ {
+ \prg_case_str:nnn { #3 }
+ { % (
+ { ) } { }
+ { - } { \regex_build_options:NNN - }
+ }
+ { \msg_error:nnx { regex } { invalid-in-option } { #3 } }
+ }
+ }
+\cs_new_protected_nopar:cpn { regex_build_option_+i: }
+ {
+ \regex_build_caseless:
+ \cs_set_eq:NN \regex_match_loop_case_hook:
+ \regex_match_loop_caseless_hook:
+ }
+\cs_new_protected_nopar:cpn { regex_build_option_-i: }
+ { \regex_build_caseful: }
\cs_new_protected_nopar:Npn \regex_build_group_quantifier:
{
\tl_set:Nn \l_regex_one_or_group_tl { group }
@@ -891,21 +948,33 @@
\int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int
\regex_build_new_state:
\tex_toks:D \l_regex_right_state_int = \tex_toks:D \l_regex_tmpa_int
- \use:x
+ \regex_toks_put_left:Nx \l_regex_right_state_int
+ {
+ \int_set:Nn \l_regex_current_state_int
+ { \int_use:N \l_regex_tmpa_int } % ^^A here we lie!
+ }
+ \cs_set:Npx \regex_tmp:w
{
\tex_toks:D \l_regex_tmpa_int
- { \s_regex_toks #1 { \int_use:N \l_regex_right_state_int } }
+ {
+ \s_regex_toks
+ #1 { \int_eval:n { \l_regex_right_state_int - \l_regex_tmpa_int } }
+ }
}
+ \regex_tmp:w
\regex_build_group_submatches:NN
\l_regex_right_state_int \l_regex_left_state_int
- \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
}
\cs_new_protected_nopar:Npn \regex_build_group_qs_aux:NN #1#2
{
\regex_build_group_shift:N \regex_action_free:n
+ \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
\regex_build_transition_aux:NN \regex_action_free:n #1
#2 \l_regex_tmpa_int
- { \regex_action_free:n { \int_use:N \l_regex_right_state_int } }
+ {
+ \regex_action_free:n
+ { \int_eval:n { \l_regex_right_state_int - \l_regex_tmpa_int } }
+ }
}
\cs_new_protected_nopar:cpn { regex_build_group_?: }
{
@@ -945,77 +1014,63 @@
\regex_action_free:n \l_regex_right_state_int
\regex_action_free:n \l_regex_tmpa_int
}
-\cs_new_protected_nopar:Npn \regex_build_group_n: #1
+\cs_new_protected_nopar:Npn \regex_build_group_n_aux:n #1
{
- \regex_build_group_shift:N \regex_action_repeat_move:n
- \regex_build_transition_aux:NN
- \regex_action_free:n \l_regex_tmpa_int
- \use:x
+ \regex_toks_put_right:Nx \l_regex_right_state_int
{
- \tex_toks:D \l_regex_tmpa_int
- {
- \s_regex_toks
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \else:
- \regex_action_no_repeat_move:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \fi:
- }
+ \regex_action_free:n
+ { \int_eval:n { \l_regex_max_state_int - \l_regex_left_state_int } }
}
- }
-\cs_new_eq:cN { regex_build_group_n?: } \regex_build_group_n:
-\cs_new_protected_nopar:Npn \regex_build_group_nn: #1#2
- {
- \regex_build_group_shift:N \regex_action_repeat_move:n
- \regex_build_transition_aux:NN
- \regex_action_free:n \l_regex_tmpa_int
- \use:x
+ \int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int
+ \int_set:Nn \l_regex_tmpb_int { \l_regex_max_state_int + \c_one }
+ \int_set:Nn \l_regex_max_state_int
{
- \tex_toks:D \l_regex_tmpa_int
- {
- \s_regex_toks
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \else:
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \fi:
- \regex_action_no_repeat_copy:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \fi:
- }
+ \l_regex_left_state_int - \c_one
+ + #1 * ( \l_regex_max_state_int - \l_regex_left_state_int + \c_one )
+ }
+ \int_until_do:nNnn \l_regex_tmpb_int > \l_regex_max_state_int
+ {
+ \tex_toks:D \l_regex_tmpb_int = \tex_toks:D \l_regex_tmpa_int
+ \int_incr:N \l_regex_tmpa_int
+ \int_incr:N \l_regex_tmpb_int
}
}
-\cs_new_protected_nopar:cpn { regex_build_group_nn?: } #1#2
- {
- \regex_build_group_shift:N \regex_action_repeat_move:n
+\cs_new_protected_nopar:Npn \regex_build_group_n: #1
+ { % ^^A todo: catch case #1 <= 0.
+ \regex_build_group_n_aux:n {#1}
\regex_build_transition_aux:NN
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_build_group_submatches:NN
+ \l_regex_tmpa_int \l_regex_left_state_int
+ }
+\cs_new_eq:cN { regex_build_group_n?: } \regex_build_group_n:
+\cs_new_protected_nopar:cpn { regex_build_group_n*: } #1
+ { % ^^A todo: catch case #1 <= 0.
+ \regex_build_group_n_aux:n {#1}
+ \regex_build_transitions_aux:NNNN
\regex_action_free:n \l_regex_tmpa_int
- \use:x
- {
- \tex_toks:D \l_regex_tmpa_int
- {
- \s_regex_toks
- \exp_not:N \if_num:w #1 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \else:
- \regex_action_no_repeat_copy:n
- { \int_use:N \l_regex_right_state_int }
- \exp_not:N \if_num:w #2 > \l_regex_repetition_int
- \tex_the:D \tex_toks:D \l_regex_tmpa_int
- \exp_not:N \fi:
- \exp_not:N \fi:
- }
- }
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_build_group_submatches:NN
+ \l_regex_tmpa_int \l_regex_left_state_int
}
-\cs_new_protected:Npn \regex_if_state_free:nT #1
- {
- \if_num:w \tex_dimen:D #1 = \l_regex_unique_step_int
- \exp_after:wN \use_none:n
- \else:
- \exp_after:wN \use:n
- \fi:
+\cs_new_protected_nopar:cpn { regex_build_group_n*?: } #1
+ { % ^^A todo: catch case #1 <= 0.
+ \regex_build_group_n_aux:n {#1}
+ \regex_build_transitions_aux:NNNN
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_action_free:n \l_regex_tmpa_int
+ \regex_build_group_submatches:NN
+ \l_regex_tmpa_int \l_regex_left_state_int
+ }
+\cs_new_protected_nopar:Npn \regex_build_group_nn: #1#2
+ { % ^^A Not Implemented Yet!
+ \msg_expandable_error:n { Quantifier~{m,n}~not~implemented~yet }
+ \use:c { regex_build_group_n*: } {#1}
+ }
+\cs_new_protected_nopar:cpn { regex_build_group_nn?: } #1#2
+ { % ^^A Not Implemented Yet!
+ \msg_expandable_error:n { Quantifier~{m,n}~not~implemented~yet }
+ \use:c { regex_build_group_n*?: } {#1}
}
\cs_new_protected:Npn \regex_store_state:n #1
{
@@ -1023,23 +1078,24 @@
\tex_skip:D \l_regex_max_index_int #1 sp \scan_stop:
\regex_store_submatches:n {#1}
}
-\cs_new_protected_nopar:Npn \regex_state_use_submatches:
+\cs_new_protected_nopar:Npn \regex_state_use_with_submatches:
{ \regex_state_use_aux:n { } }
\cs_new_protected_nopar:Npn \regex_state_use:
{ \regex_state_use_aux:n { \exp_after:wN \regex_state_use_aux_ii:w } }
-\cs_new:Npn \regex_state_use_aux_ii:w #1 \s_regex_toks { }
-\cs_new_protected:Npn \regex_state_use_aux:n #1
- {
- \regex_if_state_free:nT { \l_regex_current_state_int }
- {
- \tex_dimen:D \l_regex_current_state_int
- = \l_regex_unique_step_int sp \scan_stop:
- #1 \tex_the:D \tex_toks:D \l_regex_current_state_int \scan_stop:
- }
+\cs_new_nopar:Npn \regex_state_use_aux_ii:w #1 \s_regex_toks { }
+\cs_new_protected_nopar:Npn \regex_state_use_aux:n #1
+ {
+ \if_num:w \tex_dimen:D \l_regex_current_state_int
+ < \l_regex_unique_step_int
+ \tex_dimen:D \l_regex_current_state_int
+ = \l_regex_unique_step_int sp \scan_stop:
+ #1 \tex_the:D \tex_toks:D \exp_after:wN \l_regex_current_state_int
+ \fi:
+ \scan_stop:
}
\cs_new_protected_nopar:Npn \regex_disable_submatches:
{
- \cs_set_eq:NN \regex_state_use_submatches: \regex_state_use:
+ \cs_set_eq:NN \regex_state_use_with_submatches: \regex_state_use:
\cs_set_eq:NN \regex_store_submatches:n
\regex_protected_use_none:n
\cs_set_eq:NN \regex_action_submatches:n
@@ -1048,55 +1104,73 @@
\cs_new_protected:Npn \regex_protected_use_none:n #1 { }
\cs_new_protected:Npn \regex_store_submatches:n #1
{
- \exp_after:wN \regex_store_submatches_aux:Nw
- \exp_after:wN \l_regex_current_submatches_prop
- \tex_the:D \tex_toks:D #1 \scan_stop: \q_stop
- { #1 }
+ \tex_toks:D #1 \exp_after:wN
+ {
+ \tex_romannumeral:D
+ \exp_after:wN \regex_store_submatches_aux:w
+ \tex_the:D \tex_toks:D #1
+ }
}
-\cs_new_protected:Npn \regex_store_submatches_aux:Nw #1 #2 \s_regex_toks
+\cs_new_protected:Npn \regex_store_submatches_aux:w #1 \s_regex_toks
{
- \exp_args:No \regex_store_submatches_aux_ii:wnnwwn { #1 }
- #2
- \regex_state_submatches:nn { \c_minus_one } { \q_prop }
+ \regex_store_submatches_aux_ii:Nnnw
+ #1
+ \regex_state_submatches:nn \c_minus_one \q_prop
\s_regex_toks
}
-\cs_new_protected:Npn \regex_store_submatches_aux_ii:wnnwwn
- #1 \regex_state_submatches:nn #2#3 #4 \s_regex_toks #5 \q_stop #6
+\cs_new_protected:Npn \regex_store_submatches_aux_ii:Nnnw
+ \regex_state_submatches:nn #1 #2 #3 \s_regex_toks
{
- \tex_toks:D #6 \exp_after:wN
+ \exp_after:wN \c_zero
+ \exp_after:wN \regex_state_submatches:nn \exp_after:wN
{
- \exp_after:wN \regex_state_submatches:nn \exp_after:wN
- { \int_value:w \int_eval:w \l_regex_unique_step_int + \c_one }
- { #1 }
- \regex_state_submatches:nn {#2} {#3}
- \s_regex_toks
- #5
+ \int_value:w \int_eval:w
+ \l_regex_unique_step_int + \c_one
+ \exp_after:wN
}
+ \exp_after:wN { \l_regex_current_submatches_prop }
+ \regex_state_submatches:nn {#1} {#2}
+ \s_regex_toks
}
\cs_new_protected:Npn \regex_state_submatches:nn #1#2
{
\if_num:w #1 = \l_regex_unique_step_int
- \tl_set:Nn \l_regex_current_submatches_prop {#2}
+ \tl_set:Nn \l_regex_current_submatches_prop { #2 }
\fi:
}
\cs_new_protected:Npn \regex_match:n #1
{
- \tl_set:Nx \l_regex_query_str { \tl_to_other_str:n {#1} }
+ \tl_set:Nx \l_regex_query_other_str { \tl_to_other_str:n {#1} }
\regex_match_initial_setup:
\regex_match_once:
}
\cs_new_protected_nopar:Npn \regex_match_once:
{
\regex_match_setup:
- \exp_after:wN \regex_match_once_aux: \l_regex_query_str
+ \exp_after:wN \regex_match_once_aux: \l_regex_query_other_str
\q_recursion_tail \q_recursion_stop
\bool_if:NT \l_regex_success_bool { \l_regex_every_match_tl }
}
\cs_new_protected_nopar:Npn \regex_match_once_aux:
- { \str_skip_do:nn { \l_regex_start_step_int } { \regex_match_loop:N } }
+ {
+ \int_compare:nNnTF \l_regex_start_step_int = \c_zero
+ {
+ \int_set_eq:NN \l_regex_current_char_int \c_minus_one
+ \regex_match_loop:N
+ }
+ {
+ \str_skip_do:nn
+ { \l_regex_start_step_int - \c_one }
+ { \regex_match_once_aux_ii:N }
+ }
+ }
+\cs_new_protected_nopar:Npn \regex_match_once_aux_ii:N #1
+ {
+ \int_set:Nn \l_regex_current_char_int { `#1 }
+ \regex_match_loop:N
+ }
\cs_new_protected_nopar:Npn \regex_match_initial_setup:
{
- \tl_clear:N \l_regex_look_behind_str
\prg_stepwise_inline:nnnn {1} {1} { \l_regex_max_state_int }
{ \tex_dimen:D ##1 \c_minus_one sp \scan_stop: }
\int_set_eq:NN \l_regex_unique_step_int \c_minus_one
@@ -1118,20 +1192,11 @@
\int_zero:N \l_regex_max_index_int
\regex_store_state:n {1}
}
-\cs_new_protected_nopar:Npn \regex_match_loop_setup:
- {
- \int_incr:N \l_regex_current_step_int
- \int_incr:N \l_regex_unique_step_int
- \bool_set_false:N \l_regex_fresh_thread_bool
- }
\cs_new_eq:NN \s_regex_step \scan_stop:
\cs_new:Npn \regex_break_step:w #1 \s_regex_step { }
\cs_new_protected_nopar:Npn \regex_match_loop:N #1
{
- \regex_match_loop_setup:
- \token_if_eq_meaning:NNTF #1 \q_recursion_tail
- { \int_set_eq:NN \l_regex_current_char_int \c_minus_one }
- { \int_set:Nn \l_regex_current_char_int {`#1} }
+ \regex_match_loop_setup:N #1
\cs_set_nopar:Npx \regex_tmp:w
{
\int_zero:N \l_regex_max_index_int
@@ -1145,19 +1210,49 @@
\exp_after:wN \use_none_delimit_by_q_recursion_stop:w
\fi:
\quark_if_recursion_tail_stop:N #1
- \bool_if:NT \l_regex_look_behind_bool
- { \tl_put_left:Nx \l_regex_look_behind_str {#1} }
\regex_match_loop:N
}
\cs_new_nopar:Npn \regex_match_one_index:n #1
{
- \regex_match_one_index_aux:n { \int_value:w \tex_skip:D #1 }
+ \regex_match_one_index_aux:n
+ { \int_value:w \tex_skip:D #1 }
}
\cs_new_protected_nopar:Npn \regex_match_one_index_aux:n #1
{
\int_set:Nn \l_regex_current_state_int {#1}
\prop_clear:N \l_regex_current_submatches_prop
- \regex_state_use_submatches:
+ \regex_state_use_with_submatches:
+ }
+\cs_new_protected_nopar:Npn \regex_match_loop_setup:N #1
+ {
+ \int_incr:N \l_regex_current_step_int
+ \int_incr:N \l_regex_unique_step_int
+ \bool_set_false:N \l_regex_fresh_thread_bool
+ \int_set_eq:NN \l_regex_last_char_int \l_regex_current_char_int
+ \if_meaning:w #1 \q_recursion_tail
+ \int_set_eq:NN \l_regex_current_char_int \c_minus_one
+ \else:
+ \int_set:Nn \l_regex_current_char_int {`#1}
+ \fi:
+ \regex_match_loop_case_hook:
+ }
+\cs_new_protected_nopar:Npn \regex_match_loop_case_hook: { }
+\cs_new_protected_nopar:Npn \regex_match_loop_caseless_hook:
+ {
+ \int_set_eq:NN \l_regex_case_changed_char_int \l_regex_current_char_int
+ \if_num:w \l_regex_current_char_int < \c_ninety_one
+ \if_num:w \l_regex_current_char_int < \c_sixty_five
+ \else:
+ \int_add:Nn \l_regex_case_changed_char_int { \c_thirty_two }
+ \fi:
+ \else:
+ \if_num:w \l_regex_current_char_int < \c_one_hundred_twenty_three
+ \if_num:w \l_regex_current_char_int < \c_ninety_seven
+ \else:
+ \int_sub:Nn \l_regex_case_changed_char_int { \c_thirty_two }
+ \fi:
+ \fi:
+ \fi:
}
\cs_new_protected_nopar:Npn \regex_action_start_wildcard:nn #1#2
{
@@ -1167,7 +1262,10 @@
\regex_action_cost:n {#1}
}
\cs_new_protected_nopar:Npn \regex_action_cost:n #1
- { \regex_store_state:n {#1} }
+ {
+ \exp_args:Nf \regex_store_state:n %^^A optimize!
+ { \int_eval:n { \l_regex_current_state_int + #1 } }
+ }
\cs_new_protected_nopar:Npn \regex_action_success:
{
\regex_last_match_empty:F
@@ -1184,30 +1282,22 @@
}
\cs_new_protected_nopar:Npn \regex_action_free:n #1
{
- \regex_if_state_free:nT {#1}
+ \cs_set_nopar:Npx \regex_tmp:w
{
- \use:x
- {
- \int_set:Nn \l_regex_current_state_int {#1}
- \regex_store_submatches:n { \l_regex_current_state_int }
- \regex_state_use:
- \int_set:Nn \l_regex_current_state_int
- { \int_use:N \l_regex_current_state_int }
- \tl_set:Nn \exp_not:N \l_regex_current_submatches_prop
- { \exp_not:o \l_regex_current_submatches_prop }
- }
+ \int_add:Nn \l_regex_current_state_int {#1}
+ \regex_state_use:
+ \int_set:Nn \l_regex_current_state_int
+ { \int_use:N \l_regex_current_state_int }
+ \tl_set:Nn \exp_not:N \l_regex_current_submatches_prop
+ { \exp_not:o \l_regex_current_submatches_prop }
}
+ \regex_tmp:w
}
\cs_new_protected_nopar:Npn \regex_action_submatch:n #1
{
\prop_put:Nno \l_regex_current_submatches_prop {#1}
{ \int_use:N \l_regex_current_step_int }
- \regex_store_submatches:n { \l_regex_current_state_int }
}
-\cs_new_protected_nopar:Npn \regex_action_repeat_copy:n { \ERROR }
-\cs_new_protected_nopar:Npn \regex_action_repeat_move:n { \ERROR }
-\cs_new_protected_nopar:Npn \regex_action_no_repeat_copy:n { \ERROR }
-\cs_new_protected_nopar:Npn \regex_action_no_repeat_move:n { \ERROR }
\cs_new_protected_nopar:Npn \regex_extract:
{
\seq_gclear:N \g_regex_submatches_seq
@@ -1217,11 +1307,7 @@
\regex_extract_aux:nTF { ##1 }
{
\seq_gput_right:Nx \g_regex_submatches_seq
- {
- \str_from_to:Nnn \l_regex_query_str
- { \l_regex_tmpa_tl }
- { \l_regex_tmpb_tl }
- }
+ { \regex_query_substr:NN \l_regex_tmpa_tl \l_regex_tmpb_tl }
}
{ \seq_gput_right:Nn \g_regex_submatches_seq { } }
}
@@ -1253,9 +1339,13 @@
= \int_use:N \l_regex_max_state_int
\l_regex_capturing_group_int
= \int_use:N \l_regex_capturing_group_int
- \bool_if:NTF \l_regex_look_behind_bool
- { \bool_set_true:N \l_regex_look_behind_bool }
- { \bool_set_false:N \l_regex_look_behind_bool }
+ \token_if_eq_meaning:NNT
+ \regex_match_loop_case_hook:
+ \regex_match_loop_caseless_hook:
+ {
+ \cs_set_eq:NN \regex_match_loop_case_hook:
+ \regex_match_loop_caseless_hook:
+ }
\prg_stepwise_function:nnnN
{1} {1} {\l_regex_max_state_int}
\regex_set_aux:n
@@ -1269,7 +1359,7 @@
\cs_new:Npn \regex_nfa:Nw #1 #2 \regex_nfa_end:
{ \msg_expandable_error:n { Automaton~#1 used~incorrectly. } }
\cs_new_eq:NN \regex_nfa_end: \scan_stop:
-\prg_new_protected_conditional:Npnn \regex_check_nfa:N #1 { TF }
+\prg_new_protected_conditional:Npnn \regex_check_nfa:N #1 { T , TF }
{ \exp_after:wN \regex_check_nfa_aux:Nw #1 \q_stop }
\cs_new:Npn \regex_check_nfa_aux:Nw #1 #2 \q_stop
{
@@ -1280,11 +1370,6 @@
\prg_return_false:
\fi:
}
-\msg_new:nnn { regex } { not-nfa }
- {
- I~was~expecting~a~regular~expression~variable.\\
- Instead,~I~got~#1.
- }
\cs_new_protected_nopar:Npn \regex_use:N #1
{ \exp_after:wN \use_none:nn #1 }
\cs_new_protected:Npn \regex_user_aux:n #1
@@ -1296,7 +1381,7 @@
}
\cs_new_protected_nopar:Npn \regex_return_after_group:
{
- \if_bool:N \l_regex_success_bool
+ \if_meaning:w \c_true_bool \l_regex_success_bool
\group_insert_after:N \prg_return_true:
\else:
\group_insert_after:N \prg_return_false:
@@ -1304,7 +1389,7 @@
}
\cs_new_protected_nopar:Npn \regex_extract_after_group:N #1
{
- \if_bool:N \l_regex_success_bool
+ \if_meaning:w \c_true_bool \l_regex_success_bool
\regex_extract:
\group_insert_after:N \seq_set_eq:NN
\group_insert_after:N #1
@@ -1359,7 +1444,7 @@
}
\cs_new_protected:Npn \regex_count:NnN #1#2#3
{
- \regex_check_nfa:NTF #1
+ \regex_check_nfa:NT #1
{
\regex_user_aux:n
{
@@ -1375,9 +1460,8 @@
\regex_count_after_group:N #3
}
}
- { }
}
-\cs_new_protected:Npn \regex_extract:nnN #1#2#3
+\cs_new_protected:Npn \regex_extract_once:nnN #1#2#3
{
\regex_user_aux:n
{
@@ -1386,7 +1470,8 @@
\regex_extract_after_group:N #3
}
}
-\prg_new_protected_conditional:Npnn \regex_extract:nnN #1#2#3 { T , F , TF }
+\prg_new_protected_conditional:Npnn \regex_extract_once:nnN #1#2#3
+ { T , F , TF }
{
\regex_user_aux:n
{
@@ -1396,9 +1481,9 @@
\regex_return_after_group:
}
}
-\cs_new_protected:Npn \regex_extract:NnN #1#2#3
+\cs_new_protected:Npn \regex_extract_once:NnN #1#2#3
{
- \regex_check_nfa:NTF #1
+ \regex_check_nfa:NT #1
{
\regex_user_aux:n
{
@@ -1407,9 +1492,9 @@
\regex_extract_after_group:N #3
}
}
- { }
}
-\prg_new_protected_conditional:Npnn \regex_extract:NnN #1#2#3 { T , F , TF }
+\prg_new_protected_conditional:Npnn \regex_extract_once:NnN #1#2#3
+ { T , F , TF }
{
\regex_check_nfa:NTF #1
{
@@ -1423,6 +1508,48 @@
}
{ \prg_return_false: }
}
+\cs_new_protected:Npn \regex_extract_all:nnN #1#2#3
+ {
+ \regex_user_aux:n
+ {
+ \seq_gclear:N \g_regex_extract_all_seq
+ \tl_set:Nn \l_regex_every_match_tl { \regex_extract_all_aux: }
+ \regex_build:n {#1}
+ \regex_match:n {#2}
+ \regex_extract_all_after_group:N #3
+ }
+ }
+\cs_new_protected:Npn \regex_extract_all:NnN #1#2#3
+ {
+ \regex_check_nfa:NT #1
+ {
+ \regex_user_aux:n
+ {
+ \seq_gclear:N \g_regex_extract_all_seq
+ \tl_set:Nn \l_regex_every_match_tl { \regex_extract_all_aux: }
+ \regex_use:N #1
+ \regex_match:n {#2}
+ \regex_extract_all_after_group:N #3
+ }
+ }
+ }
+\cs_new_protected_nopar:Npn \regex_extract_all_aux:
+ {
+ \regex_extract:
+ \seq_gconcat:NNN \g_regex_extract_all_seq
+ \g_regex_extract_all_seq \g_regex_submatches_seq
+ \regex_match_once:
+ }
+\cs_new_protected_nopar:Npn \regex_extract_all_after_group:N #1
+ {
+ \seq_if_empty:NF \g_regex_extract_all_seq
+ {
+ \regex_extract:
+ \group_insert_after:N \seq_set_eq:NN
+ \group_insert_after:N #1
+ \group_insert_after:N \g_regex_extract_all_seq
+ }
+ }
\cs_new_protected:Npn \regex_split:nnN #1#2#3
{
\regex_user_aux:n
@@ -1436,7 +1563,7 @@
}
\cs_new_protected:Npn \regex_split:NnN #1#2#3
{
- \regex_check_nfa:NTF #1
+ \regex_check_nfa:NT #1
{
\regex_user_aux:n
{
@@ -1447,7 +1574,6 @@
\regex_split_after_group:N #3
}
}
- { }
}
\cs_new_protected_nopar:Npn \regex_split_aux:
{
@@ -1459,9 +1585,8 @@
{
\seq_gput_left:Nx \g_regex_submatches_seq
{
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \l_regex_tmpa_tl }
+ \regex_query_substr:NN
+ \l_regex_start_step_int \l_regex_tmpa_tl
}
}
{ \msg_error:nn { regex } { internal } }
@@ -1480,9 +1605,8 @@
{
\seq_gput_right:Nx \g_regex_split_seq
{
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \int_use:N \l_regex_current_step_int }
+ \regex_query_substr:NN
+ \l_regex_start_step_int \l_regex_current_step_int
}
}
\group_insert_after:N \seq_set_eq:NN
@@ -1494,40 +1618,57 @@
\str_aux_escape:NNNn
\prg_do_nothing:
\regex_replacement_escaped:N
- \regex_replacement_raw:N
+ \prg_do_nothing:
{#1}
\tl_set_eq:NN \l_regex_replacement_tl \g_str_result_tl
\tl_set:Nx \l_regex_replacement_tl
{ \l_regex_replacement_tl \prg_do_nothing: }
}
-\cs_new_nopar:Npn \regex_replacement_raw:N { \exp_not:N \prg_do_nothing: }
\cs_new_nopar:Npn \regex_replacement_escaped:N #1
{
- \if_num:w 9 < 1 #1 \exp_stop_f:
- \exp_not:N \regex_replacement_escaped_ii:nN {#1}
- \else:
- #1
- \fi:
+ \regex_token_if_other_digit:NTF #1
+ {
+ \exp_not:n
+ { \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } } {#1}
+ }
+ {
+ \token_if_eq_charcode:NNTF g #1
+ { \exp_not:N \regex_replacement_submatch:w }
+ { #1 }
+ }
}
-\cs_new_nopar:Npn \regex_replacement_escaped_ii:nN #1#2
+\cs_new_nopar:Npn \regex_replacement_submatch:w #1
{
- \regex_token_if_other_digit:NTF #2
- { \regex_replacement_escaped_ii:nN {#1#2} }
- { \exp_not:N \seq_item:Nn \exp_not:N \g_regex_submatches_seq {#1} #2 }
+ \exp_after:wN \token_if_eq_meaning:NNTF \c_lbrace_str #1
+ { \regex_replacement_submatch_aux:nN { } }
+ {
+ \regex_token_if_other_digit:NTF #1
+ { \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } }
+ { \msg_expandable_error:n { \g misused~in~replacement~text. } }
+ #1
+ }
}
-\prg_new_conditional:Npnn \regex_token_if_other_digit:N #1 { TF }
+\cs_new_nopar:Npn \regex_replacement_submatch_aux:nN #1 #2
{
- \if_num:w 9 < 1 \exp_not:N #1 \exp_stop_f:
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
+ \regex_token_if_other_digit:NTF #2
+ { \regex_replacement_submatch_aux:nN {#1#2} }
+ {
+ \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } {#1}
+ \exp_after:wN \token_if_eq_meaning:NNF \c_rbrace_str #2
+ {
+ \msg_expandable_error:n { \g misused~in~replacement~text. }
+ #2
+ }
+ }
}
\cs_new_protected_nopar:Npn \regex_replace_after_group:N #1
{
- \group_insert_after:N \tl_set_eq:NN
+ \group_insert_after:N \tl_set:Nx
\group_insert_after:N #1
- \group_insert_after:N \g_regex_replaced_str
+ \group_insert_after:N {
+ \group_insert_after:N \tl_to_str:N
+ \group_insert_after:N \g_regex_replaced_str
+ \group_insert_after:N }
}
\cs_new_protected:Npn \regex_replace_once_aux:Nn #1#2
{
@@ -1539,15 +1680,16 @@
\regex_extract:
\regex_extract_aux:nTF {0}
{
+ \cs_set_nopar:Npn \regex_tmp:w
+ { \str_skip_do:nn { \l_regex_tmpb_tl } { } }
\tl_gset:Nx \g_regex_replaced_str
{
- \str_from_to:Nnn \l_regex_query_str {0} { \l_regex_tmpa_tl }
+ \regex_query_substr:NN \c_zero \l_regex_tmpa_tl
\l_regex_replacement_tl
- \str_from_to:Nnn \l_regex_query_str
- { \l_regex_tmpb_tl } { \c_max_int }
+ \exp_after:wN \regex_tmp:w \l_regex_query_other_str
}
}
- { \tl_gset_eq:NN \g_regex_replaced_str \l_regex_query_str }
+ { \tl_gset_eq:NN \g_regex_replaced_str \l_regex_query_other_str }
\group_end:
}
\cs_new_protected:Npn \regex_replace_once:nnN #1#2#3
@@ -1592,12 +1734,10 @@
\tl_gclear:N \g_regex_replaced_str
#2
\exp_args:No \regex_match:n {#1}
+ \cs_set_nopar:Npn \regex_tmp:w
+ { \str_skip_do:nn { \l_regex_start_step_int } { } }
\tl_gput_right:Nx \g_regex_replaced_str
- {
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \c_max_int }
- }
+ { \exp_after:wN \regex_tmp:w \l_regex_query_other_str }
\group_end:
}
\cs_new_protected_nopar:Npn \regex_replace_all_aux:
@@ -1607,9 +1747,8 @@
{
\tl_gput_right:Nx \g_regex_replaced_str
{
- \str_from_to:Nnn \l_regex_query_str
- { \int_use:N \l_regex_start_step_int }
- { \l_regex_tmpa_tl }
+ \regex_query_substr:NN
+ \l_regex_start_step_int \l_regex_tmpa_tl
\l_regex_replacement_tl
}
}
@@ -1632,6 +1771,26 @@
\regex_replacement:n {#2}
}
}
+\msg_new:nnn { regex } { -998 } { Unsupported~construct }
+\msg_new:nnn { regex } { -997 }
+ { The~regular~expression~is~too~large~(32768~states). }
+\msg_new:nnn { regex } { 1 } { \iow_char:N\\~at~end~of~pattern }
+\msg_new:nnn { regex } { 4 }
+ { Numbers~out~of~order~in~\iow_char:N\{\iow_char\}~quantifier. }
+\msg_new:nnn { regex } { 6 }
+ { Missing~terminating~\iow_char:N\]~for~character~class }
+\msg_new:nnn { regex } { 7 }
+ { Invalid~escape~sequence~in~character~class }
+\msg_new:nnn { regex } { 8 }
+ { Range~out~of~order~in~character~class }
+\msg_new:nnn { regex } { 22 } { Mismatched~parentheses }
+\msg_new:nnn { regex } { 34 }
+ { Character~value~in~\iow_char:N\\x{...}~sequence~is~too~large }
+\msg_new:nnn { regex } { not-nfa }
+ {
+ LaTeX~was~expecting~a~regular~expression~variable.\\
+ Instead,~LaTeX~found~'#1'.
+ }
%%
%%
%% End of file `l3regex.sty'.
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty
index 9a69d0da0a6..c705f6366b3 100644
--- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty
+++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty
@@ -46,30 +46,27 @@
%%
%% -----------------------------------------------------------------------
\RequirePackage{expl3}
-\GetIdInfo$Id: l3str.dtx 2895 2011-10-09 15:58:19Z joseph $
+\GetIdInfo$Id: l3str.dtx 2921 2011-10-17 13:23:36Z bruno $
{L3 Experimental Strings}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\cs_if_exist:NF \cs_if_exist_use:cF
- {
- \cs_new:Npn \cs_if_exist_use:cF #1
- { \cs_if_exist:cTF {#1} { \use:c {#1} } }
- }
\cs_if_exist:NF \use_i:nnnnnnnn
{ \cs_new:Npn \use_i:nnnnnnnn #1#2#3#4#5#6#7#8 {#1} }
-\cs_set:Npn \str_tmp:w #1
- {
- \cs_new_protected:cpx { str_#1:Nn } ##1##2
- { \exp_not:c { tl_#1:Nx } ##1 { \exp_not:N \tl_to_str:n {##2} } }
- \exp_args:Nc \cs_generate_variant:Nn { str_#1:Nn } { Nx , cn , cx }
- }
-\str_tmp:w {set}
-\str_tmp:w {gset}
-\str_tmp:w {put_left}
-\str_tmp:w {gput_left}
-\str_tmp:w {put_right}
-\str_tmp:w {gput_right}
-\cs_set_protected_nopar:Npn \str_tmp:w { }
+\group_begin:
+ \cs_set_protected_nopar:Npn \str_tmp:w #1
+ {
+ \cs_new_protected:cpx { str_ #1 :Nn } ##1##2
+ { \exp_not:c { tl_ #1 :Nx } ##1 { \exp_not:N \tl_to_str:n {##2} } }
+ \exp_args:Nc \cs_generate_variant:Nn { str_ #1 :Nn } { Nx , cn , cx }
+ }
+ \str_tmp:w { set }
+ \str_tmp:w { gset }
+ \str_tmp:w { put_left }
+ \str_tmp:w { gput_left }
+ \str_tmp:w { put_right }
+ \str_tmp:w { gput_right }
+\group_end:
+\cs_new_protected_nopar:Npn \str_tmp:w { }
\tl_new:N \g_str_tmpa_tl
\tl_new:N \g_str_result_tl
\int_new:N \l_str_char_int
@@ -80,34 +77,31 @@
\tl_const:Nx \c_hash_str { \cs_to_str:N \# }
\tl_const:Nx \c_percent_str { \cs_to_str:N \% }
\group_begin:
-\char_set_lccode:nn {`\*}{`\ }
-\char_set_lccode:nn {`\A}{`\A}
-\tl_to_lowercase:n {
- \group_end:
- \cs_new:Npn \tl_to_other_str:n #1
- {
- \exp_after:wN \tl_to_other_str_loop:w \tl_to_str:n {#1} ~ %
- A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_mark \q_stop
- }
- \cs_new_nopar:Npn \tl_to_other_str_loop:w
+\char_set_lccode:nn { `\* } { `\ }
+\char_set_lccode:nn { `\A } { `\A }
+\tl_to_lowercase:n
+ {
+ \group_end:
+ \cs_new:Npn \tl_to_other_str:n #1
+ {
+ \exp_after:wN \tl_to_other_str_loop:w \tl_to_str:n {#1} ~ %
+ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_mark \q_stop
+ }
+ \cs_new_nopar:Npn \tl_to_other_str_loop:w
#1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 \q_stop
- {
- \if_meaning:w A #8
- \tl_to_other_str_end:w
- \fi:
- \tl_to_other_str_loop:w
- #9 #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * \q_stop
- }
- \cs_new_nopar:Npn \tl_to_other_str_end:w \fi: #1 \q_mark #2 * A #3 \q_stop
- { \fi: #2 }
-}
-\cs_new_nopar:Npn \tl_to_other_str:N
- { \exp_args:No \tl_to_other_str:n }
-\cs_new:Npn \str_sanitize_args:Nn #1 #2
- {
- \exp_args:Nf #1
- { \tl_to_other_str:n {#2} }
+ {
+ \if_meaning:w A #8
+ \tl_to_other_str_end:w
+ \fi:
+ \tl_to_other_str_loop:w
+ #9 #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * \q_stop
+ }
+ \cs_new_nopar:Npn \tl_to_other_str_end:w \fi: #1 \q_mark #2 * A #3 \q_stop
+ { \fi: #2 }
}
+\cs_new_nopar:Npn \tl_to_other_str:N { \exp_args:No \tl_to_other_str:n }
+\cs_new:Npn \str_sanitize_args:Nn #1#2
+ { \exp_args:Nf #1 { \tl_to_other_str:n {#2} } }
\cs_new:Npn \str_sanitize_args:Nnn #1#2#3
{
\exp_args:Nff #1
@@ -141,15 +135,15 @@
\fi:
\c_nine + \str_length_loop:NNNNNNNNN
}
-\cs_set_nopar:Npn \str_head:N { \exp_args:No \str_head:n }
+\cs_new_nopar:Npn \str_head:N { \exp_args:No \str_head:n }
\cs_set:Npn \str_head:n #1
{
\exp_after:wN \str_head_aux:w
\tl_to_str:n {#1}
{ { } } ~ \q_stop
}
-\cs_set_nopar:Npx \str_head_aux:w #1 ~ %
- { \exp_not:N \use_i_delimit_by_q_stop:nw #1 { ~ } }
+\cs_set_nopar:Npn \str_head_aux:w #1 ~ %
+ { \use_i_delimit_by_q_stop:nw #1 { ~ } }
\cs_new:Npn \str_head_ignore_spaces:n #1
{ \exp_after:wN \use_i_delimit_by_q_stop:nw \tl_to_str:n {#1} { } \q_stop }
\cs_new_nopar:Npn \str_head_unsafe:n #1
@@ -169,15 +163,17 @@
}
\cs_new_nopar:Npn \str_tail_unsafe:n #1
{ \str_tail_aux_ii:w #1 X { } X \q_stop }
-\cs_set_nopar:Npn \str_tail_aux_ii:w #1 #2 X #3 \q_stop { #2 }
+\cs_new_nopar:Npn \str_tail_aux_ii:w #1 #2 X #3 \q_stop { #2 }
\cs_new:Npn \str_skip_do:nn #1
{
- \int_compare:nNnTF {#1} > \c_seven
- { \str_skip_aux:nnnnnnnnn }
- { \str_skip_end:n }
+ \if_num:w \int_eval:w #1 > \c_seven
+ \exp_after:wN \str_skip_aux:nnnnnnnnn
+ \else:
+ \exp_after:wN \str_skip_end:n
+ \fi:
{#1}
}
-\cs_new:Npn \str_skip_aux:nnnnnnnnn #1#2 #3#4#5#6#7#8#9
+\cs_new:Npn \str_skip_aux:nnnnnnnnn #1#2#3#4#5#6#7#8#9
{ \exp_args:Nf \str_skip_do:nn { \int_eval:n { #1 - \c_seven } } {#2} }
\cs_new:Npn \str_skip_end:n #1
{
@@ -193,7 +189,7 @@
\else: \str_skip_end_ii:nwn { XXXXXXX }
\fi:
}
-\cs_new:Npn \str_skip_end_ii:nwn #1 #2 \fi: #3
+\cs_new:Npn \str_skip_end_ii:nwn #1#2 \fi: #3
{ \fi: \use_i:nnnnnnnn {#3} #1 }
\cs_new:Npn \str_collect_do:nn #1#2
{ \str_collect_aux:n {#1} { \str_collect_end_iii:nwNNNNNNN {#2} } }
@@ -213,18 +209,18 @@
\cs_new:Npn \str_collect_end:n #1
{
\if_case:w \int_eval:w #1 \int_eval_end:
- \str_collect_end_ii:nwn { {}{}{}{}{}{}{} }
- \or: \str_collect_end_ii:nwn { {}{}{}{}{}{} }
- \or: \str_collect_end_ii:nwn { {}{}{}{}{} }
- \or: \str_collect_end_ii:nwn { {}{}{}{} }
- \or: \str_collect_end_ii:nwn { {}{}{} }
- \or: \str_collect_end_ii:nwn { {}{} }
- \or: \str_collect_end_ii:nwn { {} }
+ \str_collect_end_ii:nwn { { } { } { } { } { } { } { } }
+ \or: \str_collect_end_ii:nwn { { } { } { } { } { } { } }
+ \or: \str_collect_end_ii:nwn { { } { } { } { } { } }
+ \or: \str_collect_end_ii:nwn { { } { } { } { } }
+ \or: \str_collect_end_ii:nwn { { } { } { } }
+ \or: \str_collect_end_ii:nwn { { } { } }
+ \or: \str_collect_end_ii:nwn { { } }
\or: \str_collect_end_ii:nwn { }
- \else: \str_collect_end_ii:nwn { {}{}{}{}{}{}{} }
+ \else: \str_collect_end_ii:nwn { { } { } { } { } { } { } { } }
\fi:
}
-\cs_new:Npn \str_collect_end_ii:nwn #1 #2 \fi: #3
+\cs_new:Npn \str_collect_end_ii:nwn #1#2 \fi: #3
{ \fi: #3 \q_stop #1 }
\cs_new:Npn \str_collect_end_iii:nwNNNNNNN #1 #2 \q_stop #3#4#5#6#7#8#9
{ #1 {#2#3#4#5#6#7#8#9} }
@@ -264,30 +260,30 @@
{ \use_none_delimit_by_q_stop:w }
}
}
-\cs_new_nopar:Npn \str_from_to:Nnn { \exp_args:No \str_from_to:nnn }
-\cs_new:Npn \str_from_to:nnn #1#2#3
+\cs_new_nopar:Npn \str_substr:Nnn { \exp_args:No \str_substr:nnn }
+\cs_new:Npn \str_substr:nnn #1#2#3
{
\exp_args:Nf \tl_to_str:n
- { \str_sanitize_args:Nn \str_from_to_unsafe:nnn {#1}{#2}{#3} }
+ { \str_sanitize_args:Nn \str_substr_unsafe:nnn {#1} {#2} {#3} }
}
-\cs_new:Npn \str_from_to_ignore_spaces:nnn #1
- { \exp_args:No \str_from_to_unsafe:nnn { \tl_to_str:n {#1} } }
-\cs_new:Npn \str_from_to_unsafe:nnn #1#2#3 % <string> <from> <to>
+\cs_new:Npn \str_substr_ignore_spaces:nnn #1
+ { \exp_args:No \str_substr_unsafe:nnn { \tl_to_str:n {#1} } }
+\cs_new:Npn \str_substr_unsafe:nnn #1#2#3
{
- \str_aux_eval_args:Nnnn \str_from_to_aux:nnnw
+ \str_aux_eval_args:Nnnn \str_substr_aux:nnnw
{ \str_length_unsafe:n {#1} }
{#2}
{#3}
#1
\q_stop
}
-\cs_new:Npn \str_from_to_aux:nnnw #1#2#3 % <len> <from> <to>
+\cs_new:Npn \str_substr_aux:nnnw #1#2#3
{
- \exp_args:Nf \str_from_to_aux_ii:nnw
+ \exp_args:Nf \str_substr_aux_ii:nnw
{ \str_aux_normalize_range:nn {#2} {#1} }
{ \str_aux_normalize_range:nn {#3} {#1} }
}
-\cs_new:Npn \str_from_to_aux_ii:nnw #1#2
+\cs_new:Npn \str_substr_aux_ii:nnw #1#2
{
\str_skip_do:nn {#1}
{
@@ -376,7 +372,7 @@
}
\prg_new_protected_conditional:Npnn \str_aux_hexadecimal_test:N #1 { TF }
{
- \tl_if_in:onTF { \tl_to_str:n {abcdef} } {#1}
+ \tl_if_in:onTF { \tl_to_str:n { abcdef } } {#1}
{
\int_set:Nn \l_str_char_int
{ \c_sixteen * \l_str_char_int + `#1 - 87 }
@@ -423,7 +419,7 @@
\cs_set_nopar:Npn \str_aux_escape_unescaped:N { #1 }
\cs_set_nopar:Npn \str_aux_escape_escaped:N { #2 }
\cs_set_nopar:Npn \str_aux_escape_raw:N { #3 }
- \int_set:Nn \tex_escapechar:D {92}
+ \int_set:Nn \tex_escapechar:D { 92 }
\tl_gset:Nx \g_str_result_tl { \tl_to_other_str:n {#4} }
\tl_gset:Nx \g_str_result_tl
{
@@ -531,28 +527,22 @@
}
}
\group_end:
-\msg_new:nnn { str } { x-missing-brace }
- {
- You~wrote~something~like~
- `\iow_char:N\\x\{ \int_to_hexadecimal:n { \l_str_char_int }'.~
- The~closing~brace~is~missing.
- }
\group_begin:
- \char_set_catcode_other:n {`\^^@}
+ \char_set_catcode_other:n { `\^^@ }
\cs_new_protected_nopar:Npn \str_aux_convert_store:
{
- \char_set_lccode:nn {\c_zero} {\l_str_char_int}
+ \char_set_lccode:nn { \c_zero } { \l_str_char_int }
\tl_to_lowercase:n { \tl_gput_right:Nx \g_str_result_tl {^^@} }
}
\cs_new_protected_nopar:Npn \str_aux_convert_store:NNn #1#2#3
{
- \char_set_lccode:nn {\c_zero} {#3}
+ \char_set_lccode:nn { \c_zero } {#3}
\tl_to_lowercase:n { #1 #2 {^^@} }
}
\group_end:
\cs_new_nopar:Npn \str_aux_byte_to_hexadecimal:N #1
{
- \int_compare:nNnTF {`#1} < {256}
+ \int_compare:nNnTF {`#1} < { 256 }
{
\int_to_letter:n { \int_div_truncate:nn {`#1} \c_sixteen }
\int_to_letter:n { \int_mod:nn {`#1} \c_sixteen }
@@ -561,14 +551,14 @@
}
\cs_new_nopar:Npn \str_aux_byte_to_octal:N #1
{
- \int_compare:nNnTF {`#1} < {64}
+ \int_compare:nNnTF {`#1} < { 64 }
{
0
\int_to_letter:n { \int_div_truncate:nn {`#1} \c_eight }
\int_to_letter:n { \int_mod:nn {`#1} \c_eight }
}
{
- \int_compare:nNnTF {`#1} < {256}
+ \int_compare:nNnTF {`#1} < { 256 }
{ \int_to_octal:n {`#1} }
{ \msg_expandable_error:n { Invalid~byte~`#1'. } }
}
@@ -579,7 +569,7 @@
{ \str_map_tokens:Nn #2 \str_aux_byte_to_hexadecimal:N }
}
\tl_const:Nx \c_str_bytes_escape_name_str
- { \c_hash_str \c_percent_str \c_lbrace_str \c_rbrace_str () /<>[] }
+ { \c_hash_str \c_percent_str \c_lbrace_str \c_rbrace_str ()/<>[] }
\cs_new_protected_nopar:Npn \str_bytes_escape_name:NN #1#2
{
\str_set:Nx #1
@@ -587,10 +577,10 @@
}
\cs_new_nopar:Npn \str_bytes_escape_name_aux:N #1
{
- \int_compare:nNnTF {`#1} < {"21}
+ \int_compare:nNnTF {`#1} < { "21 }
{ \c_hash_str \str_aux_byte_to_hexadecimal:N #1 }
{
- \int_compare:nNnTF {`#1} > {"7E}
+ \int_compare:nNnTF {`#1} > { "7E }
{ \c_hash_str \str_aux_byte_to_hexadecimal:N #1 }
{
\str_if_contains_char:NNTF \c_str_bytes_escape_name_str #1
@@ -607,10 +597,10 @@
}
\cs_new_nopar:Npn \str_bytes_escape_string_aux:N #1
{
- \int_compare:nNnTF {`#1} < {"21}
+ \int_compare:nNnTF {`#1} < { "21 }
{ \c_backslash_str \str_aux_byte_to_octal:N #1 }
{
- \int_compare:nNnTF {`#1} > {"7E}
+ \int_compare:nNnTF {`#1} > { "7E }
{ \c_backslash_str \str_aux_byte_to_octal:N #1 }
{
\str_if_contains_char:NNT \c_str_bytes_escape_string_str #1
@@ -719,16 +709,16 @@
{
\prg_case_str:xxn {#2}
{
- {n} {10}
- {r} {13}
- {t} {9}
- {b} {8}
- {f} {12}
- {(} {40}
- {)} {41}
- {\c_backslash_str} {92}
- {^^J} {-1}
- {^^M} {-1}
+ { n } { 10 }
+ { r } { 13 }
+ { t } { 9 }
+ { b } { 8 }
+ { f } { 12 }
+ { ( } { 40 }
+ { ) } { 41 }
+ { \c_backslash_str } { 92 }
+ { ^^J } { -1 }
+ { ^^M } { -1 }
}
{`#2}
}
@@ -768,14 +758,14 @@
}
\cs_new_nopar:Npn \str_bytes_percent_encode_aux:N #1
{
- \int_compare:nNnTF {`#1} < {"41}
+ \int_compare:nNnTF {`#1} < { "41 }
{
\str_if_contains_char:NNTF \c_str_bytes_percent_encode_not_str #1
{ #1 }
{ \c_percent_str \str_aux_byte_to_hexadecimal:N #1 }
}
{
- \int_compare:nNnTF {`#1} > {"7E}
+ \int_compare:nNnTF {`#1} > { "7E }
{ \c_percent_str \str_aux_byte_to_hexadecimal:N #1 }
{
\str_if_contains_char:NNTF \c_str_bytes_percent_encode_str #1
@@ -837,19 +827,18 @@
\cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_i:N #1
{
\quark_if_recursion_tail_stop:N #1
- \int_set:Nn \l_str_char_int { `#1 }
- \str_native_from_UTF_viii_aux_ii:nN {128} \c_one
- \str_native_from_UTF_viii_aux_ii:nN {64} \c_zero
- \str_native_from_UTF_viii_aux_ii:nN {32} \c_two
- \str_native_from_UTF_viii_aux_ii:nN {16} \c_three
- \str_native_from_UTF_viii_aux_ii:nN {8} \c_four
+ \int_set:Nn \l_str_char_int {`#1}
+ \str_native_from_UTF_viii_aux_ii:nN { 128 } \c_one
+ \str_native_from_UTF_viii_aux_ii:nN { 64 } \c_zero
+ \str_native_from_UTF_viii_aux_ii:nN { 32 } \c_two
+ \str_native_from_UTF_viii_aux_ii:nN { 16 } \c_three
+ \str_native_from_UTF_viii_aux_ii:nN { 8 } \c_four
\msg_error:nnx { str } { utf8-invalid-byte } {#1}
\use_i:nnn \str_native_from_UTF_viii_aux_i:N
\q_stop
\str_native_from_UTF_viii_aux_iii:N
}
-\cs_new_protected_nopar:Npn
- \str_native_from_UTF_viii_aux_ii:nN #1#2
+\cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_ii:nN #1#2
{
\int_compare:nNnTF \l_str_char_int < {#1}
{
@@ -858,8 +847,7 @@
}
{ \int_sub:Nn \l_str_char_int {#1} }
}
-\cs_new_protected_nopar:Npn
- \str_native_from_UTF_viii_aux_iii:N #1
+\cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_iii:N #1
{
\int_compare:nNnTF \l_str_bytes_int < \c_two
{ \str_native_from_UTF_viii_aux_iv: #1 }
@@ -869,11 +857,11 @@
\exp_after:wN \use_none_delimit_by_q_recursion_stop:w
\fi:
\quark_if_recursion_tail_stop:N #1
- \tex_multiply:D \l_str_char_int by 64 \scan_stop: % no interface??
+ \tex_multiply:D \l_str_char_int by 64 \scan_stop:
\int_decr:N \l_str_bytes_int
- \int_compare:nNnTF {`#1} < {128}
+ \int_compare:nNnTF {`#1} < { 128 }
{ \use_ii:nn }
- { \int_compare:nNnTF {`#1} < {192} }
+ { \int_compare:nNnTF {`#1} < { 192 } }
{
\int_add:Nn \l_str_char_int { `#1 - 128 }
\str_native_from_UTF_viii_aux_iii:N
@@ -884,47 +872,32 @@
}
}
}
-\cs_new_protected_nopar:Npn
- \str_native_from_UTF_viii_aux_iv:
+\cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_iv:
{
\int_compare:nNnTF \l_str_bytes_int = \c_zero
{
\msg_error:nnx { str } { utf8-extra-byte }
{ \int_eval:n { \l_str_char_int + 128 } }
}
+ { \str_native_from_UTF_viii_aux_v: }
+ \str_native_from_UTF_viii_aux_i:N
+ }
+\pdftex_if_engine:TF
+ {
+ \cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_v:
{
- \pdftex_if_engine:TF
+ \int_compare:nNnTF { \l_str_char_int } < { 256 }
+ { \str_aux_convert_store: }
{
- \int_compare:nNnTF { \l_str_char_int } < { 256 }
- { \str_aux_convert_store: }
- {
- \msg_error:nnx { str } { utf8-pdftex-overflow }
- { \int_use:N \l_str_char_int }
- }
+ \msg_error:nnx { str } { utf8-pdftex-overflow }
+ { \int_use:N \l_str_char_int }
}
- { \str_aux_convert_store: }
}
- \str_native_from_UTF_viii_aux_i:N
}
-\msg_new:nnn { str } { utf8-invalid-byte }
{
- \int_compare:nNnTF {`#1} < {256}
- { Byte~number~\int_eval:n {`#1}~invalid~in~utf-8~encoding. }
- { The~character~number~\int_eval:n {`#1}~is~not~a~byte. }
+ \cs_new_protected_nopar:Npn \str_native_from_UTF_viii_aux_v:
+ { \str_aux_convert_store: }
}
-\msg_new:nnn { str } { utf8-missing-byte }
- { The~byte~number~\int_eval:n {`#1}~is~not~a~valid~continuation~byte. }
-\msg_new:nnn { str } { utf8-extra-byte }
- { The~byte~number~\int_eval:n {`#1}~is~only~valid~as~a~continuation~byte. }
-\msg_new:nnnn { str } { utf8-premature-end }
- { Incomplete~last~utf8~character. }
- {
- The~sequence~of~byte~that~I~need~to~convert~to~utf8 \
- ended~before~the~last~character~was~complete.~Perhaps \
- it~was~mistakenly~truncated?
- }
-\msg_new:nnn { str } { utf8-pdftex-overflow }
- { The~character~number~#1~is~too~big~for~pdfTeX. }
\cs_new_protected_nopar:Npn \str_UTF_viii_from_native:NN #1#2
{
\group_begin:
@@ -936,14 +909,14 @@
\cs_new_protected_nopar:Npn \str_UTF_viii_from_native_aux_i:N #1
{
\int_set:Nn \l_str_char_int {`#1}
- \int_compare:nNnTF \l_str_char_int < {128}
+ \int_compare:nNnTF \l_str_char_int < { 128 }
{ \tl_gput_right:Nx \g_str_result_tl {#1} }
{
\tl_gclear:N \g_str_tmpa_tl
\int_set:Nn \l_str_bytes_int { 64 }
- \str_UTF_viii_from_native_aux_ii:n {32}
- \str_UTF_viii_from_native_aux_ii:n {16}
- \str_UTF_viii_from_native_aux_ii:n {8}
+ \str_UTF_viii_from_native_aux_ii:n { 32 }
+ \str_UTF_viii_from_native_aux_ii:n { 16 }
+ \str_UTF_viii_from_native_aux_ii:n { 8 }
\ERROR % somehow the unicode char was > "1FFFFF > "10FFFF
\tl_gclear:N \g_str_tmpa_tl
\use_none:n \q_stop
@@ -956,15 +929,41 @@
{
\str_aux_convert_store:NNn
\tl_gput_left:Nx \g_str_tmpa_tl
- { 128 + \int_mod:nn { \l_str_char_int } {64} }
- \tex_divide:D \l_str_char_int by 64 \scan_stop: % no interface??
+ { 128 + \int_mod:nn { \l_str_char_int } { 64 } }
+ \tex_divide:D \l_str_char_int by 64 \scan_stop:
\int_add:Nn \l_str_bytes_int {#1}
\int_compare:nNnT \l_str_char_int < {#1}
{ \use_none_delimit_by_q_stop:w }
}
-\cs_gset:Npn \str_length_skip_spaces:N
+\msg_new:nnnn { str } { x-missing-brace }
+ { Missing~closing~brace~in~ \token_to_str:N \x ~byte~sequence. }
+ {
+ You~wrote~something~like~
+ `\iow_char:N\\x\{ \int_to_hexadecimal:n { \l_str_char_int }'.~
+ The~closing~brace~is~missing.
+ }
+\msg_new:nnn { str } { utf8-invalid-byte }
+ {
+ \int_compare:nNnTF {`#1} < { 256 }
+ { Byte~number~ \int_eval:n {`#1} ~invalid~in~utf-8~encoding. }
+ { The~character~number~ \int_eval:n {`#1} ~is~not~a~byte. }
+ }
+\msg_new:nnn { str } { utf8-missing-byte }
+ { The~byte~number~ \int_eval:n {`#1} ~is~not~a~valid~continuation~byte. }
+\msg_new:nnn { str } { utf8-extra-byte }
+ { The~byte~number~ \int_eval:n {`#1} ~is~only~valid~as~a~continuation~byte. }
+\msg_new:nnnn { str } { utf8-premature-end }
+ { Incomplete~last~UTF8~character. }
+ {
+ The~sequence~of~byte~that~to~be~converted~to~UTF8~
+ ended~before~the~last~character~was~complete.~Perhaps~
+ it~was~mistakenly~truncated?
+ }
+\msg_new:nnn { str } { utf8-pdftex-overflow }
+ { The~character~number~#1~is~too~big~for~pdfTeX. }
+\cs_set:Npn \str_length_skip_spaces:N
{ \exp_args:No \str_length_skip_spaces:n }
-\cs_gset_eq:NN \str_length_skip_spaces:n \str_length_ignore_spaces:n
+\cs_set_eq:NN \str_length_skip_spaces:n \str_length_ignore_spaces:n
%%
%%
%% End of file `l3str.sty'.
diff --git a/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty b/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty
index 79490432742..9d4a42407e3 100644
--- a/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty
+++ b/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty
@@ -47,7 +47,7 @@
%% -----------------------------------------------------------------------
%%
\RequirePackage{xparse}
-\GetIdInfo$Id: xcoffins.dtx 2895 2011-10-09 15:58:19Z joseph $
+\GetIdInfo$Id: xcoffins.dtx 2963 2011-11-15 22:06:41Z joseph $
{L3 Experimental design-level coffins}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
@@ -146,6 +146,14 @@
{ \coffin_resize:Nnn #1 {#2} {#3} }
\NewDocumentCommand \ScaleCoffin { m m m }
{ \coffin_scale:Nnn #1 {#2} {#3} }
+\NewDocumentCommand \CoffinDepth { m }
+ { \coffin_dp:N #1 }
+\NewDocumentCommand \CoffinHeight { m }
+ { \coffin_ht:N #1 }
+\NewDocumentCommand \CoffinTotalHeight { m }
+ { \dim_eval:w \coffin_ht:N #1 + \coffin_dp:N #1 \dim_eval_end: }
+\NewDocumentCommand \CoffinWidth { m }
+ { \coffin_wd:N #1 }
\NewDocumentCommand \DisplayCoffinHandles { m m }
{
\cs_if_exist:cTF { l_coffin_poles_ \int_value:w #1 _prop }
diff --git a/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty b/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty
index b626f072d30..e8a3345204f 100644
--- a/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty
+++ b/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty
@@ -48,11 +48,14 @@
%% -----------------------------------------------------------------------
%%
\RequirePackage{l3names}
-\GetIdInfo$Id: l3galley.dtx 2899 2011-10-09 21:22:06Z joseph $
+\GetIdInfo$Id: l3galley.dtx 2938 2011-10-25 18:41:20Z joseph $
{L3 Experimental galley code}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
\package_check_loaded_expl:
+\cs_new_protected:Npn \scan_marker_new:N #1
+ { \cs_new_eq:NN #1 \scan_stop: }
+\cs_generate_variant:Nn \scan_marker_new:N { c }
\cs_new_protected_nopar:Npn \galley_leave_vmode:
{ \tex_unhbox:D \c_empty_box }
\clist_new:N \l_galley_parshape_left_indent_clist
@@ -69,7 +72,6 @@
\cs_new_eq:NN \l_galley_width_dim \tex_hsize:D
\bool_new:N \g_galley_begin_level_bool
\bool_new:N \l_galley_begin_level_bool
-\bool_gset_true:N \g_galley_begin_level_bool
\bool_new:N \g_galley_omit_next_indent_bool
\bool_new:N \l_galley_omit_next_indent_bool
\bool_new:N \g_galley_parshape_set_bool
@@ -107,9 +109,10 @@
\bool_gset_false:N \g_galley_parshape_set_bool
\int_gzero:N \g_galley_previous_par_lines_int
\tl_gclear:N \g_galley_restore_running_tl
- \tl_gclear:N \g_galley_whatsits_previous_tl
- \tl_gclear:N \g_galley_whatsits_next_tl
+ \tl_gclear:N \g_galley_whatsit_previous_tl
+ \tl_gclear:N \g_galley_whatsit_next_tl
}
+\galley_initialise_variables:
\cs_new_protected_nopar:Npn \galley_initialise_settings:
{
\dim_set_eq:NN \l_galley_text_width_dim \l_galley_width_dim
@@ -142,10 +145,10 @@
\g_galley_previous_par_lines_int
\tl_set_eq:NN \l_galley_restore_running_tl
\g_galley_restore_running_tl
- \tl_set_eq:NN \l_galley_whatsits_previous_tl
- \g_galley_whatsits_previous_tl
- \tl_set_eq:NN \l_galley_whatsits_next_tl
- \g_galley_whatsits_next_tl
+ \tl_set_eq:NN \l_galley_whatsit_previous_tl
+ \g_galley_whatsit_previous_tl
+ \tl_set_eq:NN \l_galley_whatsit_next_tl
+ \g_galley_whatsit_next_tl
}
\cs_new_protected_nopar:Npn \galley_restore_parameters:
{
@@ -171,10 +174,10 @@
\l_galley_previous_par_lines_int
\tl_gset_eq:NN \g_galley_restore_running_tl
\l_galley_restore_running_tl
- \tl_gset_eq:NN \g_galley_whatsits_previous_tl
- \l_galley_whatsits_previous_tl
- \tl_gset_eq:NN \g_galley_whatsits_next_tl
- \l_galley_whatsits_next_tl
+ \tl_gset_eq:NN \g_galley_whatsit_previous_tl
+ \l_galley_whatsit_previous_tl
+ \tl_gset_eq:NN \g_galley_whatsit_next_tl
+ \l_galley_whatsit_next_tl
}
\cs_new_protected_nopar:Npn \galley_level:
{
@@ -190,8 +193,28 @@
\galley_restore_parameters:
\group_end:
}
+\scan_marker_new:N \s_par_omit
\cs_new_protected_nopar:Npn \galley_std_par:
{
+ \s_par_omit
+ \exp_after:wN \galley_std_par_aux_i: \tex_romannumeral:D - `0
+ }
+\cs_new_protected:Npn \galley_std_par_aux_i:
+ {
+ \peek_meaning:NTF \s_par_omit
+ { \galley_std_par_aux:N }
+ { \galley_std_par_aux_ii: }
+ }
+\cs_new_protected:Npn \galley_std_par_aux:N #1
+ {
+ \str_if_eq:xxF {#1} { \s_par_omit }
+ {
+ \galley_std_par_aux_ii:
+ #1
+ }
+ }
+\cs_new_protected_nopar:Npn \galley_std_par_aux_ii:
+ {
\mode_if_vertical:TF
{ \tex_par:D }
{
@@ -206,6 +229,15 @@
\tl_gclear:N \g_galley_par_after_hook_tl
\tex_penalty:D \c_ten_thousand
}
+\cs_new_protected:Npn \galley_end_par:n #1
+ {
+ \s_par_omit
+ \bool_if:nF \g_galley_begin_level_bool
+ {
+ #1
+ \galley_std_par:
+ }
+ }
\cs_set_protected_nopar:Npn \par { \galley_std_par: }
\tl_set:Nn \@par { \galley_std_par: }
\cs_new_protected_nopar:Npn \galley_display_begin:
@@ -354,14 +386,14 @@
{
\g_galley_whatsit_next_tl
\tl_gclear:N \g_galley_whatsit_next_tl
- \bool_if:NT \g_galley_omit_next_indent_bool
+ \bool_if:NF \g_galley_omit_next_indent_bool
{
- \box_if_empty:NF \g_galley_last_box
+ \box_if_empty:NF \g_galley_last_box
{ \hbox_to_wd:nn \l_galley_par_indent_dim { } }
}
\skip_horizontal:N \l_galley_par_begin_skip
\g_galley_par_begin_hook_tl
- \bool_gset_true:N \g_galley_omit_next_indent_bool
+ \bool_gset_false:N \g_galley_omit_next_indent_bool
}
\cs_new_protected_nopar:Npn \galley_restore_running_parameters:
{
@@ -732,6 +764,20 @@
{ \int_use:N \etex_widowpenalties:D \int_eval:w #1 \int_eval_end: , }
\cs_new_protected_nopar:Npn \galley_interline_penalty:
{ \int_use:N \etex_interlinepenalties:D \etex_interlinepenalties:D \c_zero }
+\cs_set_protected_nopar:Npn \nobreak
+ { \bool_gset_true:N \g_galley_no_break_next_bool }
+\cs_set_protected_nopar:Npn \noindent
+ {
+ \tex_noindent:D
+ \bool_gset_false:N \g_galley_omit_next_indent_bool
+ }
+\cs_set_protected_nopar:Npn \vspace #1
+ {
+ \@ifstar
+ { \galley_set_user_vspace:n {#1} }
+ { \galley_set_user_vspace:n {#1} }
+ }
+\cs_set_eq:NN \@@par \galley_std_par:
\cs_set_protected_nopar:Npn \@afterheading
{
\bool_gset_true:N \g_galley_no_break_next_bool
@@ -742,6 +788,8 @@
}
\cs_set_protected:Npn \@hangfrom #1
{
+ \bool_gset_true:N \g_galley_omit_next_indent_bool
+ \leavevmode
\setbox \@tempboxa = \hbox { {#1} }
\galley_parshape_single_par:nnnN
\c_one
@@ -749,16 +797,9 @@
\c_zero_dim
\c_false_bool
\bool_gset_true:N \g_galley_no_break_next_bool
- \bool_gset_true:N \galley_omit_next_indent_bool
+ \bool_gset_true:N \g_galley_omit_next_indent_bool
\box \@tempboxa
}
-\cs_set_protected:Npn \@makefntext #1
- {
- \UseTemplate { justification } { std } { indent-width = 1 em }
- \bool_gset_true:N \galley_omit_next_indent_bool
- \galley_leave_vmode:
- \hb@xt@ 1.8em { \hss \@makefnmark } #1
- }
%%
%%
%% End of file `l3galley.sty'.
diff --git a/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty b/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty
index 160fca57631..5ebe766a12b 100644
--- a/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty
+++ b/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty
@@ -48,7 +48,7 @@
%% -----------------------------------------------------------------------
%%
\RequirePackage{l3names}
-\GetIdInfo$Id: xgalley.dtx 2895 2011-10-09 15:58:19Z joseph $
+\GetIdInfo$Id: xgalley.dtx 2922 2011-10-17 19:01:04Z joseph $
{L3 Experimental galley}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
@@ -606,11 +606,6 @@
{ \skip_eval:n { \l_galley_display_end_vspace_tl } }
}
}
-\RenewDocumentCommand \nobreak { }
- { \bool_gset_true:N \g_galley_no_break_next_bool }
-\RenewDocumentCommand \noindent { }
- { \bool_gset_false:N \g_galley_omit_next_indent_bool }
-\RenewDocumentCommand \vspace { s m } { \galley_set_vspace_user:n {#2} }
%%
%%
%% End of file `xgalley.sty'.