diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3regex.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3regex.dtx | 565 |
1 files changed, 343 insertions, 222 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx index fd57d6736cb..625907bf5a0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/05/29} +% \date{Released 2017/07/15} % % \maketitle % @@ -70,15 +70,16 @@ % \enquote{\texttt{This cat.}}, where the first % occurrence of \enquote{\texttt{at}} was replaced % by \enquote{\texttt{is}}. A more complicated example is -% a pattern to add a comma at the end of each word: +% a pattern to emphasize each word and add a comma after it: % \begin{verbatim} -% \regex_replace_all:nnN { \w+ } { \0 , } \l_my_tl +% \regex_replace_all:nnN { \w+ } { \c{emph}\cB\{ \0 \cE\} , } \l_my_tl % \end{verbatim} -% The |\w| sequence represents any \enquote{word} character, -% and |+| indicates that the |\w| sequence should be repeated -% as many times as possible (at least once), hence matching a word in the -% input token list. In the replacement text, |\0| denotes the full match -% (here, a word). +% The |\w| sequence represents any \enquote{word} character, and |+| +% indicates that the |\w| sequence should be repeated as many times as +% possible (at least once), hence matching a word in the input token +% list. In the replacement text, |\0| denotes the full match (here, a +% word). The command |\emph| is inserted using |\c{emph}|, and its +% argument |\0| is put between braces |\cB\{| and |\cE\}|. % % If a regular expression is to be used several times, % it can be compiled once, and stored in a regex @@ -97,6 +98,55 @@ % % \subsection{Syntax of regular expressions} % +% We start with a few examples, and encourage the reader to apply +% \cs{regex_show:n} to these regular expressions. +% \begin{itemize} +% \item |Cat| matches the word \enquote{Cat} capitalized in this way, +% but also matches the beginning of the word \enquote{Cattle}: use +% |\bCat\b| to match a complete word only. +% \item |[abc]| matches one letter among \enquote{a}, \enquote{b}, +% \enquote{c}; the pattern \verb"(a|b|c)" matches the same three +% possible letters (but see the discussion of submatches below). +% \item |[A-Za-z]*| matches any number (due to the quantifier +% \verb"*") of Latin letters (not accented). +% \item |\c{[A-Za-z]*}| matches a control sequence made of Latin +% letters. +% \item |\_[^\_]*\_| matches an underscore, any number of characters +% other than underscore, and another underscore; it is equivalent to +% |\_.*?\_| where |.| matches arbitrary characters and the +% lazy quantifier |*?| means to match as few characters as +% possible, thus avoiding matching underscores. +% \item |[+-]?\d+| matches an explicit integer with at most one +% sign. +% \item \verb*"[+-\ ]*\d+\ *" matches an explicit integer with any +% number of $+$ and $-$ signs, with spaces allowed except within the +% mantissa, and sourrounded by spaces. +% \item \verb*"[+-\ ]*(\d+|\d*\.\d+)\ *" matches an explict integer or +% decimal number; using \verb*"[.,]" instead of \verb*"\." would allow +% the comma as a decimal marker. +% \item +% \verb*"[+-\ ]*(\d+|\d*\.\d+)\ *((?i)pt|in|[cem]m|ex|[bs]p|[dn]d|[pcn]c)\ *" +% matches an explicit dimension with any unit that \TeX{} knows, where +% \verb*"(?i)" means to treat lowercase and uppercase letters +% identically. +% \item \verb*"[+-\ ]*((?i)nan|inf|(\d+|\d*\.\d+)(\ *e[+-\ ]*\d+)?)\ *" +% matches an explicit floating point number or the special values +% \verb*"nan" and \verb*"inf" (with signs). +% \item \verb*"[+-\ ]*(\d+|\cC.)\ *" matches an explicit integer or +% control sequence (without checking whether it is an integer +% variable). +% \item |\G.*?\K| at the beginning of a regular expression matches and +% discards (due to |\K|) everything between the end of the previous +% match (|\G|) and what is matched by the rest of the regular +% expression; this is useful in \cs{regex_replace_all:nnN} when the +% goal is to extract matches or submatches in a finer way than with +% \cs{regex_extract_all:nnN}. +% \end{itemize} +% While it is impossible for a regular expression to match only integer +% expressions, \verb*"[+-\(]*\d+\)*([+-*/][+-\(]*\d+\)*)*" matches among +% other things all valid integer expressions (made only with explicit +% integers). One should follow it with further testing. +% % Most characters match exactly themselves, % with an arbitrary category code. Some characters are % special and must be escaped with a backslash (\emph{e.g.}, |\*| @@ -114,7 +164,7 @@ % \item spaces should always be escaped (even in character % classes); % \item any other character may be escaped or not, without any -% effect: both versions will match exactly that character. +% effect: both versions match exactly that character. % \end{itemize} % Note that these rules play nicely with the fact that many % non-alphanumeric characters are difficult to input into \TeX{} @@ -161,7 +211,7 @@ % \item[\\V] Any token not matched by |\v|. % \item[\\W] Any token not matched by |\w|. % \end{l3regex-syntax} -% Of those, |.|, |\D|, |\H|, |\N|, |\S|, |\V|, and |\W| will match arbitrary +% Of those, |.|, |\D|, |\H|, |\N|, |\S|, |\V|, and |\W| match arbitrary % control sequences. % % Character classes match exactly one token in the subject. @@ -208,7 +258,7 @@ % or two |\W| tokens (including the boundary). % \item[\char`^ \textrm{or} \\A] % Start of the subject token list. -% \item[\char`$\textrm{,} \\Z \textrm{or} \\z] +% \item[\char`$\textrm{,} \\Z \textrm{or} \\z] ^^A $ % End of the subject token list. % \item[\\G] Start of the current match. This is only different from |^| % in the case of multiple matches: for instance @@ -225,7 +275,7 @@ % \item[(?:\ldots{})] Non-capturing group. % \item[(?\char`|\ldots{})] Non-capturing group which resets % the group number for capturing groups in each alternative. -% The following group will be numbered with the first unused +% The following group is numbered with the first unused % group number. % \end{l3regex-syntax} % @@ -335,12 +385,12 @@ % % Most of the features described in regular expressions do not make % sense within the replacement text. Backslash introduces various -% special constructions: +% special constructions, described further below: % \begin{itemize} % \item |\0| is the whole match; -% \item |\1|, |\2|, \ldots{}, |\9| or |\g{|\meta{number}|}| are the -% submatches (empty if there are fewer than \meta{number} capturing -% groups); +% \item |\1| is the submatch that was matched by the first (capturing) +% group |(...)|; similarly for |\2|, \ldots{}, |\9| and +% |\g{|\meta{number}|}|; % \item \verb*|\ | inserts a space (spaces are ignored when not % escaped); % \item |\a|, |\e|, |\f|, |\n|, |\r|, |\t|, |\xhh|, |\x{hhh}| @@ -363,8 +413,15 @@ % \end{verbatim} % results in \cs{l_my_tl} holding |H(ell--el)(o,--o) w(or--o)(ld--l)!| % -% Submatches always keep the same category codes as in the original -% token list. +% The submatches are numbered according to the order in which the +% opening parenthesis of capturing groups appear in the regular +% expression to match. The $n$-th submatch is empty if there are fewer +% than $n$ capturing groups or for capturing groups that appear in +% alternatives that were not used for the match. In case a capturing +% group matches several times during a match (due to quantifiers) only +% the last match is used in the replacement text. Submatches always keep +% the same category codes as in the original token list. +% % The characters inserted by the replacement have category code $12$ % (other) by default, with the exception of space characters. Spaces % inserted through \verb*|\ | have category code $10$, while spaces @@ -375,8 +432,9 @@ % \item[\\cX(\ldots{})] Produces the characters \enquote{\ldots{}} with % category~|X|, which must be one of |CBEMTPUDSLOA| as in regular % expressions. Parentheses are optional for a single character (which -% can be an escape sequence). This can be nested, for instance -% |\cL(Hello\cS\ world)!| +% can be an escape sequence). When nested, the innermost category +% code applies, for instance |\cL(Hello\cS\ world)!| gives this text +% with standard category codes. % \item[\\c\Arg{text}] Produces the control sequence with csname % \meta{text}. The \meta{text} may contain references to the % submatches |\0|, |\1|, and so on, as in the example for |\u| below. @@ -384,12 +442,11 @@ % % The escape sequence |\u|\Arg{tl~var~name} allows to insert the % contents of the token list with name \meta{tl~var~name} directly into -% the replacement, giving an easier control of category codes. -% Within |\c{|\ldots{}|}| and |\u{|\ldots{}|}| constructions, the |\u| -% and |\c|~escape sequences perform \cs{tl_to_str:v}, namely extract the -% value of the control sequence and turn it into a string. -% -% Matches can be used within the arguments of |\c| and |\u|. For +% the replacement, giving an easier control of category codes. When +% nested in |\c{|\ldots{}|}| and |\u{|\ldots{}|}| constructions, the +% |\u| and |\c|~escape sequences perform \cs{tl_to_str:v}, namely +% extract the value of the control sequence and turn it into a string. +% Matches can also be used within the arguments of |\c| and |\u|. For % instance, % \begin{verbatim} % \tl_set:Nn \l_my_one_tl { first } @@ -415,7 +472,7 @@ % \end{syntax} % Creates a new \meta{regex~var} or raises an error if the % name is already taken. The declaration is global. The -% \meta{regex~var} will initially be such that it never matches. +% \meta{regex~var} is initially such that it never matches. % \end{function} % % \begin{function}[added = 2017-05-26] @@ -432,7 +489,7 @@ % \end{verbatim} % The assignment is local for \cs{regex_set:Nn} and global for % \cs{regex_gset:Nn}. Use \cs{regex_const:Nn} for compiled expressions -% which will never change. +% which never change. % \end{function} % % \begin{function}[added = 2017-05-26]{\regex_show:n, \regex_show:N} @@ -502,26 +559,29 @@ % \cs{regex_extract_once:nnN} \Arg{regex} \Arg{token list} \meta{seq~var} % \cs{regex_extract_once:nnNTF} \Arg{regex} \Arg{token list} \meta{seq~var} \Arg{true code} \Arg{false code} % \end{syntax} -% Finds the first match of the \meta{regular expression} -% in the \meta{token list}. 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 parenthesis. The \meta{seq~var} -% is assigned locally. If there is no match, -% the \meta{seq~var} is cleared. -% The testing versions insert the \meta{true code} into the input -% stream if a match was found, and the \meta{false code} otherwise. +% Finds the first match of the \meta{regular expression} in the +% \meta{token list}. If it exists, the match is stored as the first +% item of the \meta{seq~var}, and further items are the contents of +% capturing groups, in the order of their opening parenthesis. The +% \meta{seq~var} is assigned locally. If there is no match, the +% \meta{seq~var} is cleared. 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_once:nnNTF { \A(La)?TeX(!*)\Z } { LaTeX!!! } \l_foo_seq % { true } { false } % \end{verbatim} % Then the regular expression (anchored at the start with |\A| and -% at the end with |\Z|) will match the whole token list. The first +% at the end with |\Z|) must match the whole token list. The first % capturing group, |(La)?|, matches |La|, and the second capturing -% group, |(!*)|, matches |!!!|. Thus, |\l_foo_seq| will contain +% group, |(!*)|, matches |!!!|. Thus, |\l_foo_seq| contains as a result % the items |{LaTeX!!!}|, |{La}|, and |{!!!}|, and the \texttt{true} % branch is left in the input stream. +% Note that the $n$-th item of |\l_foo_seq|, as obtained using +% \cs{seq_item:Nn}, correspond to the submatch numbered $(n-1)$ in +% functions such as \cs{regex_replace_once:nnN}. % \end{function} % % \begin{function}[TF, added = 2017-05-26] @@ -543,7 +603,7 @@ % \regex_extract_all:nnNTF { \w+ } { Hello,~world! } \l_foo_seq % { true } { false } % \end{verbatim} -% Then the regular expression will match twice, and the resulting +% Then the regular expression matches twice, the resulting % sequence contains the two items |{Hello}| and |{world}|, % and the \texttt{true} branch is left in the input stream. % \end{function} @@ -607,15 +667,13 @@ % % The following need to be done now. % \begin{itemize} -% \item Change user function names! -% \item Clean up the use of messages. % \item Rewrite the documentation in a more ordered way, perhaps add a % \textsc{bnf}? % \end{itemize} % % Additional error-checking to come. % \begin{itemize} -% \item Currently, |a{\x34}| is recognized as |a{4}|. +% \item Clean up the use of messages. % \item Cleaner error reporting in the replacement phase. % \item Add tracing information. % \item Detect attempts to use back-references and other @@ -623,7 +681,6 @@ % \item Test for the maximum register \cs{c_max_register_int}. % \item Find out whether the fact that |\W| and friends match the % end-marker leads to bugs. Possibly update \cs{__regex_item_reverse:n}. -% \item Enforce that |\cC| can only be followed by a match-all dot. % \item The empty cs should be matched by |\c{}|, not by % |\c{csname.?endcsname\s?}|. % \end{itemize} @@ -679,13 +736,24 @@ % \item Unicode properties: |\p{..}| and |\P{..}|; % |\X| which should match any \enquote{extended} Unicode sequence. % This requires to manipulate a lot of data, probably using tree-boxes. +% \item Provide a syntax such as |\ur{l_my_regex}| to use an +% already-compiled regex in a more complicated regex. This makes +% regexes more easily composable. +% \item Allowing |\u{l_my_tl}| in more places, for instance as the +% number of repetitions in a quantifier. % \end{itemize} % % The following features of \textsc{pcre} or Perl may or may not be % implemented. % \begin{itemize} -% \item |\ddd|, matching the character with octal code \texttt{ddd}; -% \item Callout with |(?C...)|; +% \item Callout with |(?C...)| or other syntax: some internal code +% changes make that possible, and it can be useful for instance in +% the replacement code to stop a regex replacement when some marker +% has been found; this raises the question of a potential +% |\regex_break:| and then of playing well with \cs{tl_map_break:} +% called from within the code in a regex. It also raises the +% question of nested calls to the regex machinery, which is a +% problem since \tn{fontdimen} are global. % \item Conditional subpatterns (other than with a look-ahead or % look-behind condition): this is non-regular, isn't it? % \item Named subpatterns: \TeX{} programmers have lived so far @@ -695,21 +763,25 @@ % The following features of \textsc{pcre} or Perl will definitely not be % implemented. % \begin{itemize} -% \item |\cx|, similar to \TeX{}'s own |\^^x|; -% \item Comments: \TeX{} already has its own system for comments. -% \item |\Q...\E| escaping: this would require to read the argument -% verbatim, which is not in the scope of this module. +% \item Back-references: non-regular feature, this requires +% backtracking, which is prohibitively slow. +% \item Recursion: this is a non-regular feature. % \item Atomic grouping, possessive quantifiers: those tools, mostly % meant to fix catastrophic backtracking, are unnecessary in a % non-backtracking algorithm, and difficult to implement. % \item Subroutine calls: this syntactic sugar is difficult to include % in a non-backtracking algorithm, in particular because the % corresponding group should be treated as atomic. -% \item Recursion: this is a non-regular feature. -% \item Back-references: non-regular feature, this requires -% backtracking, which is prohibitively slow. % \item Backtracking control verbs: intrinsically tied to % backtracking. +% \item |\ddd|, matching the character with octal code \texttt{ddd}: +% we already have |\x{...}| and the syntax is confusingly close to +% what we could have used for backreferences (|\1|, |\2|, \ldots{}), +% making it harder to produce useful error message. +% \item |\cx|, similar to \TeX{}'s own |\^^x|. +% \item Comments: \TeX{} already has its own system for comments. +% \item |\Q...\E| escaping: this would require to read the argument +% verbatim, which is not in the scope of this module. % \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. @@ -898,16 +970,16 @@ % \end{macro} % \end{macro} % -% \begin{macro}[int, rEXP]{\@@_current_cs_to_str:} +% \begin{macro}[int, rEXP]{\@@_curr_cs_to_str:} % Expands to the string representation of the token (known to be a -% control sequence) at the current position \cs{l_@@_current_pos_int}. +% control sequence) at the current position \cs{l_@@_curr_pos_int}. % It should only be used in \texttt{x}-expansion to avoid losing a % leading space. % \begin{macrocode} -\cs_new:Npn \@@_current_cs_to_str: +\cs_new:Npn \@@_curr_cs_to_str: { \exp_after:wN \exp_after:wN \exp_after:wN \cs_to_str:N - \tex_the:D \tex_toks:D \l_@@_current_pos_int + \tex_the:D \tex_toks:D \l_@@_curr_pos_int } % \end{macrocode} % \end{macro} @@ -1028,7 +1100,7 @@ % \begin{macro}[int]{\@@_item_reverse:n} % This function makes showing regular expressions easier, and lets us % define |\D| in terms of |\d| for instance. There is a subtlety: the -% end of the query is marked by $-2$, and will thus match |\D| and +% end of the query is marked by $-2$, and thus matches |\D| and % other negated properties; this case is caught by another part of % the code. % \begin{macrocode} @@ -1046,14 +1118,14 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_item_caseful_equal:n #1 { - \if_int_compare:w #1 = \l_@@_current_char_int + \if_int_compare:w #1 = \l_@@_curr_char_int \exp_after:wN \@@_break_true:w \fi: } \cs_new_protected:Npn \@@_item_caseful_range:nn #1 #2 { - \reverse_if:N \if_int_compare:w #1 > \l_@@_current_char_int - \reverse_if:N \if_int_compare:w #2 < \l_@@_current_char_int + \reverse_if:N \if_int_compare:w #1 > \l_@@_curr_char_int + \reverse_if:N \if_int_compare:w #2 < \l_@@_curr_char_int \exp_after:wN \exp_after:wN \exp_after:wN \@@_break_true:w \fi: \fi: @@ -1070,7 +1142,7 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_item_caseless_equal:n #1 { - \if_int_compare:w #1 = \l_@@_current_char_int + \if_int_compare:w #1 = \l_@@_curr_char_int \exp_after:wN \@@_break_true:w \fi: \if_int_compare:w \l_@@_case_changed_char_int = \c_max_int @@ -1082,8 +1154,8 @@ } \cs_new_protected:Npn \@@_item_caseless_range:nn #1 #2 { - \reverse_if:N \if_int_compare:w #1 > \l_@@_current_char_int - \reverse_if:N \if_int_compare:w #2 < \l_@@_current_char_int + \reverse_if:N \if_int_compare:w #1 > \l_@@_curr_char_int + \reverse_if:N \if_int_compare:w #2 < \l_@@_curr_char_int \exp_after:wN \exp_after:wN \exp_after:wN \@@_break_true:w \fi: \fi: @@ -1108,15 +1180,15 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_compute_case_changed_char: { - \int_set_eq:NN \l_@@_case_changed_char_int \l_@@_current_char_int - \if_int_compare:w \l_@@_current_char_int > `Z \exp_stop_f: - \if_int_compare:w \l_@@_current_char_int > `z \exp_stop_f: \else: - \if_int_compare:w \l_@@_current_char_int < `a \exp_stop_f: \else: + \int_set_eq:NN \l_@@_case_changed_char_int \l_@@_curr_char_int + \if_int_compare:w \l_@@_curr_char_int > `Z \exp_stop_f: + \if_int_compare:w \l_@@_curr_char_int > `z \exp_stop_f: \else: + \if_int_compare:w \l_@@_curr_char_int < `a \exp_stop_f: \else: \int_sub:Nn \l_@@_case_changed_char_int { \c_@@_ascii_lower_int } \fi: \fi: \else: - \if_int_compare:w \l_@@_current_char_int < `A \exp_stop_f: \else: + \if_int_compare:w \l_@@_curr_char_int < `A \exp_stop_f: \else: \int_add:Nn \l_@@_case_changed_char_int { \c_@@_ascii_lower_int } \fi: \fi: @@ -1146,7 +1218,7 @@ \cs_new_protected:Npn \@@_item_catcode: { " - \if_case:w \l_@@_current_catcode_int + \if_case:w \l_@@_curr_catcode_int 1 \or: 4 \or: 10 \or: 40 \or: 100 \or: \or: 1000 \or: 4000 \or: 10000 \or: \or: 100000 \or: 400000 @@ -1173,18 +1245,18 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_item_exact:nn #1#2 { - \if_int_compare:w #1 = \l_@@_current_catcode_int - \if_int_compare:w #2 = \l_@@_current_char_int + \if_int_compare:w #1 = \l_@@_curr_catcode_int + \if_int_compare:w #2 = \l_@@_curr_char_int \exp_after:wN \exp_after:wN \exp_after:wN \@@_break_true:w \fi: \fi: } \cs_new_protected:Npn \@@_item_exact_cs:n #1 { - \int_compare:nNnTF \l_@@_current_catcode_int = 0 + \int_compare:nNnTF \l_@@_curr_catcode_int = 0 { \tl_set:Nx \l_@@_internal_a_tl - { \scan_stop: \@@_current_cs_to_str: \scan_stop: } + { \scan_stop: \@@_curr_cs_to_str: \scan_stop: } \tl_if_in:noTF { \scan_stop: #1 \scan_stop: } \l_@@_internal_a_tl { \@@_break_true:w } { } } @@ -1205,10 +1277,10 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_item_cs:n #1 { - \int_compare:nNnT \l_@@_current_catcode_int = 0 + \int_compare:nNnT \l_@@_curr_catcode_int = 0 { \group_begin: - \tl_set:Nx \l_@@_cs_name_tl { \@@_current_cs_to_str: } + \tl_set:Nx \l_@@_cs_name_tl { \@@_curr_cs_to_str: } \@@_single_match: \@@_disable_submatches: \@@_build_for_cs:n {#1} @@ -1442,7 +1514,7 @@ \cs_new:cpn { @@_escape_/break:w } { \if_false: { \fi: } - \__msg_kernel_error:nn { regex } { trailing-backslash } + \__msg_kernel_error:nn { kernel } { trailing-backslash } \exp_after:wN \use_none:n \exp_after:wN { \if_false: } \fi: } \cs_new:cpn { @@_escape_~:w } { } @@ -1481,7 +1553,7 @@ { \if_false: { \fi: } \__tl_build_one:o \l_@@_internal_b_tl - \__msg_kernel_error:nnx { regex } { x-overflow } {#1} + \__msg_kernel_error:nnx { kernel } { x-overflow } {#1} \tl_set:Nx \l_@@_internal_b_tl { \if_false: } \fi: } @@ -1570,7 +1642,7 @@ { \if_false: { \fi: } \__tl_build_one:o \l_@@_internal_b_tl - \__msg_kernel_error:nnx { regex } { x-missing-rbrace } {#1} + \__msg_kernel_error:nnx { kernel } { x-missing-rbrace } {#1} \tl_set:Nx \l_@@_internal_b_tl { \if_false: } \fi: \@@_escape_loop:N #1 } @@ -1987,7 +2059,7 @@ \if_int_compare:w \l_@@_mode_int = \c_@@_class_mode_int \exp_after:wN \exp_after:wN \exp_after:wN \use:n \else: - \__msg_kernel_error:nn { regex } { c-bad-mode } + \__msg_kernel_error:nn { kernel } { c-bad-mode } \exp_after:wN \exp_after:wN \exp_after:wN \use_none:n \fi: \fi: @@ -2036,13 +2108,13 @@ { \@@_if_in_class:TF { - \__msg_kernel_error:nn { regex } { missing-rbrack } + \__msg_kernel_error:nn { kernel } { missing-rbrack } \use:c { @@_compile_]: } \prg_do_nothing: \prg_do_nothing: } { } \if_int_compare:w \l_@@_group_level_int > 0 \exp_stop_f: - \__msg_kernel_error:nnx { regex } { missing-rparen } + \__msg_kernel_error:nnx { kernel } { missing-rparen } { \int_use:N \l_@@_group_level_int } \prg_replicate:nn { \l_@@_group_level_int } @@ -2093,10 +2165,10 @@ \prg_do_nothing: \prg_do_nothing: \prg_do_nothing: \prg_do_nothing: \int_compare:nNnT \l_@@_mode_int = \c_@@_catcode_mode_int - { \__msg_kernel_error:nn { regex } { c-trailing } } + { \__msg_kernel_error:nn { kernel } { c-trailing } } \int_compare:nNnT \l_@@_mode_int < \c_@@_outer_mode_int { - \__msg_kernel_error:nn { regex } { c-missing-rbrace } + \__msg_kernel_error:nn { kernel } { c-missing-rbrace } \@@_compile_end_cs: \prg_do_nothing: \prg_do_nothing: \prg_do_nothing: \prg_do_nothing: @@ -2203,7 +2275,7 @@ \cs_new_protected:Npn \@@_compile_quantifier_abort:xNN #1#2#3 { \@@_compile_quantifier_none: - \__msg_kernel_warning:nnxx { regex } { invalid-quantifier } {#1} {#3} + \__msg_kernel_warning:nnxx { kernel } { invalid-quantifier } {#1} {#3} \@@_compile_abort_tokens:x {#1} #2 #3 } @@ -2316,7 +2388,7 @@ { #1 #2 } { \@@_compile_special:N \c_right_brace_str } { \if_int_compare:w \l_@@_internal_a_int > \l_@@_internal_b_int - \__msg_kernel_error:nnxx { regex } { backwards-quantifier } + \__msg_kernel_error:nnxx { kernel } { backwards-quantifier } { \int_use:N \l_@@_internal_a_int } { \int_use:N \l_@@_internal_b_int } \int_zero:N \l_@@_internal_b_int @@ -2350,7 +2422,7 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_compile_raw_error:N #1 { - \__msg_kernel_error:nnx { regex } { bad-escape } {#1} + \__msg_kernel_error:nnx { kernel } { bad-escape } {#1} \@@_compile_raw:N #1 } % \end{macrocode} @@ -2409,7 +2481,7 @@ \@@_if_end_range:NNTF #2 #3 { \if_int_compare:w `#1 > `#3 \exp_stop_f: - \__msg_kernel_error:nnxx { regex } { range-backwards } {#1} {#3} + \__msg_kernel_error:nnxx { kernel } { range-backwards } {#1} {#3} \else: \__tl_build_one:x { @@ -2423,7 +2495,7 @@ \fi: } { - \__msg_kernel_warning:nnxx { regex } { range-missing-end } + \__msg_kernel_warning:nnxx { kernel } { range-missing-end } {#1} { \c_backslash_str #3 } \__tl_build_one:x { @@ -2451,7 +2523,7 @@ } \cs_new_protected:cpn { @@_prop_.: } { - \if_int_compare:w \l_@@_current_char_int > - 2 \exp_stop_f: + \if_int_compare:w \l_@@_curr_char_int > - 2 \exp_stop_f: \exp_after:wN \@@_break_true:w \fi: } @@ -2613,7 +2685,7 @@ % \end{macro} % % \begin{macro}[aux]{\@@_compile_class_normal:w} -% In the \enquote{normal} case, we will insert \cs{@@_class:NnnnN} +% In the \enquote{normal} case, we insert \cs{@@_class:NnnnN} % \meta{boolean} in the compiled code. The \meta{boolean} is true for % positive classes, and false for negative classes, characterized by a % leading |^|. The auxiliary \cs{@@_compile_class:TFNN} also @@ -2701,8 +2773,8 @@ \str_case:nn { #2 } { : { \@@_compile_class_posix:NNNNw } - = { \__msg_kernel_warning:nnx { regex } { posix-unsupported } { = } } - . { \__msg_kernel_warning:nnx { regex } { posix-unsupported } { . } } + = { \__msg_kernel_warning:nnx { kernel } { posix-unsupported } { = } } + . { \__msg_kernel_warning:nnx { kernel } { posix-unsupported } { . } } } } \@@_compile_raw:N [ #1 #2 @@ -2741,7 +2813,7 @@ } } { - \__msg_kernel_warning:nnx { regex } { posix-unknown } + \__msg_kernel_warning:nnx { kernel } { posix-unknown } { \l_@@_internal_a_tl } \@@_compile_abort_tokens:x { @@ -2751,7 +2823,7 @@ } } { - \__msg_kernel_error:nnxx { regex } { posix-missing-close } + \__msg_kernel_error:nnxx { kernel } { posix-missing-close } { [: \l_@@_internal_a_tl } { #2 #4 } \@@_compile_abort_tokens:x { [: \l_@@_internal_a_tl } #1 #2 #3 #4 @@ -2793,7 +2865,7 @@ \__tl_build_one:o \l_@@_internal_regex \exp_after:wN \@@_compile_quantifier:w \else: - \__msg_kernel_warning:nn { regex } { extra-rparen } + \__msg_kernel_warning:nn { kernel } { extra-rparen } \exp_after:wN \@@_compile_raw:N \exp_after:wN ) \fi: } @@ -2817,7 +2889,7 @@ \cs_if_exist_use:cF { @@_compile_special_group_\token_to_str:N #4 :w } { - \__msg_kernel_warning:nnx { regex } { special-group-unknown } + \__msg_kernel_warning:nnx { kernel } { special-group-unknown } { (? #4 } \@@_compile_group_begin:N \@@_group:nnnN \@@_compile_raw:N ? #3 #4 @@ -2860,8 +2932,7 @@ % \begin{macro}[aux]{\@@_compile_special_group_::w} % \begin{macro}[aux]+\@@_compile_special_group_|:w+ % Non-capturing, and resetting groups are easy to take care of during -% compilation; for those groups, the harder parts will come when -% building. +% compilation; for those groups, the harder parts come when building. % \begin{macrocode} \cs_new_protected:cpn { @@_compile_special_group_::w } { \@@_compile_group_begin:N \@@_group_no_capture:nnnN } @@ -2885,7 +2956,7 @@ \cs_set:Npn \@@_item_range:nn { \@@_item_caseless_range:nn } } { - \__msg_kernel_warning:nnx { regex } { unknown-option } { (?i #2 } + \__msg_kernel_warning:nnx { kernel } { unknown-option } { (?i #2 } \@@_compile_raw:N ( \@@_compile_raw:N ? \@@_compile_raw:N i @@ -2901,7 +2972,7 @@ \cs_set:Npn \@@_item_range:nn { \@@_item_caseful_range:nn } } { - \__msg_kernel_warning:nnx { regex } { unknown-option } { (?-#2#4 } + \__msg_kernel_warning:nnx { kernel } { unknown-option } { (?-#2#4 } \@@_compile_raw:N ( \@@_compile_raw:N ? \@@_compile_raw:N - @@ -2934,17 +3005,38 @@ \else: \c_@@_catcode_in_class_mode_int \fi: + \token_if_eq_charcode:NNT C #2 { \@@_compile_c_C:NN } } } { \cs_if_exist_use:cF { @@_compile_c_#2:w } } { - \__msg_kernel_error:nnx { regex } { c-missing-category } {#2} + \__msg_kernel_error:nnx { kernel } { c-missing-category } {#2} #1 #2 } } % \end{macrocode} % \end{macro} % +% \begin{macro}[aux]{\@@_compile_c_C:NN} +% If |\cC| is not followed by |.| or |(...)| then complain because +% that construction cannot match anything, except in cases like +% |\cC[\c{...}]|, where it has no effect. +% \begin{macrocode} +\cs_new_protected:Npn \@@_compile_c_C:NN #1#2 + { + \token_if_eq_meaning:NNTF #1 \@@_compile_special:N + { + \token_if_eq_charcode:NNTF #2 . + { \use_none:n } + { \token_if_eq_charcode:NNF #2 ( } % ) + } + { \use:n } + { \__msg_kernel_error:nnn { kernel } { c-C-invalid } {#2} } + #1 #2 + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}[aux] % { % \@@_compile_c_[:w, @@ -2992,7 +3084,7 @@ { \@@_compile_c_lbrack_end: } } { - \__msg_kernel_error:nnx { regex } { c-missing-rbrack } {#2} + \__msg_kernel_error:nnx { kernel } { c-missing-rbrack } {#2} \@@_compile_c_lbrack_end: #1 #2 } @@ -3121,8 +3213,8 @@ % catcode test. Otherwise, it must be followed by a left brace. We % then collect the characters for the argument of |\u| within an % \texttt{x}-expanding assignment. In principle we could just wait to -% encounter a right brace, but this is unsafe: if the right brace is -% missing, then we will reach the end-markers of the regex, and +% encounter a right brace, but this is unsafe: if the right brace was +% missing, then we would reach the end-markers of the regex, and % continue, leading to obscure fatal errors. Instead, we only allow % raw and special characters, and stop when encountering a special % right brace, any escaped character, or the end-marker. @@ -3138,7 +3230,7 @@ \@@_compile_u_loop:NN } { - \__msg_kernel_error:nn { regex } { u-missing-lbrace } + \__msg_kernel_error:nn { kernel } { u-missing-lbrace } \@@_compile_raw:N u #1 #2 } } @@ -3156,7 +3248,7 @@ } { \if_false: { \fi: } - \__msg_kernel_error:nnx { regex } { u-missing-rbrace } {#2} + \__msg_kernel_error:nnx { kernel } { u-missing-rbrace } {#2} \@@_compile_u_end: #1 #2 } @@ -3508,8 +3600,8 @@ % \end{variable} % % \begin{variable}{\l_@@_capturing_group_int} -% \cs{l_@@_capturing_group_int} is the \textsc{id} number that will -% be assigned to a capturing group if one was opened now. This starts +% \cs{l_@@_capturing_group_int} is the next \textsc{id} number to +% be assigned to a capturing group. This starts % at $0$ for the group enclosing the full regular expression, and % groups are counted in the order of their left parenthesis, except % when encountering \texttt{resetting} groups. @@ -3548,8 +3640,8 @@ % We strive to preserve the following properties while building. % \begin{itemize} % \item The current capturing group is -% $\text{\texttt{capturing_group}}-1$, and if a group is opened now, -% it will be labelled \texttt{capturing_group}. +% $\text{\texttt{capturing_group}}-1$, and if a group opened now +% it would be labelled \texttt{capturing_group}. % \item The last allocated state is $\text{\texttt{max_state}}-1$, so % \texttt{max_state} is a free state. % \item The \texttt{left_state} points to a state to the left of the @@ -3564,7 +3656,7 @@ % The \texttt{n}-type function first compiles its argument. Reset some % variables. Allocate two states, and put a wildcard in state $0$ % (transitions to state $1$ and $0$ state). Then build the regex -% within a (capturing) group, which will be numbered $0$ (current +% within a (capturing) group numbered $0$ (current % value of \texttt{capturing_group}). Finally, if the match reaches the % last state, it is successful. % \begin{macrocode} @@ -3610,7 +3702,7 @@ \@@_pop_lr_states: \@@_toks_put_right:Nn \l_@@_right_state_int { - \if_int_compare:w \l_@@_current_pos_int = \l_@@_max_pos_int + \if_int_compare:w \l_@@_curr_pos_int = \l_@@_max_pos_int \exp_after:wN \@@_action_success: \fi: } @@ -3821,7 +3913,7 @@ % building the group, so that the thread which skips the group does % not also set the start-point of the submatch. After adding one more % state, the \texttt{left_state} is the left end of the group, from -% which all branches will stem, and the \texttt{right_state} is the +% which all branches stem, and the \texttt{right_state} is the % right end of the group, and all branches end their course in that % state. We store those two integers to be queried for each branch, we % build the \textsc{nfa} states for the contents |#2| of the group, @@ -3974,7 +4066,7 @@ % \begin{macro}[aux]{\@@_group_repeat_aux:n} % Here we repeat \tn{toks} ranging from \texttt{left_state} to % \texttt{max_state}, $|#1|>0$ times. First add a transition so that -% the copies will \enquote{chain} properly. Compute the shift +% the copies \enquote{chain} properly. Compute the shift % \texttt{c} between the original copy and the last copy we % want. Shift the \texttt{right_state} and \texttt{max_state} to their % final values. We then want to perform \texttt{c} copy operations. At @@ -4145,14 +4237,14 @@ } \cs_new_protected:Npn \@@_anchor:N #1 { - \if_int_compare:w #1 = \l_@@_current_pos_int + \if_int_compare:w #1 = \l_@@_curr_pos_int \exp_after:wN \@@_break_true:w \fi: } \cs_new_protected:Npn \@@_b_test: { \group_begin: - \int_set_eq:NN \l_@@_current_char_int \l_@@_last_char_int + \int_set_eq:NN \l_@@_curr_char_int \l_@@_last_char_int \@@_prop_w: \@@_break_point:TF { \group_end: \@@_item_reverse:n \@@_prop_w: } @@ -4189,15 +4281,15 @@ % transitions, the instruction at the new state of the \textsc{nfa} is % performed immediately. When a transition consumes a character, the % new state is appended to a list of \enquote{active states}, stored in -% \cs{g_@@_thread_state_intarray}: this thread will be active again when the next +% \cs{g_@@_thread_state_intarray}: this thread is made active again when the next % token is read from the query. At every step (for each token in the % query), we unpack that list of active states and the corresponding % submatch props, and empty those. % % If two paths through the \textsc{nfa} \enquote{collide} in the sense % that they reach the same state after reading a given token, then they -% only differ in how they previously matched, and the future execution -% will be identical for both. (Note that this would be wrong in the +% only differ in how they previously matched, and any future execution +% would be identical for both. (Note that this would be wrong in the % presence of back-references.) Hence, we only need to keep one of the % two threads: the thread with the highest priority. Our \textsc{nfa} is % built in such a way that higher priority actions always come before @@ -4217,7 +4309,7 @@ % We solve this by distinguishing \enquote{normal} free transitions % \cs{@@_action_free:n} from transitions % \cs{@@_action_free_group:n} which go back to the start of the -% group. The former will keep threads unless they have been visited by a +% group. The former keeps threads unless they have been visited by a % \enquote{completed} thread, while the latter kind of transition also % prevents going back to a state visited by the current thread. % @@ -4227,7 +4319,7 @@ % { % \l_@@_min_pos_int, % \l_@@_max_pos_int, -% \l_@@_current_pos_int, +% \l_@@_curr_pos_int, % \l_@@_start_pos_int, % \l_@@_success_pos_int, % } @@ -4244,7 +4336,7 @@ % \begin{macrocode} \int_new:N \l_@@_min_pos_int \int_new:N \l_@@_max_pos_int -\int_new:N \l_@@_current_pos_int +\int_new:N \l_@@_curr_pos_int \int_new:N \l_@@_start_pos_int \int_new:N \l_@@_success_pos_int % \end{macrocode} @@ -4252,8 +4344,8 @@ % % \begin{variable} % { -% \l_@@_current_char_int, -% \l_@@_current_catcode_int, +% \l_@@_curr_char_int, +% \l_@@_curr_catcode_int, % \l_@@_last_char_int, % \l_@@_case_changed_char_int % } @@ -4265,25 +4357,25 @@ % \texttt{current_char} variable is also used in various other phases % to hold a character code. % \begin{macrocode} -\int_new:N \l_@@_current_char_int -\int_new:N \l_@@_current_catcode_int +\int_new:N \l_@@_curr_char_int +\int_new:N \l_@@_curr_catcode_int \int_new:N \l_@@_last_char_int \int_new:N \l_@@_case_changed_char_int % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_current_state_int} +% \begin{variable}{\l_@@_curr_state_int} % For every character in the token list, each of the active states is -% considered in turn. The variable \cs{l_@@_current_state_int} +% considered in turn. The variable \cs{l_@@_curr_state_int} % holds the state of the \textsc{nfa} which is currently considered: % transitions are then given as shifts relative to the current state. % \begin{macrocode} -\int_new:N \l_@@_current_state_int +\int_new:N \l_@@_curr_state_int % \end{macrocode} % \end{variable} % % \begin{variable} -% {\l_@@_current_submatches_prop, \l_@@_success_submatches_prop} +% {\l_@@_curr_submatches_prop, \l_@@_success_submatches_prop} % The submatches for the thread which is currently active are stored % in the \texttt{current_submatches} property list variable. This % property list is stored by \cs{@@_action_cost:n} into the @@ -4291,9 +4383,9 @@ % retrieved when matching at the next position. When a thread % succeeds, this property list is copied to % \cs{l_@@_success_submatches_prop}: only the last successful thread -% will remain there. +% remains there. % \begin{macrocode} -\prop_new:N \l_@@_current_submatches_prop +\prop_new:N \l_@@_curr_submatches_prop \prop_new:N \l_@@_success_submatches_prop % \end{macrocode} % \end{variable} @@ -4334,7 +4426,7 @@ % \begin{variable}{\g_@@_state_active_intarray, \g_@@_thread_state_intarray} % \cs{g_@@_state_active_intarray} stores the last \meta{step} in which % each \meta{state} was active. \cs{g_@@_thread_state_intarray} stores -% threads that will be considered in the next step, more precisely the +% threads to be considered in the next step, more precisely the % states in which these threads are. % \begin{macrocode} \__intarray_new:Nn \g_@@_state_active_intarray { 65536 } @@ -4415,12 +4507,12 @@ %<trace> \trace_push:nnx { regex } { 1 } { @@_match } %<trace> \trace:nnx { regex } { 1 } { analyzing~query~token~list } \int_zero:N \l_@@_balance_int - \int_set:Nn \l_@@_current_pos_int { 2 * \l_@@_max_state_int } + \int_set:Nn \l_@@_curr_pos_int { 2 * \l_@@_max_state_int } \@@_query_set:nnn { } { -1 } { -2 } - \int_set_eq:NN \l_@@_min_pos_int \l_@@_current_pos_int + \int_set_eq:NN \l_@@_min_pos_int \l_@@_curr_pos_int \__tl_analysis_map_inline:nn {#1} { \@@_query_set:nnn {##1} {"##2} {##3} } - \int_set_eq:NN \l_@@_max_pos_int \l_@@_current_pos_int + \int_set_eq:NN \l_@@_max_pos_int \l_@@_curr_pos_int \@@_query_set:nnn { } { -1 } { -2 } %<trace> \trace:nnx { regex } { 1 } { initializing } \bool_gset_false:N \g_@@_success_bool @@ -4449,8 +4541,8 @@ % successful, and has no submatches yet; clear the array of active % threads, and put the starting state $0$ in it. We are then almost % ready to read our first token in the query, but we actually start -% one position earlier than the start, and \texttt{get} that token, so -% that the \texttt{last_char} will be set properly for word +% one position earlier than the start, and \texttt{get} that token, to +% set \texttt{last_char} properly for word % boundaries. Then call \cs{@@_match_loop:}, which runs through the % query until the end or until a successful match breaks early. % \begin{macrocode} @@ -4458,16 +4550,16 @@ { \if_meaning:w \c_true_bool \l_@@_empty_success_bool \cs_set:Npn \@@_if_two_empty_matches:F - { \int_compare:nNnF \l_@@_start_pos_int = \l_@@_current_pos_int } + { \int_compare:nNnF \l_@@_start_pos_int = \l_@@_curr_pos_int } \else: \cs_set_eq:NN \@@_if_two_empty_matches:F \use:n \fi: \int_set_eq:NN \l_@@_start_pos_int \l_@@_success_pos_int \bool_set_false:N \l_@@_match_success_bool - \prop_clear:N \l_@@_current_submatches_prop + \prop_clear:N \l_@@_curr_submatches_prop \int_set_eq:NN \l_@@_max_active_int \l_@@_min_active_int \@@_store_state:n { \l_@@_min_state_int } - \int_set:Nn \l_@@_current_pos_int + \int_set:Nn \l_@@_curr_pos_int { \l_@@_start_pos_int - 1 } \@@_query_get: \@@_match_loop: @@ -4518,8 +4610,8 @@ \cs_new_protected:Npn \@@_match_loop: { \int_add:Nn \l_@@_step_int { 2 } - \int_incr:N \l_@@_current_pos_int - \int_set_eq:NN \l_@@_last_char_int \l_@@_current_char_int + \int_incr:N \l_@@_curr_pos_int + \int_set_eq:NN \l_@@_last_char_int \l_@@_curr_char_int \int_set_eq:NN \l_@@_case_changed_char_int \c_max_int \@@_query_get: \use:x @@ -4534,7 +4626,7 @@ \__prg_break_point: \bool_set_false:N \l_@@_fresh_thread_bool %^^A was arg of break_point:n \if_int_compare:w \l_@@_max_active_int > \l_@@_min_active_int - \if_int_compare:w \l_@@_current_pos_int < \l_@@_max_pos_int + \if_int_compare:w \l_@@_curr_pos_int < \l_@@_max_pos_int \exp_after:wN \exp_after:wN \exp_after:wN \@@_match_loop: \fi: \fi: @@ -4559,13 +4651,13 @@ \cs_new_protected:Npn \@@_query_set:nnn #1#2#3 { \__intarray_gset_fast:Nnn \g_@@_charcode_intarray - { \l_@@_current_pos_int } {#3} + { \l_@@_curr_pos_int } {#3} \__intarray_gset_fast:Nnn \g_@@_catcode_intarray - { \l_@@_current_pos_int } {#2} + { \l_@@_curr_pos_int } {#2} \__intarray_gset_fast:Nnn \g_@@_balance_intarray - { \l_@@_current_pos_int } { \l_@@_balance_int } - \@@_toks_set:Nn \l_@@_current_pos_int {#1} - \int_incr:N \l_@@_current_pos_int + { \l_@@_curr_pos_int } { \l_@@_balance_int } + \@@_toks_set:Nn \l_@@_curr_pos_int {#1} + \int_incr:N \l_@@_curr_pos_int \if_case:w #2 \exp_stop_f: \or: \int_incr:N \l_@@_balance_int \or: \int_decr:N \l_@@_balance_int @@ -4580,12 +4672,12 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_query_get: { - \l_@@_current_char_int + \l_@@_curr_char_int = \__intarray_item_fast:Nn \g_@@_charcode_intarray - { \l_@@_current_pos_int } \scan_stop: - \l_@@_current_catcode_int + { \l_@@_curr_pos_int } \scan_stop: + \l_@@_curr_catcode_int = \__intarray_item_fast:Nn \g_@@_catcode_intarray - { \l_@@_current_pos_int } \scan_stop: + { \l_@@_curr_pos_int } \scan_stop: } % \end{macrocode} % \end{macro} @@ -4603,13 +4695,13 @@ \cs_new_protected:Npn \@@_use_state: { %<*trace> - \trace:nnx { regex } { 2 } { state~\int_use:N \l_@@_current_state_int } + \trace:nnx { regex } { 2 } { state~\int_use:N \l_@@_curr_state_int } %</trace> \__intarray_gset_fast:Nnn \g_@@_state_active_intarray - { \l_@@_current_state_int } { \l_@@_step_int } - \@@_toks_use:w \l_@@_current_state_int + { \l_@@_curr_state_int } { \l_@@_step_int } + \@@_toks_use:w \l_@@_curr_state_int \__intarray_gset_fast:Nnn \g_@@_state_active_intarray - { \l_@@_current_state_int } { \l_@@_step_int + 1 } + { \l_@@_curr_state_int } { \l_@@_step_int + 1 } } % \end{macrocode} % \end{macro} @@ -4622,12 +4714,12 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_use_state_and_submatches:nn #1 #2 { - \int_set:Nn \l_@@_current_state_int {#1} + \int_set:Nn \l_@@_curr_state_int {#1} \if_int_compare:w \__intarray_item_fast:Nn \g_@@_state_active_intarray - { \l_@@_current_state_int } + { \l_@@_curr_state_int } < \l_@@_step_int - \tl_set:Nn \l_@@_current_submatches_prop {#2} + \tl_set:Nn \l_@@_curr_submatches_prop {#2} \exp_after:wN \@@_use_state: \fi: \scan_stop: @@ -4661,12 +4753,12 @@ % state has not already been used at this position. If not, store % submatches in the new state, and insert the instructions for that % state in the input stream. Then restore the old value of -% \cs{l_@@_current_state_int} and of the current submatches. The +% \cs{l_@@_curr_state_int} and of the current submatches. The % two types of free transitions differ by how they test that the state % has not been encountered yet: the \texttt{group} version is % stricter, and will not use a state if it was used earlier in the % current thread, hence forcefully breaking the loop, while the -% \enquote{normal} version will revisit a state when within the thread +% \enquote{normal} version will revisit a state even within the thread % itself. % \begin{macrocode} \cs_new_protected:Npn \@@_action_free:n @@ -4677,20 +4769,20 @@ { \use:x { - \int_add:Nn \l_@@_current_state_int {#2} + \int_add:Nn \l_@@_curr_state_int {#2} \exp_not:n { \if_int_compare:w \__intarray_item_fast:Nn \g_@@_state_active_intarray - { \l_@@_current_state_int } + { \l_@@_curr_state_int } #1 \exp_after:wN \@@_use_state: \fi: } - \int_set:Nn \l_@@_current_state_int - { \int_use:N \l_@@_current_state_int } - \tl_set:Nn \exp_not:N \l_@@_current_submatches_prop - { \exp_not:o \l_@@_current_submatches_prop } + \int_set:Nn \l_@@_curr_state_int + { \int_use:N \l_@@_curr_state_int } + \tl_set:Nn \exp_not:N \l_@@_curr_submatches_prop + { \exp_not:o \l_@@_curr_submatches_prop } } } % \end{macrocode} @@ -4706,7 +4798,7 @@ \cs_new_protected:Npn \@@_action_cost:n #1 { \exp_args:No \@@_store_state:n - { \__int_value:w \__int_eval:w \l_@@_current_state_int + #1 } + { \__int_value:w \__int_eval:w \l_@@_curr_state_int + #1 } } % \end{macrocode} % \end{macro} @@ -4727,7 +4819,7 @@ \cs_new_protected:Npn \@@_store_submatches: { \@@_toks_set:No \l_@@_max_active_int - { \l_@@_current_submatches_prop } + { \l_@@_curr_submatches_prop } } % \end{macrocode} % \end{macro} @@ -4753,8 +4845,8 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_action_submatch:n #1 { - \prop_put:Nno \l_@@_current_submatches_prop {#1} - { \int_use:N \l_@@_current_pos_int } + \prop_put:Nno \l_@@_curr_submatches_prop {#1} + { \int_use:N \l_@@_curr_pos_int } } % \end{macrocode} % \end{macro} @@ -4776,9 +4868,9 @@ \bool_set_true:N \l_@@_match_success_bool \bool_set_eq:NN \l_@@_empty_success_bool \l_@@_fresh_thread_bool - \int_set_eq:NN \l_@@_success_pos_int \l_@@_current_pos_int + \int_set_eq:NN \l_@@_success_pos_int \l_@@_curr_pos_int \prop_set_eq:NN \l_@@_success_submatches_prop - \l_@@_current_submatches_prop + \l_@@_curr_submatches_prop \__prg_break: } } @@ -4844,7 +4936,7 @@ % replacement text. Hence concatenating the result of this function % with all possible arguments (one call for each match), as well as % the range from the end of the last match to the end of the string, -% will produce the fully replaced token list. The initialization does +% produces the fully replaced token list. The initialization does % not matter, but (as an example) we set it as for an empty replacement. % \begin{macrocode} \cs_new:Npn \@@_replacement_do_one_match:n #1 @@ -4879,7 +4971,7 @@ % exclusive. The function \cs{@@_query_range:nn} \Arg{min} % \Arg{max} unpacks registers from the position \meta{min} to the % position $\meta{max}-1$ included. Once this is expanded, a second -% \texttt{x}-expansion will result in the actual tokens from the +% \texttt{x}-expansion results in the actual tokens from the % query. That second expansion is only done by user functions at the % very end of their operation, after checking (and correcting) the % brace balance first. @@ -4956,7 +5048,7 @@ % The replacement text is built incrementally by abusing \tn{toks} % within a group (see \pkg{l3tl-build}). We keep track in % \cs{l_@@_balance_int} of the balance of explicit begin- and -% end-group tokens and \cs{l_@@_balance_tl} will consist of some +% end-group tokens and we store in \cs{l_@@_balance_tl} some % code to compute the brace balance from submatches (see its % description). Detect unescaped right braces, and escaped characters, % with trailing \cs{prg_do_nothing:} because some of the later @@ -4984,14 +5076,14 @@ {#1} \prg_do_nothing: \prg_do_nothing: \if_int_compare:w \l_@@_replacement_csnames_int > 0 \exp_stop_f: - \__msg_kernel_error:nnx { regex } { replacement-missing-rbrace } + \__msg_kernel_error:nnx { kernel } { replacement-missing-rbrace } { \int_use:N \l_@@_replacement_csnames_int } \__tl_build_one:x { \prg_replicate:nn \l_@@_replacement_csnames_int \cs_end: } \fi: \seq_if_empty:NF \l_@@_replacement_category_seq { - \__msg_kernel_error:nnx { regex } { replacement-missing-rparen } + \__msg_kernel_error:nnx { kernel } { replacement-missing-rparen } { \seq_count:N \l_@@_replacement_category_seq } \seq_clear:N \l_@@_replacement_category_seq } @@ -5076,7 +5168,7 @@ % submatch number is larger than the number of capturing groups. % Unless the submatch appears inside a |\c{...}| or |\u{...}| % construction, it must be taken into account in the brace balance. -% Here, |##1| will receive a pointer to the $0$-th submatch for a +% Later on, |##1| will be replaced by a pointer to the $0$-th submatch for a % given match. We cannot use \cs{int_eval:n} because it is % expandable, and would be expanded too early (short of adding % \cs{exp_not:N}, making the code messy again). @@ -5163,7 +5255,7 @@ % \end{macro} % % \begin{macro}[aux]{\@@_replacement_cu_aux:Nw} -% Start a control sequence with \cs{cs:w}, which will be protected +% Start a control sequence with \cs{cs:w}, protected % from expansion by |#1| (either \cs{@@_replacement_exp_not:N} or % \cs{exp_not:V}), or turned to a string by \cs{tl_to_str:V} if inside % another csname construction |\c| or |\u|. We use \cs{tl_to_str:V} @@ -5226,12 +5318,12 @@ \cs_new_protected:Npn \@@_replacement_cat:NNN #1#2#3 { \token_if_eq_meaning:NNTF \prg_do_nothing: #3 - { \__msg_kernel_error:nn { regex } { replacement-catcode-end } } + { \__msg_kernel_error:nn { kernel } { replacement-catcode-end } } { \int_compare:nNnTF { \l_@@_replacement_csnames_int } > 0 { \__msg_kernel_error:nnnn - { regex } { replacement-catcode-in-cs } {#1} {#3} + { kernel } { replacement-catcode-in-cs } {#1} {#3} #2 #3 } { @@ -5241,14 +5333,26 @@ \l_@@_replacement_category_tl \tl_set:Nn \l_@@_replacement_category_tl {#1} } - { \use:c { @@_replacement_c_#1:w } #2 #3 } + { + \token_if_eq_meaning:NNT #2 \@@_replacement_escaped:N + { + \@@_char_if_alphanumeric:NTF #3 + { + \__msg_kernel_error:nnnn + { kernel } { replacement-catcode-escaped } + {#1} {#3} + } + { } + } + \use:c { @@_replacement_c_#1:w } #2 #3 + } } } } % \end{macrocode} % \end{macro} % -% We will need to change the category code of the null character many +% We now need to change the category code of the null character many % times, hence work in a group. The catcode-specific macros below are % defined in alphabetical order; if you are trying to understand the % code, start from the end of the alphabet as those categories are @@ -5396,7 +5500,7 @@ \cs_new_protected:Npn \@@_replacement_c_S:w #1#2 { \if_int_compare:w `#2 = 0 \exp_stop_f: - \__msg_kernel_error:nn { regex } { replacement-null-space } + \__msg_kernel_error:nn { kernel } { replacement-null-space } \fi: \tex_lccode:D `\ = `#2 \scan_stop: \tex_lowercase:D { \__tl_build_one:n {~} } @@ -5439,7 +5543,7 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_replacement_error:NNN #1#2#3 { - \__msg_kernel_error:nnx { regex } { replacement-#1 } {#3} + \__msg_kernel_error:nnx { kernel } { replacement-#1 } {#3} #2 #3 } % \end{macrocode} @@ -5733,7 +5837,7 @@ } #1 \@@_match:n {#2} -%<assert>\assert_int:n { \l_@@_current_pos_int = \l_@@_max_pos_int } +%<assert>\assert_int:n { \l_@@_curr_pos_int = \l_@@_max_pos_int } \__intarray_gset_fast:Nnn \g_@@_submatch_prev_intarray { \l_@@_submatch_int } { 0 } \__intarray_gset_fast:Nnn \g_@@_submatch_end_intarray @@ -5781,7 +5885,7 @@ { \flag_height:n { @@_begin } + \flag_height:n { @@_end } } = 0 { - \__msg_kernel_error:nnxxx { regex } { result-unbalanced } + \__msg_kernel_error:nnxxx { kernel } { result-unbalanced } { splitting~or~extracting~submatches } { \flag_height:n { @@_end } } { \flag_height:n { @@_begin } } @@ -5972,7 +6076,7 @@ { \if_int_compare:w \l_@@_balance_int = 0 \exp_stop_f: \else: - \__msg_kernel_error:nnxxx { regex } { result-unbalanced } + \__msg_kernel_error:nnxxx { kernel } { result-unbalanced } { replacing } { \int_max:nn { - \l_@@_balance_int } { 0 } } { \int_max:nn { \l_@@_balance_int } { 0 } } @@ -6003,20 +6107,20 @@ % % Messages for the preparsing phase. % \begin{macrocode} -\__msg_kernel_new:nnnn { regex } { trailing-backslash } +\__msg_kernel_new:nnnn { kernel } { trailing-backslash } { Trailing~escape~character~'\iow_char:N\\'. } { A~regular~expression~or~its~replacement~text~ends~with~ the~escape~character~'\iow_char:N\\'.~It~will~be~ignored. } -\__msg_kernel_new:nnnn { regex } { x-missing-rbrace } +\__msg_kernel_new:nnnn { kernel } { x-missing-rbrace } { Missing~closing~brace~in~'\iow_char:N\\x'~hexadecimal~sequence. } { You~wrote~something~like~ '\iow_char:N\\x\{...#1'.~ The~closing~brace~is~missing. } -\__msg_kernel_new:nnnn { regex } { x-overflow } +\__msg_kernel_new:nnnn { kernel } { x-overflow } { Character~code~'#1'~too~large~in~'\iow_char:N\\x'~hexadecimal~sequence. } { You~wrote~something~like~ @@ -6028,7 +6132,7 @@ % % Invalid quantifier. % \begin{macrocode} -\__msg_kernel_new:nnnn { regex } { invalid-quantifier } +\__msg_kernel_new:nnnn { kernel } { invalid-quantifier } { Braced~quantifier~'#1'~may~not~be~followed~by~'#2'. } { The~character~'#2'~is~invalid~in~the~braced~quantifier~'#1'.~ @@ -6040,13 +6144,13 @@ % Messages for missing or extra closing brackets and parentheses, with % some fancy singular/plural handling for the case of parentheses. % \begin{macrocode} -\__msg_kernel_new:nnnn { regex } { missing-rbrack } +\__msg_kernel_new:nnnn { kernel } { missing-rbrack } { Missing~right~bracket~inserted~in~regular~expression. } { LaTeX~was~given~a~regular~expression~where~a~character~class~ was~started~with~'[',~but~the~matching~']'~is~missing. } -\__msg_kernel_new:nnnn { regex } { missing-rparen } +\__msg_kernel_new:nnnn { kernel } { missing-rparen } { Missing~right~ \int_compare:nTF { #1 = 1 } { parenthesis } { parentheses } ~ @@ -6056,7 +6160,7 @@ LaTeX~was~given~a~regular~expression~with~\int_eval:n {#1} ~ more~left~parentheses~than~right~parentheses. } -\__msg_kernel_new:nnnn { regex } { extra-rparen } +\__msg_kernel_new:nnnn { kernel } { extra-rparen } { Extra~right~parenthesis~ignored~in~regular~expression. } { LaTeX~came~across~a~closing~parenthesis~when~no~submatch~group~ @@ -6066,7 +6170,7 @@ % % Some escaped alphanumerics are not allowed everywhere. % \begin{macrocode} -\__msg_kernel_new:nnnn { regex } { bad-escape } +\__msg_kernel_new:nnnn { kernel } { bad-escape } { Invalid~escape~'\iow_char:N\\#1'~ \@@_if_in_cs:TF { within~a~control~sequence. } @@ -6094,14 +6198,14 @@ % % Range errors. % \begin{macrocode} -\__msg_kernel_new:nnnn { regex } { range-missing-end } +\__msg_kernel_new:nnnn { kernel } { range-missing-end } { Invalid~end-point~for~range~'#1-#2'~in~character~class. } { The~end-point~'#2'~of~the~range~'#1-#2'~may~not~serve~as~an~ end-point~for~a~range:~alphanumeric~characters~should~not~be~ escaped,~and~non-alphanumeric~characters~should~be~escaped. } -\__msg_kernel_new:nnnn { regex } { range-backwards } +\__msg_kernel_new:nnnn { kernel } { range-backwards } { Range~'[#1-#2]'~out~of~order~in~character~class. } { In~ranges~of~characters~'[x-y]'~appearing~in~character~classes,~ @@ -6113,27 +6217,34 @@ % % Errors related to |\c| and |\u|. % \begin{macrocode} -\__msg_kernel_new:nnnn { regex } { c-bad-mode } +\__msg_kernel_new:nnnn { kernel } { c-bad-mode } { Invalid~nested~'\iow_char:N\\c'~escape~in~regular~expression. } { The~'\iow_char:N\\c'~escape~cannot~be~used~within~ a~control~sequence~test~'\iow_char:N\\c{...}'.~ To~combine~several~category~tests,~use~'\iow_char:N\\c[...]'. } -\__msg_kernel_new:nnnn { regex } { c-missing-rbrace } +\__msg_kernel_new:nnnn { kernel } { c-C-invalid } + { '\iow_char:N\\cC'~should~be~followed~by~'.'~or~'(',~not~'#1'. } + { + The~'\iow_char:N\\cC'~construction~restricts~the~next~item~to~be~a~ + control~sequence~or~the~next~group~to~be~made~of~control~sequences.~ + It~only~makes~sense~to~follow~it~by~'.'~or~by~a~group. + } +\__msg_kernel_new:nnnn { kernel } { c-missing-rbrace } { Missing~right~brace~inserted~for~'\iow_char:N\\c'~escape. } { LaTeX~was~given~a~regular~expression~where~a~ '\iow_char:N\\c\iow_char:N\{...'~construction~was~not~ended~ with~a~closing~brace~'\iow_char:N\}'. } -\__msg_kernel_new:nnnn { regex } { c-missing-rbrack } +\__msg_kernel_new:nnnn { kernel } { c-missing-rbrack } { Missing~right~bracket~inserted~for~'\iow_char:N\\c'~escape. } { A~construction~'\iow_char:N\\c[...'~appears~in~a~ regular~expression,~but~the~closing~']'~is~not~present. } -\__msg_kernel_new:nnnn { regex } { c-missing-category } +\__msg_kernel_new:nnnn { kernel } { c-missing-category } { Invalid~character~'#1'~following~'\iow_char:N\\c'~escape. } { In~regular~expressions,~the~'\iow_char:N\\c'~escape~sequence~ @@ -6141,19 +6252,19 @@ capital~letter~representing~a~character~category,~namely~ one~of~'ABCDELMOPSTU'. } -\__msg_kernel_new:nnnn { regex } { c-trailing } +\__msg_kernel_new:nnnn { kernel } { c-trailing } { Trailing~category~code~escape~'\iow_char:N\\c'... } { A~regular~expression~ends~with~'\iow_char:N\\c'~followed~ by~a~letter.~It~will~be~ignored. } -\__msg_kernel_new:nnnn { regex } { u-missing-lbrace } +\__msg_kernel_new:nnnn { kernel } { u-missing-lbrace } { Missing~left~brace~following~'\iow_char:N\\u'~escape. } { The~'\iow_char:N\\u'~escape~sequence~must~be~followed~by~ a~brace~group~with~the~name~of~the~variable~to~use. } -\__msg_kernel_new:nnnn { regex } { u-missing-rbrace } +\__msg_kernel_new:nnnn { kernel } { u-missing-rbrace } { Missing~right~brace~inserted~for~'\iow_char:N\\u'~escape. } { LaTeX~ @@ -6166,14 +6277,14 @@ % % Errors when encountering the \textsc{posix} syntax |[:...:]|. % \begin{macrocode} -\__msg_kernel_new:nnnn { regex } { posix-unsupported } +\__msg_kernel_new:nnnn { kernel } { posix-unsupported } { POSIX~collating~element~'[#1 ~ #1]'~not~supported. } { The~'[.foo.]'~and~'[=bar=]'~syntaxes~have~a~special~meaning~ in~POSIX~regular~expressions.~This~is~not~supported~by~LaTeX.~ Maybe~you~forgot~to~escape~a~left~bracket~in~a~character~class? } -\__msg_kernel_new:nnnn { regex } { posix-unknown } +\__msg_kernel_new:nnnn { kernel } { posix-unknown } { POSIX~class~'[:#1:]'~unknown. } { '[:#1:]'~is~not~among~the~known~POSIX~classes~ @@ -6182,7 +6293,7 @@ '[:print:]',~'[:punct:]',~'[:space:]',~'[:upper:]',~ '[:word:]',~and~'[:xdigit:]'. } -\__msg_kernel_new:nnnn { regex } { posix-missing-close } +\__msg_kernel_new:nnnn { kernel } { posix-missing-close } { Missing~closing~':]'~for~POSIX~class. } { The~POSIX~syntax~'#1'~must~be~followed~by~':]',~not~'#2'. } % \end{macrocode} @@ -6191,7 +6302,7 @@ % with an unbalanced token list, which we must re-balance by adding % begin-group or end-group character tokens. % \begin{macrocode} -\__msg_kernel_new:nnnn { regex } { result-unbalanced } +\__msg_kernel_new:nnnn { kernel } { result-unbalanced } { Missing~brace~inserted~when~#1. } { LaTeX~was~asked~to~do~some~regular~expression~operation,~ @@ -6203,13 +6314,13 @@ % % Error message for unknown options. % \begin{macrocode} -\__msg_kernel_new:nnnn { regex } { unknown-option } +\__msg_kernel_new:nnnn { kernel } { unknown-option } { Unknown~option~'#1'~for~regular~expressions. } { The~only~available~option~is~'case-insensitive',~toggled~by~ '(?i)'~and~'(?-i)'. } -\__msg_kernel_new:nnnn { regex } { special-group-unknown } +\__msg_kernel_new:nnnn { kernel } { special-group-unknown } { Unknown~special~group~'#1~...'~in~a~regular~expression. } { The~only~valid~constructions~starting~with~'(?'~are~ @@ -6219,21 +6330,21 @@ % % Errors in the replacement text. % \begin{macrocode} -\__msg_kernel_new:nnnn { regex } { replacement-c } +\__msg_kernel_new:nnnn { kernel } { replacement-c } { Misused~'\iow_char:N\\c'~command~in~a~replacement~text. } { In~a~replacement~text,~the~'\iow_char:N\\c'~escape~sequence~ can~be~followed~by~one~of~the~letters~'ABCDELMOPSTU'~ or~a~brace~group,~not~by~'#1'. } -\__msg_kernel_new:nnnn { regex } { replacement-u } +\__msg_kernel_new:nnnn { kernel } { replacement-u } { Misused~'\iow_char:N\\u'~command~in~a~replacement~text. } { In~a~replacement~text,~the~'\iow_char:N\\u'~escape~sequence~ must~be~~followed~by~a~brace~group~holding~the~name~of~the~ variable~to~use. } -\__msg_kernel_new:nnnn { regex } { replacement-g } +\__msg_kernel_new:nnnn { kernel } { replacement-g } { Missing~brace~for~the~'\iow_char:N\\g'~construction~ in~a~replacement~text. @@ -6243,7 +6354,7 @@ submatches~are~represented~either~as~'\iow_char:N \\g{dd..d}',~ or~'\\d',~where~'d'~are~single~digits.~Here,~a~brace~is~missing. } -\__msg_kernel_new:nnnn { regex } { replacement-catcode-end } +\__msg_kernel_new:nnnn { kernel } { replacement-catcode-end } { Missing~character~for~the~'\iow_char:N\\c<category><character>'~ construction~in~a~replacement~text. @@ -6254,7 +6365,17 @@ the~character~category.~Then,~a~character~must~follow.~LaTeX~ reached~the~end~of~the~replacement~when~looking~for~that. } -\__msg_kernel_new:nnnn { regex } { replacement-catcode-in-cs } +\__msg_kernel_new:nnnn { kernel } { replacement-catcode-escaped } + { + Escaped~letter~or~digit~after~category~code~in~replacement~text. + } + { + In~a~replacement~text,~the~'\iow_char:N\\c'~escape~sequence~ + can~be~followed~by~one~of~the~letters~'ABCDELMOPSTU'~representing~ + the~character~category.~Then,~a~character~must~follow,~not~ + '\iow_char:N\\#2'. + } +\__msg_kernel_new:nnnn { kernel } { replacement-catcode-in-cs } { Category~code~'\iow_char:N\\c#1#3'~ignored~inside~ '\iow_char:N\\c\{...\}'~in~a~replacement~text. @@ -6264,7 +6385,7 @@ '\iow_char:N\\c\{...\}'~are~ignored~when~building~the~control~ sequence~name. } -\__msg_kernel_new:nnnn { regex } { replacement-null-space } +\__msg_kernel_new:nnnn { kernel } { replacement-null-space } { TeX~cannot~build~a~space~token~with~character~code~0. } { You~asked~for~a~character~token~with~category~space,~ @@ -6273,13 +6394,13 @@ This~specific~case~is~impossible~and~will~be~replaced~ by~a~normal~space. } -\__msg_kernel_new:nnnn { regex } { replacement-missing-rbrace } +\__msg_kernel_new:nnnn { kernel } { replacement-missing-rbrace } { Missing~right~brace~inserted~in~replacement~text. } { There~ \int_compare:nTF { #1 = 1 } { was } { were } ~ #1~ missing~right~\int_compare:nTF { #1 = 1 } { brace } { braces } . } -\__msg_kernel_new:nnnn { regex } { replacement-missing-rparen } +\__msg_kernel_new:nnnn { kernel } { replacement-missing-rparen } { Missing~right~parenthesis~inserted~in~replacement~text. } { There~ \int_compare:nTF { #1 = 1 } { was } { were } ~ #1~ |