summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/l3experimental
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2012-02-28 00:40:17 +0000
committerKarl Berry <karl@freefriends.org>2012-02-28 00:40:17 +0000
commited49b3dfe19b91f9fd96ab70fe95dcda8fba24c8 (patch)
tree0eb59527efd68f813d629e7d0977fe31d8d6419f /Master/texmf-dist/tex/latex/l3experimental
parentb1436d6ee293a02df32a18832d21c54348335565 (diff)
l3experimental 3471 (26feb12)
git-svn-id: svn://tug.org/texlive/trunk@25523 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/l3experimental')
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/l3dt/l3dt.sty2
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/l3sort/l3sort.sty2
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty2824
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty3638
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty68
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty35
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-build.sty120
-rw-r--r--Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty2
8 files changed, 4892 insertions, 1799 deletions
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3dt/l3dt.sty b/Master/texmf-dist/tex/latex/l3experimental/l3dt/l3dt.sty
index 5346944521c..99bd83e7764 100644
--- a/Master/texmf-dist/tex/latex/l3experimental/l3dt/l3dt.sty
+++ b/Master/texmf-dist/tex/latex/l3experimental/l3dt/l3dt.sty
@@ -47,7 +47,7 @@
%% -----------------------------------------------------------------------
%%
\RequirePackage{expl3}
-\GetIdInfo$Id: l3dt.dtx 3251 2012-01-28 09:42:44Z joseph $
+\GetIdInfo$Id: l3dt.dtx 3459 2012-02-26 08:58:53Z joseph $
{L3 Experimental data tables}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3sort/l3sort.sty b/Master/texmf-dist/tex/latex/l3experimental/l3sort/l3sort.sty
index 4de96fa88a3..b24bacd3794 100644
--- a/Master/texmf-dist/tex/latex/l3experimental/l3sort/l3sort.sty
+++ b/Master/texmf-dist/tex/latex/l3experimental/l3sort/l3sort.sty
@@ -47,7 +47,7 @@
%% -----------------------------------------------------------------------
%%
\RequirePackage{expl3}
-\GetIdInfo$Id: l3sort.dtx 3295 2012-02-02 09:30:14Z joseph $
+\GetIdInfo$Id: l3sort.dtx 3467 2012-02-26 15:39:35Z bruno $
{L3 Experimental sorting functions}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty
new file mode 100644
index 00000000000..60abf42cd5d
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty
@@ -0,0 +1,2824 @@
+%%
+%% This is file `l3regex-trace.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% l3regex.dtx (with options: `package,trace')
+%%
+%% EXPERIMENTAL CODE
+%%
+%% Do not distribute this file without also distributing the
+%% source files specified above.
+%%
+%% Do not distribute a modified version of this file.
+%%
+%% File: l3regex.dtx Copyright (C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3experimental bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The released version of this bundle is available from CTAN.
+%%
+%% -----------------------------------------------------------------------
+%%
+%% The development version of the bundle can be found at
+%%
+%% http://www.latex-project.org/svnroot/experimental/trunk/
+%%
+%% for those people who are interested.
+%%
+%%%%%%%%%%%
+%% NOTE: %%
+%%%%%%%%%%%
+%%
+%% Snapshots taken from the repository represent work in progress and may
+%% not work or may contain conflicting material! We therefore ask
+%% people _not_ to put them into distributions, archives, etc. without
+%% prior consultation with the LaTeX3 Project.
+%%
+%% -----------------------------------------------------------------------
+\RequirePackage{expl3}
+\GetIdInfo$Id: l3regex.dtx 3463 2012-02-26 15:05:14Z bruno $
+ {L3 Experimental Regular Expressions}
+\ProvidesExplPackage
+ {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
+\RequirePackage{l3tl-build, l3tl-analysis, l3flag, l3str}
+\cs_generate_variant:Nn \tl_to_str:n { V }
+\cs_new:Npn \regex_tmp:w { }
+\tl_new:N \l_regex_internal_a_tl
+\tl_new:N \l_regex_internal_b_tl
+\int_new:N \l_regex_internal_a_int
+\int_new:N \l_regex_internal_b_int
+\int_new:N \l_regex_internal_c_int
+\bool_new:N \l_regex_internal_bool
+\seq_new:N \l_regex_internal_seq
+\tl_new:N \g_regex_internal_tl
+\tl_const:Nn \c_regex_no_match_regex
+ {
+ \regex_branch:n
+ { \regex_class:NnnnN \c_true_bool { } { 1 } { 0 } \c_true_bool }
+ }
+\int_new:N \l_regex_balance_int
+\cs_new_protected:Npn \regex_break_true:w
+ #1 \regex_break_point:TF #2 #3 {#2}
+\cs_new_protected:Npn \regex_break_point:TF #1 #2 { #2 }
+\cs_new_protected:Npn \regex_item_reverse:n #1
+ {
+ #1
+ \regex_break_point:TF { } \regex_break_true:w
+ }
+\cs_new_protected: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_protected: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
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
+ \fi:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_item_caseless_equal:n #1
+ {
+ \if_num:w #1 = \l_regex_current_char_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ \if_num:w \l_regex_case_changed_char_int = \c_max_int
+ \regex_compute_case_changed_char:
+ \fi:
+ \if_num:w #1 = \l_regex_case_changed_char_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ }
+\cs_new_protected:Npn \regex_item_caseless_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
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
+ \fi:
+ \fi:
+ \if_num:w \l_regex_case_changed_char_int = \c_max_int
+ \regex_compute_case_changed_char:
+ \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_compute_case_changed_char:
+ {
+ \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_eq:NN \regex_item_equal:n ?
+\cs_new_eq:NN \regex_item_range:nn ?
+\cs_new_protected:Npn \regex_item_catcode_aux:
+ {
+ "
+ \if_case:w \l_regex_current_catcode_int
+ 1 \or: 4 \or: 10 \or: 40
+ \or: 100 \or: \or: 1000 \or: 4000
+ \or: 10000 \or: \or: 100000 \or: 400000
+ \or: 1000000 \or: 4000000 \else: 1*\c_zero
+ \fi:
+ }
+\cs_new_protected:Npn \regex_item_catcode:nT #1
+ {
+ \if_int_odd:w \int_eval:w #1 / \regex_item_catcode_aux: \int_eval_end:
+ \exp_after:wN \use:n
+ \else:
+ \exp_after:wN \use_none:n
+ \fi:
+ }
+\cs_new_protected:Npn \regex_item_catcode_reverse:nT #1#2
+ { \regex_item_catcode:nT {#1} { \regex_item_reverse:n {#2} } }
+\cs_new_protected:Npn \regex_item_exact:nn #1#2
+ {
+ \if_num:w #1 = \l_regex_current_catcode_int
+ \if_num:w #2 = \l_regex_current_char_int
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
+ \fi:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_item_exact_cs:c #1
+ {
+ \int_compare:nNnTF \l_regex_current_catcode_int = \c_zero
+ {
+ \str_if_eq:xxTF
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \cs_to_str:N
+ \tex_the:D \tex_toks:D \l_regex_current_pos_int
+ }
+ { #1 }
+ { \regex_break_true:w } { }
+ }
+ { }
+ }
+\cs_new_protected:Npn \regex_item_cs:n #1
+ {
+ \int_compare:nNnT \l_regex_current_catcode_int = \c_zero
+ {
+ \group_begin:
+ \regex_single_match:
+ \regex_disable_submatches:
+ \regex_build_for_cs:n {#1}
+ \bool_set_eq:NN \l_regex_saved_success_bool \g_regex_success_bool
+ \exp_args:Nx \regex_match:n
+ {
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \cs_to_str:N
+ \tex_the:D \tex_toks:D \l_regex_current_pos_int
+ }
+ \if_meaning:w \c_true_bool \g_regex_success_bool
+ \group_insert_after:N \regex_break_true:w
+ \fi:
+ \bool_gset_eq:NN \g_regex_success_bool \l_regex_saved_success_bool
+ \group_end:
+ }
+ }
+\cs_new_protected_nopar:Npn \regex_prop_d:
+ { \regex_item_caseful_range:nn \c_forty_eight { 57 } } % 0--9
+\cs_new_protected_nopar:Npn \regex_prop_h:
+ {
+ \regex_item_caseful_equal:n \c_thirty_two % space
+ \regex_item_caseful_equal:n \c_nine % tab
+ }
+\cs_new_protected_nopar:Npn \regex_prop_s:
+ {
+ \regex_item_caseful_equal:n \c_thirty_two % space
+ \regex_item_caseful_equal:n \c_nine % tab
+ \regex_item_caseful_equal:n \c_ten % lf
+ \regex_item_caseful_equal:n \c_twelve % ff
+ \regex_item_caseful_equal:n \c_thirteen % cr
+ }
+\cs_new_protected_nopar:Npn \regex_prop_v:
+ { \regex_item_caseful_range:nn \c_ten \c_thirteen } % lf, vtab, ff, cr
+\cs_new_protected_nopar:Npn \regex_prop_w:
+ {
+ \regex_item_caseful_range:nn \c_ninety_seven { 122 } % a--z
+ \regex_item_caseful_range:nn \c_sixty_five { 90 } % A--Z
+ \regex_item_caseful_range:nn \c_forty_eight { 57 } % 0--9
+ \regex_item_caseful_equal:n { 95 } % _
+ }
+\cs_new_protected_nopar:Npn \regex_prop_N:
+ { \regex_item_reverse:n { \regex_item_caseful_equal:n \c_ten } }
+\cs_new_protected_nopar:Npn \regex_posix_alnum:
+ { \regex_posix_alpha: \regex_posix_digit: }
+\cs_new_protected_nopar:Npn \regex_posix_alpha:
+ { \regex_posix_lower: \regex_posix_upper: }
+\cs_new_protected_nopar:Npn \regex_posix_ascii:
+ { \regex_item_caseful_range:nn \c_zero \c_one_hundred_twenty_seven }
+\cs_new_eq:NN \regex_posix_blank: \regex_prop_h:
+\cs_new_protected_nopar:Npn \regex_posix_cntrl:
+ {
+ \regex_item_caseful_range:nn \c_zero { 31 }
+ \regex_item_caseful_equal:n \c_one_hundred_twenty_seven
+ }
+\cs_new_eq:NN \regex_posix_digit: \regex_prop_d:
+\cs_new_protected_nopar:Npn \regex_posix_graph:
+ { \regex_item_caseful_range:nn { 33 } { 126 } }
+\cs_new_protected_nopar:Npn \regex_posix_lower:
+ { \regex_item_caseful_range:nn \c_ninety_seven { 122 } }
+\cs_new_protected_nopar:Npn \regex_posix_print:
+ { \regex_item_caseful_range:nn \c_thirty_two { 126 } }
+\cs_new_protected_nopar:Npn \regex_posix_punct:
+ {
+ \regex_item_caseful_range:nn { 33 } { 47 }
+ \regex_item_caseful_range:nn { 58 } { 64 }
+ \regex_item_caseful_range:nn { 91 } { 96 }
+ \regex_item_caseful_range:nn { 123 } { 126 }
+ }
+\cs_new_protected_nopar:Npn \regex_posix_space:
+ {
+ \regex_item_caseful_equal:n \c_thirty_two
+ \regex_item_caseful_range:nn \c_nine \c_thirteen
+ }
+\cs_new_protected_nopar:Npn \regex_posix_upper:
+ { \regex_item_caseful_range:nn \c_sixty_five { 90 } }
+\cs_new_eq:NN \regex_posix_word: \regex_prop_w:
+\cs_new_protected_nopar:Npn \regex_posix_xdigit:
+ {
+ \regex_posix_digit:
+ \regex_item_caseful_range:nn \c_sixty_five { 70 }
+ \regex_item_caseful_range:nn \c_ninety_seven { 102 }
+ }
+\cs_new_protected:Npn \regex_escape_use:nnnn #1#2#3#4
+ {
+ \trace_push:nnn { regex } { 1 } { regex_escape_use:nnnn }
+ \tl_set_build:Nw \l_regex_internal_a_tl
+ \cs_set_nopar:Npn \regex_escape_unescaped:N ##1 { #1 }
+ \cs_set_nopar:Npn \regex_escape_escaped:N ##1 { #2 }
+ \cs_set_nopar:Npn \regex_escape_raw:N ##1 { #3 }
+ \int_set:Nn \tex_escapechar:D { 92 }
+ \str_gset_other:Nn \g_regex_internal_tl { #4 }
+ \tl_set:Nx \l_regex_internal_b_tl
+ {
+ \exp_after:wN \regex_escape_loop:N \g_regex_internal_tl
+ { break } \prg_break_point:n { }
+ }
+ \tl_build_one:o \l_regex_internal_b_tl
+ \tl_build_end:
+ \trace_pop:nnn { regex } { 1 } { regex_escape_use:nnnn }
+ \l_regex_internal_a_tl
+ }
+\cs_new:Npn \regex_escape_loop:N #1
+ {
+ \cs_if_exist_use:cF { regex_escape_\token_to_str:N #1:w }
+ { \regex_escape_unescaped:N #1 }
+ \regex_escape_loop:N
+ }
+\cs_new_nopar:cpn { regex_escape_ \c_backslash_str :w }
+ \regex_escape_loop:N #1
+ {
+ \cs_if_exist_use:cF { regex_escape_/\token_to_str:N #1:w }
+ { \regex_escape_escaped:N #1 }
+ \regex_escape_loop:N
+ }
+\cs_new_eq:NN \regex_escape_unescaped:N ?
+\cs_new_eq:NN \regex_escape_escaped:N ?
+\cs_new_eq:NN \regex_escape_raw:N ?
+\cs_new_eq:NN \regex_escape_break:w \prg_map_break:
+\cs_new_nopar:cpn { regex_escape_/break:w }
+ {
+ \if_false: { \fi: }
+ \msg_kernel_error:nn { regex } { trailing-backslash }
+ \exp_after:wN \use_none:n \exp_after:wN { \if_false: } \fi:
+ }
+\cs_new_nopar:cpn { regex_escape_~:w } { }
+\cs_new_nopar:cpx { regex_escape_/a:w }
+ { \exp_not:N \regex_escape_raw:N \iow_char:N \^^G }
+\cs_new_nopar:cpx { regex_escape_/t:w }
+ { \exp_not:N \regex_escape_raw:N \iow_char:N \^^I }
+\cs_new_nopar:cpx { regex_escape_/n:w }
+ { \exp_not:N \regex_escape_raw:N \iow_char:N \^^J }
+\cs_new_nopar:cpx { regex_escape_/f:w }
+ { \exp_not:N \regex_escape_raw:N \iow_char:N \^^L }
+\cs_new_nopar:cpx { regex_escape_/r:w }
+ { \exp_not:N \regex_escape_raw:N \iow_char:N \^^M }
+\cs_new_nopar:cpx { regex_escape_/e:w }
+ { \exp_not:N \regex_escape_raw:N \iow_char:N \^^[ }
+\cs_new:cpn { regex_escape_/x:w } \regex_escape_loop:N
+ {
+ \exp_after:wN \regex_escape_x_end:w
+ \int_value:w "0 \regex_escape_x_test:N
+ }
+\cs_new:Npn \regex_escape_x_end:w #1 ;
+ {
+ \int_compare:nNnTF {#1} < \c_two_hundred_fifty_six
+ {
+ \exp_last_unbraced:Nf \regex_escape_raw:N
+ { \str_output_byte:n {#1} }
+ }
+ { \regex_escape_x_large:n {#1} }
+ }
+\group_begin:
+ \char_set_catcode_other:n { 0 }
+ \cs_new:Npn \regex_escape_x_large:n #1
+ {
+ \if_false: { \fi: }
+ \tl_build_one:o \l_regex_internal_b_tl
+ \int_compare:nNnTF {#1} > \c_max_char_int
+ {
+ \msg_kernel_error:nnx { regex } { x-overflow } {#1}
+ \tl_set:Nx \l_regex_internal_b_tl
+ { \if_false: } \fi: \regex_escape_loop:N
+ }
+ {
+ \char_set_lccode:nn { \c_zero } {#1}
+ \tl_to_lowercase:n
+ {
+ \tl_set:Nx \l_regex_internal_b_tl
+ { \if_false: } \fi:
+ \regex_escape_raw:N ^^@
+ \regex_escape_loop:N
+ }
+ }
+ }
+\group_end:
+\cs_new:Npn \regex_escape_x_test:N #1
+ {
+ \str_if_eq:xxTF {#1} { break } { ; }
+ {
+ \if_charcode:w \c_space_token #1
+ \exp_after:wN \regex_escape_x_test:N
+ \else:
+ \exp_after:wN \regex_escape_x_test_ii:N
+ \exp_after:wN #1
+ \fi:
+ }
+ }
+\cs_new:Npn \regex_escape_x_test_ii:N #1
+ {
+ \if_charcode:w \c_lbrace_str #1
+ \exp_after:wN \regex_escape_x_loop:N
+ \else:
+ \str_aux_hexadecimal_use:NTF #1
+ { \exp_after:wN \regex_escape_x_ii:N }
+ { ; \exp_after:wN \regex_escape_loop:N \exp_after:wN #1 }
+ \fi:
+ }
+\cs_new:Npn \regex_escape_x_ii:N #1
+ {
+ \str_if_eq:xxTF {#1} { break } { ; }
+ {
+ \str_aux_hexadecimal_use:NTF #1
+ { ; \regex_escape_loop:N }
+ { ; \regex_escape_loop:N #1 }
+ }
+ }
+\cs_new:Npn \regex_escape_x_loop:N #1
+ {
+ \str_aux_hexadecimal_use:NTF #1
+ { \regex_escape_x_loop:N }
+ {
+ \token_if_eq_charcode:NNTF \c_space_token #1
+ { \regex_escape_x_loop:N }
+ {
+ ;
+ \exp_after:wN \token_if_eq_charcode:NNTF \c_rbrace_str #1
+ { \regex_escape_loop:N }
+ {
+ \if_false: { \fi: }
+ \tl_build_one:o \l_regex_internal_b_tl
+ \msg_kernel_error:nn { regex } { x-missing-rbrace } {#1}
+ \tl_set:Nx \l_regex_internal_b_tl
+ { \if_false: } \fi: \regex_escape_loop:N #1
+ }
+ }
+ }
+ }
+\prg_new_conditional:Npnn \regex_char_if_special:N #1 { TF }
+ {
+ \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 `#1 < \c_sixty_five
+ \prg_return_true: \else: \prg_return_false: \fi:
+ \fi:
+ \else:
+ \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:
+ \if_num:w `#1 < \c_one_hundred_twenty_seven
+ \prg_return_true: \else: \prg_return_false: \fi:
+ \fi:
+ \fi:
+ }
+\prg_new_conditional:Npnn \regex_char_if_alphanumeric:N #1 { TF }
+ {
+ \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:
+ \if_num:w `#1 < \c_sixty_five
+ \prg_return_false: \else: \prg_return_true: \fi:
+ \fi:
+ \else:
+ \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:
+ \fi:
+ }
+\int_new:N \l_regex_group_level_int
+\int_new:N \l_regex_mode_int
+\int_new:N \l_regex_catcodes_int
+\int_new:N \l_regex_default_catcodes_int
+\bool_new:N \l_regex_catcodes_bool
+\int_const:Nn \c_regex_catcode_C_int { "1 }
+\int_const:Nn \c_regex_catcode_B_int { "4 }
+\int_const:Nn \c_regex_catcode_E_int { "10 }
+\int_const:Nn \c_regex_catcode_M_int { "40 }
+\int_const:Nn \c_regex_catcode_T_int { "100 }
+\int_const:Nn \c_regex_catcode_P_int { "1000 }
+\int_const:Nn \c_regex_catcode_U_int { "4000 }
+\int_const:Nn \c_regex_catcode_D_int { "10000 }
+\int_const:Nn \c_regex_catcode_S_int { "100000 }
+\int_const:Nn \c_regex_catcode_L_int { "400000 }
+\int_const:Nn \c_regex_catcode_O_int { "1000000 }
+\int_const:Nn \c_regex_catcode_A_int { "4000000 }
+\int_const:Nn \c_regex_all_catcodes_int { "5515155 }
+\cs_new_eq:NN \l_regex_internal_regex \c_regex_no_match_regex
+\seq_new:N \l_regex_show_prefix_seq
+\int_new:N \l_regex_show_lines_int
+\cs_new_protected:Npn \regex_get_digits:NTFw #1#2#3#4#5
+ {
+ \regex_if_raw_digit:NNTF #4 #5
+ { #1 = #5 \regex_get_digits_loop:nw {#2} }
+ { #3 #4 #5 }
+ }
+\cs_new:Npn \regex_get_digits_loop:nw #1#2#3
+ {
+ \regex_if_raw_digit:NNTF #2 #3
+ { #3 \regex_get_digits_loop:nw {#1} }
+ { \scan_stop: #1 #2 #3 }
+ }
+\prg_new_conditional:Npnn \regex_if_raw_digit:NN #1#2 { TF }
+ {
+ \if_meaning:w \regex_compile_raw:N #1
+ \if_int_compare:w \c_one < 1 #2 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\cs_new_nopar:Npn \regex_if_in_class:TF
+ {
+ \if_int_odd:w \l_regex_mode_int
+ \exp_after:wN \use_i:nn
+ \else:
+ \exp_after:wN \use_ii:nn
+ \fi:
+ }
+\cs_new_nopar:Npn \regex_if_in_cs:TF
+ {
+ \if_int_odd:w \l_regex_mode_int
+ \exp_after:wN \use_ii:nn
+ \else:
+ \if_int_compare:w \l_regex_mode_int < \c_zero
+ \exp_after:wN \exp_after:wN \exp_after:wN \use_i:nn
+ \else:
+ \exp_after:wN \exp_after:wN \exp_after:wN \use_ii:nn
+ \fi:
+ \fi:
+ }
+\cs_new_nopar:Npn \regex_if_in_class_or_catcode:TF
+ {
+ \if_int_odd:w \l_regex_mode_int
+ \exp_after:wN \use_i:nn
+ \else:
+ \if_int_compare:w \l_regex_mode_int > \c_zero
+ \exp_after:wN \exp_after:wN \exp_after:wN \use_i:nn
+ \else:
+ \exp_after:wN \exp_after:wN \exp_after:wN \use_ii:nn
+ \fi:
+ \fi:
+ }
+\cs_new_nopar:Npn \regex_if_within_catcode:TF
+ {
+ \if_int_compare:w \l_regex_mode_int > \c_zero
+ \exp_after:wN \use_i:nn
+ \else:
+ \exp_after:wN \use_ii:nn
+ \fi:
+ }
+\cs_new_protected:Npn \regex_chk_c_allowed:T
+ {
+ \if_num:w \l_regex_mode_int = \c_zero
+ \exp_after:wN \use:n
+ \else:
+ \if_num:w \l_regex_mode_int = \c_three
+ \exp_after:wN \exp_after:wN \exp_after:wN \use:n
+ \else:
+ \msg_kernel_error:nn { regex } { c-bad-mode }
+ \exp_after:wN \exp_after:wN \exp_after:wN \use_none:n
+ \fi:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_mode_quit_c:
+ {
+ \if_num:w \l_regex_mode_int = \c_two
+ \l_regex_mode_int = \c_zero
+ \else:
+ \if_num:w \l_regex_mode_int = \c_six
+ \l_regex_mode_int = \c_three
+ \fi:
+ \fi:
+ }
+\cs_new_protected_nopar:Npn \regex_compile:w
+ {
+ \tl_set_build_x:Nw \l_regex_internal_regex
+ \int_zero:N \l_regex_group_level_int
+ \int_set_eq:NN \l_regex_default_catcodes_int \c_regex_all_catcodes_int
+ \int_set_eq:NN \l_regex_catcodes_int \l_regex_default_catcodes_int
+ \cs_set_nopar:Npn \regex_item_equal:n { \regex_item_caseful_equal:n }
+ \cs_set_nopar:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
+ \tl_build_one:n { \regex_branch:n { \if_false: } \fi: }
+ }
+\cs_new_protected_nopar:Npn \regex_compile_end:
+ {
+ \regex_if_in_class:TF
+ {
+ \msg_kernel_error:nn { regex } { missing-rbrack }
+ \use:c { regex_compile_]: }
+ \prg_do_nothing: \prg_do_nothing:
+ }
+ { }
+ \if_num:w \l_regex_group_level_int > \c_zero
+ \msg_kernel_error:nnx { regex } { missing-rparen }
+ { \int_use:N \l_regex_group_level_int }
+ \prg_replicate:nn
+ { \l_regex_group_level_int }
+ {
+ \tl_build_one:n
+ {
+ \if_false: { \fi: }
+ \if_false: { \fi: } { 1 } { 0 } \c_true_bool
+ }
+ \tl_build_end:
+ \tl_build_one:o \l_regex_internal_regex
+ }
+ \fi:
+ \tl_build_one:n { \if_false: { \fi: } }
+ \tl_build_end:
+ }
+\cs_new_protected:Npn \regex_compile:n #1
+ {
+ \regex_compile:w
+ \int_set:Nn \tex_escapechar:D { 92 }
+ \int_set_eq:NN \l_regex_mode_int \c_zero
+ \regex_escape_use:nnnn
+ {
+ \regex_char_if_special:NTF ##1
+ \regex_compile_special:N \regex_compile_raw:N ##1
+ }
+ {
+ \regex_char_if_alphanumeric:NTF ##1
+ \regex_compile_escaped:N \regex_compile_raw:N ##1
+ }
+ { \regex_compile_raw:N ##1 }
+ { #1 }
+ \prg_do_nothing: \prg_do_nothing:
+ \prg_do_nothing: \prg_do_nothing:
+ \int_compare:nNnT \l_regex_mode_int < \c_zero
+ {
+ \msg_kernel_error:nn { regex } { c-missing-rbrace }
+ \regex_compile_end:
+ \regex_compile_one:x
+ { \regex_item_cs:n { \exp_not:o \l_regex_internal_regex } }
+ \prg_do_nothing: \prg_do_nothing:
+ \prg_do_nothing: \prg_do_nothing:
+ }
+ \regex_compile_end:
+ }
+\cs_new_protected:Npn \regex_compile_special:N #1
+ {
+ \cs_if_exist_use:cF { regex_compile_#1: }
+ { \regex_compile_raw:N #1 }
+ }
+\cs_new_protected:Npn \regex_compile_escaped:N #1
+ {
+ \cs_if_exist_use:cF { regex_compile_/#1: }
+ { \regex_compile_raw:N #1 }
+ }
+\cs_new_protected:Npn \regex_compile_one:x #1
+ {
+ \regex_mode_quit_c:
+ \regex_if_in_class:TF { }
+ {
+ \tl_build_one:n
+ { \regex_class:NnnnN \c_true_bool { \if_false: } \fi: }
+ }
+ \tl_build_one:x
+ {
+ \if_num:w \l_regex_catcodes_int < \c_regex_all_catcodes_int
+ \regex_item_catcode:nT { \int_use:N \l_regex_catcodes_int }
+ { \exp_not:N \exp_not:n {#1} }
+ \else:
+ \exp_not:N \exp_not:n {#1}
+ \fi:
+ }
+ \int_set_eq:NN \l_regex_catcodes_int \l_regex_default_catcodes_int
+ \regex_if_in_class:TF { } { \regex_compile_quantifier:w }
+ }
+\cs_new_protected:Npn \regex_compile_abort_tokens:n #1
+ {
+ \use:x
+ {
+ \exp_args:No \tl_map_function:nN { \tl_to_str:n {#1} }
+ \regex_compile_raw:N
+ }
+ }
+\cs_generate_variant:Nn \regex_compile_abort_tokens:n { x }
+\cs_new_protected:Npn \regex_compile_quantifier:w #1#2
+ {
+ \token_if_eq_meaning:NNTF #1 \regex_compile_special:N
+ {
+ \cs_if_exist_use:cF { regex_compile_quantifier_#2:w }
+ { \regex_compile_quantifier_none: #1 #2 }
+ }
+ { \regex_compile_quantifier_none: #1 #2 }
+ }
+\cs_new_protected:Npn \regex_compile_quantifier_none:
+ { \tl_build_one:n { \if_false: { \fi: } { 1 } { 0 } \c_false_bool } }
+\cs_new_protected:Npn \regex_compile_quantifier_abort:xNN #1#2#3
+ {
+ \regex_compile_quantifier_none:
+ \msg_kernel_warning:nnxx { regex } { invalid-quantifier } {#1} {#3}
+ \regex_compile_abort_tokens:x {#1}
+ #2 #3
+ }
+\cs_new_protected:Npn \regex_compile_quantifier_lazyness:nnNN #1#2#3#4
+ {
+ \str_if_eq:nnTF { #3 #4 } { \regex_compile_special:N ? }
+ { \tl_build_one:n { \if_false: { \fi: } { #1 } { #2 } \c_true_bool } }
+ {
+ \tl_build_one:n { \if_false: { \fi: } { #1 } { #2 } \c_false_bool }
+ #3 #4
+ }
+ }
+\cs_new_protected_nopar:cpn { regex_compile_quantifier_?:w }
+ { \regex_compile_quantifier_lazyness:nnNN { 0 } { 1 } }
+\cs_new_protected_nopar:cpn { regex_compile_quantifier_*:w }
+ { \regex_compile_quantifier_lazyness:nnNN { 0 } { -1 } }
+\cs_new_protected_nopar:cpn { regex_compile_quantifier_+:w }
+ { \regex_compile_quantifier_lazyness:nnNN { 1 } { -1 } }
+\cs_new_protected:cpn { regex_compile_quantifier_ \c_lbrace_str :w }
+ {
+ \regex_get_digits:NTFw \l_regex_internal_a_int
+ { \regex_compile_quantifier_braced_i:w }
+ { \regex_compile_quantifier_abort:xNN { \c_lbrace_str } }
+ }
+\cs_new_protected:Npn \regex_compile_quantifier_braced_i:w #1#2
+ {
+ \prg_case_str:xxn { #1 #2 }
+ {
+ { \regex_compile_special:N \c_rbrace_str }
+ {
+ \exp_args:No \regex_compile_quantifier_lazyness:nnNN
+ { \int_use:N \l_regex_internal_a_int } { 0 }
+ }
+ { \regex_compile_special:N , }
+ {
+ \regex_get_digits:NTFw \l_regex_internal_b_int
+ { \regex_compile_quantifier_braced_iii:w }
+ { \regex_compile_quantifier_braced_ii:w }
+ }
+ }
+ {
+ \regex_compile_quantifier_abort:xNN
+ { \c_lbrace_str \int_use:N \l_regex_internal_a_int }
+ #1 #2
+ }
+ }
+\cs_new_protected:Npn \regex_compile_quantifier_braced_ii:w #1#2
+ {
+ \str_if_eq:xxTF
+ { #1 #2 } { \regex_compile_special:N \c_rbrace_str }
+ {
+ \exp_args:No \regex_compile_quantifier_lazyness:nnNN
+ { \int_use:N \l_regex_internal_a_int } { -1 }
+ }
+ {
+ \regex_compile_quantifier_abort:xNN
+ { \c_lbrace_str \int_use:N \l_regex_internal_a_int , }
+ #1 #2
+ }
+ }
+\cs_new_protected:Npn \regex_compile_quantifier_braced_iii:w #1#2
+ {
+ \str_if_eq:xxTF
+ { #1 #2 } { \regex_compile_special:N \c_rbrace_str }
+ {
+ \if_num:w \l_regex_internal_a_int > \l_regex_internal_b_int
+ \msg_kernel_error:nnxx { regex } { backwards-quantifier }
+ { \int_use:N \l_regex_internal_a_int }
+ { \int_use:N \l_regex_internal_b_int }
+ \int_zero:N \l_regex_internal_b_int
+ \else:
+ \int_sub:Nn \l_regex_internal_b_int \l_regex_internal_a_int
+ \fi:
+ \exp_args:Noo \regex_compile_quantifier_lazyness:nnNN
+ { \int_use:N \l_regex_internal_a_int }
+ { \int_use:N \l_regex_internal_b_int }
+ }
+ {
+ \regex_compile_quantifier_abort:xNN
+ {
+ \c_lbrace_str
+ \int_use:N \l_regex_internal_a_int ,
+ \int_use:N \l_regex_internal_b_int
+ }
+ #1 #2
+ }
+ }
+\cs_new_protected:Npn \regex_compile_raw_error:N #1
+ {
+ \msg_kernel_error:nnx { regex } { bad-escape } {#1}
+ \regex_compile_raw:N #1
+ }
+\cs_new_protected:Npn \regex_compile_raw:N #1#2#3
+ {
+ \regex_if_in_class:TF
+ {
+ \str_if_eq:nnTF {#2#3} { \regex_compile_special:N - }
+ { \regex_compile_range:Nw #1 }
+ {
+ \regex_compile_one:x
+ { \regex_item_equal:n { \int_value:w `#1 ~ } }
+ #2 #3
+ }
+ }
+ {
+ \regex_compile_one:x
+ { \regex_item_equal:n { \int_value:w `#1 ~ } }
+ #2 #3
+ }
+ }
+\prg_new_protected_conditional:Npnn \regex_if_end_range:NN #1#2 { TF }
+ {
+ \if_meaning:w \regex_compile_raw:N #1
+ \prg_return_true:
+ \else:
+ \if_meaning:w \regex_compile_special:N #1
+ \if_charcode:w ] #2
+ \prg_return_false:
+ \else:
+ \prg_return_true:
+ \fi:
+ \else:
+ \prg_return_false:
+ \fi:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_compile_range:Nw #1#2#3
+ {
+ \regex_if_end_range:NNTF #2 #3
+ {
+ \if_num:w `#1 > `#3 \exp_stop_f:
+ \msg_kernel_error:nnxx { regex } { range-backwards } {#1} {#3}
+ \else:
+ \tl_build_one:x
+ {
+ \if_num:w `#1 = `#3 \exp_stop_f:
+ \regex_item_equal:n
+ \else:
+ \regex_item_range:nn { \int_value:w `#1 ~ }
+ \fi:
+ { \int_value:w `#3 ~ }
+ }
+ \fi:
+ }
+ {
+ \msg_kernel_warning:nnxx { regex } { range-missing-end }
+ {#1} { \c_backslash_str #3 }
+ \tl_build_one:x
+ {
+ \regex_item_equal:n { \int_value:w `#1 ~ }
+ \regex_item_equal:n { \int_value:w `- ~ }
+ }
+ #2#3
+ }
+ }
+\cs_new_protected_nopar:cpx { regex_compile_.: }
+ {
+ \exp_not:N \regex_if_in_class:TF
+ { \regex_compile_raw:N . }
+ { \regex_compile_one:x \exp_not:c { regex_prop_.: } }
+ }
+\cs_new_protected_nopar:cpn { regex_prop_.: }
+ {
+ \if_num:w \l_regex_current_char_int > - \c_two
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ }
+\cs_set_protected:Npn \regex_tmp:w #1#2
+ {
+ \cs_new_protected_nopar:cpx { regex_compile_/#1: }
+ { \regex_compile_one:x \exp_not:c { regex_prop_#1: } }
+ \cs_new_protected_nopar:cpx { regex_compile_/#2: }
+ {
+ \regex_compile_one:x
+ { \regex_item_reverse:n \exp_not:c { regex_prop_#1: } }
+ }
+ }
+\regex_tmp:w d D
+\regex_tmp:w h H
+\regex_tmp:w s S
+\regex_tmp:w v V
+\regex_tmp:w w W
+\cs_new_protected_nopar:cpn { regex_compile_/N: }
+ { \regex_compile_one:x \regex_prop_N: }
+\cs_new_protected:Npn \regex_compile_anchor:NF #1#2
+ {
+ \regex_if_in_class_or_catcode:TF {#2}
+ {
+ \tl_build_one:n
+ { \regex_assertion:Nn \c_true_bool { \regex_anchor:N #1 } }
+ }
+ }
+\cs_set_protected:Npn \regex_tmp:w #1#2
+ {
+ \cs_new_protected_nopar:cpn { regex_compile_/#1: }
+ { \regex_compile_anchor:NF #2 { \regex_compile_raw_error:N #1 } }
+ }
+\regex_tmp:w A \l_regex_min_pos_int
+\regex_tmp:w G \l_regex_start_pos_int
+\regex_tmp:w Z \l_regex_max_pos_int
+\regex_tmp:w z \l_regex_max_pos_int
+\cs_set_protected:Npn \regex_tmp:w #1#2
+ {
+ \cs_new_protected_nopar:cpn { regex_compile_#1: }
+ { \regex_compile_anchor:NF #2 { \regex_compile_raw:N #1 } }
+ }
+\exp_args:Nx \regex_tmp:w { \iow_char:N \^ } \l_regex_min_pos_int
+\exp_args:Nx \regex_tmp:w { \iow_char:N \$ } \l_regex_max_pos_int
+\cs_new_protected_nopar:cpn { regex_compile_/b: }
+ {
+ \regex_if_in_class_or_catcode:TF
+ { \regex_compile_raw_error:N b }
+ {
+ \tl_build_one:n
+ { \regex_assertion:Nn \c_true_bool { \regex_b_test: } }
+ }
+ }
+\cs_new_protected_nopar:cpn { regex_compile_/B: }
+ {
+ \regex_if_in_class_or_catcode:TF
+ { \regex_compile_raw_error:N B }
+ {
+ \tl_build_one:n
+ { \regex_assertion:Nn \c_false_bool { \regex_b_test: } }
+ }
+ }
+\cs_new_protected:cpn { regex_compile_]: }
+ {
+ \regex_if_in_class:TF
+ {
+ \if_num:w \l_regex_mode_int > \c_sixteen
+ \tl_build_one:n { \if_false: { \fi: } }
+ \fi:
+ \tex_advance:D \l_regex_mode_int - \c_fifteen
+ \tex_divide:D \l_regex_mode_int \c_thirteen
+ \if_int_odd:w \l_regex_mode_int \else:
+ \exp_after:wN \regex_compile_quantifier:w
+ \fi:
+ }
+ { \regex_compile_raw:N ] }
+ }
+\cs_new_protected_nopar:cpn { regex_compile_[: }
+ {
+ \regex_if_in_class:TF
+ { \regex_compile_class_posix_test:w }
+ {
+ \regex_if_within_catcode:TF
+ {
+ \exp_after:wN \regex_compile_class_catcode:w
+ \int_use:N \l_regex_catcodes_int ;
+ }
+ { \regex_compile_class_normal:w }
+ }
+ }
+\cs_new_protected_nopar:Npn \regex_compile_class_normal:w
+ {
+ \regex_compile_class:TFNN
+ { \regex_class:NnnnN \c_true_bool }
+ { \regex_class:NnnnN \c_false_bool }
+ }
+\cs_new_protected:Npn \regex_compile_class_catcode:w #1;
+ {
+ \if_int_compare:w \l_regex_mode_int = \c_two
+ \tl_build_one:n
+ { \regex_class:NnnnN \c_true_bool { \if_false: } \fi: }
+ \fi:
+ \int_set_eq:NN \l_regex_catcodes_int \l_regex_default_catcodes_int
+ \regex_compile_class:TFNN
+ { \regex_item_catcode:nT {#1} }
+ { \regex_item_catcode_reverse:nT {#1} }
+ }
+\cs_new_protected:Npn \regex_compile_class:TFNN #1#2#3#4
+ {
+ \l_regex_mode_int = \int_value:w \l_regex_mode_int 3 \exp_stop_f:
+ \str_if_eq:nnTF { #3 #4 } { \regex_compile_special:N ^ }
+ {
+ \tl_build_one:n { #2 { \if_false: } \fi: }
+ \regex_compile_class_ii:NN
+ }
+ {
+ \tl_build_one:n { #1 { \if_false: } \fi: }
+ \regex_compile_class_ii:NN #3 #4
+ }
+ }
+\cs_new_protected:Npn \regex_compile_class_ii:NN #1#2
+ {
+ \token_if_eq_charcode:NNTF #2 ]
+ { \regex_compile_raw:N #2 }
+ { #1 #2 }
+ }
+\cs_new_protected:Npn \regex_compile_class_posix_test:w #1#2
+ {
+ \token_if_eq_meaning:NNT \regex_compile_special:N #1
+ {
+ \prg_case_str:nnn { #2 }
+ {
+ : { \regex_compile_class_posix:NNNNw }
+ = { \msg_kernel_warning:nnx { regex } { posix-unsupported } { = } }
+ . { \msg_kernel_warning:nnx { regex } { posix-unsupported } { . } }
+ }
+ { }
+ }
+ \regex_compile_raw:N [ #1 #2
+ }
+\cs_new_protected:Npn \regex_compile_class_posix:NNNNw #1#2#3#4#5#6
+ {
+ \str_if_eq:nnTF { #5 #6 } { \regex_compile_special:N ^ }
+ {
+ \bool_set_false:N \l_regex_internal_bool
+ \tl_set:Nx \l_regex_internal_a_tl { \if_false: } \fi:
+ \regex_compile_class_posix_loop:w
+ }
+ {
+ \bool_set_true:N \l_regex_internal_bool
+ \tl_set:Nx \l_regex_internal_a_tl { \if_false: } \fi:
+ \regex_compile_class_posix_loop:w #5 #6
+ }
+ }
+\cs_new:Npn \regex_compile_class_posix_loop:w #1#2
+ {
+ \token_if_eq_meaning:NNTF \regex_compile_raw:N #1
+ { #2 \regex_compile_class_posix_loop:w }
+ { \if_false: { \fi: } \regex_compile_class_posix_end:w #1 #2 }
+ }
+\cs_new_protected:Npn \regex_compile_class_posix_end:w #1#2#3#4
+ {
+ \str_if_eq:nnTF { #1 #2 #3 #4 }
+ { \regex_compile_special:N : \regex_compile_special:N ] }
+ {
+ \cs_if_exist:cTF { regex_posix_ \l_regex_internal_a_tl : }
+ {
+ \regex_compile_one:x
+ {
+ \bool_if:NF \l_regex_internal_bool \regex_item_reverse:n
+ \exp_not:c { regex_posix_ \l_regex_internal_a_tl : }
+ }
+ }
+ {
+ \msg_kernel_warning:nnx { regex } { posix-unknown }
+ { \l_regex_internal_a_tl }
+ \regex_compile_abort_tokens:x
+ {
+ [: \bool_if:NF \l_regex_internal_bool { ^ }
+ \l_regex_internal_a_tl :]
+ }
+ }
+ }
+ {
+ \msg_kernel_error:nnxx { regex } { posix-missing-close }
+ { [: \l_regex_internal_a_tl } { #2 #4 }
+ \regex_compile_abort_tokens:x { [: \l_regex_internal_a_tl }
+ #1 #2 #3 #4
+ }
+ }
+\cs_new_protected:Npn \regex_compile_group_begin:N #1
+ {
+ \tl_build_one:n { #1 { \if_false: } \fi: }
+ \regex_mode_quit_c:
+ \tl_set_build:Nw \l_regex_internal_regex
+ \int_set_eq:NN \l_regex_default_catcodes_int \l_regex_catcodes_int
+ \int_incr:N \l_regex_group_level_int
+ \tl_build_one:n { \regex_branch:n { \if_false: } \fi: }
+ }
+\cs_new_protected:Npn \regex_compile_group_end:
+ {
+ \if_num:w \l_regex_group_level_int > \c_zero
+ \tl_build_one:n { \if_false: { \fi: } }
+ \tl_build_end:
+ \int_set_eq:NN \l_regex_catcodes_int \l_regex_default_catcodes_int
+ \tl_build_one:o \l_regex_internal_regex
+ \exp_after:wN \regex_compile_quantifier:w
+ \else:
+ \msg_kernel_warning:nn { regex } { extra-rparen }
+ \exp_after:wN \regex_compile_raw:N \exp_after:wN )
+ \fi:
+ }
+\cs_new_protected_nopar:cpn { regex_compile_(: }
+ {
+ \regex_if_in_class:TF { \regex_compile_raw:N ( }
+ { \regex_compile_lparen:w }
+ }
+\cs_new_protected:Npn \regex_compile_lparen:w #1#2#3#4
+ {
+ \str_if_eq:nnTF { #1 #2 } { \regex_compile_special:N ? }
+ {
+ \cs_if_exist_use:cF
+ { regex_compile_special_group_\token_to_str:N #4 :w }
+ {
+ \msg_kernel_warning:nnx { regex } { special-group-unknown }
+ { (? \token_to_str:N #4 }
+ \regex_compile_group_begin:N \regex_group:nnnN
+ \regex_compile_raw:N ? #3 #4
+ }
+ }
+ {
+ \regex_compile_group_begin:N \regex_group:nnnN
+ #1 #2 #3 #4
+ }
+ }
+\cs_new_protected_nopar:cpn { regex_compile_|: }
+ {
+ \regex_if_in_class:TF { \regex_compile_raw:N | }
+ {
+ \tl_build_one:n
+ { \if_false: { \fi: } \regex_branch:n { \if_false: } \fi: }
+ }
+ }
+\cs_new_protected_nopar:cpn { regex_compile_): }
+ {
+ \regex_if_in_class:TF { \regex_compile_raw:N ) }
+ { \regex_compile_group_end: }
+ }
+\cs_new_protected_nopar:cpn { regex_compile_special_group_::w }
+ { \regex_compile_group_begin:N \regex_group_no_capture:nnnN }
+\cs_new_protected_nopar:cpn { regex_compile_special_group_|:w }
+ { \regex_compile_group_begin:N \regex_group_resetting:nnnN }
+\cs_new_protected:Npn \regex_compile_special_group_i:w #1#2
+ {
+ \str_if_eq:nnTF { #1 #2 } { \regex_compile_special:N ) }
+ {
+ \cs_set_nopar:Npn \regex_item_equal:n { \regex_item_caseless_equal:n }
+ \cs_set_nopar:Npn \regex_item_range:nn { \regex_item_caseless_range:nn }
+ }
+ {
+ \msg_kernel_warning:nnx { regex } { unknown-option } { (?i #2 }
+ \regex_compile_raw:N (
+ \regex_compile_raw:N ?
+ \regex_compile_raw:N i
+ #1 #2
+ }
+ }
+\cs_new_protected_nopar:cpn { regex_compile_special_group_-:w } #1#2#3#4
+ {
+ \str_if_eq:nnTF { #1 #2 #3 #4 }
+ { \regex_compile_raw:N i \regex_compile_special:N ) }
+ {
+ \cs_set_nopar:Npn \regex_item_equal:n { \regex_item_caseful_equal:n }
+ \cs_set_nopar:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
+ }
+ {
+ \msg_kernel_warning:nnx { regex } { unknown-option } { (?-#2#4 }
+ \regex_compile_raw:N (
+ \regex_compile_raw:N ?
+ \regex_compile_raw:N -
+ #1 #2 #3 #4
+ }
+ }
+\cs_new_protected:cpn { regex_compile_/c: }
+ { \regex_chk_c_allowed:T { \regex_compile_c_test:NN } }
+\cs_new_protected:Npn \regex_compile_c_test:NN #1#2
+ {
+ \token_if_eq_meaning:NNTF #1 \regex_compile_raw:N
+ {
+ \cs_if_exist:cTF { c_regex_catcode_#2_int }
+ {
+ \int_set_eq:Nc \l_regex_catcodes_int { c_regex_catcode_#2_int }
+ \l_regex_mode_int
+ = \if_case:w \l_regex_mode_int \c_two \else: \c_six \fi:
+ }
+ }
+ { \cs_if_exist_use:cF { regex_compile_c_#2:w } }
+ {
+ \msg_kernel_error:nnx { regex } { c-missing-category } {#2}
+ #1 #2
+ }
+ }
+\cs_new_protected:cpn { regex_compile_c_[:w } #1#2
+ {
+ \l_regex_mode_int
+ = \if_case:w \l_regex_mode_int \c_two \else: \c_six \fi:
+ \int_zero:N \l_regex_catcodes_int
+ \str_if_eq:nnTF { #1 #2 } { \regex_compile_special:N ^ }
+ {
+ \bool_set_false:N \l_regex_catcodes_bool
+ \regex_compile_c_lbrack_loop:NN
+ }
+ {
+ \bool_set_true:N \l_regex_catcodes_bool
+ \regex_compile_c_lbrack_loop:NN
+ #1 #2
+ }
+ }
+\cs_new_protected:Npn \regex_compile_c_lbrack_loop:NN #1#2
+ {
+ \token_if_eq_meaning:NNTF #1 \regex_compile_raw:N
+ {
+ \cs_if_exist:cTF { c_regex_catcode_#2_int }
+ {
+ \exp_args:Nc \regex_compile_c_lbrack_add:N
+ { c_regex_catcode_#2_int }
+ \regex_compile_c_lbrack_loop:NN
+ }
+ }
+ {
+ \token_if_eq_charcode:NNTF #2 ]
+ { \regex_compile_c_lbrack_end: }
+ }
+ {
+ \msg_kernel_error:nnx { regex } { c-missing-rbrack } {#2}
+ \regex_compile_c_lbrack_end:
+ #1 #2
+ }
+ }
+\cs_new_protected:Npn \regex_compile_c_lbrack_add:N #1
+ {
+ \if_int_odd:w \int_eval:w \l_regex_catcodes_int / #1 \int_eval_end:
+ \else:
+ \tex_advance:D \l_regex_catcodes_int #1
+ \fi:
+ }
+\cs_new_protected_nopar:Npn \regex_compile_c_lbrack_end:
+ {
+ \if_meaning:w \c_false_bool \l_regex_catcodes_bool
+ \int_set:Nn \l_regex_catcodes_int
+ { \c_regex_all_catcodes_int - \l_regex_catcodes_int }
+ \fi:
+ }
+\cs_new_protected_nopar:cpn { regex_compile_c_ \c_lbrace_str :w }
+ {
+ \regex_compile:w
+ \regex_disable_submatches:
+ \l_regex_mode_int
+ = - \if_case:w \l_regex_mode_int \c_two \else: \c_six \fi:
+ }
+\cs_new_protected:cpn { regex_compile_ \c_rbrace_str : }
+ {
+ \regex_if_in_cs:TF
+ {
+ \regex_compile_end:
+ \regex_compile_one:x
+ { \regex_item_cs:n { \exp_not:o \l_regex_internal_regex } }
+ }
+ { \exp_after:wN \regex_compile_raw:N \c_rbrace_str }
+ }
+\cs_new_protected:cpn { regex_compile_/u: } #1#2
+ {
+ \regex_if_in_class_or_catcode:TF
+ { \regex_compile_raw_error:N u #1 #2 }
+ {
+ \str_if_eq:xxTF {#1#2} { \regex_compile_special:N \c_lbrace_str }
+ {
+ \tl_set:Nx \l_regex_internal_a_tl { \if_false: } \fi:
+ \regex_compile_u_loop:NN
+ }
+ {
+ \msg_kernel_error:nn { regex } { u-missing-lbrace }
+ \regex_compile_raw:N u #1 #2
+ }
+ }
+ }
+\cs_new:Npn \regex_compile_u_loop:NN #1#2
+ {
+ \token_if_eq_meaning:NNTF #1 \regex_compile_raw:N
+ { #2 \regex_compile_u_loop:NN }
+ {
+ \token_if_eq_meaning:NNTF #1 \regex_compile_special:N
+ {
+ \exp_after:wN \token_if_eq_charcode:NNTF \c_rbrace_str #2
+ { \if_false: { \fi: } \regex_compile_u_end: }
+ { #2 \regex_compile_u_loop:NN }
+ }
+ {
+ \if_false: { \fi: }
+ \msg_kernel_error:nnx { regex } { u-missing-rbrace } {#2}
+ \regex_compile_u_end:
+ #1 #2
+ }
+ }
+ }
+\cs_new_protected:Npn \regex_compile_u_end:
+ {
+ \tl_set:Nv \l_regex_internal_a_tl { \l_regex_internal_a_tl }
+ \if_num:w \l_regex_mode_int = \c_zero
+ \regex_compile_u_not_cs:
+ \else:
+ \regex_compile_u_in_cs:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_compile_u_in_cs:
+ {
+ \exp_args:NNo \str_gset_other:Nn \g_regex_internal_tl
+ { \l_regex_internal_a_tl }
+ \tl_build_one:x
+ {
+ \tl_map_function:NN \g_regex_internal_tl
+ \regex_compile_u_in_cs_aux:n
+ }
+ }
+\cs_new:Npn \regex_compile_u_in_cs_aux:n #1
+ {
+ \regex_class:NnnnN \c_true_bool
+ { \regex_item_caseful_equal:n { \int_value:w `#1 } }
+ { 1 } { 0 } \c_false_bool
+ }
+\cs_new_protected:Npn \regex_compile_u_not_cs:
+ {
+ \exp_args:No \tl_analysis_map_inline:nn { \l_regex_internal_a_tl }
+ {
+ \tl_build_one:n
+ {
+ \regex_class:NnnnN \c_true_bool
+ {
+ \if_num:w "##2 = \c_zero
+ \regex_item_exact_cs:c { \exp_after:wN \cs_to_str:N ##1 }
+ \else:
+ \regex_item_exact:nn { \int_value:w "##2 } { ##3 }
+ \fi:
+ }
+ { 1 } { 0 } \c_false_bool
+ }
+ }
+ }
+\cs_new_protected_nopar:cpn { regex_compile_/K: }
+ {
+ \int_compare:nNnTF \l_regex_mode_int = \c_zero
+ { \tl_build_one:n { \regex_command_K: } }
+ { \regex_compile_raw_error:N K }
+ }
+\cs_new_protected:Npn \regex_show_aux:Nx #1#2
+ {
+ \tl_set_build:Nw \l_regex_internal_a_tl
+ \cs_set_protected_nopar:Npn \regex_branch:n
+ {
+ \seq_pop_right:NN \l_regex_show_prefix_seq \l_regex_internal_a_tl
+ \regex_show_one:n { +-branch }
+ \seq_put_right:No \l_regex_show_prefix_seq \l_regex_internal_a_tl
+ \use:n
+ }
+ \cs_set_protected_nopar:Npn \regex_group:nnnN
+ { \regex_show_group_aux:nnnnN { } }
+ \cs_set_protected_nopar:Npn \regex_group_no_capture:nnnN
+ { \regex_show_group_aux:nnnnN { ~(no~capture) } }
+ \cs_set_protected_nopar:Npn \regex_group_resetting:nnnN
+ { \regex_show_group_aux:nnnnN { ~(resetting) } }
+ \cs_set_eq:NN \regex_class:NnnnN \regex_show_class:NnnnN
+ \cs_set_protected_nopar:Npn \regex_command_K:
+ { \regex_show_one:n { reset~match~start~(\iow_char:N\\K) } }
+ \cs_set_protected:Npn \regex_assertion:Nn ##1##2
+ { \regex_show_one:n { \bool_if:NF ##1 { negative~ } assertion:~##2 } }
+ \cs_set_nopar:Npn \regex_b_test: { word~boundary }
+ \cs_set_eq:NN \regex_anchor:N \regex_show_anchor_to_str:N
+ \cs_set_protected:Npn \regex_item_caseful_equal:n ##1
+ { \regex_show_one:n { char~code~\int_eval:n{##1} } }
+ \cs_set_protected:Npn \regex_item_caseful_range:nn ##1##2
+ { \regex_show_one:n { range~[\int_eval:n{##1}, \int_eval:n{##2}] } }
+ \cs_set_protected:Npn \regex_item_caseless_equal:n ##1
+ { \regex_show_one:n { char~code~\int_eval:n{##1}~(caseless) } }
+ \cs_set_protected:Npn \regex_item_caseless_range:nn ##1##2
+ {
+ \regex_show_one:n
+ { Range~[\int_eval:n{##1}, \int_eval:n{##2}]~(caseless) }
+ }
+ \cs_set_protected:Npn \regex_item_catcode:nT
+ { \regex_show_item_catcode:NnT \c_true_bool }
+ \cs_set_protected:Npn \regex_item_catcode_reverse:nT
+ { \regex_show_item_catcode:NnT \c_false_bool }
+ \cs_set_protected:Npn \regex_item_reverse:n
+ { \regex_show_scope:nn { Reversed~match } }
+ \cs_set_protected:Npn \regex_item_exact:nn ##1##2
+ { \regex_show_one:n { char~##2,~catcode~##1 } }
+ \cs_set_protected:Npn \regex_item_exact_cs:c ##1
+ { \regex_show_one:n { control~sequence~\iow_char:N\\##1 } }
+ \cs_set_protected:Npn \regex_item_cs:n
+ { \regex_show_scope:nn { control~sequence } }
+ \cs_set:cpn { regex_prop_.: } { \regex_show_one:n { any~token } }
+ \seq_clear:N \l_regex_show_prefix_seq
+ \regex_show_push:n { ~ }
+ #1
+ \tl_build_end:
+ \msg_aux_show:x { > Compiled~regex~#2: \l_regex_internal_a_tl }
+ }
+\cs_new_protected:Npn \regex_show_one:n #1
+ {
+ \int_incr:N \l_regex_show_lines_int
+ \tl_build_one:x
+ { \iow_newline: \seq_use:N \l_regex_show_prefix_seq #1 }
+ }
+\cs_new_protected:Npn \regex_show_push:n #1
+ { \seq_put_right:Nx \l_regex_show_prefix_seq { #1 ~ } }
+\cs_new_protected:Npn \regex_show_pop:
+ { \seq_pop_right:NN \l_regex_show_prefix_seq \l_regex_internal_a_tl }
+\cs_new_protected:Npn \regex_show_scope:nn #1#2
+ {
+ \regex_show_one:n {#1}
+ \regex_show_push:n { ~ }
+ #2
+ \regex_show_pop:
+ }
+\cs_new_protected:Npn \regex_show_group_aux:nnnnN #1#2#3#4#5
+ {
+ \regex_show_one:n { ,-group~begin #1 }
+ \regex_show_push:n { | }
+ \use_ii:nn #2
+ \regex_show_pop:
+ \regex_show_one:n
+ { `-group~end \regex_msg_repeated:nnN {#3} {#4} #5 }
+ }
+\cs_set:Npn \regex_show_class:NnnnN #1#2#3#4#5
+ {
+ \tl_set_build:Nw \l_regex_internal_a_tl
+ \int_zero:N \l_regex_show_lines_int
+ \regex_show_push:n {~}
+ #2
+ \exp_last_unbraced:Nf
+ \prg_case_int:nnn { \l_regex_show_lines_int }
+ {
+ {0}
+ {
+ \tl_build_end:
+ \regex_show_one:n { \bool_if:NTF #1 { Fail } { Pass } }
+ }
+ {1}
+ {
+ \tl_build_end:
+ \bool_if:NTF #1
+ {
+ #2
+ \tl_build_one:n { \regex_msg_repeated:nnN {#3} {#4} #5 }
+ }
+ {
+ \regex_show_one:n
+ { Don't~match~\regex_msg_repeated:nnN {#3} {#4} #5 }
+ \tl_build_one:o \l_regex_internal_a_tl
+ }
+ }
+ }
+ {
+ \tl_build_end:
+ \regex_show_one:n
+ {
+ \bool_if:NTF #1 { M } { Don't~m } atch
+ \regex_msg_repeated:nnN {#3} {#4} #5
+ }
+ \tl_build_one:o \l_regex_internal_a_tl
+ }
+ }
+\cs_new:Npn \regex_show_anchor_to_str:N #1
+ {
+ anchor~at~
+ \prg_case_str:nnn { #1 }
+ {
+ { \l_regex_min_pos_int } { start~(\iow_char:N\\A) }
+ { \l_regex_start_pos_int } { start~of~match~(\iow_char:N\\G) }
+ { \l_regex_max_pos_int } { end~(\iow_char:N\\Z) }
+ }
+ { <error:~'#1'~not~recognized> }
+ }
+\cs_new_protected:Npn \regex_show_item_catcode:NnT #1#2
+ {
+ \seq_set_split:Nnn \l_regex_internal_seq { } { CBEMTPUDSLOA }
+ \seq_set_filter:NNn \l_regex_internal_seq \l_regex_internal_seq
+ { \int_if_odd_p:n { #2 / \int_use:c { c_regex_catcode_##1_int } } }
+ \regex_show_scope:nn
+ {
+ categories~\seq_use:N \l_regex_internal_seq, ~
+ \bool_if:NF #1 { negative~ } class
+ }
+ }
+\int_new:N \l_regex_min_state_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
+\int_new:N \l_regex_capturing_group_int
+\cs_new_protected:Npn \regex_build:n #1
+ {
+ \regex_compile:n {#1}
+ \regex_build:N \l_regex_internal_regex
+ }
+\cs_new_protected:Npn \regex_build:N #1
+ {
+ \trace_push:nnn { regex } { 1 } { regex_build }
+ \int_set:Nn \tex_escapechar:D { 92 }
+ \int_zero:N \l_regex_capturing_group_int
+ \int_set_eq:NN \l_regex_max_state_int \l_regex_min_state_int
+ \regex_build_new_state:
+ \regex_build_new_state:
+ \regex_toks_put_right:Nn \l_regex_left_state_int
+ { \regex_action_start_wildcard: }
+ \regex_group:nnnN {#1} { 1 } { 0 } \c_false_bool
+ \regex_toks_put_right:Nn \l_regex_right_state_int
+ { \regex_action_success: }
+ \regex_trace_states:n { 2 }
+ \trace_pop:nnn { regex } { 1 } { regex_build }
+ }
+\cs_new_protected:Npn \regex_build_for_cs:n #1
+ {
+ \trace_push:nnn { regex } { 1 } { regex_build_for_cs }
+ \int_set_eq:NN \l_regex_max_state_int \l_regex_min_state_int
+ \regex_build_new_state:
+ \regex_build_new_state:
+ \regex_push_lr_states:
+ #1
+ \regex_pop_lr_states:
+ \regex_toks_put_right:Nn \l_regex_right_state_int
+ {
+ \if_num:w \l_regex_current_pos_int = \l_regex_max_pos_int
+ \exp_after:wN \regex_action_success:
+ \fi:
+ }
+ \regex_trace_states:n { 2 }
+ \trace_pop:nnn { regex } { 1 } { regex_build_for_cs }
+ }
+\cs_new_protected_nopar:Npn \regex_push_lr_states:
+ {
+ \seq_push:No \l_regex_left_state_seq
+ { \int_use:N \l_regex_left_state_int }
+ \seq_push:No \l_regex_right_state_seq
+ { \int_use:N \l_regex_right_state_int }
+ }
+\cs_new_protected_nopar:Npn \regex_pop_lr_states:
+ {
+ \seq_pop:NN \l_regex_left_state_seq \l_regex_internal_a_tl
+ \int_set:Nn \l_regex_left_state_int \l_regex_internal_a_tl
+ \seq_pop:NN \l_regex_right_state_seq \l_regex_internal_a_tl
+ \int_set:Nn \l_regex_right_state_int \l_regex_internal_a_tl
+ }
+\cs_new_protected:Npn \regex_toks_put_left:Nx #1#2
+ {
+ \cs_set_nopar:Npx \regex_tmp:w { #2 }
+ \tex_toks:D #1 \exp_after:wN \exp_after:wN \exp_after:wN
+ { \exp_after:wN \regex_tmp:w \tex_the:D \tex_toks:D #1 }
+ }
+\cs_new_protected:Npn \regex_toks_put_right:Nx #1#2
+ {
+ \cs_set_nopar:Npx \regex_tmp:w {#2}
+ \tex_toks:D #1 \exp_after:wN
+ { \tex_the:D \tex_toks:D \exp_after:wN #1 \regex_tmp:w }
+ }
+\cs_new_protected:Npn \regex_toks_put_right:Nn #1#2
+ { \tex_toks:D #1 \exp_after:wN { \tex_the:D \tex_toks:D #1 #2 } }
+\cs_new_protected:Npn \regex_build_transition_left:NNN #1#2#3
+ { \regex_toks_put_left:Nx #2 { #1 { \int_eval:n { #3 - #2 } } } }
+\cs_new_protected:Npn \regex_build_transition_right:nNn #1#2#3
+ { \regex_toks_put_right:Nx #2 { #1 { \int_eval:n { #3 - #2 } } } }
+\cs_new_protected_nopar:Npn \regex_build_new_state:
+ {
+ \trace:nnx { regex } { 2 }
+ {
+ regex~new~state~
+ L=\int_use:N \l_regex_left_state_int ~ -> ~
+ R=\int_use:N \l_regex_right_state_int ~ -> ~
+ M=\int_use:N \l_regex_max_state_int ~ -> ~
+ \int_eval:n { \l_regex_max_state_int + \c_one }
+ }
+ \tex_toks:D \l_regex_max_state_int { }
+ \int_set_eq:NN \l_regex_left_state_int \l_regex_right_state_int
+ \int_set_eq:NN \l_regex_right_state_int \l_regex_max_state_int
+ \int_incr:N \l_regex_max_state_int
+ }
+\cs_new_protected:Npn \regex_build_transitions_lazyness:NNNNN #1#2#3#4#5
+ {
+ \regex_build_new_state:
+ \regex_toks_put_right:Nx \l_regex_left_state_int
+ {
+ \if_meaning:w \c_true_bool #1
+ #2 { \int_eval:n { #3 - \l_regex_left_state_int } }
+ #4 { \int_eval:n { #5 - \l_regex_left_state_int } }
+ \else:
+ #4 { \int_eval:n { #5 - \l_regex_left_state_int } }
+ #2 { \int_eval:n { #3 - \l_regex_left_state_int } }
+ \fi:
+ }
+ }
+\cs_new_protected:Npn \regex_class:NnnnN #1#2#3#4#5
+ {
+ \cs_set_nopar:Npx \regex_tests_action_cost:n ##1
+ {
+ \exp_not:n { \exp_not:n {#2} }
+ \bool_if:NTF #1
+ { \regex_break_point:TF { \regex_action_cost:n {##1} } { } }
+ { \regex_break_point:TF { } { \regex_action_cost:n {##1} } }
+ }
+ \if_case:w - #4 \exp_stop_f:
+ \regex_class_repeat:n {#3}
+ \or: \regex_class_repeat:nN {#3} #5
+ \else: \regex_class_repeat:nnN {#3} {#4} #5
+ \fi:
+ }
+\cs_new:Npn \regex_tests_action_cost:n { \regex_action_cost:n }
+\cs_new_protected:Npn \regex_class_repeat:n #1
+ {
+ \prg_replicate:nn {#1}
+ {
+ \regex_build_new_state:
+ \regex_build_transition_right:nNn \regex_tests_action_cost:n
+ \l_regex_left_state_int \l_regex_right_state_int
+ }
+ }
+\cs_new_protected:Npn \regex_class_repeat:nN #1#2
+ {
+ \if_num:w #1 = \c_zero
+ \regex_build_transitions_lazyness:NNNNN #2
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_tests_action_cost:n \l_regex_left_state_int
+ \else:
+ \regex_class_repeat:n {#1}
+ \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
+ \regex_build_transitions_lazyness:NNNNN #2
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_action_free:n \l_regex_internal_a_int
+ \fi:
+ }
+\cs_new_protected:Npn \regex_class_repeat:nnN #1#2#3
+ {
+ \regex_class_repeat:n {#1}
+ \int_set:Nn \l_regex_internal_a_int
+ { \l_regex_max_state_int + #2 - \c_one }
+ \prg_replicate:nn { #2 }
+ {
+ \regex_build_transitions_lazyness:NNNNN #3
+ \regex_action_free:n \l_regex_internal_a_int
+ \regex_tests_action_cost:n \l_regex_right_state_int
+ }
+ }
+\cs_new_protected:Npn \regex_group_aux:nnnnN #1#2#3#4#5
+ {
+ \trace_push:nnn { regex } { 1 } { regex_group }
+ \if_num:w #3 = \c_zero
+ \regex_build_new_state:
+ \regex_build_transition_right:nNn \regex_action_free_group:n
+ \l_regex_left_state_int \l_regex_right_state_int
+ \fi:
+ \regex_build_new_state:
+ \regex_push_lr_states:
+ #2
+ \regex_pop_lr_states:
+ \if_case:w - #4 \exp_stop_f:
+ \regex_group_repeat:nn {#1} {#3}
+ \or: \regex_group_repeat:nnN {#1} {#3} #5
+ \else: \regex_group_repeat:nnnN {#1} {#3} {#4} #5
+ \fi:
+ \trace_pop:nnn { regex } { 1 } { regex_group }
+ }
+\cs_new_protected:Npn \regex_group:nnnN #1
+ {
+ \exp_args:No \regex_group_aux:nnnnN
+ { \int_use:N \l_regex_capturing_group_int }
+ {
+ \int_incr:N \l_regex_capturing_group_int
+ #1
+ }
+ }
+\cs_new_protected_nopar:Npn \regex_group_no_capture:nnnN
+ { \regex_group_aux:nnnnN { -1 } }
+\cs_new_protected:Npn \regex_group_resetting:nnnN #1
+ {
+ \regex_group_aux:nnnnN { -1 }
+ {
+ \exp_args:Noo \regex_group_resetting_loop:nnNn
+ { \int_use:N \l_regex_capturing_group_int }
+ { \int_use:N \l_regex_capturing_group_int }
+ #1
+ { ?? \prg_map_break:n } { }
+ \prg_break_point:n { }
+ }
+ }
+\cs_new_protected:Npn \regex_group_resetting_loop:nnNn #1#2#3#4
+ {
+ \use_none:nn #3 { \int_set:Nn \l_regex_capturing_group_int {#1} }
+ \int_set:Nn \l_regex_capturing_group_int {#2}
+ #3 {#4}
+ \exp_args:Nf \regex_group_resetting_loop:nnNn
+ { \int_max:nn {#1} { \l_regex_capturing_group_int } }
+ {#2}
+ }
+\cs_new_protected:Npn \regex_branch:n #1
+ {
+ \trace_push:nnn { regex } { 1 } { regex_branch }
+ \regex_build_new_state:
+ \seq_get:NN \l_regex_left_state_seq \l_regex_internal_a_tl
+ \int_set:Nn \l_regex_left_state_int \l_regex_internal_a_tl
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_left_state_int \l_regex_right_state_int
+ #1
+ \seq_get:NN \l_regex_right_state_seq \l_regex_internal_a_tl
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_right_state_int \l_regex_internal_a_tl
+ \trace_pop:nnn { regex } { 1 } { regex_branch }
+ }
+\cs_new_protected:Npn \regex_group_repeat:nn #1#2
+ {
+ \if_num:w #2 = \c_zero
+ \int_set:Nn \l_regex_max_state_int
+ { \l_regex_left_state_int - \c_one }
+ \regex_build_new_state:
+ \else:
+ \regex_group_repeat_aux:n {#2}
+ \regex_group_submatches:nNN {#1}
+ \l_regex_internal_a_int \l_regex_right_state_int
+ \regex_build_new_state:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_group_submatches:nNN #1#2#3
+ {
+ \if_num:w #1 > \c_minus_one
+ \regex_toks_put_left:Nx #2 { \regex_action_submatch:n { #1 < } }
+ \regex_toks_put_left:Nx #3 { \regex_action_submatch:n { #1 > } }
+ \fi:
+ }
+\cs_new_protected:Npn \regex_group_repeat_aux:n #1
+ {
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_right_state_int \l_regex_max_state_int
+ \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
+ \int_set_eq:NN \l_regex_internal_b_int \l_regex_max_state_int
+ \if_num:w \int_eval:w #1 > \c_one
+ \int_set:Nn \l_regex_internal_c_int
+ {
+ ( #1 - \c_one )
+ * ( \l_regex_internal_b_int - \l_regex_internal_a_int )
+ }
+ \tex_advance:D \l_regex_right_state_int \l_regex_internal_c_int
+ \tex_advance:D \l_regex_max_state_int \l_regex_internal_c_int
+ \prg_replicate:nn \l_regex_internal_c_int
+ {
+ \tex_toks:D \l_regex_internal_b_int
+ = \tex_toks:D \l_regex_internal_a_int
+ \tex_advance:D \l_regex_internal_a_int \c_one
+ \tex_advance:D \l_regex_internal_b_int \c_one
+ }
+ \fi:
+ }
+\cs_new_protected:Npn \regex_group_repeat:nnN #1#2#3
+ {
+ \if_num:w #2 = \c_zero
+ \regex_group_submatches:nNN {#1}
+ \l_regex_left_state_int \l_regex_right_state_int
+ \int_set:Nn \l_regex_internal_a_int
+ { \l_regex_left_state_int - \c_one }
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_right_state_int \l_regex_internal_a_int
+ \regex_build_new_state:
+ \if_meaning:w \c_true_bool #3
+ \regex_build_transition_left:NNN \regex_action_free:n
+ \l_regex_internal_a_int \l_regex_right_state_int
+ \else:
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_internal_a_int \l_regex_right_state_int
+ \fi:
+ \else:
+ \regex_group_repeat_aux:n {#2}
+ \regex_group_submatches:nNN {#1}
+ \l_regex_internal_a_int \l_regex_right_state_int
+ \if_meaning:w \c_true_bool #3
+ \regex_build_transition_right:nNn \regex_action_free_group:n
+ \l_regex_right_state_int \l_regex_internal_a_int
+ \else:
+ \regex_build_transition_left:NNN \regex_action_free_group:n
+ \l_regex_right_state_int \l_regex_internal_a_int
+ \fi:
+ \regex_build_new_state:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_group_repeat:nnnN #1#2#3#4
+ {
+ \regex_group_submatches:nNN {#1}
+ \l_regex_left_state_int \l_regex_right_state_int
+ \regex_group_repeat_aux:n { #2 + #3 }
+ \if_meaning:w \c_true_bool #4
+ \int_set_eq:NN \l_regex_left_state_int \l_regex_max_state_int
+ \prg_replicate:nn { #3 }
+ {
+ \int_sub:Nn \l_regex_left_state_int
+ { \l_regex_internal_b_int - \l_regex_internal_a_int }
+ \regex_build_transition_left:NNN \regex_action_free:n
+ \l_regex_left_state_int \l_regex_max_state_int
+ }
+ \else:
+ \prg_replicate:nn { #3 - \c_one }
+ {
+ \int_sub:Nn \l_regex_right_state_int
+ { \l_regex_internal_b_int - \l_regex_internal_a_int }
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_right_state_int \l_regex_max_state_int
+ }
+ \if_num:w #2 = \c_zero
+ \int_set:Nn \l_regex_right_state_int
+ { \l_regex_left_state_int - \c_one }
+ \else:
+ \int_sub:Nn \l_regex_right_state_int
+ { \l_regex_internal_b_int - \l_regex_internal_a_int }
+ \fi:
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_right_state_int \l_regex_max_state_int
+ \fi:
+ \regex_build_new_state:
+ }
+\cs_new_protected:Npn \regex_assertion:Nn #1#2
+ {
+ \regex_build_new_state:
+ \regex_toks_put_right:Nx \l_regex_left_state_int
+ {
+ \exp_not:n {#2}
+ \regex_break_point:TF
+ \bool_if:NF #1 { { } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
+ \bool_if:NT #1 { { } }
+ }
+ }
+\cs_new_protected:Npn \regex_anchor:N #1
+ {
+ \if_num:w #1 = \l_regex_current_pos_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
+ }
+\cs_new_protected_nopar:Npn \regex_b_test:
+ {
+ \group_begin:
+ \int_set_eq:NN \l_regex_current_char_int \l_regex_last_char_int
+ \regex_prop_w:
+ \regex_break_point:TF
+ { \group_end: \regex_item_reverse:n \regex_prop_w: }
+ { \group_end: \regex_prop_w: }
+ }
+\cs_new_protected_nopar:Npn \regex_command_K:
+ {
+ \regex_build_new_state:
+ \regex_toks_put_right:Nx \l_regex_left_state_int
+ {
+ \regex_action_submatch:n { 0< }
+ \bool_set_true:N \l_regex_fresh_thread_bool
+ \regex_action_free:n
+ { \int_eval:n { \l_regex_right_state_int - \l_regex_left_state_int } }
+ \bool_set_false:N \l_regex_fresh_thread_bool
+ }
+ }
+\int_new:N \l_regex_min_pos_int
+\int_new:N \l_regex_max_pos_int
+\int_new:N \l_regex_current_pos_int
+\int_new:N \l_regex_start_pos_int
+\int_new:N \l_regex_success_pos_int
+\int_new:N \l_regex_current_char_int
+\int_new:N \l_regex_current_catcode_int
+\int_new:N \l_regex_last_char_int
+\int_new:N \l_regex_case_changed_char_int
+\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_step_int
+\int_new:N \l_regex_min_active_int
+\int_new:N \l_regex_max_active_int
+\tl_new:N \l_regex_every_match_tl
+\bool_new:N \l_regex_fresh_thread_bool
+\bool_new:N \l_regex_empty_success_bool
+\cs_new_eq:NN \regex_if_two_empty_matches:F \use:n
+\bool_new:N \g_regex_success_bool
+\bool_new:N \l_regex_saved_success_bool
+\bool_new:N \l_regex_match_success_bool
+\cs_new_protected:Npn \regex_match:n #1
+ {
+ \trace_push:nnx { regex } { 1 } { regex_match }
+ \trace:nnx { regex } { 1 } { analyzing~query~token~list }
+ \int_zero:N \l_regex_balance_int
+ \int_set:Nn \l_regex_current_pos_int { \c_two * \l_regex_max_state_int }
+ \regex_query_set:nnn { } { -1 } { -2 }
+ \int_set_eq:NN \l_regex_min_pos_int \l_regex_current_pos_int
+ \tl_analysis_map_inline:nn {#1}
+ { \regex_query_set:nnn {##1} {"##2} {##3} }
+ \int_set_eq:NN \l_regex_max_pos_int \l_regex_current_pos_int
+ \regex_query_set:nnn { } { -1 } { -2 }
+ \trace:nnx { regex } { 1 } { initializing }
+ \bool_gset_false:N \g_regex_success_bool
+ \prg_stepwise_inline:nnnn
+ \l_regex_min_state_int \c_one { \l_regex_max_state_int - \c_one }
+ { \tex_dimen:D ##1 \c_one sp \scan_stop: }
+ \int_set_eq:NN \l_regex_min_active_int \l_regex_max_state_int
+ \int_set_eq:NN \l_regex_step_int \c_zero
+ \int_set_eq:NN \l_regex_success_pos_int \l_regex_min_pos_int
+ \int_set:Nn \l_regex_submatch_int
+ { \c_two * \l_regex_max_state_int }
+ \bool_set_false:N \l_regex_empty_success_bool
+ \regex_match_once:
+ \trace_pop:nnx { regex } { 1 } { regex_match }
+ }
+\cs_new_protected_nopar:Npn \regex_match_once:
+ {
+ \if_meaning:w \c_true_bool \l_regex_empty_success_bool
+ \cs_set_nopar:Npn \regex_if_two_empty_matches:F
+ { \int_compare:nNnF \l_regex_start_pos_int = \l_regex_current_pos_int }
+ \else:
+ \cs_set_eq:NN \regex_if_two_empty_matches:F \use:n
+ \fi:
+ \int_set_eq:NN \l_regex_start_pos_int \l_regex_success_pos_int
+ \bool_set_false:N \l_regex_match_success_bool
+ \prop_clear:N \l_regex_current_submatches_prop
+ \int_set_eq:NN \l_regex_max_active_int \l_regex_min_active_int
+ \regex_store_state:n { \l_regex_min_state_int }
+ \int_set:Nn \l_regex_current_pos_int
+ { \l_regex_start_pos_int - \c_one }
+ \regex_query_get:
+ \regex_match_loop:
+ \l_regex_every_match_tl
+ }
+\cs_new_protected_nopar:Npn \regex_single_match:
+ {
+ \tl_set:Nn \l_regex_every_match_tl
+ { \bool_gset_eq:NN \g_regex_success_bool \l_regex_match_success_bool }
+ }
+\cs_new_protected:Npn \regex_multi_match:n #1
+ {
+ \tl_set:Nn \l_regex_every_match_tl
+ {
+ \if_meaning:w \c_true_bool \l_regex_match_success_bool
+ \bool_gset_true:N \g_regex_success_bool
+ #1
+ \exp_after:wN \regex_match_once:
+ \fi:
+ }
+ }
+\cs_new_protected_nopar:Npn \regex_match_loop:
+ {
+ \tex_advance:D \l_regex_step_int \c_two
+ \int_incr:N \l_regex_current_pos_int
+ \int_set_eq:NN \l_regex_last_char_int \l_regex_current_char_int
+ \int_set_eq:NN \l_regex_case_changed_char_int \c_max_int
+ \regex_query_get:
+ \use:x
+ {
+ \int_set_eq:NN \l_regex_max_active_int \l_regex_min_active_int
+ \exp_after:wN \regex_match_one_active:w
+ \int_use:N \l_regex_min_active_int ;
+ }
+ \prg_break_point:n { \bool_set_false:N \l_regex_fresh_thread_bool }
+ \if_num:w \l_regex_max_active_int > \l_regex_min_active_int
+ \if_num:w \l_regex_current_pos_int < \l_regex_max_pos_int
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_match_loop:
+ \fi:
+ \fi:
+ }
+\cs_new:Npn \regex_match_one_active:w #1;
+ {
+ \if_num:w #1 < \l_regex_max_active_int
+ \regex_use_state_and_submatches:nn
+ { \int_value:w \tex_skip:D #1 }
+ { \tex_the:D \tex_toks:D #1 }
+ \exp_after:wN \regex_match_one_active:w
+ \int_use:N \int_eval:w #1 + \c_one \exp_after:wN ;
+ \fi:
+ }
+\cs_new_protected:Npn \regex_query_set:nnn #1#2#3
+ {
+ \tex_muskip:D \l_regex_current_pos_int
+ = \etex_gluetomu:D
+ #3 sp
+ plus #2 sp
+ minus \l_regex_balance_int sp
+ \scan_stop:
+ \tex_toks:D \l_regex_current_pos_int {#1}
+ \int_incr:N \l_regex_current_pos_int
+ \if_case:w #2 \exp_stop_f:
+ \or: \int_incr:N \l_regex_balance_int
+ \or: \int_decr:N \l_regex_balance_int
+ \fi:
+ }
+\cs_new_protected_nopar:Npn \regex_query_get:
+ {
+ \l_regex_current_char_int
+ = \etex_mutoglue:D \tex_muskip:D \l_regex_current_pos_int
+ \l_regex_current_catcode_int = \etex_gluestretch:D
+ \etex_mutoglue:D \tex_muskip:D \l_regex_current_pos_int
+ }
+\cs_new_protected_nopar:Npn \regex_use_state:
+ {
+ \trace:nnx { regex } { 2 } { state~\int_use:N \l_regex_current_state_int }
+ \tex_dimen:D \l_regex_current_state_int
+ = \l_regex_step_int sp \scan_stop:
+ \tex_the:D \tex_toks:D \l_regex_current_state_int
+ \tex_dimen:D \l_regex_current_state_int
+ = \int_eval:w \l_regex_step_int + \c_one \int_eval_end: sp \scan_stop:
+ }
+\cs_new_protected:Npn \regex_use_state_and_submatches:nn #1 #2
+ {
+ \int_set:Nn \l_regex_current_state_int {#1}
+ \if_num:w \tex_dimen:D \l_regex_current_state_int < \l_regex_step_int
+ \tl_set:Nn \l_regex_current_submatches_prop {#2}
+ \exp_after:wN \regex_use_state:
+ \fi:
+ \scan_stop:
+ }
+\cs_new_protected_nopar:Npn \regex_action_start_wildcard:
+ {
+ \bool_set_true:N \l_regex_fresh_thread_bool
+ \regex_action_free:n {1}
+ \bool_set_false:N \l_regex_fresh_thread_bool
+ \regex_action_cost:n {0}
+ }
+\cs_new_protected_nopar:Npn \regex_action_free:n
+ { \regex_action_free_aux:nn { > \l_regex_step_int \else: } }
+\cs_new_protected_nopar:Npn \regex_action_free_group:n
+ { \regex_action_free_aux:nn { < \l_regex_step_int } }
+\cs_new_protected:Npn \regex_action_free_aux:nn #1#2
+ {
+ \use:x
+ {
+ \int_add:Nn \l_regex_current_state_int {#2}
+ \exp_not:n
+ {
+ \if_num:w \tex_dimen:D \l_regex_current_state_int #1
+ \exp_after:wN \regex_use_state:
+ \fi:
+ }
+ \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 }
+ }
+ }
+\cs_new_protected:Npn \regex_action_cost:n #1
+ {
+ \exp_args:No \regex_store_state:n
+ { \int_use:N \int_eval:w \l_regex_current_state_int + #1 }
+ }
+\cs_new_protected:Npn \regex_store_state:n #1
+ {
+ \regex_store_submatches:
+ \tex_skip:D \l_regex_max_active_int = #1 sp \scan_stop:
+ \int_incr:N \l_regex_max_active_int
+ }
+\cs_new_protected_nopar:Npn \regex_store_submatches:
+ {
+ \tex_toks:D \l_regex_max_active_int \exp_after:wN
+ { \l_regex_current_submatches_prop }
+ }
+\cs_new_protected_nopar:Npn \regex_disable_submatches:
+ {
+ \cs_set_protected_nopar:Npn \regex_store_submatches: { }
+ \cs_set_protected:Npn \regex_action_submatch:n ##1 { }
+ }
+\cs_new_protected:Npn \regex_action_submatch:n #1
+ {
+ \prop_put:Nno \l_regex_current_submatches_prop {#1}
+ { \int_use:N \l_regex_current_pos_int }
+ }
+\cs_new_protected_nopar:Npn \regex_action_success:
+ {
+ \regex_if_two_empty_matches:F
+ {
+ \bool_set_true:N \l_regex_match_success_bool
+ \bool_set_eq:NN \l_regex_empty_success_bool
+ \l_regex_fresh_thread_bool
+ \int_set_eq:NN \l_regex_success_pos_int \l_regex_current_pos_int
+ \prop_set_eq:NN \l_regex_success_submatches_prop
+ \l_regex_current_submatches_prop
+ \prg_map_break:
+ }
+ }
+\int_new:N \l_regex_replacement_csnames_int
+\tl_new:N \l_regex_balance_tl
+\cs_new:Npn \regex_replacement_balance_one_match:n #1
+ { - \regex_submatch_balance:n {#1} }
+\cs_new:Npn \regex_replacement_do_one_match:n #1
+ {
+ \regex_query_range:nn
+ { \etex_glueshrink:D \tex_skip:D #1 }
+ { \tex_skip:D #1 }
+ }
+\cs_new:Npn \regex_replacement_exp_not:N #1 { \exp_not:n {#1} }
+\cs_new:Npn \regex_query_range:nn #1#2
+ {
+ \exp_after:wN \regex_query_range_loop:ww
+ \int_use:N \int_eval:w #1 \exp_after:wN ;
+ \int_use:N \int_eval:w #2 ;
+ \prg_break_point:n { }
+ }
+\cs_new:Npn \regex_query_range_loop:ww #1 ; #2 ;
+ {
+ \if_num:w #1 < #2 \exp_stop_f:
+ \else:
+ \exp_after:wN \prg_map_break:
+ \fi:
+ \tex_the:D \tex_toks:D #1 \exp_stop_f:
+ \exp_after:wN \regex_query_range_loop:ww
+ \int_use:N \int_eval:w #1 + \c_one ; #2 ;
+ }
+\cs_new:Npn \regex_query_submatch:n #1
+ {
+ \regex_query_range:nn
+ { \tex_skip:D \int_eval:w #1 }
+ { \etex_gluestretch:D \tex_skip:D \int_eval:w #1 }
+ }
+\cs_new_protected:Npn \regex_submatch_balance:n #1
+ {
+ \etex_glueshrink:D \etex_mutoglue:D \etex_muexpr:D
+ \tex_muskip:D \etex_gluestretch:D \tex_skip:D #1
+ - \tex_muskip:D \tex_skip:D #1
+ \scan_stop:
+ }
+\cs_new_protected:Npn \regex_replacement:n #1
+ {
+ \trace_push:nnn { regex } { 1 } { regex_replacement:n }
+ \tl_set_build:Nw \l_regex_internal_a_tl
+ \int_zero:N \l_regex_balance_int
+ \tl_clear:N \l_regex_balance_tl
+ \regex_escape_use:nnnn
+ {
+ \if_charcode:w \c_rbrace_str ##1
+ \regex_replacement_rbrace:N \else: \tl_build_one:n \fi: ##1
+ }
+ { \regex_replacement_escaped:N ##1 }
+ { \tl_build_one:n ##1 }
+ {#1}
+ \prg_do_nothing: \prg_do_nothing:
+ \if_int_compare:w \l_regex_replacement_csnames_int > \c_zero
+ \msg_kernel_error:nnx { regex } { replacement-missing-rbrace }
+ { \int_use:N \l_regex_replacement_csnames_int }
+ \tl_build_one:x
+ { \prg_replicate:nn \l_regex_replacement_csnames_int \cs_end: }
+ \fi:
+ \cs_gset:Npx \regex_replacement_balance_one_match:n ##1
+ {
+ + \int_use:N \l_regex_balance_int
+ \l_regex_balance_tl
+ - \regex_submatch_balance:n {##1}
+ }
+ \tl_build_end:
+ \exp_args:No \regex_replacement_aux:n \l_regex_internal_a_tl
+ \trace_pop:nnn { regex } { 1 } { regex_replacement:n }
+ }
+\cs_new_protected:Npn \regex_replacement_aux:n #1
+ {
+ \cs_set:Npn \regex_replacement_do_one_match:n ##1
+ {
+ \regex_query_range:nn
+ { \etex_glueshrink:D \tex_skip:D ##1 }
+ { \tex_skip:D ##1 }
+ #1
+ }
+ }
+\cs_new_protected:Npn \regex_replacement_escaped:N #1
+ {
+ \cs_if_exist_use:cF { regex_replacement_#1:w }
+ {
+ \if_num:w \c_one < 1#1 \exp_stop_f:
+ \regex_replacement_put_submatch:n {#1}
+ \else:
+ \tl_build_one:n #1
+ \fi:
+ }
+ }
+\cs_new_protected:Npn \regex_replacement_put_submatch:n #1
+ {
+ \if_num:w #1 < \l_regex_capturing_group_int
+ \tl_build_one:n { \regex_query_submatch:n { #1 + ##1 } }
+ \if_num:w \l_regex_replacement_csnames_int = \c_zero
+ \tl_put_right:Nn \l_regex_balance_tl
+ { + \regex_submatch_balance:n { \int_eval:w #1+##1 \int_eval_end: } }
+ \fi:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_replacement_g:w #1#2
+ {
+ \str_if_eq:xxTF { #1#2 } { \tl_build_one:n \c_lbrace_str }
+ {
+ \int_zero:N \l_regex_internal_a_int
+ \regex_replacement_g_digits:NN
+ }
+ { \regex_replacement_error:NNN g #1 #2 }
+ }
+\cs_new_protected:Npn \regex_replacement_g_digits:NN #1#2
+ {
+ \token_if_eq_meaning:NNTF #1 \tl_build_one:n
+ {
+ \if_num:w \c_one < 1#2 \exp_stop_f:
+ \int_set:Nn \l_regex_internal_a_int
+ { \c_ten * \l_regex_internal_a_int + #2 }
+ \exp_after:wN \use_i:nnn
+ \exp_after:wN \regex_replacement_g_digits:NN
+ \else:
+ \exp_after:wN \regex_replacement_error:NNN
+ \exp_after:wN g
+ \fi:
+ }
+ {
+ \if_meaning:w \regex_replacement_rbrace:N #1
+ \exp_args:No \regex_replacement_put_submatch:n
+ { \int_use:N \l_regex_internal_a_int }
+ \exp_after:wN \use_none:nn
+ \else:
+ \exp_after:wN \regex_replacement_error:NNN
+ \exp_after:wN g
+ \fi:
+ }
+ #1 #2
+ }
+\cs_new_protected:Npn \regex_replacement_c:w #1#2
+ {
+ \token_if_eq_meaning:NNTF #1 \tl_build_one:n
+ {
+ \cs_if_exist_use:cF { regex_replacement_c_#2:w }
+ { \regex_replacement_error:NNN c #1#2 }
+ }
+ { \regex_replacement_error:NNN c #1#2 }
+ }
+\cs_new_protected_nopar:cpn { regex_replacement_c_ \c_lbrace_str :w }
+ {
+ \if_case:w \l_regex_replacement_csnames_int
+ \tl_build_one:n
+ { \exp_not:n { \exp_after:wN \regex_replacement_exp_not:N \cs:w } }
+ \else:
+ \tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:N \cs:w } }
+ \fi:
+ \int_incr:N \l_regex_replacement_csnames_int
+ }
+\cs_new_protected:Npn \regex_replacement_u:w #1#2
+ {
+ \str_if_eq:xxTF { #1#2 } { \tl_build_one:n \c_lbrace_str }
+ {
+ \if_case:w \l_regex_replacement_csnames_int
+ \tl_build_one:n { \exp_not:n { \exp_after:wN \exp_not:V \cs:w } }
+ \else:
+ \tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:V \cs:w } }
+ \fi:
+ \int_incr:N \l_regex_replacement_csnames_int
+ }
+ { \regex_replacement_error:NNN u #1#2 }
+ }
+\cs_new_protected:Npn \regex_replacement_rbrace:N #1
+ {
+ \if_int_compare:w \l_regex_replacement_csnames_int > \c_zero
+ \tl_build_one:n \cs_end:
+ \int_decr:N \l_regex_replacement_csnames_int
+ \else:
+ \tl_build_one:n #1
+ \fi:
+ }
+\group_begin:
+ \cs_new_protected:Npn \regex_replacement_char:nNN #1#2#3
+ {
+ \if_meaning:w \prg_do_nothing: #3
+ \msg_kernel_error:nn { regex } { replacement-catcode-end }
+ \else:
+ \tex_lccode:D \c_zero = `#3 \scan_stop:
+ \tl_to_lowercase:n { \tl_build_one:n {#1} }
+ \fi:
+ }
+ \char_set_catcode_active:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_A:w
+ { \regex_replacement_char:nNN { \exp_not:n { \exp_not:N ^^@ } } }
+ \char_set_catcode_group_begin:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_B:w
+ {
+ \if_num:w \l_regex_replacement_csnames_int = \c_zero
+ \int_incr:N \l_regex_balance_int
+ \fi:
+ \regex_replacement_char:nNN
+ { \exp_not:n { \exp_after:wN ^^@ \if_false: } \fi: } }
+ }
+ \cs_new_protected:Npn \regex_replacement_c_C:w #1#2
+ { \tl_build_one:n { \exp_not:N \exp_not:N \exp_not:c {#2} } }
+ \char_set_catcode_math_subscript:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_D:w
+ { \regex_replacement_char:nNN { ^^@ } }
+ \char_set_catcode_group_end:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_E:w
+ {
+ \if_num:w \l_regex_replacement_csnames_int = \c_zero
+ \int_decr:N \l_regex_balance_int
+ \fi:
+ \regex_replacement_char:nNN
+ { \exp_not:n { \if_false: { \fi: ^^@ } }
+ }
+ \char_set_catcode_letter:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_L:w
+ { \regex_replacement_char:nNN { ^^@ } }
+ \char_set_catcode_math_toggle:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_M:w
+ { \regex_replacement_char:nNN { ^^@ } }
+ \char_set_catcode_other:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_O:w
+ { \regex_replacement_char:nNN { ^^@ } }
+ \char_set_catcode_parameter:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_P:w
+ {
+ \regex_replacement_char:nNN
+ { \exp_not:n { \exp_not:n { ^^@^^@^^@^^@ } } }
+ }
+ \cs_new_protected:Npn \regex_replacement_c_S:w #1#2
+ {
+ \if_meaning:w \prg_do_nothing: #2
+ \msg_kernel_error:nn { regex } { replacement-catcode-end }
+ \else:
+ \if_num:w `#2 = \c_zero
+ \msg_kernel_error:nn { regex } { replacement-null-space }
+ \fi:
+ \tex_lccode:D 32 = `#2 \scan_stop:
+ \tl_to_lowercase:n { \tl_build_one:n {~} }
+ \fi:
+ }
+ \char_set_catcode_alignment:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_T:w
+ { \regex_replacement_char:nNN { ^^@ } }
+ \char_set_catcode_math_superscript:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_U:w
+ { \regex_replacement_char:nNN { ^^@ } }
+\group_end:
+\cs_new_protected:Npn \regex_replacement_error:NNN #1#2#3
+ {
+ \msg_kernel_error:nnx { regex } { replacement-#1 } {#3}
+ #2 #3
+ }
+\cs_new_protected:Npn \regex_new:N #1
+ { \cs_new_eq:NN #1 \c_regex_no_match_regex }
+\cs_new_protected_nopar:Npn \regex_set:Nn #1#2
+ {
+ \regex_compile:n {#2}
+ \tl_set_eq:NN #1 \l_regex_internal_regex
+ }
+\cs_new_protected_nopar:Npn \regex_gset:Nn #1#2
+ {
+ \regex_compile:n {#2}
+ \tl_gset_eq:NN #1 \l_regex_internal_regex
+ }
+\cs_new_protected_nopar:Npn \regex_const:Nn #1#2
+ {
+ \regex_compile:n {#2}
+ \tl_const:Nx #1 { \exp_not:o \l_regex_internal_regex }
+ }
+\cs_new_protected:Npn \regex_show:n #1
+ {
+ \regex_compile:n {#1}
+ \regex_show_aux:Nx \l_regex_internal_regex
+ { { \tl_to_str:n {#1} } }
+ }
+\cs_new_protected:Npn \regex_show:N #1
+ { \regex_show_aux:Nx #1 { variable~\token_to_str:N #1 } }
+\prg_new_protected_conditional:Npnn \regex_match:nn #1#2 { T , F , TF }
+ {
+ \regex_match_aux:nn { \regex_build:n {#1} } {#2}
+ \regex_aux_return:
+ }
+\prg_new_protected_conditional:Npnn \regex_match:Nn #1#2 { T , F , TF }
+ {
+ \regex_match_aux:nn { \regex_build:N #1 } {#2}
+ \regex_aux_return:
+ }
+\cs_new_protected:Npn \regex_count:nnN #1
+ { \regex_count_aux:nnN { \regex_build:n {#1} } }
+\cs_new_protected:Npn \regex_count:NnN #1
+ { \regex_count_aux:nnN { \regex_build:N #1 } }
+\cs_set_protected:Npn \regex_tmp:w #1#2#3
+ {
+ \cs_new_protected:Npn #2 ##1 { #1 { \regex_build:n {##1} } }
+ \cs_new_protected:Npn #3 ##1 { #1 { \regex_build:N ##1 } }
+ \prg_new_protected_conditional:Npnn #2 ##1##2##3 { T , F , TF }
+ { #1 { \regex_build:n {##1} } {##2} ##3 \regex_aux_return: }
+ \prg_new_protected_conditional:Npnn #3 ##1##2##3 { T , F , TF }
+ { #1 { \regex_build:N ##1 } {##2} ##3 \regex_aux_return: }
+ }
+\regex_tmp:w \regex_extract_once_aux:nnN
+ \regex_extract_once:nnN \regex_extract_once:NnN
+\regex_tmp:w \regex_extract_all_aux:nnN
+ \regex_extract_all:nnN \regex_extract_all:NnN
+\regex_tmp:w \regex_replace_once_aux:nnN
+ \regex_replace_once:nnN \regex_replace_once:NnN
+\regex_tmp:w \regex_replace_all_aux:nnN
+ \regex_replace_all:nnN \regex_replace_all:NnN
+\regex_tmp:w \regex_split_aux:nnN \regex_split:nnN \regex_split:NnN
+\int_new:N \l_regex_match_count_int
+\flag_new:n { regex_begin }
+\flag_new:n { regex_end }
+\int_new:N \l_regex_submatch_int
+\int_new:N \l_regex_zeroth_submatch_int
+\cs_new_protected_nopar:Npn \regex_aux_return:
+ {
+ \if_meaning:w \c_true_bool \g_regex_success_bool
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_match_aux:nn #1#2
+ {
+ \group_begin:
+ \regex_disable_submatches:
+ \regex_single_match:
+ #1
+ \regex_match:n {#2}
+ \group_end:
+ }
+\cs_new_protected:Npn \regex_count_aux:nnN #1#2#3
+ {
+ \group_begin:
+ \regex_disable_submatches:
+ \int_zero:N \l_regex_match_count_int
+ \regex_multi_match:n { \int_incr:N \l_regex_match_count_int }
+ #1
+ \regex_match:n {#2}
+ \exp_args:NNNo
+ \group_end:
+ \int_set:Nn #3 { \int_use:N \l_regex_match_count_int }
+ }
+\cs_new_protected:Npn \regex_extract_once_aux:nnN #1#2#3
+ {
+ \group_begin:
+ \regex_single_match:
+ #1
+ \regex_match:n {#2}
+ \regex_extract:
+ \regex_group_end_extract_seq:N #3
+ }
+\cs_new_protected:Npn \regex_extract_all_aux:nnN #1#2#3
+ {
+ \group_begin:
+ \regex_multi_match:n { \regex_extract: }
+ #1
+ \regex_match:n {#2}
+ \regex_group_end_extract_seq:N #3
+ }
+\cs_new_protected:Npn \regex_split_aux:nnN #1#2#3
+ {
+ \group_begin:
+ \regex_multi_match:n
+ {
+ \if_num:w \l_regex_start_pos_int < \l_regex_success_pos_int
+ \regex_extract:
+ \tex_skip:D \l_regex_zeroth_submatch_int
+ = \l_regex_start_pos_int sp
+ plus \tex_skip:D \l_regex_zeroth_submatch_int \scan_stop:
+ \fi:
+ }
+ #1
+ \regex_match:n {#2}
+ \tex_skip:D \l_regex_submatch_int
+ = \l_regex_start_pos_int sp plus \l_regex_max_pos_int sp \scan_stop:
+ \int_incr:N \l_regex_submatch_int
+ \if_meaning:w \c_true_bool \l_regex_empty_success_bool
+ \if_num:w \l_regex_start_pos_int = \l_regex_max_pos_int
+ \int_decr:N \l_regex_submatch_int
+ \fi:
+ \fi:
+ \regex_group_end_extract_seq:N #3
+ }
+\cs_new_protected:Npn \regex_group_end_extract_seq:N #1
+ {
+ \cs_set_eq:NN \seq_item:n \scan_stop:
+ \flag_clear:n { regex_begin }
+ \flag_clear:n { regex_end }
+ \tl_set:Nx \l_regex_internal_a_tl
+ {
+ \prg_stepwise_function:nnnN
+ { \c_two * \l_regex_max_state_int }
+ \c_one
+ { \l_regex_submatch_int - \c_one }
+ \regex_extract_seq_aux:n
+ }
+ \int_compare:nNnF
+ { \flag_height:n { regex_begin } + \flag_height:n { regex_end } }
+ = \c_zero
+ {
+ \msg_kernel_error:nnxxx { regex } { result-unbalanced }
+ { splitting~or~extracting~submatches }
+ { \flag_height:n { regex_end } }
+ { \flag_height:n { regex_begin } }
+ }
+ \use:x
+ {
+ \group_end:
+ \tl_set:Nn \exp_not:N #1 { \l_regex_internal_a_tl }
+ }
+ }
+\cs_new:Npn \regex_extract_seq_aux:n #1
+ {
+ \seq_item:n
+ {
+ \exp_after:wN \regex_extract_seq_aux:ww
+ \int_value:w \regex_submatch_balance:n {#1} ; #1;
+ }
+ }
+\cs_new:Npn \regex_extract_seq_aux:ww #1; #2;
+ {
+ \if_num:w #1 < \c_zero
+ \flag_raise:n { regex_end }
+ \prg_replicate:nn {-#1} { \exp_not:n { { \if_false: } \fi: } }
+ \fi:
+ \regex_query_submatch:n {#2}
+ \if_num:w #1 > \c_zero
+ \flag_raise:n { regex_begin }
+ \prg_replicate:nn {#1} { \exp_not:n { \if_false: { \fi: } } }
+ \fi:
+ }
+\cs_new_protected_nopar:Npn \regex_extract:
+ {
+ \if_meaning:w \c_true_bool \g_regex_success_bool
+ \int_set_eq:NN \l_regex_zeroth_submatch_int \l_regex_submatch_int
+ \prg_replicate:nn \l_regex_capturing_group_int
+ {
+ \tex_skip:D \l_regex_submatch_int \c_zero sp \scan_stop:
+ \int_incr:N \l_regex_submatch_int
+ }
+ \prop_map_inline:Nn \l_regex_success_submatches_prop
+ {
+ \if_num:w ##1 \c_minus_one
+ \exp_after:wN \regex_extract_aux_e:wn \int_value:w
+ \else:
+ \exp_after:wN \regex_extract_aux_b:wn \int_value:w
+ \fi:
+ \int_eval:w \l_regex_zeroth_submatch_int + ##1 {##2}
+ }
+ \tex_skip:D \l_regex_zeroth_submatch_int
+ = \tex_the:D \tex_skip:D \l_regex_zeroth_submatch_int
+ minus \l_regex_start_pos_int sp \scan_stop:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_extract_aux_b:wn #1 < #2
+ {
+ \tex_skip:D #1 = #2 sp
+ plus \etex_gluestretch:D \tex_skip:D #1 \scan_stop:
+ }
+\cs_new_protected:Npn \regex_extract_aux_e:wn #1 > #2
+ {
+ \tex_skip:D #1
+ = 1 \tex_skip:D #1 plus #2 sp \scan_stop:
+ }
+\cs_new_protected:Npn \regex_replace_once_aux:nnN #1#2#3
+ {
+ \group_begin:
+ \regex_single_match:
+ #1
+ \regex_replacement:n {#2}
+ \exp_args:No \regex_match:n { #3 }
+ \if_meaning:w \c_false_bool \g_regex_success_bool
+ \group_end:
+ \else:
+ \regex_extract:
+ \int_set:Nn \l_regex_balance_int
+ {
+ \regex_replacement_balance_one_match:n
+ { \l_regex_zeroth_submatch_int }
+ }
+ \tl_set:Nx \l_regex_internal_a_tl
+ {
+ \regex_replacement_do_one_match:n { \l_regex_zeroth_submatch_int }
+ \regex_query_range:nn
+ { \etex_gluestretch:D \tex_skip:D \l_regex_zeroth_submatch_int }
+ { \l_regex_max_pos_int }
+ }
+ \regex_group_end_replace:N #3
+ \fi:
+ }
+\cs_new_protected:Npn \regex_replace_all_aux:nnN #1#2#3
+ {
+ \group_begin:
+ \regex_multi_match:n { \regex_extract: }
+ #1
+ \regex_replacement:n {#2}
+ \exp_args:No \regex_match:n {#3}
+ \int_set:Nn \l_regex_balance_int
+ {
+ 0
+ \prg_stepwise_function:nnnN
+ { \c_two * \l_regex_max_state_int }
+ \l_regex_capturing_group_int
+ { \l_regex_submatch_int - \c_one }
+ \regex_replacement_balance_one_match:n
+ }
+ \tl_set:Nx \l_regex_internal_a_tl
+ {
+ \prg_stepwise_function:nnnN
+ { \c_two * \l_regex_max_state_int }
+ \l_regex_capturing_group_int
+ { \l_regex_submatch_int - \c_one }
+ \regex_replacement_do_one_match:n
+ \regex_query_range:nn
+ \l_regex_start_pos_int \l_regex_max_pos_int
+ }
+ \regex_group_end_replace:N #3
+ }
+\cs_new_protected_nopar:Npn \regex_group_end_replace:N #1
+ {
+ \if_num:w \l_regex_balance_int = \c_zero
+ \else:
+ \msg_kernel_error:nnxxx { regex } { result-unbalanced }
+ { replacing }
+ { \int_max:nn { - \l_regex_balance_int } { \c_zero } }
+ { \int_max:nn { \l_regex_balance_int } { \c_zero } }
+ \fi:
+ \use:x
+ {
+ \group_end:
+ \tl_set:Nn \exp_not:N #1
+ {
+ \if_int_compare:w \l_regex_balance_int < \c_zero
+ \prg_replicate:nn { - \l_regex_balance_int }
+ { { \if_false: } \fi: }
+ \fi:
+ \l_regex_internal_a_tl
+ \if_int_compare:w \l_regex_balance_int > \c_zero
+ \prg_replicate:nn { \l_regex_balance_int }
+ { \if_false: { \fi: } }
+ \fi:
+ }
+ }
+ }
+\msg_kernel_new:nnnn { regex } { 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 }
+ { Missing~closing~brace~in~\iow_char:N\\x~hexadecimal~sequence. }
+ {
+ You~wrote~something~like~
+ `\iow_char:N\\x\{\int_to_hexadecimal:n{#1}'.~
+ The~closing~brace~is~missing.
+ }
+\msg_kernel_new:nnnn { regex } { x-overflow }
+ { Character~code~'#1'~too~large~in~\iow_char:N\\x~hexadecimal~sequence. }
+ {
+ You~wrote~something~like~
+ `\iow_char:N\\x\{\int_to_hexadecimal:n{#1}\}'.~
+ The~character~code~'#1'~is~larger~than~\int_use:N \c_max_char_int.
+ }
+\msg_kernel_new:nnnn { regex } { invalid-quantifier }
+ { Braced~quantifier~'#1'~may~not~be~followed~by~'#2'. }
+ {
+ The~character~'#2'~is~invalid~in~the~braced~quantifier~'#1'.~
+ The~only~valid~quantifiers~are~'*',~'?',~'+',~'{<int>}',~
+ '{<min>,}'~and~'{<min>,<max>}',~followed~or~not~by~'?'.
+ }
+\msg_kernel_new:nnnn { regex } { 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 }
+ {
+ Missing~right~parenthes\int_compare:nTF{#1=1}{i}{e}s~
+ inserted~in~regular~expression.
+ }
+ {
+ LaTeX~was~given~a~regular~expression~with~\int_eval:n{#1}~
+ more~left~parenthes\int_compare:nTF{#1=1}{i}{e}s~than~right~
+ parenthes\int_compare:nTF{#1=1}{i}{e}s.
+ }
+\msg_kernel_new:nnnn { regex } { extra-rparen }
+ { Extra~right~parenthesis~ignored~in~regular~expression. }
+ {
+ LaTeX~came~across~a~closing~parenthesis~when~no~submatch~group~
+ was~open.~The~parenthesis~will~be~ignored.
+ }
+\msg_kernel_new:nnnn { regex } { bad-escape }
+ {
+ Invalid~escape~\c_backslash_str #1~
+ \regex_if_in_cs:TF { within~a~control~sequence. }
+ {
+ \regex_if_in_class:TF
+ { in~a~character~class. }
+ { following~a~category~test. }
+ }
+ }
+ {
+ The~escape~sequence~\iow_char:N\\#1~may~not~appear~
+ \regex_if_in_cs:TF
+ {
+ within~a~control~sequence~test~introduced~by~
+ \iow_char:N\\c\iow_char:N\{.
+ }
+ {
+ \regex_if_in_class:TF
+ { within~a~character~class~ }
+ { following~a~category~test~such~as~\iow_char:N\\cL~ }
+ because~it~does~not~match~exactly~one~character.
+ }
+ }
+\msg_kernel_new:nnnn { regex } { 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 }
+ { Range~[#1-#2]~out~of~order~in~character~class. }
+ {
+ In~ranges~of~characters~[x-y]~appearing~in~character~classes,~
+ the~first~character~code~must~not~be~larger~than~the~second.~
+ Here,~#1~has~character~code~\int_eval:n {`#1},~while~#2~has~
+ character~code~\int_eval:n {`#2}.
+ }
+\msg_kernel_new:nnnn { regex } { 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 }
+ { 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 }
+ { 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 }
+ { Invalid~character~'#1'~following~\iow_char:N\\c~escape. }
+ {
+ In~regular~expressions,~the~\iow_char:N\\c~escape~sequence~
+ may~only~be~followed~by~a~left~brace,~a~left~bracket,~or~a~
+ capital~letter~representing~a~character~category,~namely~
+ one~of~ABCDELMOPSTU.
+ }
+\msg_kernel_new:nnnn { regex } { 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 }
+ { Missing~right~brace~inserted~for~\iow_char:N\\u~escape. }
+ {
+ LaTeX~
+ \tl_if_empty:xTF {#2}
+ { reached~the~end~of~the~string~ }
+ { encountered~an~escaped~alphanumeric~character '\iow_char:N\\#2'~ }
+ when~parsing~the~argument~of~an~'\iow_char:N\\u\iow_char:N\{...\}'~escape.
+ }
+\msg_kernel_new:nnnn { regex } { 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 }
+ { POSIX~class~[:#1:]~unknown. }
+ {
+ [:#1:]~is~not~among~the~known~POSIX~classes~
+ [:alnum:],~[:alpha:],~[:ascii:],~[:blank:],~
+ [:cntrl:],~[:digit:],~[:graph:],~[:lower:],~
+ [:print:],~[:punct:],~[:space:],~[:upper:],~
+ [:word:],~and~[:xdigit:].
+ }
+\msg_kernel_new:nnnn { regex } { posix-missing-close }
+ { Missing~closing~':]'~for~POSIX~class. }
+ { The~POSIX~syntax~'#1'~must~be~followed~by~':]',~not~'#2'. }
+\msg_kernel_new:nnnn { regex } { result-unbalanced }
+ { Missing~brace~inserted~when~#1. }
+ {
+ LaTeX~was~asked~to~do~some~regular~expression~operation,~
+ and~the~resulting~token~list~would~not~have~the~same~number~
+ of~begin-group~and~end-group~tokens.~Braces~were~inserted:~
+ #2~left,~#3~right.
+ }
+\msg_kernel_new:nnnn { regex } { 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 } { 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 }
+ { 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 }
+ { Missing~brace~for~the~\iow_char:N\\g~construction~in~a~replacement~text. }
+ {
+ In~the~replacement~text~for~a~regular~expression~search,~
+ 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 }
+ {
+ Missing~character~for~the~\iow_char:N\\c<category><character>~
+ construction~in~a~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.~LaTeX~
+ reached~the~end~of~the~replacement~when~looking~for~that.
+ }
+\msg_kernel_new:nnnn { regex } { replacement-null-space }
+ { TeX~cannot~build~a~space~token~with~character~code~0. }
+ {
+ You~asked~for~a~character~token~with~category~'space',~
+ and~character~code~0,~for~instance~through~
+ '\iow_char:N\\cS\iow_char:N\\x00'.~
+ This~specific~case~is~impossible~and~will~be~replaced~
+ by~a~normal~space.
+ }
+\msg_kernel_new:nnnn { regex } { replacement-missing-rbrace }
+ { Missing~right~brace~inserted~in~replacement~text. }
+ {
+ There~were~\int_use:N \l_regex_replacement_csnames_int \
+ missing~right~braces.
+ }
+\cs_new:Npn \regex_msg_repeated:nnN #1#2#3
+ {
+ \str_if_eq:xxF { #1 #2 } { 1 0 }
+ {
+ , ~ repeated ~
+ \prg_case_int:nnn {#2}
+ {
+ { -1 } { #1~or~more~times,~\bool_if:NTF #3 { lazy } { greedy } }
+ { 0 } { #1~times }
+ }
+ {
+ between~#1~and~\int_eval:n {#1+#2}~times,~
+ \bool_if:NTF #3 { lazy } { greedy }
+ }
+ }
+ }
+\cs_new_protected:Npn \regex_trace_states:n #1
+ {
+ \prg_stepwise_inline:nnnn
+ \l_regex_min_state_int
+ \c_one
+ { \l_regex_max_state_int - 1 }
+ {
+ \trace:nnx { regex } { #1 }
+ { \iow_char:N \\toks ##1 = { \tex_the:D \tex_toks:D ##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 2b99a8eb661..17480334049 100644
--- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty
+++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty
@@ -46,236 +46,35 @@
%%
%% -----------------------------------------------------------------------
\RequirePackage{expl3}
-\GetIdInfo$Id: l3regex.dtx 3326 2012-02-07 00:39:44Z bruno $
+\GetIdInfo$Id: l3regex.dtx 3463 2012-02-26 15:05:14Z bruno $
{L3 Experimental Regular Expressions}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\RequirePackage{l3str, l3tl-analysis, l3flag}
+\RequirePackage{l3tl-build, l3tl-analysis, l3flag, l3str}
+\cs_generate_variant:Nn \tl_to_str:n { V }
\cs_new:Npn \regex_tmp:w { }
\tl_new:N \l_regex_internal_a_tl
\tl_new:N \l_regex_internal_b_tl
\int_new:N \l_regex_internal_a_int
\int_new:N \l_regex_internal_b_int
\int_new:N \l_regex_internal_c_int
+\bool_new:N \l_regex_internal_bool
+\seq_new:N \l_regex_internal_seq
\tl_new:N \g_regex_internal_tl
-\tl_const:Nn \c_regex_d_tl
- { \regex_item_range:nn \c_forty_eight { 57 } } % 0--9
-\tl_const:Nn \c_regex_h_tl
- {
- \regex_item_equal:n \c_thirty_two % space
- \regex_item_equal:n \c_nine % tab
- }
-\tl_const:Nn \c_regex_s_tl
- {
- \regex_item_equal:n \c_thirty_two % space
- \regex_item_equal:n \c_nine % tab
- \regex_item_equal:n \c_ten % lf
- \regex_item_equal:n \c_twelve % ff
- \regex_item_equal:n \c_thirteen % cr
- }
-\tl_const:Nn \c_regex_v_tl
- { \regex_item_range:nn \c_ten \c_thirteen } % lf, vtab, ff, cr
-\tl_const:Nn \c_regex_w_tl
- {
- \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_D_tl
- { \c_regex_d_tl \regex_break_point:TF { } \regex_break_true:w }
-\tl_const:Nn \c_regex_H_tl
- { \c_regex_h_tl \regex_break_point:TF { } \regex_break_true:w }
-\tl_const:Nn \c_regex_S_tl
- { \c_regex_s_tl \regex_break_point:TF { } \regex_break_true:w }
-\tl_const:Nn \c_regex_V_tl
- { \c_regex_v_tl \regex_break_point:TF { } \regex_break_true:w }
-\tl_const:Nn \c_regex_W_tl
- { \c_regex_w_tl \regex_break_point:TF { } \regex_break_true:w }
-\tl_const:Nn \c_regex_N_tl
- {
- \regex_item_equal:n \c_ten
- \regex_break_point:TF { } { \regex_break_true:w }
- }
-\tl_const:cn { c_regex_._tl }
- {
- \if_num:w \l_regex_current_char_int > - \c_two
- \exp_after:wN \regex_break_true:w
- \fi:
- }
-\int_new:N \l_regex_build_mode_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_end_group_seq
-\seq_new:N \l_regex_end_alternation_seq
-\int_new:N \l_regex_capturing_group_int
-\seq_new:N \l_regex_capturing_group_seq
-\int_new:N \l_regex_capturing_group_max_int
-\tl_new:N \l_regex_one_or_group_tl
-\int_new:N \l_regex_catcodes_int
-\int_new:N \l_regex_catcodes_default_int
-\int_const:Nn \c_regex_catcode_C_int { "1 }
-\int_const:Nn \c_regex_catcode_B_int { "4 }
-\int_const:Nn \c_regex_catcode_E_int { "10 }
-\int_const:Nn \c_regex_catcode_M_int { "40 }
-\int_const:Nn \c_regex_catcode_T_int { "100 }
-\int_const:Nn \c_regex_catcode_P_int { "1000 }
-\int_const:Nn \c_regex_catcode_U_int { "4000 }
-\int_const:Nn \c_regex_catcode_D_int { "10000 }
-\int_const:Nn \c_regex_catcode_S_int { "100000 }
-\int_const:Nn \c_regex_catcode_L_int { "400000 }
-\int_const:Nn \c_regex_catcode_O_int { "1000000 }
-\int_const:Nn \c_regex_catcode_A_int { "4000000 }
-\int_const:Nn \c_regex_catcodes_all_int { "5515155 }
-\bool_new:N \l_regex_catcodes_bool
-\bool_new:N \l_regex_tests_bool
-\tl_new:N \l_regex_tests_tl
-\bool_new:N \l_regex_tests_saved_bool
-\tl_new:N \l_regex_tests_saved_tl
-\int_new:N \l_regex_catcodes_saved_int
-\int_new:N \l_regex_min_index_int
-\int_new:N \l_regex_max_index_int
-\int_new:N \l_regex_nesting_int
-\int_new:N \l_regex_current_index_int
-\int_new:N \l_regex_start_index_int
-\int_new:N \l_regex_success_index_int
-\int_new:N \l_regex_current_char_int
-\int_new:N \l_regex_current_catcode_int
-\tl_new:N \l_regex_current_token_tl
-\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_step_int
-\int_new:N \l_regex_max_active_int
-\tl_new:N \l_regex_every_match_tl
-\bool_new:N \l_regex_fresh_thread_bool
-\bool_new:N \l_regex_success_empty_bool
-\cs_new_eq:NN \regex_if_two_empty_matches:F \use:n
-\bool_new:N \g_regex_success_bool
-\bool_new:N \l_regex_saved_success_bool
-\bool_new:N \l_regex_success_match_bool
\tl_const:Nn \c_regex_no_match_regex
{
- \regex_nfa:Nw \c_regex_no_match_regex
- \l_regex_max_state_int = \c_one
- \l_regex_capturing_group_int = \c_zero
- \tex_toks:D \c_zero { \s_stop }
- \s_stop
- }
-\cs_new_protected:Npn \regex_new:N #1
- {
- \chk_if_free_cs:N #1
- \cs_gset_eq:NN #1 \c_regex_no_match_regex
- }
-\regex_new:N \l_regex_internal_regex
-\int_new:N \l_regex_replacement_csnames_int
-\int_new:N \l_regex_replacement_int
-\int_new:N \l_regex_submatch_int
-\int_new:N \l_regex_submatch_start_int
-\int_new:N \l_regex_match_count_int
-\flag_new:n { regex_begin }
-\flag_new:n { regex_end }
-\cs_new_protected:Npn \regex_toks_put_left:Nx #1#2
- {
- \cs_set_nopar:Npx \regex_tmp:w \s_stop { \s_stop #2 }
- \tex_toks:D #1 \exp_after:wN \exp_after:wN \exp_after:wN
- { \exp_after:wN \regex_tmp:w \tex_the:D \tex_toks:D #1 }
- }
-\cs_new_protected:Npn \regex_toks_put_right:Nx #1#2
- {
- \cs_set_nopar:Npx \regex_tmp:w {#2}
- \tex_toks:D #1 \exp_after:wN
- { \tex_the:D \tex_toks:D \exp_after:wN #1 \regex_tmp:w }
- }
-\cs_new:Npn \regex_toks_range:nn #1#2
- {
- \exp_after:wN \regex_toks_range:ww
- \int_use:N \int_eval:w #1 \exp_after:wN ;
- \int_use:N \int_eval:w #2 ;
- \prg_break_point:n { }
- }
-\cs_new:Npn \regex_toks_range:ww #1 ; #2 ;
- {
- \if_num:w #1 < #2 \exp_stop_f:
- \else:
- \exp_after:wN \prg_map_break:
- \fi:
- \tex_the:D \tex_toks:D #1 \exp_stop_f:
- \exp_after:wN \regex_toks_range:ww
- \int_use:N \int_eval:w #1 + \c_one ; #2 ;
- }
-\cs_new:Npn \regex_query_submatch:nn #1#2
- {
- \if_num:w #1 < \l_regex_capturing_group_int
- \exp_after:wN \regex_query_submatch:w
- \int_use:N \int_eval:w #1 + #2 ;
- \fi:
- }
-\cs_new:Npn \regex_query_submatch:w #1 ;
- {
- \regex_toks_range:nn
- { \tex_skip:D #1 }
- { \etex_gluestretch:D \tex_skip:D #1 }
- }
-\cs_new_protected:Npn \regex_seq_pop_int:NN #1#2
- {
- \seq_pop:NN #1 \l_regex_internal_a_tl
- \int_set:Nn #2 \l_regex_internal_a_tl
- }
-\cs_new_protected:Npn \regex_seq_get_int:NN #1#2
- {
- \seq_get:NN #1 \l_regex_internal_a_tl
- \int_set:Nn #2 \l_regex_internal_a_tl
- }
-\cs_new_protected:Npn \regex_seq_push_int:NN #1#2
- { \seq_push:No #1 { \int_use:N #2 } }
-\cs_new_protected:Npn \regex_seq_pop_use:N #1
- {
- \seq_pop:NN #1 \l_regex_internal_a_tl
- \l_regex_internal_a_tl
- }
-\cs_new_protected:Npn \regex_seq_get_use:N #1
- {
- \seq_get:NN #1 \l_regex_internal_a_tl
- \l_regex_internal_a_tl
- }
-\cs_new_protected:Npn \regex_get_digits:nw #1
- {
- \tex_afterassignment:D \regex_tmp:w
- \cs_set_nopar:Npx \regex_tmp:w
- {
- \exp_not:n {#1}
- { \if_false: } } \fi:
- \regex_get_digits_aux:NN
- }
-\cs_new:Npn \regex_get_digits_aux:NN #1#2
- {
- \if_meaning:w \regex_build_raw:N #1
- \if_num:w 9 < 1 \exp_not:N #2 \exp_stop_f:
- #2
- \else:
- \regex_get_digits_end:w #1 #2
- \fi:
- \else:
- \regex_get_digits_end:w #1 #2
- \fi:
- \regex_get_digits_aux:NN
- }
-\cs_new:Npn \regex_get_digits_end:w #1 \fi: #2 \regex_get_digits_aux:NN
- {
- \fi: #2
- \if_false: { { \fi: } }
- #1
+ \regex_branch:n
+ { \regex_class:NnnnN \c_true_bool { } { 1 } { 0 } \c_true_bool }
}
+\int_new:N \l_regex_balance_int
\cs_new_protected:Npn \regex_break_true:w
#1 \regex_break_point:TF #2 #3 {#2}
\cs_new_protected:Npn \regex_break_point:TF #1 #2 { #2 }
+\cs_new_protected:Npn \regex_item_reverse:n #1
+ {
+ #1
+ \regex_break_point:TF { } \regex_break_true:w
+ }
\cs_new_protected:Npn \regex_item_caseful_equal:n #1
{
\if_num:w #1 = \l_regex_current_char_int
@@ -290,17 +89,14 @@
\fi:
\fi:
}
-\cs_new_protected:Npn \regex_item_caseful_geq:n #1
- {
- \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
- \exp_after:wN \regex_break_true:w
- \fi:
- }
\cs_new_protected:Npn \regex_item_caseless_equal:n #1
{
\if_num:w #1 = \l_regex_current_char_int
\exp_after:wN \regex_break_true:w
\fi:
+ \if_num:w \l_regex_case_changed_char_int = \c_max_int
+ \regex_compute_case_changed_char:
+ \fi:
\if_num:w #1 = \l_regex_case_changed_char_int
\exp_after:wN \regex_break_true:w
\fi:
@@ -312,38 +108,34 @@
\exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
\fi:
\fi:
+ \if_num:w \l_regex_case_changed_char_int = \c_max_int
+ \regex_compute_case_changed_char:
+ \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:Npn \regex_item_caseless_geq:n #1
+\cs_new_protected_nopar:Npn \regex_compute_case_changed_char:
{
- \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
+ \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: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_eq:NN \regex_item_equal:n ?
+\cs_new_eq:NN \regex_item_range:nn ?
\cs_new_protected:Npn \regex_item_catcode_aux:
{
"
@@ -362,44 +154,134 @@
\exp_after:wN \use_none:n
\fi:
}
-\cs_new_protected:Npn \regex_item_cs:n #1
+\cs_new_protected:Npn \regex_item_catcode_reverse:nT #1#2
+ { \regex_item_catcode:nT {#1} { \regex_item_reverse:n {#2} } }
+\cs_new_protected:Npn \regex_item_exact:nn #1#2
{
- \int_compare:nNnT \l_regex_current_catcode_int = \c_zero
+ \if_num:w #1 = \l_regex_current_catcode_int
+ \if_num:w #2 = \l_regex_current_char_int
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
+ \fi:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_item_exact_cs:c #1
+ {
+ \int_compare:nNnTF \l_regex_current_catcode_int = \c_zero
{
- \tl_set:Nn \l_regex_internal_regex {#1}
- \bool_set_eq:NN \l_regex_saved_success_bool \g_regex_success_bool
- \exp_args:NNx \regex_match:NnTF \l_regex_internal_regex
+ \str_if_eq:xxTF
{
- \exp_after:wN \exp_after:wN
- \exp_after:wN \cs_to_str:N \l_regex_current_token_tl
+ \exp_after:wN \exp_after:wN \exp_after:wN \cs_to_str:N
+ \tex_the:D \tex_toks:D \l_regex_current_pos_int
}
- {
- \bool_gset_eq:NN \g_regex_success_bool \l_regex_saved_success_bool
- \regex_break_true:w
- }
- { \bool_gset_eq:NN \g_regex_success_bool \l_regex_saved_success_bool }
+ { #1 }
+ { \regex_break_true:w } { }
}
+ { }
+ }
+\cs_new_protected:Npn \regex_item_cs:n #1
+ {
+ \int_compare:nNnT \l_regex_current_catcode_int = \c_zero
+ {
+ \group_begin:
+ \regex_single_match:
+ \regex_disable_submatches:
+ \regex_build_for_cs:n {#1}
+ \bool_set_eq:NN \l_regex_saved_success_bool \g_regex_success_bool
+ \exp_args:Nx \regex_match:n
+ {
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \cs_to_str:N
+ \tex_the:D \tex_toks:D \l_regex_current_pos_int
+ }
+ \if_meaning:w \c_true_bool \g_regex_success_bool
+ \group_insert_after:N \regex_break_true:w
+ \fi:
+ \bool_gset_eq:NN \g_regex_success_bool \l_regex_saved_success_bool
+ \group_end:
+ }
+ }
+\cs_new_protected_nopar:Npn \regex_prop_d:
+ { \regex_item_caseful_range:nn \c_forty_eight { 57 } } % 0--9
+\cs_new_protected_nopar:Npn \regex_prop_h:
+ {
+ \regex_item_caseful_equal:n \c_thirty_two % space
+ \regex_item_caseful_equal:n \c_nine % tab
+ }
+\cs_new_protected_nopar:Npn \regex_prop_s:
+ {
+ \regex_item_caseful_equal:n \c_thirty_two % space
+ \regex_item_caseful_equal:n \c_nine % tab
+ \regex_item_caseful_equal:n \c_ten % lf
+ \regex_item_caseful_equal:n \c_twelve % ff
+ \regex_item_caseful_equal:n \c_thirteen % cr
+ }
+\cs_new_protected_nopar:Npn \regex_prop_v:
+ { \regex_item_caseful_range:nn \c_ten \c_thirteen } % lf, vtab, ff, cr
+\cs_new_protected_nopar:Npn \regex_prop_w:
+ {
+ \regex_item_caseful_range:nn \c_ninety_seven { 122 } % a--z
+ \regex_item_caseful_range:nn \c_sixty_five { 90 } % A--Z
+ \regex_item_caseful_range:nn \c_forty_eight { 57 } % 0--9
+ \regex_item_caseful_equal:n { 95 } % _
+ }
+\cs_new_protected_nopar:Npn \regex_prop_N:
+ { \regex_item_reverse:n { \regex_item_caseful_equal:n \c_ten } }
+\cs_new_protected_nopar:Npn \regex_posix_alnum:
+ { \regex_posix_alpha: \regex_posix_digit: }
+\cs_new_protected_nopar:Npn \regex_posix_alpha:
+ { \regex_posix_lower: \regex_posix_upper: }
+\cs_new_protected_nopar:Npn \regex_posix_ascii:
+ { \regex_item_caseful_range:nn \c_zero \c_one_hundred_twenty_seven }
+\cs_new_eq:NN \regex_posix_blank: \regex_prop_h:
+\cs_new_protected_nopar:Npn \regex_posix_cntrl:
+ {
+ \regex_item_caseful_range:nn \c_zero { 31 }
+ \regex_item_caseful_equal:n \c_one_hundred_twenty_seven
+ }
+\cs_new_eq:NN \regex_posix_digit: \regex_prop_d:
+\cs_new_protected_nopar:Npn \regex_posix_graph:
+ { \regex_item_caseful_range:nn { 33 } { 126 } }
+\cs_new_protected_nopar:Npn \regex_posix_lower:
+ { \regex_item_caseful_range:nn \c_ninety_seven { 122 } }
+\cs_new_protected_nopar:Npn \regex_posix_print:
+ { \regex_item_caseful_range:nn \c_thirty_two { 126 } }
+\cs_new_protected_nopar:Npn \regex_posix_punct:
+ {
+ \regex_item_caseful_range:nn { 33 } { 47 }
+ \regex_item_caseful_range:nn { 58 } { 64 }
+ \regex_item_caseful_range:nn { 91 } { 96 }
+ \regex_item_caseful_range:nn { 123 } { 126 }
+ }
+\cs_new_protected_nopar:Npn \regex_posix_space:
+ {
+ \regex_item_caseful_equal:n \c_thirty_two
+ \regex_item_caseful_range:nn \c_nine \c_thirteen
+ }
+\cs_new_protected_nopar:Npn \regex_posix_upper:
+ { \regex_item_caseful_range:nn \c_sixty_five { 90 } }
+\cs_new_eq:NN \regex_posix_word: \regex_prop_w:
+\cs_new_protected_nopar:Npn \regex_posix_xdigit:
+ {
+ \regex_posix_digit:
+ \regex_item_caseful_range:nn \c_sixty_five { 70 }
+ \regex_item_caseful_range:nn \c_ninety_seven { 102 }
}
\cs_new_protected:Npn \regex_escape_use:nnnn #1#2#3#4
{
- \group_begin:
+ \tl_set_build:Nw \l_regex_internal_a_tl
\cs_set_nopar:Npn \regex_escape_unescaped:N ##1 { #1 }
\cs_set_nopar:Npn \regex_escape_escaped:N ##1 { #2 }
\cs_set_nopar:Npn \regex_escape_raw:N ##1 { #3 }
\int_set:Nn \tex_escapechar:D { 92 }
- \str_gset_other:Nn \g_regex_internal_tl {#4}
- \int_zero:N \l_regex_internal_a_int
- \tl_set:Nx \l_regex_internal_a_tl
+ \str_gset_other:Nn \g_regex_internal_tl { #4 }
+ \tl_set:Nx \l_regex_internal_b_tl
{
\exp_after:wN \regex_escape_loop:N \g_regex_internal_tl
{ break } \prg_break_point:n { }
}
- \use:x
- {
- \group_end:
- \regex_toks_range:nn \c_zero \l_regex_internal_a_int
- \exp_not:o \l_regex_internal_a_tl
- }
+ \tl_build_one:o \l_regex_internal_b_tl
+ \tl_build_end:
+ \l_regex_internal_a_tl
}
\cs_new:Npn \regex_escape_loop:N #1
{
@@ -437,82 +319,96 @@
{ \exp_not:N \regex_escape_raw:N \iow_char:N \^^M }
\cs_new_nopar:cpx { regex_escape_/e:w }
{ \exp_not:N \regex_escape_raw:N \iow_char:N \^^[ }
-\cs_new_nopar:cpn { regex_escape_/x:w } \regex_escape_loop:N
+\cs_new:cpn { regex_escape_/x:w } \regex_escape_loop:N
{
- \if_false: { \fi: }
- \tex_toks:D \l_regex_internal_a_int
- \exp_after:wN { \l_regex_internal_a_tl }
- \int_incr:N \l_regex_internal_a_int
- \int_zero:N \l_regex_current_char_int
- \regex_escape_x_test:N
+ \exp_after:wN \regex_escape_x_end:w
+ \int_value:w "0 \regex_escape_x_test:N
}
-\cs_new_protected:Npx \regex_escape_x_test:N #1
+\cs_new:Npn \regex_escape_x_end:w #1 ;
{
- \exp_not:N \token_if_eq_charcode:NNTF \c_space_token #1
- { \exp_not:N \regex_escape_x_test:N }
+ \int_compare:nNnTF {#1} < \c_two_hundred_fifty_six
{
- \l_regex_current_char_int = "0
- \exp_not:N \token_if_eq_charcode:NNTF \c_lbrace_str #1
- { \exp_not:N \regex_escape_x_braced_loop:N }
- { \exp_not:N \regex_escape_x_unbraced_i:N #1 }
+ \exp_last_unbraced:Nf \regex_escape_raw:N
+ { \str_output_byte:n {#1} }
}
+ { \regex_escape_x_large:n {#1} }
}
-\cs_new:Npn \regex_escape_x_unbraced_i:N #1
- {
- \str_aux_hexadecimal_use:NTF #1
- { \regex_escape_x_unbraced_ii:N }
- { \exp_stop_f: \regex_escape_x_end: #1 }
- }
-\cs_new:Npn \regex_escape_x_unbraced_ii:N #1
+\group_begin:
+ \char_set_catcode_other:n { 0 }
+ \cs_new:Npn \regex_escape_x_large:n #1
+ {
+ \if_false: { \fi: }
+ \tl_build_one:o \l_regex_internal_b_tl
+ \int_compare:nNnTF {#1} > \c_max_char_int
+ {
+ \msg_kernel_error:nnx { regex } { x-overflow } {#1}
+ \tl_set:Nx \l_regex_internal_b_tl
+ { \if_false: } \fi: \regex_escape_loop:N
+ }
+ {
+ \char_set_lccode:nn { \c_zero } {#1}
+ \tl_to_lowercase:n
+ {
+ \tl_set:Nx \l_regex_internal_b_tl
+ { \if_false: } \fi:
+ \regex_escape_raw:N ^^@
+ \regex_escape_loop:N
+ }
+ }
+ }
+\group_end:
+\cs_new:Npn \regex_escape_x_test:N #1
{
- \token_if_eq_charcode:NNTF \c_space_token #1
- { \regex_escape_x_unbraced_ii:N }
+ \str_if_eq:xxTF {#1} { break } { ; }
{
- \str_aux_hexadecimal_use:NTF #1
- { \exp_stop_f: \regex_escape_x_end: }
- { \exp_stop_f: \regex_escape_x_end: #1 }
+ \if_charcode:w \c_space_token #1
+ \exp_after:wN \regex_escape_x_test:N
+ \else:
+ \exp_after:wN \regex_escape_x_test_ii:N
+ \exp_after:wN #1
+ \fi:
}
}
-\cs_new:Npn \regex_escape_x_braced_loop:N #1
+\cs_new:Npn \regex_escape_x_test_ii:N #1
{
- \token_if_eq_charcode:NNTF \c_space_token #1
- { \regex_escape_x_braced_loop:N }
+ \if_charcode:w \c_lbrace_str #1
+ \exp_after:wN \regex_escape_x_loop:N
+ \else:
+ \str_aux_hexadecimal_use:NTF #1
+ { \exp_after:wN \regex_escape_x_ii:N }
+ { ; \exp_after:wN \regex_escape_loop:N \exp_after:wN #1 }
+ \fi:
+ }
+\cs_new:Npn \regex_escape_x_ii:N #1
+ {
+ \str_if_eq:xxTF {#1} { break } { ; }
{
\str_aux_hexadecimal_use:NTF #1
- { \regex_escape_x_braced_loop:N }
- { \exp_stop_f: \regex_escape_x_braced_end:N #1 }
+ { ; \regex_escape_loop:N }
+ { ; \regex_escape_loop:N #1 }
}
}
-\cs_new_protected:Npx \regex_escape_x_braced_end:N #1
+\cs_new:Npn \regex_escape_x_loop:N #1
{
- \exp_not:N \token_if_eq_charcode:NNTF \c_rbrace_str #1
- { \exp_not:N \regex_escape_x_end: }
+ \str_aux_hexadecimal_use:NTF #1
+ { \regex_escape_x_loop:N }
{
- \msg_kernel_error:nnx { regex } { x-missing-rbrace }
- { \int_use:N \l_regex_current_char_int }
- \exp_not:N \regex_escape_x_end: #1
+ \token_if_eq_charcode:NNTF \c_space_token #1
+ { \regex_escape_x_loop:N }
+ {
+ ;
+ \exp_after:wN \token_if_eq_charcode:NNTF \c_rbrace_str #1
+ { \regex_escape_loop:N }
+ {
+ \if_false: { \fi: }
+ \tl_build_one:o \l_regex_internal_b_tl
+ \msg_kernel_error:nn { regex } { x-missing-rbrace } {#1}
+ \tl_set:Nx \l_regex_internal_b_tl
+ { \if_false: } \fi: \regex_escape_loop:N #1
+ }
+ }
}
}
-\group_begin:
- \char_set_catcode_other:N \^^@
- \cs_new_protected_nopar:Npn \regex_escape_x_end:
- {
- \if_num:w \l_regex_current_char_int > \c_max_char_int
- \msg_kernel_error:nnx { regex } { x-overflow }
- { \int_use:N \l_regex_current_char_int }
- \exp_after:wN \use:n
- \else:
- \tex_lccode:D \c_zero \l_regex_current_char_int
- \exp_after:wN \tl_to_lowercase:n
- \fi:
- {
- \tl_set:Nx \l_regex_internal_a_tl
- { \if_false: } \fi:
- \regex_escape_raw:N ^^@
- \regex_escape_loop:N
- }
- }
-\group_end:
\prg_new_conditional:Npnn \regex_char_if_special:N #1 { TF }
{
\if_num:w `#1 < \c_ninety_one
@@ -554,198 +450,368 @@
\fi:
\fi:
}
-\cs_new_nopar:Npn \regex_build_if_in_class:TF
+\int_new:N \l_regex_group_level_int
+\int_new:N \l_regex_mode_int
+\int_new:N \l_regex_catcodes_int
+\int_new:N \l_regex_default_catcodes_int
+\bool_new:N \l_regex_catcodes_bool
+\int_const:Nn \c_regex_catcode_C_int { "1 }
+\int_const:Nn \c_regex_catcode_B_int { "4 }
+\int_const:Nn \c_regex_catcode_E_int { "10 }
+\int_const:Nn \c_regex_catcode_M_int { "40 }
+\int_const:Nn \c_regex_catcode_T_int { "100 }
+\int_const:Nn \c_regex_catcode_P_int { "1000 }
+\int_const:Nn \c_regex_catcode_U_int { "4000 }
+\int_const:Nn \c_regex_catcode_D_int { "10000 }
+\int_const:Nn \c_regex_catcode_S_int { "100000 }
+\int_const:Nn \c_regex_catcode_L_int { "400000 }
+\int_const:Nn \c_regex_catcode_O_int { "1000000 }
+\int_const:Nn \c_regex_catcode_A_int { "4000000 }
+\int_const:Nn \c_regex_all_catcodes_int { "5515155 }
+\cs_new_eq:NN \l_regex_internal_regex \c_regex_no_match_regex
+\seq_new:N \l_regex_show_prefix_seq
+\int_new:N \l_regex_show_lines_int
+\cs_new_protected:Npn \regex_get_digits:NTFw #1#2#3#4#5
+ {
+ \regex_if_raw_digit:NNTF #4 #5
+ { #1 = #5 \regex_get_digits_loop:nw {#2} }
+ { #3 #4 #5 }
+ }
+\cs_new:Npn \regex_get_digits_loop:nw #1#2#3
+ {
+ \regex_if_raw_digit:NNTF #2 #3
+ { #3 \regex_get_digits_loop:nw {#1} }
+ { \scan_stop: #1 #2 #3 }
+ }
+\prg_new_conditional:Npnn \regex_if_raw_digit:NN #1#2 { TF }
+ {
+ \if_meaning:w \regex_compile_raw:N #1
+ \if_int_compare:w \c_one < 1 #2 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\cs_new_nopar:Npn \regex_if_in_class:TF
{
- \if_int_odd:w \l_regex_build_mode_int
+ \if_int_odd:w \l_regex_mode_int
\exp_after:wN \use_i:nn
\else:
\exp_after:wN \use_ii:nn
\fi:
}
-\cs_new_nopar:Npn \regex_build_if_assertions_forbidden:TF
+\cs_new_nopar:Npn \regex_if_in_cs:TF
{
- \if_int_odd:w \l_regex_build_mode_int
- \exp_after:wN \use_i:nn
+ \if_int_odd:w \l_regex_mode_int
+ \exp_after:wN \use_ii:nn
\else:
- \if_int_compare:w \l_regex_build_mode_int > \c_zero
+ \if_int_compare:w \l_regex_mode_int < \c_zero
\exp_after:wN \exp_after:wN \exp_after:wN \use_i:nn
\else:
\exp_after:wN \exp_after:wN \exp_after:wN \use_ii:nn
\fi:
\fi:
}
-\cs_new_protected_nopar:Npn \regex_build_new_state:
+\cs_new_nopar:Npn \regex_if_in_class_or_catcode:TF
{
- \tex_toks:D \l_regex_max_state_int { \s_stop }
- \int_set_eq:NN \l_regex_left_state_int \l_regex_right_state_int
- \int_set_eq:NN \l_regex_right_state_int \l_regex_max_state_int
- \int_incr:N \l_regex_max_state_int
+ \if_int_odd:w \l_regex_mode_int
+ \exp_after:wN \use_i:nn
+ \else:
+ \if_int_compare:w \l_regex_mode_int > \c_zero
+ \exp_after:wN \exp_after:wN \exp_after:wN \use_i:nn
+ \else:
+ \exp_after:wN \exp_after:wN \exp_after:wN \use_ii:nn
+ \fi:
+ \fi:
}
-\cs_new_protected:Npn \regex_build_transition:NN #1#2
+\cs_new_nopar:Npn \regex_if_within_catcode:TF
{
- \regex_build_new_state:
- \regex_toks_put_right:Nx \l_regex_left_state_int
- { #1 { \int_eval:n { #2 - \l_regex_left_state_int } } }
+ \if_int_compare:w \l_regex_mode_int > \c_zero
+ \exp_after:wN \use_i:nn
+ \else:
+ \exp_after:wN \use_ii:nn
+ \fi:
}
-\cs_new_protected:Npn \regex_build_transitions:NNNN #1#2#3#4
+\cs_new_protected:Npn \regex_chk_c_allowed:T
{
- \regex_build_new_state:
- \regex_toks_put_right:Nx \l_regex_left_state_int
- {
- #1 { \int_eval:n { #2 - \l_regex_left_state_int } }
- #3 { \int_eval:n { #4 - \l_regex_left_state_int } }
- }
+ \if_num:w \l_regex_mode_int = \c_zero
+ \exp_after:wN \use:n
+ \else:
+ \if_num:w \l_regex_mode_int = \c_three
+ \exp_after:wN \exp_after:wN \exp_after:wN \use:n
+ \else:
+ \msg_kernel_error:nn { regex } { c-bad-mode }
+ \exp_after:wN \exp_after:wN \exp_after:wN \use_none:n
+ \fi:
+ \fi:
}
-\cs_new_protected_nopar:Npn \regex_build:w
+\cs_new_protected:Npn \regex_mode_quit_c:
{
- \int_set_eq:NN \l_regex_catcodes_default_int \c_regex_catcodes_all_int
- \int_set_eq:NN \l_regex_catcodes_int \l_regex_catcodes_default_int
- \int_set_eq:NN \l_regex_capturing_group_int \c_zero
- \seq_clear:N \l_regex_capturing_group_seq
- \tl_clear:N \l_regex_tests_tl
- \bool_set_true:N \l_regex_tests_bool
- \int_zero:N \l_regex_max_state_int
- \regex_build_new_state:
+ \if_num:w \l_regex_mode_int = \c_two
+ \l_regex_mode_int = \c_zero
+ \else:
+ \if_num:w \l_regex_mode_int = \c_six
+ \l_regex_mode_int = \c_three
+ \fi:
+ \fi:
}
-\cs_new_protected_nopar:Npn \regex_build_end:
+\cs_new_protected_nopar:Npn \regex_compile:w
{
- \regex_build_exit_class:
- \regex_build_exit_groups:
- \regex_toks_put_right:Nx \l_regex_right_state_int
- { \regex_action_success: }
- \int_incr:N \l_regex_capturing_group_int
+ \tl_set_build_x:Nw \l_regex_internal_regex
+ \int_zero:N \l_regex_group_level_int
+ \int_set_eq:NN \l_regex_default_catcodes_int \c_regex_all_catcodes_int
+ \int_set_eq:NN \l_regex_catcodes_int \l_regex_default_catcodes_int
+ \cs_set_nopar:Npn \regex_item_equal:n { \regex_item_caseful_equal:n }
+ \cs_set_nopar:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
+ \tl_build_one:n { \regex_branch:n { \if_false: } \fi: }
}
-\cs_new_protected_nopar:Npn \regex_build_exit_class:
+\cs_new_protected_nopar:Npn \regex_compile_end:
{
- \regex_build_if_in_class:TF
- {
- \msg_kernel_error:nn { regex } { missing-rbrack }
- \use:c { regex_build_]: }
- }
- { }
- }
-\cs_new_protected_nopar:Npn \regex_build_exit_groups:
- {
- \seq_if_empty:NF \l_regex_capturing_group_seq
- {
+ \regex_if_in_class:TF
+ {
+ \msg_kernel_error:nn { regex } { missing-rbrack }
+ \use:c { regex_compile_]: }
+ \prg_do_nothing: \prg_do_nothing:
+ }
+ { }
+ \if_num:w \l_regex_group_level_int > \c_zero
\msg_kernel_error:nnx { regex } { missing-rparen }
- { \seq_length:N \l_regex_capturing_group_seq }
+ { \int_use:N \l_regex_group_level_int }
\prg_replicate:nn
- { \seq_length:N \l_regex_capturing_group_seq }
- { \regex_build_close_aux: \regex_build_group_: }
- }
- }
-\cs_new_protected:Npn \regex_build:n #1
- {
- \regex_build:w
- \int_set_eq:NN \l_regex_build_mode_int \c_zero
- \regex_build_new_state:
- \regex_toks_put_right:Nx \l_regex_left_state_int
- { \regex_action_start_wildcard: }
- \regex_build_open_aux:
- \regex_escape_use:nnnn
+ { \l_regex_group_level_int }
{
- \regex_char_if_special:NTF ##1
- \regex_build_special:N \regex_build_raw:N ##1
- }
- {
- \regex_char_if_alphanumeric:NTF ##1
- \regex_build_escaped:N \regex_build_raw:N ##1
+ \tl_build_one:n
+ {
+ \if_false: { \fi: }
+ \if_false: { \fi: } { 1 } { 0 } \c_true_bool
+ }
+ \tl_build_end:
+ \tl_build_one:o \l_regex_internal_regex
}
- { \regex_build_raw:N ##1 }
- { #1 }
- \prg_do_nothing: \prg_do_nothing:
- \prg_do_nothing: \prg_do_nothing:
- \int_compare:nNnT \l_regex_build_mode_int < \c_zero
+ \fi:
+ \tl_build_one:n { \if_false: { \fi: } }
+ \tl_build_end:
+ }
+\cs_new_protected:Npn \regex_compile:n #1
+ {
+ \regex_compile:w
+ \int_set:Nn \tex_escapechar:D { 92 }
+ \int_set_eq:NN \l_regex_mode_int \c_zero
+ \regex_escape_use:nnnn
+ {
+ \regex_char_if_special:NTF ##1
+ \regex_compile_special:N \regex_compile_raw:N ##1
+ }
+ {
+ \regex_char_if_alphanumeric:NTF ##1
+ \regex_compile_escaped:N \regex_compile_raw:N ##1
+ }
+ { \regex_compile_raw:N ##1 }
+ { #1 }
+ \prg_do_nothing: \prg_do_nothing:
+ \prg_do_nothing: \prg_do_nothing:
+ \int_compare:nNnT \l_regex_mode_int < \c_zero
{
\msg_kernel_error:nn { regex } { c-missing-rbrace }
- \exp_after:wN \regex_build_special:N \c_rbrace_str
+ \regex_compile_end:
+ \regex_compile_one:x
+ { \regex_item_cs:n { \exp_not:o \l_regex_internal_regex } }
+ \prg_do_nothing: \prg_do_nothing:
+ \prg_do_nothing: \prg_do_nothing:
}
- \seq_put_right:Nn \l_regex_capturing_group_seq {0}
- \regex_build_close_aux: \regex_build_group_:
- \regex_build_end:
+ \regex_compile_end:
}
-\cs_new_protected:Npn \regex_build_special:N #1
+\cs_new_protected:Npn \regex_compile_special:N #1
{
- \cs_if_exist_use:cF { regex_build_#1: }
- { \regex_build_raw:N #1 }
+ \cs_if_exist_use:cF { regex_compile_#1: }
+ { \regex_compile_raw:N #1 }
}
-\cs_new_protected:Npn \regex_build_escaped:N #1
+\cs_new_protected:Npn \regex_compile_escaped:N #1
{
- \cs_if_exist_use:cF { regex_build_/#1: }
- { \regex_build_raw:N #1 }
+ \cs_if_exist_use:cF { regex_compile_/#1: }
+ { \regex_compile_raw:N #1 }
}
-\cs_new_protected:Npn \regex_build_one:n #1
- { \regex_build_one:x { \exp_not:n {#1} } }
-\cs_new_protected:Npn \regex_build_one:x #1
+\cs_new_protected:Npn \regex_compile_one:x #1
{
- \tl_put_right:Nx \l_regex_tests_tl
+ \regex_mode_quit_c:
+ \regex_if_in_class:TF { }
{
- \if_num:w \l_regex_catcodes_int < \c_regex_catcodes_all_int
+ \tl_build_one:n
+ { \regex_class:NnnnN \c_true_bool { \if_false: } \fi: }
+ }
+ \tl_build_one:x
+ {
+ \if_num:w \l_regex_catcodes_int < \c_regex_all_catcodes_int
\regex_item_catcode:nT { \int_use:N \l_regex_catcodes_int }
+ { \exp_not:N \exp_not:n {#1} }
\else:
- \exp_after:wN \use:n
+ \exp_not:N \exp_not:n {#1}
\fi:
- {#1}
}
- \int_set_eq:NN \l_regex_catcodes_int \l_regex_catcodes_default_int
- \if_num:w \l_regex_build_mode_int = \c_two
- \l_regex_build_mode_int = \c_zero
- \else:
- \if_num:w \l_regex_build_mode_int = \c_six
- \l_regex_build_mode_int = \c_three
- \fi:
- \fi:
- \if_int_odd:w \l_regex_build_mode_int \else:
- \exp_after:wN \regex_build_one_quantifier:
- \fi:
+ \int_set_eq:NN \l_regex_catcodes_int \l_regex_default_catcodes_int
+ \regex_if_in_class:TF { } { \regex_compile_quantifier:w }
}
-\cs_new:Npn \regex_tests_action_cost:n #1
+\cs_new_protected:Npn \regex_compile_abort_tokens:n #1
{
- \exp_not:o \l_regex_tests_tl
- \bool_if:NTF \l_regex_tests_bool
- { \regex_break_point:TF { \regex_action_cost:n {#1} } { } }
- { \regex_break_point:TF { } { \regex_action_cost:n {#1} } }
+ \use:x
+ {
+ \exp_args:No \tl_map_function:nN { \tl_to_str:n {#1} }
+ \regex_compile_raw:N
+ }
}
-\cs_new_protected:Npn \regex_build_raw_error:N #1
+\cs_generate_variant:Nn \regex_compile_abort_tokens:n { x }
+\cs_new_protected:Npn \regex_compile_quantifier:w #1#2
{
- \if_int_odd:w \l_regex_build_mode_int
- \msg_kernel_error:nnx { regex } { class-bad-escape } {#1}
- \else:
- \msg_kernel_error:nnx { regex } { catcode-bad-escape } {#1}
- \fi:
- \regex_build_raw:N #1
+ \token_if_eq_meaning:NNTF #1 \regex_compile_special:N
+ {
+ \cs_if_exist_use:cF { regex_compile_quantifier_#2:w }
+ { \regex_compile_quantifier_none: #1 #2 }
+ }
+ { \regex_compile_quantifier_none: #1 #2 }
}
-\cs_new_protected:Npn \regex_build_raw:N #1#2#3
+\cs_new_protected:Npn \regex_compile_quantifier_none:
+ { \tl_build_one:n { \if_false: { \fi: } { 1 } { 0 } \c_false_bool } }
+\cs_new_protected:Npn \regex_compile_quantifier_abort:xNN #1#2#3
{
- \regex_build_if_in_class:TF
- { \str_if_eq:nnTF {#2#3} { \regex_build_special:N - } }
- { \use_ii:nn }
- { \regex_class_range:Nw #1 }
+ \regex_compile_quantifier_none:
+ \msg_kernel_warning:nnxx { regex } { invalid-quantifier } {#1} {#3}
+ \regex_compile_abort_tokens:x {#1}
+ #2 #3
+ }
+\cs_new_protected:Npn \regex_compile_quantifier_lazyness:nnNN #1#2#3#4
+ {
+ \str_if_eq:nnTF { #3 #4 } { \regex_compile_special:N ? }
+ { \tl_build_one:n { \if_false: { \fi: } { #1 } { #2 } \c_true_bool } }
{
- \regex_build_one:x { \regex_item_equal:n { \int_value:w `#1 ~ } }
- #2 #3
+ \tl_build_one:n { \if_false: { \fi: } { #1 } { #2 } \c_false_bool }
+ #3 #4
}
}
-\cs_new_protected:Npn \regex_class_range:Nw #1#2#3
+\cs_new_protected_nopar:cpn { regex_compile_quantifier_?:w }
+ { \regex_compile_quantifier_lazyness:nnNN { 0 } { 1 } }
+\cs_new_protected_nopar:cpn { regex_compile_quantifier_*:w }
+ { \regex_compile_quantifier_lazyness:nnNN { 0 } { -1 } }
+\cs_new_protected_nopar:cpn { regex_compile_quantifier_+:w }
+ { \regex_compile_quantifier_lazyness:nnNN { 1 } { -1 } }
+\cs_new_protected:cpn { regex_compile_quantifier_ \c_lbrace_str :w }
{
- \token_if_eq_meaning:NNTF #2 \regex_build_escaped:N % [
- { \use_i:nn } { \str_if_eq:nnTF { #2#3 } { \regex_build_special:N ] } }
+ \regex_get_digits:NTFw \l_regex_internal_a_int
+ { \regex_compile_quantifier_braced_i:w }
+ { \regex_compile_quantifier_abort:xNN { \c_lbrace_str } }
+ }
+\cs_new_protected:Npn \regex_compile_quantifier_braced_i:w #1#2
+ {
+ \prg_case_str:xxn { #1 #2 }
{
- \msg_kernel_warning:nnxx { regex } { range-missing-end } % [
- {#1} { \token_if_eq_charcode:NNF #3 ] { \c_backslash_str } #3 }
- \tl_put_right:Nx \l_regex_tests_tl
+ { \regex_compile_special:N \c_rbrace_str }
{
- \regex_item_equal:n { \int_value:w `#1 ~ }
- \regex_item_equal:n { \int_value:w `- ~ }
+ \exp_args:No \regex_compile_quantifier_lazyness:nnNN
+ { \int_use:N \l_regex_internal_a_int } { 0 }
+ }
+ { \regex_compile_special:N , }
+ {
+ \regex_get_digits:NTFw \l_regex_internal_b_int
+ { \regex_compile_quantifier_braced_iii:w }
+ { \regex_compile_quantifier_braced_ii:w }
+ }
+ }
+ {
+ \regex_compile_quantifier_abort:xNN
+ { \c_lbrace_str \int_use:N \l_regex_internal_a_int }
+ #1 #2
+ }
+ }
+\cs_new_protected:Npn \regex_compile_quantifier_braced_ii:w #1#2
+ {
+ \str_if_eq:xxTF
+ { #1 #2 } { \regex_compile_special:N \c_rbrace_str }
+ {
+ \exp_args:No \regex_compile_quantifier_lazyness:nnNN
+ { \int_use:N \l_regex_internal_a_int } { -1 }
+ }
+ {
+ \regex_compile_quantifier_abort:xNN
+ { \c_lbrace_str \int_use:N \l_regex_internal_a_int , }
+ #1 #2
+ }
+ }
+\cs_new_protected:Npn \regex_compile_quantifier_braced_iii:w #1#2
+ {
+ \str_if_eq:xxTF
+ { #1 #2 } { \regex_compile_special:N \c_rbrace_str }
+ {
+ \if_num:w \l_regex_internal_a_int > \l_regex_internal_b_int
+ \msg_kernel_error:nnxx { regex } { backwards-quantifier }
+ { \int_use:N \l_regex_internal_a_int }
+ { \int_use:N \l_regex_internal_b_int }
+ \int_zero:N \l_regex_internal_b_int
+ \else:
+ \int_sub:Nn \l_regex_internal_b_int \l_regex_internal_a_int
+ \fi:
+ \exp_args:Noo \regex_compile_quantifier_lazyness:nnNN
+ { \int_use:N \l_regex_internal_a_int }
+ { \int_use:N \l_regex_internal_b_int }
+ }
+ {
+ \regex_compile_quantifier_abort:xNN
+ {
+ \c_lbrace_str
+ \int_use:N \l_regex_internal_a_int ,
+ \int_use:N \l_regex_internal_b_int
+ }
+ #1 #2
+ }
+ }
+\cs_new_protected:Npn \regex_compile_raw_error:N #1
+ {
+ \msg_kernel_error:nnx { regex } { bad-escape } {#1}
+ \regex_compile_raw:N #1
+ }
+\cs_new_protected:Npn \regex_compile_raw:N #1#2#3
+ {
+ \regex_if_in_class:TF
+ {
+ \str_if_eq:nnTF {#2#3} { \regex_compile_special:N - }
+ { \regex_compile_range:Nw #1 }
+ {
+ \regex_compile_one:x
+ { \regex_item_equal:n { \int_value:w `#1 ~ } }
+ #2 #3
}
- #2#3
}
{
+ \regex_compile_one:x
+ { \regex_item_equal:n { \int_value:w `#1 ~ } }
+ #2 #3
+ }
+ }
+\prg_new_protected_conditional:Npnn \regex_if_end_range:NN #1#2 { TF }
+ {
+ \if_meaning:w \regex_compile_raw:N #1
+ \prg_return_true:
+ \else:
+ \if_meaning:w \regex_compile_special:N #1
+ \if_charcode:w ] #2
+ \prg_return_false:
+ \else:
+ \prg_return_true:
+ \fi:
+ \else:
+ \prg_return_false:
+ \fi:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_compile_range:Nw #1#2#3
+ {
+ \regex_if_end_range:NNTF #2 #3
+ {
\if_num:w `#1 > `#3 \exp_stop_f:
\msg_kernel_error:nnxx { regex } { range-backwards } {#1} {#3}
\else:
- \tl_put_right:Nx \l_regex_tests_tl
+ \tl_build_one:x
{
\if_num:w `#1 = `#3 \exp_stop_f:
\regex_item_equal:n
@@ -756,1088 +822,1125 @@
}
\fi:
}
- }
-\cs_new_protected_nopar:cpx { regex_build_.: }
- {
- \exp_not:N \regex_build_if_in_class:TF
- { \regex_build_raw:N . }
- { \regex_build_one:n \exp_not:c { c_regex_._tl } }
- }
-\tl_map_inline:nn { dDhHsSvVwWN }
- {
- \cs_new_protected_nopar:cpx { regex_build_/#1: }
- { \regex_build_one:n \exp_not:c { c_regex_#1_tl } }
- }
-\cs_new_protected:Npn \regex_build_simple_assertion:nn #1#2
- {
- \regex_build_if_assertions_forbidden:TF {#1}
{
- \regex_build_new_state:
- \regex_toks_put_right:Nx \l_regex_left_state_int
+ \msg_kernel_warning:nnxx { regex } { range-missing-end }
+ {#1} { \c_backslash_str #3 }
+ \tl_build_one:x
{
- \exp_not:n {#2}
- {
- \regex_action_free:n
- {
- \int_eval:n
- { \l_regex_right_state_int - \l_regex_left_state_int }
- }
- }
+ \regex_item_equal:n { \int_value:w `#1 ~ }
+ \regex_item_equal:n { \int_value:w `- ~ }
}
- %^^A todo: add \regex_assertion_quantifier:
+ #2#3
}
}
-\cs_new_protected_nopar:cpn { regex_build_^: }
- {
- \regex_build_simple_assertion:nn { \regex_build_raw:N ^ }
- { \int_compare:nNnT \l_regex_min_index_int = \l_regex_current_index_int }
- }
-\cs_new_protected_nopar:cpn { regex_build_/A: }
+\cs_new_protected_nopar:cpx { regex_compile_.: }
{
- \regex_build_simple_assertion:nn { \regex_build_raw_error:N A }
- { \int_compare:nNnT \l_regex_min_index_int = \l_regex_current_index_int }
+ \exp_not:N \regex_if_in_class:TF
+ { \regex_compile_raw:N . }
+ { \regex_compile_one:x \exp_not:c { regex_prop_.: } }
}
-\cs_new_protected_nopar:cpn { regex_build_/G: }
+\cs_new_protected_nopar:cpn { regex_prop_.: }
{
- \regex_build_simple_assertion:nn { \regex_build_raw_error:N G }
- { \int_compare:nNnT \l_regex_start_index_int = \l_regex_current_index_int }
+ \if_num:w \l_regex_current_char_int > - \c_two
+ \exp_after:wN \regex_break_true:w
+ \fi:
}
-\group_begin:
- \char_set_catcode_other:N \$
- \cs_new_protected_nopar:cpn { regex_build_$: } % $
- {
- \regex_build_simple_assertion:nn { \regex_build_raw:N $ } % $
- { \int_compare:nNnT \l_regex_current_char_int < \c_minus_one }
- }
-\group_end:
-\cs_new_protected_nopar:cpn { regex_build_/Z: }
+\cs_set_protected:Npn \regex_tmp:w #1#2
{
- \regex_build_simple_assertion:nn { \regex_build_raw_error:N Z }
- { \int_compare:nNnT \l_regex_current_char_int < \c_minus_one }
+ \cs_new_protected_nopar:cpx { regex_compile_/#1: }
+ { \regex_compile_one:x \exp_not:c { regex_prop_#1: } }
+ \cs_new_protected_nopar:cpx { regex_compile_/#2: }
+ {
+ \regex_compile_one:x
+ { \regex_item_reverse:n \exp_not:c { regex_prop_#1: } }
+ }
}
-\cs_new_protected_nopar:cpn { regex_build_/z: }
+\regex_tmp:w d D
+\regex_tmp:w h H
+\regex_tmp:w s S
+\regex_tmp:w v V
+\regex_tmp:w w W
+\cs_new_protected_nopar:cpn { regex_compile_/N: }
+ { \regex_compile_one:x \regex_prop_N: }
+\cs_new_protected:Npn \regex_compile_anchor:NF #1#2
{
- \regex_build_simple_assertion:nn { \regex_build_raw_error:N z }
- { \int_compare:nNnT \l_regex_current_char_int < \c_minus_one }
+ \regex_if_in_class_or_catcode:TF {#2}
+ {
+ \tl_build_one:n
+ { \regex_assertion:Nn \c_true_bool { \regex_anchor:N #1 } }
+ }
}
-\cs_new_protected_nopar:cpn { regex_build_/b: }
+\cs_set_protected:Npn \regex_tmp:w #1#2
{
- \regex_build_simple_assertion:nn { \regex_build_raw_error:N b }
- { \regex_if_word_boundary:T }
+ \cs_new_protected_nopar:cpn { regex_compile_/#1: }
+ { \regex_compile_anchor:NF #2 { \regex_compile_raw_error:N #1 } }
}
-\cs_new_protected_nopar:cpn { regex_build_/B: }
+\regex_tmp:w A \l_regex_min_pos_int
+\regex_tmp:w G \l_regex_start_pos_int
+\regex_tmp:w Z \l_regex_max_pos_int
+\regex_tmp:w z \l_regex_max_pos_int
+\cs_set_protected:Npn \regex_tmp:w #1#2
{
- \regex_build_simple_assertion:nn { \regex_build_raw_error:N B }
- { \regex_if_word_boundary:TF { } }
+ \cs_new_protected_nopar:cpn { regex_compile_#1: }
+ { \regex_compile_anchor:NF #2 { \regex_compile_raw:N #1 } }
}
-\cs_new_protected_nopar:Npn \regex_if_word_boundary:TF
+\exp_args:Nx \regex_tmp:w { \iow_char:N \^ } \l_regex_min_pos_int
+\exp_args:Nx \regex_tmp:w { \iow_char:N \$ } \l_regex_max_pos_int
+\cs_new_protected_nopar:cpn { regex_compile_/b: }
{
- \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 { -2 } }
- { \group_end: \c_regex_w_tl }
- \regex_break_point:TF
+ \regex_if_in_class_or_catcode:TF
+ { \regex_compile_raw_error:N b }
+ {
+ \tl_build_one:n
+ { \regex_assertion:Nn \c_true_bool { \regex_b_test: } }
+ }
}
-\cs_new_protected_nopar:Npn \regex_if_word_boundary:T
- { \regex_if_word_boundary:TF \use:n \use_none:n }
-\cs_new_protected_nopar:cpn { regex_build_[: }
+\cs_new_protected_nopar:cpn { regex_compile_/B: }
{
- \regex_build_if_in_class:TF
- { \regex_build_raw:N [ }
- { \regex_class_first:NNNN }
+ \regex_if_in_class_or_catcode:TF
+ { \regex_compile_raw_error:N B }
+ {
+ \tl_build_one:n
+ { \regex_assertion:Nn \c_false_bool { \regex_b_test: } }
+ }
}
-\cs_new_protected:cpn { regex_build_]: }
+\cs_new_protected:cpn { regex_compile_]: }
{
- \regex_build_if_in_class:TF
+ \regex_if_in_class:TF
{
- \if_num:w \l_regex_build_mode_int > \c_sixteen
- \tl_set:Nx \l_regex_tests_tl
- {
- \exp_not:o \l_regex_tests_saved_tl
- \if_num:w \l_regex_catcodes_saved_int < \c_regex_catcodes_all_int
- \regex_item_catcode:nT
- { \int_use:N \l_regex_catcodes_saved_int }
- \else:
- \exp_after:wN \use:n
- \fi:
- {
- \exp_not:o \l_regex_tests_tl
- \bool_if:NF \l_regex_tests_bool
- { \regex_break_point:TF { } \regex_break_true:w }
- }
- }
- \bool_set_eq:NN \l_regex_tests_bool \l_regex_tests_saved_bool
+ \if_num:w \l_regex_mode_int > \c_sixteen
+ \tl_build_one:n { \if_false: { \fi: } }
\fi:
- \tex_advance:D \l_regex_build_mode_int - \c_fifteen
- \tex_divide:D \l_regex_build_mode_int \c_thirteen
- \if_int_odd:w \l_regex_build_mode_int \else:
- \exp_after:wN \regex_build_one_quantifier:
+ \tex_advance:D \l_regex_mode_int - \c_fifteen
+ \tex_divide:D \l_regex_mode_int \c_thirteen
+ \if_int_odd:w \l_regex_mode_int \else:
+ \exp_after:wN \regex_compile_quantifier:w
\fi:
}
- { \regex_build_raw:N ] }
+ { \regex_compile_raw:N ] }
}
-\cs_new_protected:Npn \regex_class_first:NNNN #1#2#3#4
+\cs_new_protected_nopar:cpn { regex_compile_[: }
{
- \l_regex_build_mode_int = \int_value:w \l_regex_build_mode_int 3 ~ %
- \if_num:w \l_regex_build_mode_int > \c_sixteen
- \tl_set_eq:NN \l_regex_tests_saved_tl \l_regex_tests_tl
- \bool_set_eq:NN \l_regex_tests_saved_bool \l_regex_tests_bool
- \int_set_eq:NN \l_regex_catcodes_saved_int \l_regex_catcodes_int
- \int_set_eq:NN \l_regex_catcodes_int \c_regex_catcodes_all_int
- \fi:
- \token_if_eq_meaning:NNTF #1 \regex_build_special:N
+ \regex_if_in_class:TF
+ { \regex_compile_class_posix_test:w }
{
- \token_if_eq_charcode:NNTF #2 ^
+ \regex_if_within_catcode:TF
{
- \bool_set_false:N \l_regex_tests_bool % [
- \str_if_eq:nnTF {#3#4} { \regex_build_special:N ] }
- { \regex_build_raw:N }
- }
- { % [
- \token_if_eq_charcode:NNTF #2 ]
- { \regex_build_raw:N #2 }
- { #1 #2 }
+ \exp_after:wN \regex_compile_class_catcode:w
+ \int_use:N \l_regex_catcodes_int ;
}
+ { \regex_compile_class_normal:w }
}
- { #1 #2 }
- #3 #4
- }
-\cs_new_protected:cpn { regex_build_/c: }
- {
- \if_case:w \l_regex_build_mode_int
- \exp_after:wN \regex_build_c_aux:wNN
- \or: \or: \or: \exp_after:wN \regex_build_c_aux:wNN
- \fi:
- \msg_kernel_error:nn { regex } { c-bad-mode }
- \s_stop
}
-\cs_new_protected:Npn \regex_build_c_aux:wNN #1 \s_stop #2#3
+\cs_new_protected_nopar:Npn \regex_compile_class_normal:w
{
- \token_if_eq_meaning:NNTF #2 \regex_build_raw:N
- {
- \cs_if_exist:cTF { c_regex_catcode_#3_int }
- {
- \int_set_eq:Nc \l_regex_catcodes_int { c_regex_catcode_#3_int }
- \l_regex_build_mode_int
- = \if_case:w \l_regex_build_mode_int \c_two \else: \c_six \fi:
- }
- }
- { \cs_if_exist_use:cF { regex_build_c_#3: } }
- {
- \msg_kernel_error:nnx { regex } { c-missing-category } {#3}
- #2 #3
- }
+ \regex_compile_class:TFNN
+ { \regex_class:NnnnN \c_true_bool }
+ { \regex_class:NnnnN \c_false_bool }
}
-\cs_new_protected:cpn { regex_build_c_ \c_lbrace_str : }
+\cs_new_protected:Npn \regex_compile_class_catcode:w #1;
{
- \group_begin:
- \l_regex_build_mode_int
- = - \if_case:w \l_regex_build_mode_int \c_two \else: \c_six \fi:
- \regex_build:w
+ \if_int_compare:w \l_regex_mode_int = \c_two
+ \tl_build_one:n
+ { \regex_class:NnnnN \c_true_bool { \if_false: } \fi: }
+ \fi:
+ \int_set_eq:NN \l_regex_catcodes_int \l_regex_default_catcodes_int
+ \regex_compile_class:TFNN
+ { \regex_item_catcode:nT {#1} }
+ { \regex_item_catcode_reverse:nT {#1} }
}
-\cs_new_protected:cpn { regex_build_c_[: } #1#2
+\cs_new_protected:Npn \regex_compile_class:TFNN #1#2#3#4
{
- \int_zero:N \l_regex_catcodes_int
- \str_if_eq:nnTF { #1 #2 } { \regex_build_special:N ^ }
+ \l_regex_mode_int = \int_value:w \l_regex_mode_int 3 \exp_stop_f:
+ \str_if_eq:nnTF { #3 #4 } { \regex_compile_special:N ^ }
{
- \bool_set_false:N \l_regex_catcodes_bool
- \regex_build_c_lbrack_loop:NN
+ \tl_build_one:n { #2 { \if_false: } \fi: }
+ \regex_compile_class_ii:NN
}
{
- \bool_set_true:N \l_regex_catcodes_bool
- \regex_build_c_lbrack_loop:NN
- #1#2
+ \tl_build_one:n { #1 { \if_false: } \fi: }
+ \regex_compile_class_ii:NN #3 #4
}
}
-\cs_new_protected:Npn \regex_build_c_lbrack_loop:NN #1#2
+\cs_new_protected:Npn \regex_compile_class_ii:NN #1#2
{
- \token_if_eq_meaning:NNTF #1 \regex_build_raw:N
+ \token_if_eq_charcode:NNTF #2 ]
+ { \regex_compile_raw:N #2 }
+ { #1 #2 }
+ }
+\cs_new_protected:Npn \regex_compile_class_posix_test:w #1#2
+ {
+ \token_if_eq_meaning:NNT \regex_compile_special:N #1
{
- \cs_if_exist:cTF { c_regex_catcode_#2_int }
+ \prg_case_str:nnn { #2 }
{
- \exp_args:Nc \regex_build_c_lbrack_add:N
- { c_regex_catcode_#2_int }
- \regex_build_c_lbrack_loop:NN
+ : { \regex_compile_class_posix:NNNNw }
+ = { \msg_kernel_warning:nnx { regex } { posix-unsupported } { = } }
+ . { \msg_kernel_warning:nnx { regex } { posix-unsupported } { . } }
}
+ { }
}
- { % [
- \token_if_eq_charcode:NNTF #2 ]
- { \regex_build_c_lbrack_end: }
- }
- {
- \msg_kernel_error:nnx { regex } { c-missing-rbrack } {#2}
- \regex_build_c_lbrack_end:
- }
+ \regex_compile_raw:N [ #1 #2
}
-\cs_new_protected_nopar:Npn \regex_build_c_lbrack_end:
+\cs_new_protected:Npn \regex_compile_class_posix:NNNNw #1#2#3#4#5#6
{
- \l_regex_build_mode_int
- = \if_case:w \l_regex_build_mode_int \c_two \else: \c_six \fi:
- \if_meaning:w \c_false_bool \l_regex_catcodes_bool
- \int_set:Nn \l_regex_catcodes_int
- { \c_regex_catcodes_all_int - \l_regex_catcodes_int }
- \fi:
+ \str_if_eq:nnTF { #5 #6 } { \regex_compile_special:N ^ }
+ {
+ \bool_set_false:N \l_regex_internal_bool
+ \tl_set:Nx \l_regex_internal_a_tl { \if_false: } \fi:
+ \regex_compile_class_posix_loop:w
+ }
+ {
+ \bool_set_true:N \l_regex_internal_bool
+ \tl_set:Nx \l_regex_internal_a_tl { \if_false: } \fi:
+ \regex_compile_class_posix_loop:w #5 #6
+ }
}
-\cs_new_protected:Npn \regex_build_c_lbrack_add:N #1
+\cs_new:Npn \regex_compile_class_posix_loop:w #1#2
{
- \if_int_odd:w \int_eval:w \l_regex_catcodes_int / #1 \int_eval_end:
- \else:
- \tex_advance:D \l_regex_catcodes_int #1
- \fi:
+ \token_if_eq_meaning:NNTF \regex_compile_raw:N #1
+ { #2 \regex_compile_class_posix_loop:w }
+ { \if_false: { \fi: } \regex_compile_class_posix_end:w #1 #2 }
}
-\cs_new_protected:cpn { regex_build_ \c_rbrace_str : }
+\cs_new_protected:Npn \regex_compile_class_posix_end:w #1#2#3#4
{
- \int_compare:nNnTF \l_regex_build_mode_int < \c_zero
+ \str_if_eq:nnTF { #1 #2 #3 #4 }
+ { \regex_compile_special:N : \regex_compile_special:N ] }
{
- \regex_build_exit_class:
- \regex_build_exit_groups:
- \regex_build_escaped:N Z
- \regex_build_end:
- \use:x
+ \cs_if_exist:cTF { regex_posix_ \l_regex_internal_a_tl : }
{
- \group_end:
- \regex_build_one:n
- {
- \regex_item_cs:n
- { \regex_set_aux:N \l_regex_internal_regex }
- }
+ \regex_compile_one:x
+ {
+ \bool_if:NF \l_regex_internal_bool \regex_item_reverse:n
+ \exp_not:c { regex_posix_ \l_regex_internal_a_tl : }
+ }
}
- }
- { \exp_after:wN \regex_build_raw:N \c_rbrace_str }
- }
-\cs_new_protected:Npn \regex_build_quantifier:w #1#2
- {
- \token_if_eq_meaning:NNTF #1 \regex_build_special:N
- {
- \cs_if_exist_use:cF { regex_build_quantifier_#2:w }
{
- \regex_build_quantifier_end:nn { } { }
- #1 #2
+ \msg_kernel_warning:nnx { regex } { posix-unknown }
+ { \l_regex_internal_a_tl }
+ \regex_compile_abort_tokens:x
+ {
+ [: \bool_if:NF \l_regex_internal_bool { ^ }
+ \l_regex_internal_a_tl :]
+ }
}
}
{
- \regex_build_quantifier_end:nn { } { }
- #1 #2
+ \msg_kernel_error:nnxx { regex } { posix-missing-close }
+ { [: \l_regex_internal_a_tl } { #2 #4 }
+ \regex_compile_abort_tokens:x { [: \l_regex_internal_a_tl }
+ #1 #2 #3 #4
}
}
-\cs_new_protected_nopar:cpn { regex_build_quantifier_?:w }
- { \regex_build_quantifier_aux:nnNN { } { ? } }
-\cs_new_protected_nopar:cpn { regex_build_quantifier_*:w }
- { \regex_build_quantifier_aux:nnNN { } { * } }
-\cs_new_protected_nopar:cpn { regex_build_quantifier_+:w }
- { \regex_build_quantifier_aux:nnNN { } { + } }
-\cs_new_protected:Npn \regex_build_quantifier_aux:nnNN #1#2#3#4
+\cs_new_protected:Npn \regex_compile_group_begin:N #1
{
- \str_if_eq:nnTF { #3 #4 } { \regex_build_special:N ? }
- { \regex_build_quantifier_end:nn { #2 #4 } {#1} }
- {
- \regex_build_quantifier_end:nn { #2 } {#1}
- #3 #4
- }
+ \tl_build_one:n { #1 { \if_false: } \fi: }
+ \regex_mode_quit_c:
+ \tl_set_build:Nw \l_regex_internal_regex
+ \int_set_eq:NN \l_regex_default_catcodes_int \l_regex_catcodes_int
+ \int_incr:N \l_regex_group_level_int
+ \tl_build_one:n { \regex_branch:n { \if_false: } \fi: }
}
-\cs_new_protected_nopar:cpn { regex_build_quantifier_ \c_lbrace_str :w }
- { \regex_get_digits:nw { \regex_build_quantifier_lbrace:n } }
-\cs_new_protected:Npn \regex_build_quantifier_lbrace:n #1
+\cs_new_protected:Npn \regex_compile_group_end:
{
- \tl_if_empty:nTF {#1}
- {
- \regex_build_quantifier_end:nn { } { }
- \exp_after:wN \regex_build_raw:N \c_lbrace_str
- }
- { \regex_build_quantifier_lbrace:nw {#1} }
+ \if_num:w \l_regex_group_level_int > \c_zero
+ \tl_build_one:n { \if_false: { \fi: } }
+ \tl_build_end:
+ \int_set_eq:NN \l_regex_catcodes_int \l_regex_default_catcodes_int
+ \tl_build_one:o \l_regex_internal_regex
+ \exp_after:wN \regex_compile_quantifier:w
+ \else:
+ \msg_kernel_warning:nn { regex } { extra-rparen }
+ \exp_after:wN \regex_compile_raw:N \exp_after:wN )
+ \fi:
+ }
+\cs_new_protected_nopar:cpn { regex_compile_(: }
+ {
+ \regex_if_in_class:TF { \regex_compile_raw:N ( }
+ { \regex_compile_lparen:w }
}
-\cs_new_protected:Npx \regex_build_quantifier_lbrace:nw #1#2#3
+\cs_new_protected:Npn \regex_compile_lparen:w #1#2#3#4
{
- \exp_not:N \prg_case_str:nnn { #2 #3 }
+ \str_if_eq:nnTF { #1 #2 } { \regex_compile_special:N ? }
{
- { \exp_not:N \regex_build_special:N , }
+ \cs_if_exist_use:cF
+ { regex_compile_special_group_\token_to_str:N #4 :w }
{
- \exp_not:N \regex_get_digits:nw
- { \exp_not:N \regex_build_quantifier_lbrace:nnw {#1} }
+ \msg_kernel_warning:nnx { regex } { special-group-unknown }
+ { (? \token_to_str:N #4 }
+ \regex_compile_group_begin:N \regex_group:nnnN
+ \regex_compile_raw:N ? #3 #4
}
- { \exp_not:N \regex_build_special:N \c_rbrace_str }
- { \exp_not:N \regex_build_quantifier_end:nn {n} { {#1} } }
}
{
- \exp_not:N \regex_build_quantifier_end:nn { } { }
- \exp_not:N \regex_build_raw:N \c_lbrace_str #1#2
+ \regex_compile_group_begin:N \regex_group:nnnN
+ #1 #2 #3 #4
}
}
-\cs_new_protected:Npn \regex_build_quantifier_lbrace:nnw #1#2#3#4
+\cs_new_protected_nopar:cpn { regex_compile_|: }
{
- \str_if_eq:xxTF
- { \exp_not:n {#3#4} }
- { \exp_not:N \regex_build_special:N \c_rbrace_str }
+ \regex_if_in_class:TF { \regex_compile_raw:N | }
{
- \tl_if_empty:nTF {#2}
- { \regex_build_quantifier_aux:nnNN { {#1} } { n* } }
- { \regex_build_quantifier_aux:nnNN { {#1} {#2} } { nn } }
+ \tl_build_one:n
+ { \if_false: { \fi: } \regex_branch:n { \if_false: } \fi: }
}
- {
- \regex_build_quantifier_end:nn { } { }
- \use:x
- {
- \exp_args:No \tl_map_function:nN
- { \c_lbrace_str #1 , #2 }
- \regex_build_raw:N
- }
- #3 #4
- }
- }
-\cs_new_protected:Npn \regex_build_quantifier_end:nn #1#2
- {
- \use:c { regex_build_ \l_regex_one_or_group_tl _ #1 : } #2
- \tl_clear:N \l_regex_tests_tl
- \bool_set_true:N \l_regex_tests_bool
}
-\cs_new_protected_nopar:Npn \regex_build_one_quantifier:
+\cs_new_protected_nopar:cpn { regex_compile_): }
{
- \tl_set:Nx \l_regex_one_or_group_tl { one }
- \regex_build_quantifier:w
+ \regex_if_in_class:TF { \regex_compile_raw:N ) }
+ { \regex_compile_group_end: }
}
-\cs_new_protected:Npn \regex_build_one_n: #1
+\cs_new_protected_nopar:cpn { regex_compile_special_group_::w }
+ { \regex_compile_group_begin:N \regex_group_no_capture:nnnN }
+\cs_new_protected_nopar:cpn { regex_compile_special_group_|:w }
+ { \regex_compile_group_begin:N \regex_group_resetting:nnnN }
+\cs_new_protected:Npn \regex_compile_special_group_i:w #1#2
{
- \prg_replicate:nn {#1}
+ \str_if_eq:nnTF { #1 #2 } { \regex_compile_special:N ) }
{
- \regex_build_transition:NN
- \regex_tests_action_cost:n \l_regex_right_state_int
- }
- }
-\cs_new_eq:cN { regex_build_one_n?: } \regex_build_one_n:
-\cs_new_protected_nopar:Npn \regex_build_one_:
- { \regex_build_one_n: \c_one }
-\cs_new_protected:cpn { regex_build_one_n*: } #1
- {
- \int_compare:nNnTF {#1} = \c_zero
- {
- \regex_build_transitions:NNNN
- \regex_tests_action_cost:n \l_regex_left_state_int
- \regex_action_free:n \l_regex_right_state_int
+ \cs_set_nopar:Npn \regex_item_equal:n { \regex_item_caseless_equal:n }
+ \cs_set_nopar:Npn \regex_item_range:nn { \regex_item_caseless_range:nn }
}
{
- \regex_build_one_n: {#1}
- \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
- \regex_build_transitions:NNNN
- \regex_action_free:n \l_regex_internal_a_int
- \regex_action_free:n \l_regex_right_state_int
+ \msg_kernel_warning:nnx { regex } { unknown-option } { (?i #2 }
+ \regex_compile_raw:N (
+ \regex_compile_raw:N ?
+ \regex_compile_raw:N i
+ #1 #2
}
}
-\cs_new_protected:cpn { regex_build_one_n*?: } #1
+\cs_new_protected_nopar:cpn { regex_compile_special_group_-:w } #1#2#3#4
{
- \int_compare:nNnTF {#1} = \c_zero
- {
- \regex_build_transitions:NNNN
- \regex_action_free:n \l_regex_right_state_int
- \regex_tests_action_cost:n \l_regex_left_state_int
- }
+ \str_if_eq:nnTF { #1 #2 #3 #4 }
+ { \regex_compile_raw:N i \regex_compile_special:N ) }
{
- \regex_build_one_n: {#1}
- \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
- \regex_build_transitions:NNNN
- \regex_action_free:n \l_regex_right_state_int
- \regex_action_free:n \l_regex_internal_a_int
+ \cs_set_nopar:Npn \regex_item_equal:n { \regex_item_caseful_equal:n }
+ \cs_set_nopar:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
}
- }
-\cs_new_protected_nopar:cpx { regex_build_one_*: }
- { \exp_not:c { regex_build_one_n*: } \c_zero }
-\cs_new_protected_nopar:cpx { regex_build_one_*?: }
- { \exp_not:c { regex_build_one_n*?: } \c_zero }
-\cs_new_protected_nopar:cpx { regex_build_one_+: }
- { \exp_not:c { regex_build_one_n*: } \c_one }
-\cs_new_protected_nopar:cpx { regex_build_one_+?: }
- { \exp_not:c { regex_build_one_n*?: } \c_one }
-\cs_new_protected_nopar:Npn \regex_build_one_nn:
- {
- \regex_build_one_nn_aux:nnnn { }
{
- \regex_build_transitions:NNNN
- \regex_tests_action_cost:n \l_regex_right_state_int
- \regex_action_free:n \l_regex_internal_a_int
+ \msg_kernel_warning:nnx { regex } { unknown-option } { (?-#2#4 }
+ \regex_compile_raw:N (
+ \regex_compile_raw:N ?
+ \regex_compile_raw:N -
+ #1 #2 #3 #4
}
}
-\cs_new_protected_nopar:cpn { regex_build_one_nn?: }
+\cs_new_protected:cpn { regex_compile_/c: }
+ { \regex_chk_c_allowed:T { \regex_compile_c_test:NN } }
+\cs_new_protected:Npn \regex_compile_c_test:NN #1#2
{
- \regex_build_one_nn_aux:nnnn {?}
+ \token_if_eq_meaning:NNTF #1 \regex_compile_raw:N
{
- \regex_build_transitions:NNNN
- \regex_action_free:n \l_regex_internal_a_int
- \regex_tests_action_cost:n \l_regex_right_state_int
+ \cs_if_exist:cTF { c_regex_catcode_#2_int }
+ {
+ \int_set_eq:Nc \l_regex_catcodes_int { c_regex_catcode_#2_int }
+ \l_regex_mode_int
+ = \if_case:w \l_regex_mode_int \c_two \else: \c_six \fi:
+ }
}
+ { \cs_if_exist_use:cF { regex_compile_c_#2:w } }
+ {
+ \msg_kernel_error:nnx { regex } { c-missing-category } {#2}
+ #1 #2
+ }
}
-\cs_new_protected:Npn \regex_build_one_nn_aux:nnnn #1#2#3#4
+\cs_new_protected:cpn { regex_compile_c_[:w } #1#2
{
- \regex_build_one_n: {#3}
- \int_compare:nNnTF {#3} > {#4}
+ \l_regex_mode_int
+ = \if_case:w \l_regex_mode_int \c_two \else: \c_six \fi:
+ \int_zero:N \l_regex_catcodes_int
+ \str_if_eq:nnTF { #1 #2 } { \regex_compile_special:N ^ }
{
- \msg_kernel_error:nnxxx
- { regex } { quantifier-backwards } {#3} {#4} {#1}
+ \bool_set_false:N \l_regex_catcodes_bool
+ \regex_compile_c_lbrack_loop:NN
}
{
- \int_set:Nn \l_regex_internal_a_int
- { \l_regex_right_state_int + #4 - #3 }
- \prg_replicate:nn { #4 - #3 } { #2 }
+ \bool_set_true:N \l_regex_catcodes_bool
+ \regex_compile_c_lbrack_loop:NN
+ #1 #2
}
}
-\cs_new_protected_nopar:cpn { regex_build_one_?: }
- { \regex_build_one_nn: \c_zero \c_one }
-\cs_new_protected_nopar:cpx { regex_build_one_??: }
- { \exp_not:c { regex_build_one_nn?: } \c_zero \c_one }
-\cs_new_protected:cpn { regex_build_(: } #1#2
+\cs_new_protected:Npn \regex_compile_c_lbrack_loop:NN #1#2
{
- \regex_build_if_in_class:TF
+ \token_if_eq_meaning:NNTF #1 \regex_compile_raw:N
{
- \regex_build_raw:N (
- #1 #2
+ \cs_if_exist:cTF { c_regex_catcode_#2_int }
+ {
+ \exp_args:Nc \regex_compile_c_lbrack_add:N
+ { c_regex_catcode_#2_int }
+ \regex_compile_c_lbrack_loop:NN
+ }
}
{
- \str_if_eq:nnTF { #1 #2 } { \regex_build_special:N ? }
- { \regex_build_special_group:NN }
+ \token_if_eq_charcode:NNTF #2 ]
+ { \regex_compile_c_lbrack_end: }
+ }
{
- \int_incr:N \l_regex_capturing_group_int
- \regex_seq_push_int:NN
- \l_regex_capturing_group_seq \l_regex_capturing_group_int
- \regex_build_open_aux:
+ \msg_kernel_error:nnx { regex } { c-missing-rbrack } {#2}
+ \regex_compile_c_lbrack_end:
#1 #2
}
- }
}
-\cs_new_protected_nopar:Npn \regex_build_open_aux:
+\cs_new_protected:Npn \regex_compile_c_lbrack_add:N #1
{
- \regex_build_new_state:
- \regex_seq_push_int:NN \l_regex_left_state_seq \l_regex_left_state_int
- \regex_seq_push_int:NN \l_regex_right_state_seq \l_regex_right_state_int
- \bool_if:NTF \l_regex_caseless_bool
- { \seq_push:Nn \l_regex_end_group_seq \regex_build_caseless: }
- { \seq_push:Nn \l_regex_end_group_seq \regex_build_caseful: }
- \seq_push:Nn \l_regex_end_alternation_seq { }
- \regex_build_begin_alternation:
+ \if_int_odd:w \int_eval:w \l_regex_catcodes_int / #1 \int_eval_end:
+ \else:
+ \tex_advance:D \l_regex_catcodes_int #1
+ \fi:
}
-\cs_new_protected_nopar:cpn { regex_build_|: }
+\cs_new_protected_nopar:Npn \regex_compile_c_lbrack_end:
{
- \regex_build_if_in_class:TF { \regex_build_raw:N | }
- {
- \regex_build_end_alternation:
- \regex_build_begin_alternation:
- }
+ \if_meaning:w \c_false_bool \l_regex_catcodes_bool
+ \int_set:Nn \l_regex_catcodes_int
+ { \c_regex_all_catcodes_int - \l_regex_catcodes_int }
+ \fi:
}
-\cs_new_protected_nopar:cpn { regex_build_): }
+\cs_new_protected_nopar:cpn { regex_compile_c_ \c_lbrace_str :w }
{
- \regex_build_if_in_class:TF { \regex_build_raw:N ) }
- {
- \seq_if_empty:NTF \l_regex_capturing_group_seq
- { \msg_kernel_error:nn { regex } { extra-rparen } }
- {
- \regex_build_close_aux:
- \regex_build_group_quantifier:
- }
- }
+ \regex_compile:w
+ \regex_disable_submatches:
+ \l_regex_mode_int
+ = - \if_case:w \l_regex_mode_int \c_two \else: \c_six \fi:
}
-\cs_new_protected_nopar:Npn \regex_build_close_aux:
+\cs_new_protected:cpn { regex_compile_ \c_rbrace_str : }
{
- \regex_build_end_alternation:
- \regex_seq_pop_int:NN \l_regex_left_state_seq \l_regex_left_state_int
- \regex_seq_pop_int:NN \l_regex_right_state_seq \l_regex_right_state_int
- \regex_seq_pop_use:N \l_regex_end_group_seq
- \seq_pop:NN \l_regex_end_alternation_seq \l_regex_internal_a_tl
+ \regex_if_in_cs:TF
+ {
+ \regex_compile_end:
+ \regex_compile_one:x
+ { \regex_item_cs:n { \exp_not:o \l_regex_internal_regex } }
+ }
+ { \exp_after:wN \regex_compile_raw:N \c_rbrace_str }
}
-\cs_new_protected_nopar:Npn \regex_build_begin_alternation:
+\cs_new_protected:cpn { regex_compile_/u: } #1#2
{
- \regex_build_new_state:
- \regex_seq_get_int:NN \l_regex_left_state_seq \l_regex_left_state_int
- \regex_toks_put_right:Nx \l_regex_left_state_int
+ \regex_if_in_class_or_catcode:TF
+ { \regex_compile_raw_error:N u #1 #2 }
{
- \regex_action_free:n
+ \str_if_eq:xxTF {#1#2} { \regex_compile_special:N \c_lbrace_str }
{
- \int_eval:n
- { \l_regex_right_state_int - \l_regex_left_state_int }
+ \tl_set:Nx \l_regex_internal_a_tl { \if_false: } \fi:
+ \regex_compile_u_loop:NN
+ }
+ {
+ \msg_kernel_error:nn { regex } { u-missing-lbrace }
+ \regex_compile_raw:N u #1 #2
}
}
}
-\cs_new_protected_nopar:Npn \regex_build_end_alternation:
+\cs_new:Npn \regex_compile_u_loop:NN #1#2
{
- \int_set_eq:NN \l_regex_left_state_int \l_regex_right_state_int
- \regex_seq_get_int:NN \l_regex_right_state_seq \l_regex_right_state_int
- \regex_toks_put_right:Nx \l_regex_left_state_int
+ \token_if_eq_meaning:NNTF #1 \regex_compile_raw:N
+ { #2 \regex_compile_u_loop:NN }
{
- \regex_action_free:n
+ \token_if_eq_meaning:NNTF #1 \regex_compile_special:N
{
- \int_eval:n
- { \l_regex_right_state_int - \l_regex_left_state_int }
+ \exp_after:wN \token_if_eq_charcode:NNTF \c_rbrace_str #2
+ { \if_false: { \fi: } \regex_compile_u_end: }
+ { #2 \regex_compile_u_loop:NN }
+ }
+ {
+ \if_false: { \fi: }
+ \msg_kernel_error:nnx { regex } { u-missing-rbrace } {#2}
+ \regex_compile_u_end:
+ #1 #2
}
}
- \regex_seq_get_use:N \l_regex_end_alternation_seq
}
-\cs_new_protected:Npn \regex_build_special_group:NN #1#2
+\cs_new_protected:Npn \regex_compile_u_end:
+ {
+ \tl_set:Nv \l_regex_internal_a_tl { \l_regex_internal_a_tl }
+ \if_num:w \l_regex_mode_int = \c_zero
+ \regex_compile_u_not_cs:
+ \else:
+ \regex_compile_u_in_cs:
+ \fi:
+ }
+\cs_new_protected:Npn \regex_compile_u_in_cs:
{
- \cs_if_exist_use:cF { regex_build_special_group_\token_to_str:N #2 : }
+ \exp_args:NNo \str_gset_other:Nn \g_regex_internal_tl
+ { \l_regex_internal_a_tl }
+ \tl_build_one:x
{
- \msg_kernel_error:nnx { regex } { special-group-unknown }
- { (? \token_to_str:N #2 } %)
- \regex_build_special:N ( % )
- \regex_build_raw:N ?
- #1 #2
+ \tl_map_function:NN \g_regex_internal_tl
+ \regex_compile_u_in_cs_aux:n
}
}
-\cs_new_protected_nopar:cpn { regex_build_special_group_:: }
+\cs_new:Npn \regex_compile_u_in_cs_aux:n #1
{
- \regex_seq_push_int:NN \l_regex_capturing_group_seq \c_minus_one
- \regex_build_open_aux:
+ \regex_class:NnnnN \c_true_bool
+ { \regex_item_caseful_equal:n { \int_value:w `#1 } }
+ { 1 } { 0 } \c_false_bool
}
-\cs_new_protected_nopar:cpn { regex_build_special_group_|: }
+\cs_new_protected:Npn \regex_compile_u_not_cs:
{
- \regex_seq_push_int:NN \l_regex_capturing_group_seq \c_minus_one
- \regex_build_new_state:
- \regex_seq_push_int:NN \l_regex_left_state_seq \l_regex_left_state_int
- \regex_seq_push_int:NN \l_regex_right_state_seq \l_regex_right_state_int
- \seq_push:Nx \l_regex_end_alternation_seq
+ \exp_args:No \tl_analysis_map_inline:nn { \l_regex_internal_a_tl }
{
- \exp_not:N \int_compare:nNnT
- \l_regex_capturing_group_int
- > \l_regex_capturing_group_max_int
+ \tl_build_one:n
{
- \int_set_eq:NN
- \l_regex_capturing_group_max_int
- \l_regex_capturing_group_int
+ \regex_class:NnnnN \c_true_bool
+ {
+ \if_num:w "##2 = \c_zero
+ \regex_item_exact_cs:c { \exp_after:wN \cs_to_str:N ##1 }
+ \else:
+ \regex_item_exact:nn { \int_value:w "##2 } { ##3 }
+ \fi:
+ }
+ { 1 } { 0 } \c_false_bool
}
- \int_set:Nn \l_regex_capturing_group_int
- { \int_use:N \l_regex_capturing_group_int }
}
- \seq_push:Nx \l_regex_end_group_seq
- {
- \bool_if:NTF \l_regex_caseless_bool
- \regex_build_caseless:
- \regex_build_caseful:
- \int_set_eq:NN
- \l_regex_capturing_group_int
- \l_regex_capturing_group_max_int
- }
- \regex_build_begin_alternation:
}
-\cs_new_protected_nopar:Npn \regex_build_special_group_i:
+\cs_new_protected_nopar:cpn { regex_compile_/K: }
{
- \regex_build_options:NNN +
- \regex_build_raw:N i
+ \int_compare:nNnTF \l_regex_mode_int = \c_zero
+ { \tl_build_one:n { \regex_command_K: } }
+ { \regex_compile_raw_error:N K }
}
-\cs_new_protected_nopar:cpn { regex_build_special_group_-: }
+\cs_new_protected:Npn \regex_show_aux:Nx #1#2
{
- \regex_build_options:NNN -
+ \tl_set_build:Nw \l_regex_internal_a_tl
+ \cs_set_protected_nopar:Npn \regex_branch:n
+ {
+ \seq_pop_right:NN \l_regex_show_prefix_seq \l_regex_internal_a_tl
+ \regex_show_one:n { +-branch }
+ \seq_put_right:No \l_regex_show_prefix_seq \l_regex_internal_a_tl
+ \use:n
+ }
+ \cs_set_protected_nopar:Npn \regex_group:nnnN
+ { \regex_show_group_aux:nnnnN { } }
+ \cs_set_protected_nopar:Npn \regex_group_no_capture:nnnN
+ { \regex_show_group_aux:nnnnN { ~(no~capture) } }
+ \cs_set_protected_nopar:Npn \regex_group_resetting:nnnN
+ { \regex_show_group_aux:nnnnN { ~(resetting) } }
+ \cs_set_eq:NN \regex_class:NnnnN \regex_show_class:NnnnN
+ \cs_set_protected_nopar:Npn \regex_command_K:
+ { \regex_show_one:n { reset~match~start~(\iow_char:N\\K) } }
+ \cs_set_protected:Npn \regex_assertion:Nn ##1##2
+ { \regex_show_one:n { \bool_if:NF ##1 { negative~ } assertion:~##2 } }
+ \cs_set_nopar:Npn \regex_b_test: { word~boundary }
+ \cs_set_eq:NN \regex_anchor:N \regex_show_anchor_to_str:N
+ \cs_set_protected:Npn \regex_item_caseful_equal:n ##1
+ { \regex_show_one:n { char~code~\int_eval:n{##1} } }
+ \cs_set_protected:Npn \regex_item_caseful_range:nn ##1##2
+ { \regex_show_one:n { range~[\int_eval:n{##1}, \int_eval:n{##2}] } }
+ \cs_set_protected:Npn \regex_item_caseless_equal:n ##1
+ { \regex_show_one:n { char~code~\int_eval:n{##1}~(caseless) } }
+ \cs_set_protected:Npn \regex_item_caseless_range:nn ##1##2
+ {
+ \regex_show_one:n
+ { Range~[\int_eval:n{##1}, \int_eval:n{##2}]~(caseless) }
+ }
+ \cs_set_protected:Npn \regex_item_catcode:nT
+ { \regex_show_item_catcode:NnT \c_true_bool }
+ \cs_set_protected:Npn \regex_item_catcode_reverse:nT
+ { \regex_show_item_catcode:NnT \c_false_bool }
+ \cs_set_protected:Npn \regex_item_reverse:n
+ { \regex_show_scope:nn { Reversed~match } }
+ \cs_set_protected:Npn \regex_item_exact:nn ##1##2
+ { \regex_show_one:n { char~##2,~catcode~##1 } }
+ \cs_set_protected:Npn \regex_item_exact_cs:c ##1
+ { \regex_show_one:n { control~sequence~\iow_char:N\\##1 } }
+ \cs_set_protected:Npn \regex_item_cs:n
+ { \regex_show_scope:nn { control~sequence } }
+ \cs_set:cpn { regex_prop_.: } { \regex_show_one:n { any~token } }
+ \seq_clear:N \l_regex_show_prefix_seq
+ \regex_show_push:n { ~ }
+ #1
+ \tl_build_end:
+ \msg_aux_show:x { > Compiled~regex~#2: \l_regex_internal_a_tl }
}
-\cs_new_protected:Npn \regex_build_options:NNN #1#2#3
+\cs_new_protected:Npn \regex_show_one:n #1
{
- \token_if_eq_meaning:NNTF \regex_build_raw:N #2
- {
- \cs_if_exist_use:cF { regex_build_option_#1#3: }
- { \msg_kernel_error:nnx { regex } { unknown-option } { #3 } }
- \regex_build_options:NNN #1
- }
- {
- \prg_case_str:nnn { #3 }
- { % (
- { ) } { }
- { - } { \regex_build_options:NNN - }
- }
- { \msg_kernel_error:nnx { regex } { invalid-in-option } { #3 } }
- }
+ \int_incr:N \l_regex_show_lines_int
+ \tl_build_one:x
+ { \iow_newline: \seq_use:N \l_regex_show_prefix_seq #1 }
}
-\cs_new_protected_nopar:cpn { regex_build_option_+i: }
+\cs_new_protected:Npn \regex_show_push:n #1
+ { \seq_put_right:Nx \l_regex_show_prefix_seq { #1 ~ } }
+\cs_new_protected:Npn \regex_show_pop:
+ { \seq_pop_right:NN \l_regex_show_prefix_seq \l_regex_internal_a_tl }
+\cs_new_protected:Npn \regex_show_scope:nn #1#2
{
- \regex_build_caseless:
- \cs_set_eq:NN \regex_match_loop_case_hook:
- \regex_match_loop_caseless_hook:
+ \regex_show_one:n {#1}
+ \regex_show_push:n { ~ }
+ #2
+ \regex_show_pop:
}
-\cs_new_protected_nopar:cpn { regex_build_option_-i: }
- { \regex_build_caseful: }
-\cs_new_protected_nopar:Npn \regex_build_group_quantifier:
+\cs_new_protected:Npn \regex_show_group_aux:nnnnN #1#2#3#4#5
{
- \tl_set:Nn \l_regex_one_or_group_tl { group }
- \regex_build_quantifier:w
+ \regex_show_one:n { ,-group~begin #1 }
+ \regex_show_push:n { | }
+ \use_ii:nn #2
+ \regex_show_pop:
+ \regex_show_one:n
+ { `-group~end \regex_msg_repeated:nnN {#3} {#4} #5 }
}
-\cs_new_protected:Npn \regex_build_group_submatches:NN #1#2
+\cs_set:Npn \regex_show_class:NnnnN #1#2#3#4#5
{
- \seq_pop:NN \l_regex_capturing_group_seq \l_regex_internal_a_tl
- \int_compare:nNnF { \l_regex_internal_a_tl } < \c_zero
+ \tl_set_build:Nw \l_regex_internal_a_tl
+ \int_zero:N \l_regex_show_lines_int
+ \regex_show_push:n {~}
+ #2
+ \exp_last_unbraced:Nf
+ \prg_case_int:nnn { \l_regex_show_lines_int }
{
- \regex_toks_put_left:Nx #1
- { \regex_action_submatch:n { \l_regex_internal_a_tl < } }
- \regex_toks_put_left:Nx #2
- { \regex_action_submatch:n { \l_regex_internal_a_tl > } }
- }
- }
-\cs_new_protected_nopar:Npn \regex_build_group_qs_aux:
- {
- \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
- \regex_build_new_state:
- \tex_toks:D \l_regex_right_state_int = \tex_toks:D \l_regex_internal_a_int
- \regex_toks_put_left:Nx \l_regex_right_state_int
- {
- \int_sub:Nn \l_regex_current_state_int
+ {0}
{
- \int_eval:n % ^^A here we lie!
- { \l_regex_right_state_int - \l_regex_internal_a_int }
+ \tl_build_end:
+ \regex_show_one:n { \bool_if:NTF #1 { Fail } { Pass } }
}
- }
- \use:x
- {
- \tex_toks:D \l_regex_internal_a_int
+ {1}
{
- \s_stop
- \regex_action_free:n
+ \tl_build_end:
+ \bool_if:NTF #1
{
- \int_eval:n
- { \l_regex_right_state_int - \l_regex_internal_a_int }
+ #2
+ \tl_build_one:n { \regex_msg_repeated:nnN {#3} {#4} #5 }
+ }
+ {
+ \regex_show_one:n
+ { Don't~match~\regex_msg_repeated:nnN {#3} {#4} #5 }
+ \tl_build_one:o \l_regex_internal_a_tl
}
}
}
- \regex_build_group_submatches:NN
- \l_regex_right_state_int \l_regex_left_state_int
+ {
+ \tl_build_end:
+ \regex_show_one:n
+ {
+ \bool_if:NTF #1 { M } { Don't~m } atch
+ \regex_msg_repeated:nnN {#3} {#4} #5
+ }
+ \tl_build_one:o \l_regex_internal_a_tl
+ }
}
-\cs_new_protected:Npn \regex_build_group_qs_aux:NN #1#2
+\cs_new:Npn \regex_show_anchor_to_str:N #1
{
- \regex_build_group_qs_aux:
- \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
- \regex_build_transition:NN \regex_action_free:n #1
- #2 \l_regex_internal_a_int
+ anchor~at~
+ \prg_case_str:nnn { #1 }
{
- \regex_action_free:n
- { \int_eval:n { \l_regex_right_state_int - \l_regex_internal_a_int } }
+ { \l_regex_min_pos_int } { start~(\iow_char:N\\A) }
+ { \l_regex_start_pos_int } { start~of~match~(\iow_char:N\\G) }
+ { \l_regex_max_pos_int } { end~(\iow_char:N\\Z) }
}
+ { <error:~'#1'~not~recognized> }
}
-\cs_new_protected_nopar:cpn { regex_build_group_?: }
+\cs_new_protected:Npn \regex_show_item_catcode:NnT #1#2
{
- \regex_build_group_qs_aux:NN
- \l_regex_right_state_int \regex_toks_put_right:Nx
+ \seq_set_split:Nnn \l_regex_internal_seq { } { CBEMTPUDSLOA }
+ \seq_set_filter:NNn \l_regex_internal_seq \l_regex_internal_seq
+ { \int_if_odd_p:n { #2 / \int_use:c { c_regex_catcode_##1_int } } }
+ \regex_show_scope:nn
+ {
+ categories~\seq_use:N \l_regex_internal_seq, ~
+ \bool_if:NF #1 { negative~ } class
+ }
}
-\cs_new_protected_nopar:cpn { regex_build_group_??: }
+\int_new:N \l_regex_min_state_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
+\int_new:N \l_regex_capturing_group_int
+\cs_new_protected:Npn \regex_build:n #1
{
- \regex_build_group_qs_aux:NN
- \l_regex_right_state_int \regex_toks_put_left:Nx
+ \regex_compile:n {#1}
+ \regex_build:N \l_regex_internal_regex
}
-\cs_new_protected:Npn \regex_build_group_transition_right_max:
+\cs_new_protected:Npn \regex_build: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_right_state_int } }
- }
+ \int_set:Nn \tex_escapechar:D { 92 }
+ \int_zero:N \l_regex_capturing_group_int
+ \int_set_eq:NN \l_regex_max_state_int \l_regex_min_state_int
+ \regex_build_new_state:
+ \regex_build_new_state:
+ \regex_toks_put_right:Nn \l_regex_left_state_int
+ { \regex_action_start_wildcard: }
+ \regex_group:nnnN {#1} { 1 } { 0 } \c_false_bool
+ \regex_toks_put_right:Nn \l_regex_right_state_int
+ { \regex_action_success: }
}
-\cs_new_protected:Npn \regex_build_group_n_aux:n #1
+\cs_new_protected:Npn \regex_build_for_cs:n #1
{
- \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
- \int_set_eq:NN \l_regex_internal_b_int \l_regex_max_state_int
- \int_add:Nn \l_regex_right_state_int
- { ( #1 - 1 ) * ( \l_regex_max_state_int - \l_regex_left_state_int ) }
- \int_set:Nn \l_regex_max_state_int
- {
- \l_regex_left_state_int
- + (#1) * ( \l_regex_max_state_int - \l_regex_left_state_int )
- }
- \int_while_do:nNnn \l_regex_internal_b_int < \l_regex_max_state_int
+ \int_set_eq:NN \l_regex_max_state_int \l_regex_min_state_int
+ \regex_build_new_state:
+ \regex_build_new_state:
+ \regex_push_lr_states:
+ #1
+ \regex_pop_lr_states:
+ \regex_toks_put_right:Nn \l_regex_right_state_int
{
- \tex_toks:D \l_regex_internal_b_int
- = \tex_toks:D \l_regex_internal_a_int
- \int_incr:N \l_regex_internal_a_int
- \int_incr:N \l_regex_internal_b_int
+ \if_num:w \l_regex_current_pos_int = \l_regex_max_pos_int
+ \exp_after:wN \regex_action_success:
+ \fi:
}
}
-\cs_new_protected:Npn \regex_build_group_n: #1
+\cs_new_protected_nopar:Npn \regex_push_lr_states:
{
- \regex_build_group_transition_right_max:
- \regex_build_group_n_aux:n {#1}
- \regex_build_new_state:
- \int_compare:nNnF {#1} = \c_zero
- {
- \regex_build_group_submatches:NN
- \l_regex_internal_a_int \l_regex_left_state_int
- }
+ \seq_push:No \l_regex_left_state_seq
+ { \int_use:N \l_regex_left_state_int }
+ \seq_push:No \l_regex_right_state_seq
+ { \int_use:N \l_regex_right_state_int }
}
-\cs_new_eq:cN { regex_build_group_n?: } \regex_build_group_n:
-\cs_new_protected_nopar:Npn \regex_build_group_:
- { \regex_build_group_n: \c_one }
-\cs_new_protected_nopar:cpn { regex_build_group_n*: }
+\cs_new_protected_nopar:Npn \regex_pop_lr_states:
{
- \regex_build_group_n_star_aux:NNn
- \regex_toks_put_right:Nx \regex_toks_put_left:Nx
+ \seq_pop:NN \l_regex_left_state_seq \l_regex_internal_a_tl
+ \int_set:Nn \l_regex_left_state_int \l_regex_internal_a_tl
+ \seq_pop:NN \l_regex_right_state_seq \l_regex_internal_a_tl
+ \int_set:Nn \l_regex_right_state_int \l_regex_internal_a_tl
}
-\cs_new_protected_nopar:cpn { regex_build_group_n*?: }
+\cs_new_protected:Npn \regex_toks_put_left:Nx #1#2
{
- \regex_build_group_n_star_aux:NNn
- \regex_toks_put_left:Nx \regex_toks_put_right:Nx
+ \cs_set_nopar:Npx \regex_tmp:w { #2 }
+ \tex_toks:D #1 \exp_after:wN \exp_after:wN \exp_after:wN
+ { \exp_after:wN \regex_tmp:w \tex_the:D \tex_toks:D #1 }
}
-\cs_new_protected:Npn \regex_build_group_n_star_aux:NNn #1#2#3
+\cs_new_protected:Npn \regex_toks_put_right:Nx #1#2
{
- \int_compare:nNnTF {#3} = \c_zero
- { \regex_build_group_qs_aux:NN \l_regex_internal_a_int #1 }
- {
- \regex_build_group_transition_right_max:
- \regex_build_group_n_aux:n {#3}
- \regex_build_new_state:
- #2 \l_regex_left_state_int
- {
- \regex_action_free:n
- {
- \int_eval:n
- { \l_regex_internal_a_int - \l_regex_left_state_int }
- }
- }
- \regex_build_group_submatches:NN
- \l_regex_internal_a_int \l_regex_left_state_int
- }
+ \cs_set_nopar:Npx \regex_tmp:w {#2}
+ \tex_toks:D #1 \exp_after:wN
+ { \tex_the:D \tex_toks:D \exp_after:wN #1 \regex_tmp:w }
}
-\cs_new_protected_nopar:cpx { regex_build_group_*: }
- { \exp_not:c { regex_build_group_n*: } \c_zero }
-\cs_new_protected_nopar:cpx { regex_build_group_*?: }
- { \exp_not:c { regex_build_group_n*?: } \c_zero }
-\cs_new_protected_nopar:cpx { regex_build_group_+: }
- { \exp_not:c { regex_build_group_n*: } \c_one }
-\cs_new_protected_nopar:cpx { regex_build_group_+?: }
- { \exp_not:c { regex_build_group_n*?: } \c_one }
-\cs_new_protected_nopar:Npn \regex_build_group_nn:
+\cs_new_protected:Npn \regex_toks_put_right:Nn #1#2
+ { \tex_toks:D #1 \exp_after:wN { \tex_the:D \tex_toks:D #1 #2 } }
+\cs_new_protected:Npn \regex_build_transition_left:NNN #1#2#3
+ { \regex_toks_put_left:Nx #2 { #1 { \int_eval:n { #3 - #2 } } } }
+\cs_new_protected:Npn \regex_build_transition_right:nNn #1#2#3
+ { \regex_toks_put_right:Nx #2 { #1 { \int_eval:n { #3 - #2 } } } }
+\cs_new_protected_nopar:Npn \regex_build_new_state:
{
- \regex_build_group_nn_aux:nnnn { }
- \regex_build_group_transition_right_max:
+ \tex_toks:D \l_regex_max_state_int { }
+ \int_set_eq:NN \l_regex_left_state_int \l_regex_right_state_int
+ \int_set_eq:NN \l_regex_right_state_int \l_regex_max_state_int
+ \int_incr:N \l_regex_max_state_int
}
-\cs_new_protected_nopar:cpn { regex_build_group_nn?: }
+\cs_new_protected:Npn \regex_build_transitions_lazyness:NNNNN #1#2#3#4#5
{
- \regex_build_group_nn_aux:nnnn { }
+ \regex_build_new_state:
+ \regex_toks_put_right:Nx \l_regex_left_state_int
{
- \use:x
- {
- \tex_toks:D \l_regex_right_state_int
- {
- \exp_after:wN \regex_build_group_nn_aux_ii:w
- \tex_the:D \tex_toks:D \l_regex_right_state_int
- }
- }
+ \if_meaning:w \c_true_bool #1
+ #2 { \int_eval:n { #3 - \l_regex_left_state_int } }
+ #4 { \int_eval:n { #5 - \l_regex_left_state_int } }
+ \else:
+ #4 { \int_eval:n { #5 - \l_regex_left_state_int } }
+ #2 { \int_eval:n { #3 - \l_regex_left_state_int } }
+ \fi:
}
}
-\cs_new_protected:Npn \regex_build_group_nn_aux:nnnn #1#2#3#4
+\cs_new_protected:Npn \regex_class:NnnnN #1#2#3#4#5
{
- \int_compare:nNnTF {#3} > {#4}
- {
- \msg_kernel_error:nnxxx
- { regex } { quantifier-backwards } {#3} {#4} {#1}
- }
+ \cs_set_nopar:Npx \regex_tests_action_cost:n ##1
{
- \int_compare:nNnTF {#3} = \c_zero
- {
- \regex_build_group_qs_aux:
- \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
- \int_set_eq:NN \l_regex_left_state_int \l_regex_internal_a_int
- \regex_build_group_transition_right_max:
- \regex_build_group_n_aux:n { #4 - #3 }
- \int_set_eq:NN \l_regex_internal_c_int \l_regex_right_state_int
- \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
- \prg_replicate:nn { #4 - #3 }
- {
- #2
- \int_add:Nn \l_regex_right_state_int
- { \l_regex_internal_b_int - \l_regex_internal_a_int }
- }
- \int_set_eq:NN \l_regex_right_state_int \l_regex_internal_c_int
- \int_set_eq:NN \l_regex_left_state_int \l_regex_internal_a_int
- \regex_build_new_state:
- }
- {
- \regex_build_group_transition_right_max:
- \regex_build_group_n_aux:n {#3}
- \int_set_eq:NN \l_regex_left_state_int \l_regex_internal_a_int
- \regex_build_group_submatches:NN
- \l_regex_left_state_int \l_regex_right_state_int
- \regex_build_group_n_aux:n { #4 - #3 + \c_one }
- \int_sub:Nn \l_regex_right_state_int
- { \l_regex_internal_a_int - \l_regex_left_state_int }
- \prg_replicate:nn { #4 - #3 }
- {
- #2
- \int_add:Nn \l_regex_right_state_int
- { \l_regex_internal_b_int - \l_regex_internal_a_int }
- }
- \int_set_eq:NN \l_regex_left_state_int \l_regex_internal_a_int
- \regex_build_new_state:
- }
+ \exp_not:n { \exp_not:n {#2} }
+ \bool_if:NTF #1
+ { \regex_break_point:TF { \regex_action_cost:n {##1} } { } }
+ { \regex_break_point:TF { } { \regex_action_cost:n {##1} } }
}
+ \if_case:w - #4 \exp_stop_f:
+ \regex_class_repeat:n {#3}
+ \or: \regex_class_repeat:nN {#3} #5
+ \else: \regex_class_repeat:nnN {#3} {#4} #5
+ \fi:
}
-\cs_new_protected:Npn \regex_build_group_nn_aux_ii:w #1 \regex_action_free:n
+\cs_new:Npn \regex_tests_action_cost:n { \regex_action_cost:n }
+\cs_new_protected:Npn \regex_class_repeat:n #1
{
- #1
- \regex_action_free:n
+ \prg_replicate:nn {#1}
{
- \int_eval:n
- { \l_regex_max_state_int - \l_regex_right_state_int }
+ \regex_build_new_state:
+ \regex_build_transition_right:nNn \regex_tests_action_cost:n
+ \l_regex_left_state_int \l_regex_right_state_int
}
- \regex_action_free:n
}
-\cs_new_protected:cpn { regex_build_/u: } #1#2
+\cs_new_protected:Npn \regex_class_repeat:nN #1#2
{
- \regex_build_if_assertions_forbidden:TF
- { \regex_build_raw_error:N u #1#2 }
- {
- \str_if_eq:xxTF {#1#2} { \regex_build_special:N \c_lbrace_str }
- {
- \tl_set:Nx \l_regex_internal_a_tl { \if_false: } \fi:
- \regex_build_u_loop:NN
- }
- {
- \msg_kernel_error:nn { regex } { u-missing-lbrace }
- #1#2
- }
- }
+ \if_num:w #1 = \c_zero
+ \regex_build_transitions_lazyness:NNNNN #2
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_tests_action_cost:n \l_regex_left_state_int
+ \else:
+ \regex_class_repeat:n {#1}
+ \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
+ \regex_build_transitions_lazyness:NNNNN #2
+ \regex_action_free:n \l_regex_right_state_int
+ \regex_action_free:n \l_regex_internal_a_int
+ \fi:
}
-\cs_new:Npn \regex_build_u_loop:NN #1#2
+\cs_new_protected:Npn \regex_class_repeat:nnN #1#2#3
{
- \token_if_eq_meaning:NNTF #1 \regex_build_raw:N
- { #2 \regex_build_u_loop:NN }
+ \regex_class_repeat:n {#1}
+ \int_set:Nn \l_regex_internal_a_int
+ { \l_regex_max_state_int + #2 - \c_one }
+ \prg_replicate:nn { #2 }
{
- \token_if_eq_meaning:NNTF #1 \regex_build_special:N
- {
- \exp_after:wN \token_if_eq_charcode:NNTF \c_rbrace_str #2
- { \if_false: { \fi: } \regex_build_u_end: }
- { #2 \regex_build_u_loop:NN }
- }
- {
- \if_false: { \fi: }
- \msg_kernel_error:nnx { regex } { u-missing-rbrace } {#2}
- \regex_build_u_end:
- #1#2
- }
+ \regex_build_transitions_lazyness:NNNNN #3
+ \regex_action_free:n \l_regex_internal_a_int
+ \regex_tests_action_cost:n \l_regex_right_state_int
}
}
-\cs_new_protected:Npn \regex_build_u_end:
+\cs_new_protected:Npn \regex_group_aux:nnnnN #1#2#3#4#5
{
- \tl_set:Nv \l_regex_internal_a_tl \l_regex_internal_a_tl
- \if_num:w \l_regex_build_mode_int = \c_zero
- \regex_build_u_not_cs:
- \else:
- \regex_build_u_in_cs:
- \fi:
- \tl_clear:N \l_regex_tests_tl
+ \if_num:w #3 = \c_zero
+ \regex_build_new_state:
+ \regex_build_transition_right:nNn \regex_action_free_group:n
+ \l_regex_left_state_int \l_regex_right_state_int
+ \fi:
+ \regex_build_new_state:
+ \regex_push_lr_states:
+ #2
+ \regex_pop_lr_states:
+ \if_case:w - #4 \exp_stop_f:
+ \regex_group_repeat:nn {#1} {#3}
+ \or: \regex_group_repeat:nnN {#1} {#3} #5
+ \else: \regex_group_repeat:nnnN {#1} {#3} {#4} #5
+ \fi:
}
-\cs_new_protected:Npn \regex_build_u_in_cs:
+\cs_new_protected:Npn \regex_group:nnnN #1
{
- \exp_args:NNo \str_gset_other:Nn \g_regex_internal_tl
- { \l_regex_internal_a_tl }
- \tl_map_inline:Nn \g_regex_internal_tl
+ \exp_args:No \regex_group_aux:nnnnN
+ { \int_use:N \l_regex_capturing_group_int }
{
- \tl_set:Nx \l_regex_tests_tl { \regex_item_equal:n { `##1 } }
- \regex_build_one_:
+ \int_incr:N \l_regex_capturing_group_int
+ #1
}
}
-\cs_new_protected:Npn \regex_build_u_not_cs:
+\cs_new_protected_nopar:Npn \regex_group_no_capture:nnnN
+ { \regex_group_aux:nnnnN { -1 } }
+\cs_new_protected:Npn \regex_group_resetting:nnnN #1
{
- \exp_args:No \tl_analysis_map_inline:nn { \l_regex_internal_a_tl }
+ \regex_group_aux:nnnnN { -1 }
{
- \tl_set:Nx \l_regex_tests_tl
- {
- \exp_not:N \int_compare:nNnT
- \l_regex_current_catcode_int = { \int_value:w "##2 }
- {
- \int_compare:nNnTF { "##2 } = \c_zero
- {
- \exp_not:n
- { \str_if_eq:xxT { \l_regex_current_token_tl } {##1} }
- { \regex_break_true:w }
- }
- { \regex_item_equal:n {##3} }
- }
- }
- \regex_build_one_:
+ \exp_args:Noo \regex_group_resetting_loop:nnNn
+ { \int_use:N \l_regex_capturing_group_int }
+ { \int_use:N \l_regex_capturing_group_int }
+ #1
+ { ?? \prg_map_break:n } { }
+ \prg_break_point:n { }
}
}
-\cs_new_protected:Npn \regex_store_state:n #1
+\cs_new_protected:Npn \regex_group_resetting_loop:nnNn #1#2#3#4
{
- \int_incr:N \l_regex_max_active_int
- \tex_skip:D \l_regex_max_active_int #1 sp \scan_stop:
- \regex_store_submatches:n {#1}
+ \use_none:nn #3 { \int_set:Nn \l_regex_capturing_group_int {#1} }
+ \int_set:Nn \l_regex_capturing_group_int {#2}
+ #3 {#4}
+ \exp_args:Nf \regex_group_resetting_loop:nnNn
+ { \int_max:nn {#1} { \l_regex_capturing_group_int } }
+ {#2}
}
-\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 \use_none_delimit_by_s_stop:w } }
-\cs_new_protected:Npn \regex_state_use_aux:n #1
+\cs_new_protected:Npn \regex_branch:n #1
{
- \if_num:w \tex_dimen:D \l_regex_current_state_int < \l_regex_step_int
- \tex_dimen:D \l_regex_current_state_int
- = \l_regex_step_int sp \scan_stop:
- #1 \tex_the:D \tex_toks:D \exp_after:wN \l_regex_current_state_int
- \fi:
- \scan_stop:
+ \regex_build_new_state:
+ \seq_get:NN \l_regex_left_state_seq \l_regex_internal_a_tl
+ \int_set:Nn \l_regex_left_state_int \l_regex_internal_a_tl
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_left_state_int \l_regex_right_state_int
+ #1
+ \seq_get:NN \l_regex_right_state_seq \l_regex_internal_a_tl
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_right_state_int \l_regex_internal_a_tl
}
-\cs_new_protected_nopar:Npn \regex_disable_submatches:
+\cs_new_protected:Npn \regex_group_repeat:nn #1#2
{
- \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
- \regex_protected_use_none:n
+ \if_num:w #2 = \c_zero
+ \int_set:Nn \l_regex_max_state_int
+ { \l_regex_left_state_int - \c_one }
+ \regex_build_new_state:
+ \else:
+ \regex_group_repeat_aux:n {#2}
+ \regex_group_submatches:nNN {#1}
+ \l_regex_internal_a_int \l_regex_right_state_int
+ \regex_build_new_state:
+ \fi:
}
-\cs_new_protected:Npn \regex_protected_use_none:n #1 { }
-\cs_new_protected:Npn \regex_store_submatches:n #1
+\cs_new_protected:Npn \regex_group_submatches:nNN #1#2#3
{
- \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
- }
+ \if_num:w #1 > \c_minus_one
+ \regex_toks_put_left:Nx #2 { \regex_action_submatch:n { #1 < } }
+ \regex_toks_put_left:Nx #3 { \regex_action_submatch:n { #1 > } }
+ \fi:
}
-\cs_new_protected:Npn \regex_store_submatches_aux:w #1 \s_stop
+\cs_new_protected:Npn \regex_group_repeat_aux:n #1
{
- \regex_store_submatches_aux_ii:Nnnw
- #1
- \regex_state_submatches:nn \c_minus_one \q_prop
- \s_stop
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_right_state_int \l_regex_max_state_int
+ \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
+ \int_set_eq:NN \l_regex_internal_b_int \l_regex_max_state_int
+ \if_num:w \int_eval:w #1 > \c_one
+ \int_set:Nn \l_regex_internal_c_int
+ {
+ ( #1 - \c_one )
+ * ( \l_regex_internal_b_int - \l_regex_internal_a_int )
+ }
+ \tex_advance:D \l_regex_right_state_int \l_regex_internal_c_int
+ \tex_advance:D \l_regex_max_state_int \l_regex_internal_c_int
+ \prg_replicate:nn \l_regex_internal_c_int
+ {
+ \tex_toks:D \l_regex_internal_b_int
+ = \tex_toks:D \l_regex_internal_a_int
+ \tex_advance:D \l_regex_internal_a_int \c_one
+ \tex_advance:D \l_regex_internal_b_int \c_one
+ }
+ \fi:
}
-\cs_new_protected:Npn \regex_store_submatches_aux_ii:Nnnw
- \regex_state_submatches:nn #1 #2 #3 \s_stop
+\cs_new_protected:Npn \regex_group_repeat:nnN #1#2#3
{
- \exp_after:wN \c_zero
- \exp_after:wN \regex_state_submatches:nn \exp_after:wN
- { \int_value:w \int_eval:w \l_regex_step_int + \c_one \exp_after:wN }
- \exp_after:wN { \l_regex_current_submatches_prop }
- \regex_state_submatches:nn {#1} {#2}
- \s_stop
+ \if_num:w #2 = \c_zero
+ \regex_group_submatches:nNN {#1}
+ \l_regex_left_state_int \l_regex_right_state_int
+ \int_set:Nn \l_regex_internal_a_int
+ { \l_regex_left_state_int - \c_one }
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_right_state_int \l_regex_internal_a_int
+ \regex_build_new_state:
+ \if_meaning:w \c_true_bool #3
+ \regex_build_transition_left:NNN \regex_action_free:n
+ \l_regex_internal_a_int \l_regex_right_state_int
+ \else:
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_internal_a_int \l_regex_right_state_int
+ \fi:
+ \else:
+ \regex_group_repeat_aux:n {#2}
+ \regex_group_submatches:nNN {#1}
+ \l_regex_internal_a_int \l_regex_right_state_int
+ \if_meaning:w \c_true_bool #3
+ \regex_build_transition_right:nNn \regex_action_free_group:n
+ \l_regex_right_state_int \l_regex_internal_a_int
+ \else:
+ \regex_build_transition_left:NNN \regex_action_free_group:n
+ \l_regex_right_state_int \l_regex_internal_a_int
+ \fi:
+ \regex_build_new_state:
+ \fi:
}
-\cs_new_protected:Npn \regex_state_submatches:nn #1#2
+\cs_new_protected:Npn \regex_group_repeat:nnnN #1#2#3#4
{
- \if_num:w #1 = \l_regex_step_int
- \tl_set:Nn \l_regex_current_submatches_prop { #2 }
+ \regex_group_submatches:nNN {#1}
+ \l_regex_left_state_int \l_regex_right_state_int
+ \regex_group_repeat_aux:n { #2 + #3 }
+ \if_meaning:w \c_true_bool #4
+ \int_set_eq:NN \l_regex_left_state_int \l_regex_max_state_int
+ \prg_replicate:nn { #3 }
+ {
+ \int_sub:Nn \l_regex_left_state_int
+ { \l_regex_internal_b_int - \l_regex_internal_a_int }
+ \regex_build_transition_left:NNN \regex_action_free:n
+ \l_regex_left_state_int \l_regex_max_state_int
+ }
+ \else:
+ \prg_replicate:nn { #3 - \c_one }
+ {
+ \int_sub:Nn \l_regex_right_state_int
+ { \l_regex_internal_b_int - \l_regex_internal_a_int }
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_right_state_int \l_regex_max_state_int
+ }
+ \if_num:w #2 = \c_zero
+ \int_set:Nn \l_regex_right_state_int
+ { \l_regex_left_state_int - \c_one }
+ \else:
+ \int_sub:Nn \l_regex_right_state_int
+ { \l_regex_internal_b_int - \l_regex_internal_a_int }
+ \fi:
+ \regex_build_transition_right:nNn \regex_action_free:n
+ \l_regex_right_state_int \l_regex_max_state_int
\fi:
+ \regex_build_new_state:
}
-\cs_new_protected:Npn \regex_match:n #1
+\cs_new_protected:Npn \regex_assertion:Nn #1#2
{
- \int_zero:N \l_regex_nesting_int
- \int_set_eq:NN \l_regex_current_index_int \l_regex_max_state_int
- \regex_query_set:nnn { } { -1 } { -2 }
- \int_set_eq:NN \l_regex_min_index_int \l_regex_current_index_int
- \tl_analysis_map_inline:nn {#1}
+ \regex_build_new_state:
+ \regex_toks_put_right:Nx \l_regex_left_state_int
{
- \regex_query_set:nnn {##1} {"##2} {##3}
- \if_case:w "##2 \exp_stop_f:
- \or: \int_incr:N \l_regex_nesting_int
- \or: \int_decr:N \l_regex_nesting_int
- \fi:
+ \exp_not:n {#2}
+ \regex_break_point:TF
+ \bool_if:NF #1 { { } }
+ {
+ \regex_action_free:n
+ {
+ \int_eval:n
+ { \l_regex_right_state_int - \l_regex_left_state_int }
+ }
+ }
+ \bool_if:NT #1 { { } }
}
- \int_set_eq:NN \l_regex_max_index_int \l_regex_current_index_int
- \regex_query_set:nnn { } { -1 } { -2 }
- \regex_match_initial_setup:
- \regex_match_once:
}
-\cs_new_protected:Npn \regex_query_set:nnn #1#2#3
+\cs_new_protected:Npn \regex_anchor:N #1
{
- \tex_muskip:D \l_regex_current_index_int
- = \etex_gluetomu:D
- #3 sp
- plus #2 sp
- minus \l_regex_nesting_int sp
- \scan_stop:
- \tex_toks:D \l_regex_current_index_int {#1}
- \int_incr:N \l_regex_current_index_int
+ \if_num:w #1 = \l_regex_current_pos_int
+ \exp_after:wN \regex_break_true:w
+ \fi:
}
-\cs_new_protected_nopar:Npn \regex_query_get:
+\cs_new_protected_nopar:Npn \regex_b_test:
{
- \tl_set:Nx \l_regex_current_token_tl
- { \tex_the:D \tex_toks:D \l_regex_current_index_int }
- \l_regex_current_char_int
- = \etex_mutoglue:D \tex_muskip:D \l_regex_current_index_int
- \l_regex_current_catcode_int = \etex_gluestretch:D
- \etex_mutoglue:D \tex_muskip:D \l_regex_current_index_int
+ \group_begin:
+ \int_set_eq:NN \l_regex_current_char_int \l_regex_last_char_int
+ \regex_prop_w:
+ \regex_break_point:TF
+ { \group_end: \regex_item_reverse:n \regex_prop_w: }
+ { \group_end: \regex_prop_w: }
}
-\cs_new_protected_nopar:Npn \regex_match_once:
+\cs_new_protected_nopar:Npn \regex_command_K:
{
- \regex_match_setup:
- \regex_query_get:
- \regex_match_loop:
- \prg_break_point:n { }
- \bool_if:NT \l_regex_success_match_bool
+ \regex_build_new_state:
+ \regex_toks_put_right:Nx \l_regex_left_state_int
{
- \bool_gset_true:N \g_regex_success_bool
- \l_regex_every_match_tl
+ \regex_action_submatch:n { 0< }
+ \bool_set_true:N \l_regex_fresh_thread_bool
+ \regex_action_free:n
+ { \int_eval:n { \l_regex_right_state_int - \l_regex_left_state_int } }
+ \bool_set_false:N \l_regex_fresh_thread_bool
}
}
-\cs_new_protected_nopar:Npn \regex_match_initial_setup:
+\int_new:N \l_regex_min_pos_int
+\int_new:N \l_regex_max_pos_int
+\int_new:N \l_regex_current_pos_int
+\int_new:N \l_regex_start_pos_int
+\int_new:N \l_regex_success_pos_int
+\int_new:N \l_regex_current_char_int
+\int_new:N \l_regex_current_catcode_int
+\int_new:N \l_regex_last_char_int
+\int_new:N \l_regex_case_changed_char_int
+\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_step_int
+\int_new:N \l_regex_min_active_int
+\int_new:N \l_regex_max_active_int
+\tl_new:N \l_regex_every_match_tl
+\bool_new:N \l_regex_fresh_thread_bool
+\bool_new:N \l_regex_empty_success_bool
+\cs_new_eq:NN \regex_if_two_empty_matches:F \use:n
+\bool_new:N \g_regex_success_bool
+\bool_new:N \l_regex_saved_success_bool
+\bool_new:N \l_regex_match_success_bool
+\cs_new_protected:Npn \regex_match:n #1
{
- \int_set_eq:NN \l_regex_step_int \c_minus_one
- \prg_stepwise_inline:nnnn
- \c_zero \c_one { \l_regex_max_state_int - \c_one }
- { \tex_dimen:D ##1 \l_regex_step_int sp }
- \int_set:Nn \l_regex_start_index_int
- { \l_regex_min_index_int - \c_one }
- \int_set_eq:NN \l_regex_current_index_int \l_regex_min_index_int
- \int_set_eq:NN \l_regex_success_index_int \l_regex_min_index_int
- \int_set_eq:NN \l_regex_submatch_int \l_regex_max_state_int
- \bool_set_false:N \l_regex_success_empty_bool
+ \int_zero:N \l_regex_balance_int
+ \int_set:Nn \l_regex_current_pos_int { \c_two * \l_regex_max_state_int }
+ \regex_query_set:nnn { } { -1 } { -2 }
+ \int_set_eq:NN \l_regex_min_pos_int \l_regex_current_pos_int
+ \tl_analysis_map_inline:nn {#1}
+ { \regex_query_set:nnn {##1} {"##2} {##3} }
+ \int_set_eq:NN \l_regex_max_pos_int \l_regex_current_pos_int
+ \regex_query_set:nnn { } { -1 } { -2 }
\bool_gset_false:N \g_regex_success_bool
+ \prg_stepwise_inline:nnnn
+ \l_regex_min_state_int \c_one { \l_regex_max_state_int - \c_one }
+ { \tex_dimen:D ##1 \c_one sp \scan_stop: }
+ \int_set_eq:NN \l_regex_min_active_int \l_regex_max_state_int
+ \int_set_eq:NN \l_regex_step_int \c_zero
+ \int_set_eq:NN \l_regex_success_pos_int \l_regex_min_pos_int
+ \int_set:Nn \l_regex_submatch_int
+ { \c_two * \l_regex_max_state_int }
+ \bool_set_false:N \l_regex_empty_success_bool
+ \regex_match_once:
}
-\cs_new_protected_nopar:Npn \regex_match_setup:
+\cs_new_protected_nopar:Npn \regex_match_once:
{
+ \if_meaning:w \c_true_bool \l_regex_empty_success_bool
+ \cs_set_nopar:Npn \regex_if_two_empty_matches:F
+ { \int_compare:nNnF \l_regex_start_pos_int = \l_regex_current_pos_int }
+ \else:
+ \cs_set_eq:NN \regex_if_two_empty_matches:F \use:n
+ \fi:
+ \int_set_eq:NN \l_regex_start_pos_int \l_regex_success_pos_int
+ \bool_set_false:N \l_regex_match_success_bool
\prop_clear:N \l_regex_current_submatches_prop
- \bool_if:NTF \l_regex_success_empty_bool
- { \cs_set_eq:NN \regex_if_two_empty_matches:F \regex_if_match_empty:F }
- { \cs_set_eq:NN \regex_if_two_empty_matches:F \use:n }
- \int_set_eq:NN \l_regex_start_index_int \l_regex_success_index_int
- \int_set:Nn \l_regex_current_index_int
- { \l_regex_start_index_int - \c_one }
- \bool_set_false:N \l_regex_success_match_bool
- \int_zero:N \l_regex_max_active_int
- \regex_store_state:n {0} %^^A _state_int!
+ \int_set_eq:NN \l_regex_max_active_int \l_regex_min_active_int
+ \regex_store_state:n { \l_regex_min_state_int }
+ \int_set:Nn \l_regex_current_pos_int
+ { \l_regex_start_pos_int - \c_one }
+ \regex_query_get:
+ \regex_match_loop:
+ \l_regex_every_match_tl
+ }
+\cs_new_protected_nopar:Npn \regex_single_match:
+ {
+ \tl_set:Nn \l_regex_every_match_tl
+ { \bool_gset_eq:NN \g_regex_success_bool \l_regex_match_success_bool }
+ }
+\cs_new_protected:Npn \regex_multi_match:n #1
+ {
+ \tl_set:Nn \l_regex_every_match_tl
+ {
+ \if_meaning:w \c_true_bool \l_regex_match_success_bool
+ \bool_gset_true:N \g_regex_success_bool
+ #1
+ \exp_after:wN \regex_match_once:
+ \fi:
+ }
}
\cs_new_protected_nopar:Npn \regex_match_loop:
{
- \int_incr:N \l_regex_current_index_int
- \int_incr:N \l_regex_step_int
- \bool_set_false:N \l_regex_fresh_thread_bool
+ \tex_advance:D \l_regex_step_int \c_two
+ \int_incr:N \l_regex_current_pos_int
\int_set_eq:NN \l_regex_last_char_int \l_regex_current_char_int
+ \int_set_eq:NN \l_regex_case_changed_char_int \c_max_int
\regex_query_get:
- \regex_match_loop_case_hook:
\use:x
{
- \int_zero:N \l_regex_max_active_int
- \regex_match_one_active:w 1 ; \prg_break_point:n { }
- \exp_not:N \prg_break_point:n { }
+ \int_set_eq:NN \l_regex_max_active_int \l_regex_min_active_int
+ \exp_after:wN \regex_match_one_active:w
+ \int_use:N \l_regex_min_active_int ;
}
- \if_num:w \l_regex_current_char_int < \c_minus_one
- \exp_after:wN \prg_map_break:
- \fi:
- \if_num:w \l_regex_max_active_int = \c_zero
- \exp_after:wN \prg_map_break:
+ \prg_break_point:n { \bool_set_false:N \l_regex_fresh_thread_bool }
+ \if_num:w \l_regex_max_active_int > \l_regex_min_active_int
+ \if_num:w \l_regex_current_pos_int < \l_regex_max_pos_int
+ \exp_after:wN \exp_after:wN \exp_after:wN \regex_match_loop:
+ \fi:
\fi:
- \regex_match_loop:
}
\cs_new:Npn \regex_match_one_active:w #1;
{
- \if_num:w #1 > \l_regex_max_active_int
- \exp_after:wN \prg_map_break:
+ \if_num:w #1 < \l_regex_max_active_int
+ \regex_use_state_and_submatches:nn
+ { \int_value:w \tex_skip:D #1 }
+ { \tex_the:D \tex_toks:D #1 }
+ \exp_after:wN \regex_match_one_active:w
+ \int_use:N \int_eval:w #1 + \c_one \exp_after:wN ;
\fi:
- \regex_match_one_active_aux:n
- { \int_value:w \tex_skip:D #1 }
- \exp_after:wN \regex_match_one_active:w
- \int_use:N \int_eval:w #1 + \c_one ;
}
-\cs_new_protected:Npn \regex_match_one_active_aux:n #1
+\cs_new_protected:Npn \regex_query_set:nnn #1#2#3
{
- \int_set:Nn \l_regex_current_state_int {#1}
- \prop_clear:N \l_regex_current_submatches_prop
- \regex_state_use_with_submatches:
+ \tex_muskip:D \l_regex_current_pos_int
+ = \etex_gluetomu:D
+ #3 sp
+ plus #2 sp
+ minus \l_regex_balance_int sp
+ \scan_stop:
+ \tex_toks:D \l_regex_current_pos_int {#1}
+ \int_incr:N \l_regex_current_pos_int
+ \if_case:w #2 \exp_stop_f:
+ \or: \int_incr:N \l_regex_balance_int
+ \or: \int_decr:N \l_regex_balance_int
+ \fi:
}
-\cs_new_protected_nopar:Npn \regex_match_loop_case_hook: { }
-\cs_new_protected_nopar:Npn \regex_match_loop_caseless_hook:
+\cs_new_protected_nopar:Npn \regex_query_get:
{
- \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:
+ \l_regex_current_char_int
+ = \etex_mutoglue:D \tex_muskip:D \l_regex_current_pos_int
+ \l_regex_current_catcode_int = \etex_gluestretch:D
+ \etex_mutoglue:D \tex_muskip:D \l_regex_current_pos_int
+ }
+\cs_new_protected_nopar:Npn \regex_use_state:
+ {
+ \tex_dimen:D \l_regex_current_state_int
+ = \l_regex_step_int sp \scan_stop:
+ \tex_the:D \tex_toks:D \l_regex_current_state_int
+ \tex_dimen:D \l_regex_current_state_int
+ = \int_eval:w \l_regex_step_int + \c_one \int_eval_end: sp \scan_stop:
+ }
+\cs_new_protected:Npn \regex_use_state_and_submatches:nn #1 #2
+ {
+ \int_set:Nn \l_regex_current_state_int {#1}
+ \if_num:w \tex_dimen:D \l_regex_current_state_int < \l_regex_step_int
+ \tl_set:Nn \l_regex_current_submatches_prop {#2}
+ \exp_after:wN \regex_use_state:
\fi:
+ \scan_stop:
}
\cs_new_protected_nopar:Npn \regex_action_start_wildcard:
{
@@ -1846,96 +1949,145 @@
\bool_set_false:N \l_regex_fresh_thread_bool
\regex_action_cost:n {0}
}
+\cs_new_protected_nopar:Npn \regex_action_free:n
+ { \regex_action_free_aux:nn { > \l_regex_step_int \else: } }
+\cs_new_protected_nopar:Npn \regex_action_free_group:n
+ { \regex_action_free_aux:nn { < \l_regex_step_int } }
+\cs_new_protected:Npn \regex_action_free_aux:nn #1#2
+ {
+ \use:x
+ {
+ \int_add:Nn \l_regex_current_state_int {#2}
+ \exp_not:n
+ {
+ \if_num:w \tex_dimen:D \l_regex_current_state_int #1
+ \exp_after:wN \regex_use_state:
+ \fi:
+ }
+ \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 }
+ }
+ }
\cs_new_protected:Npn \regex_action_cost:n #1
{
- \exp_args:Nf \regex_store_state:n
- { \int_eval:n { \l_regex_current_state_int + #1 } }
+ \exp_args:No \regex_store_state:n
+ { \int_use:N \int_eval:w \l_regex_current_state_int + #1 }
+ }
+\cs_new_protected:Npn \regex_store_state:n #1
+ {
+ \regex_store_submatches:
+ \tex_skip:D \l_regex_max_active_int = #1 sp \scan_stop:
+ \int_incr:N \l_regex_max_active_int
+ }
+\cs_new_protected_nopar:Npn \regex_store_submatches:
+ {
+ \tex_toks:D \l_regex_max_active_int \exp_after:wN
+ { \l_regex_current_submatches_prop }
+ }
+\cs_new_protected_nopar:Npn \regex_disable_submatches:
+ {
+ \cs_set_protected_nopar:Npn \regex_store_submatches: { }
+ \cs_set_protected:Npn \regex_action_submatch:n ##1 { }
+ }
+\cs_new_protected:Npn \regex_action_submatch:n #1
+ {
+ \prop_put:Nno \l_regex_current_submatches_prop {#1}
+ { \int_use:N \l_regex_current_pos_int }
}
\cs_new_protected_nopar:Npn \regex_action_success:
{
\regex_if_two_empty_matches:F
{
- \bool_set_true:N \l_regex_success_match_bool
- \bool_set_eq:NN \l_regex_success_empty_bool
+ \bool_set_true:N \l_regex_match_success_bool
+ \bool_set_eq:NN \l_regex_empty_success_bool
\l_regex_fresh_thread_bool
- \int_set_eq:NN \l_regex_success_index_int \l_regex_current_index_int
+ \int_set_eq:NN \l_regex_success_pos_int \l_regex_current_pos_int
\prop_set_eq:NN \l_regex_success_submatches_prop
\l_regex_current_submatches_prop
\prg_map_break:
}
}
-\cs_new_protected:Npn \regex_action_free:n #1
+\int_new:N \l_regex_replacement_csnames_int
+\tl_new:N \l_regex_balance_tl
+\cs_new:Npn \regex_replacement_balance_one_match:n #1
+ { - \regex_submatch_balance:n {#1} }
+\cs_new:Npn \regex_replacement_do_one_match:n #1
{
- \use:x
- {
- \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_query_range:nn
+ { \etex_glueshrink:D \tex_skip:D #1 }
+ { \tex_skip:D #1 }
}
-\cs_new_protected:Npn \regex_action_submatch:n #1
+\cs_new:Npn \regex_replacement_exp_not:N #1 { \exp_not:n {#1} }
+\cs_new:Npn \regex_query_range:nn #1#2
{
- \prop_put:Nno \l_regex_current_submatches_prop {#1}
- { \int_use:N \l_regex_current_index_int }
+ \exp_after:wN \regex_query_range_loop:ww
+ \int_use:N \int_eval:w #1 \exp_after:wN ;
+ \int_use:N \int_eval:w #2 ;
+ \prg_break_point:n { }
}
-\cs_new:Npn \regex_if_match_empty:T
- { \int_compare:nNnT \l_regex_start_index_int = \l_regex_current_index_int }
-\cs_new:Npn \regex_if_match_empty:F
- { \int_compare:nNnF \l_regex_start_index_int = \l_regex_current_index_int }
-\cs_new_protected:Npn \regex_submatch_nesting_aux:n #1
+\cs_new:Npn \regex_query_range_loop:ww #1 ; #2 ;
{
- + \etex_glueshrink:D \etex_mutoglue:D \etex_muexpr:D
- \tex_muskip:D \etex_gluestretch:D \tex_skip:D #1
- - \tex_muskip:D \tex_skip:D #1
- \scan_stop:
+ \if_num:w #1 < #2 \exp_stop_f:
+ \else:
+ \exp_after:wN \prg_map_break:
+ \fi:
+ \tex_the:D \tex_toks:D #1 \exp_stop_f:
+ \exp_after:wN \regex_query_range_loop:ww
+ \int_use:N \int_eval:w #1 + \c_one ; #2 ;
}
-\cs_new:Npn \regex_nesting:n #1 { } %^^A move. Rename?
-\tl_new:N \l_regex_nesting_tl
-\cs_new_protected:Npn \regex_replacement:n #1
+\cs_new:Npn \regex_query_submatch:n #1
{
- \int_zero:N \l_regex_replacement_int
- \int_zero:N \l_regex_nesting_int
- \tl_clear:N \l_regex_nesting_tl
- \regex_escape_use:nnnn
- { \regex_replacement_unescaped:N ##1 }
- { \regex_replacement_escaped:N ##1 }
- { \regex_replacement_raw:N ##1 }
- {#1}
- \prg_do_nothing: \prg_do_nothing:
- \cs_set:Npx \regex_nesting:n ##1
- {
- + \int_use:N \l_regex_nesting_int
- \l_regex_nesting_tl
- - \regex_submatch_nesting_aux:n {##1}
- }
- \use:x
- {
- \exp_not:n { \cs_set:Npn \regex_replacement_tl:n ##1 }
- { \regex_toks_range:nn \c_zero \l_regex_replacement_int }
- }
- % ^^A rename!
+ \regex_query_range:nn
+ { \tex_skip:D \int_eval:w #1 }
+ { \etex_gluestretch:D \tex_skip:D \int_eval:w #1 }
}
-\cs_new_protected:Npn \regex_replacement_raw:N #1
- { \regex_replacement_put:n {#1} }
-\cs_new_protected:Npn \regex_replacement_put:n #1
+\cs_new_protected:Npn \regex_submatch_balance:n #1
{
- \tex_toks:D \l_regex_replacement_int {#1}
- \int_incr:N \l_regex_replacement_int
+ \etex_glueshrink:D \etex_mutoglue:D \etex_muexpr:D
+ \tex_muskip:D \etex_gluestretch:D \tex_skip:D #1
+ - \tex_muskip:D \tex_skip:D #1
+ \scan_stop:
}
-\cs_new_protected:Npn \regex_replacement_unescaped:N #1
+\cs_new_protected:Npn \regex_replacement:n #1
{
- \if_charcode:w \c_rbrace_str #1
- \if_num:w \l_regex_replacement_csnames_int > \c_zero
- \regex_replacement_put:n \cs_end:
- \else:
- \regex_replacement_put:n #1
+ \tl_set_build:Nw \l_regex_internal_a_tl
+ \int_zero:N \l_regex_balance_int
+ \tl_clear:N \l_regex_balance_tl
+ \regex_escape_use:nnnn
+ {
+ \if_charcode:w \c_rbrace_str ##1
+ \regex_replacement_rbrace:N \else: \tl_build_one:n \fi: ##1
+ }
+ { \regex_replacement_escaped:N ##1 }
+ { \tl_build_one:n ##1 }
+ {#1}
+ \prg_do_nothing: \prg_do_nothing:
+ \if_int_compare:w \l_regex_replacement_csnames_int > \c_zero
+ \msg_kernel_error:nnx { regex } { replacement-missing-rbrace }
+ { \int_use:N \l_regex_replacement_csnames_int }
+ \tl_build_one:x
+ { \prg_replicate:nn \l_regex_replacement_csnames_int \cs_end: }
\fi:
- \else:
- \regex_replacement_put:n #1
- \fi:
+ \cs_gset:Npx \regex_replacement_balance_one_match:n ##1
+ {
+ + \int_use:N \l_regex_balance_int
+ \l_regex_balance_tl
+ - \regex_submatch_balance:n {##1}
+ }
+ \tl_build_end:
+ \exp_args:No \regex_replacement_aux:n \l_regex_internal_a_tl
+ }
+\cs_new_protected:Npn \regex_replacement_aux:n #1
+ {
+ \cs_set:Npn \regex_replacement_do_one_match:n ##1
+ {
+ \regex_query_range:nn
+ { \etex_glueshrink:D \tex_skip:D ##1 }
+ { \tex_skip:D ##1 }
+ #1
+ }
}
\cs_new_protected:Npn \regex_replacement_escaped:N #1
{
@@ -1944,34 +2096,23 @@
\if_num:w \c_one < 1#1 \exp_stop_f:
\regex_replacement_put_submatch:n {#1}
\else:
- \regex_replacement_put:n #1
+ \tl_build_one:n #1
\fi:
}
}
\cs_new_protected:Npn \regex_replacement_put_submatch:n #1
{
- \regex_replacement_put:n
- { \regex_query_submatch:nn {#1} {##1} }
- \if_num:w \l_regex_replacement_csnames_int = \c_zero
- \tl_put_right:Nn \l_regex_nesting_tl
- {
- \exp_not:N \if_num:w #1 < \l_regex_capturing_group_int
- \regex_submatch_nesting_aux:n { \int_eval:w #1+##1 \int_eval_end: }
- \exp_not:N \fi:
- }
+ \if_num:w #1 < \l_regex_capturing_group_int
+ \tl_build_one:n { \regex_query_submatch:n { #1 + ##1 } }
+ \if_num:w \l_regex_replacement_csnames_int = \c_zero
+ \tl_put_right:Nn \l_regex_balance_tl
+ { + \regex_submatch_balance:n { \int_eval:w #1+##1 \int_eval_end: } }
+ \fi:
\fi:
}
-\cs_new_protected:Npn \regex_replacement_error:NNN #1#2#3
- {
- \msg_kernel_error:nnxx { regex } { #1-command }
- { replacement~text } {#3}
- #2 #3
- }
\cs_new_protected:Npn \regex_replacement_g:w #1#2
{
- \str_if_eq:xxTF
- { \exp_not:n { #1#2 } }
- { \regex_replacement_unescaped:N \c_lbrace_str }
+ \str_if_eq:xxTF { #1#2 } { \tl_build_one:n \c_lbrace_str }
{
\int_zero:N \l_regex_internal_a_int
\regex_replacement_g_digits:NN
@@ -1980,40 +2121,33 @@
}
\cs_new_protected:Npn \regex_replacement_g_digits:NN #1#2
{
- \token_if_eq_meaning:NNTF #1 \regex_replacement_unescaped:N
+ \token_if_eq_meaning:NNTF #1 \tl_build_one:n
{
\if_num:w \c_one < 1#2 \exp_stop_f:
- \int_set:Nn \l_regex_internal_a_int { \c_ten * \l_regex_internal_a_int + #2 }
+ \int_set:Nn \l_regex_internal_a_int
+ { \c_ten * \l_regex_internal_a_int + #2 }
\exp_after:wN \use_i:nnn
\exp_after:wN \regex_replacement_g_digits:NN
\else:
- \if_charcode:w \c_rbrace_str #2
- \exp_args:No \regex_replacement_put_submatch:n
- { \int_use:N \l_regex_internal_a_int }
- \exp_after:wN \exp_after:wN \exp_after:wN \use_none:nn
- \else:
- \exp_after:wN \exp_after:wN
- \exp_after:wN \regex_replacement_error:NNN
- \exp_after:wN \exp_after:wN \exp_after:wN g
- \fi:
+ \exp_after:wN \regex_replacement_error:NNN
+ \exp_after:wN g
\fi:
}
- { \regex_replacement_error:NNN g }
- #1 #2
- }
-\cs_new_protected:Npn \regex_replacement_u:w #1#2
- {
- \str_if_eq:xxTF { #1#2 } { \regex_replacement_unescaped:N \c_lbrace_str }
{
- \int_incr:N \l_regex_replacement_csnames_int
- \regex_replacement_put:n
- { \exp_not:n { \exp_after:wN \exp_not:V \cs:w } }
+ \if_meaning:w \regex_replacement_rbrace:N #1
+ \exp_args:No \regex_replacement_put_submatch:n
+ { \int_use:N \l_regex_internal_a_int }
+ \exp_after:wN \use_none:nn
+ \else:
+ \exp_after:wN \regex_replacement_error:NNN
+ \exp_after:wN g
+ \fi:
}
- { \regex_replacement_error:NNN u #1#2 }
+ #1 #2
}
\cs_new_protected:Npn \regex_replacement_c:w #1#2
{
- \token_if_eq_meaning:NNTF #1 \regex_replacement_unescaped:N
+ \token_if_eq_meaning:NNTF #1 \tl_build_one:n
{
\cs_if_exist_use:cF { regex_replacement_c_#2:w }
{ \regex_replacement_error:NNN c #1#2 }
@@ -2022,121 +2156,173 @@
}
\cs_new_protected_nopar:cpn { regex_replacement_c_ \c_lbrace_str :w }
{
+ \if_case:w \l_regex_replacement_csnames_int
+ \tl_build_one:n
+ { \exp_not:n { \exp_after:wN \regex_replacement_exp_not:N \cs:w } }
+ \else:
+ \tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:N \cs:w } }
+ \fi:
\int_incr:N \l_regex_replacement_csnames_int
- \regex_replacement_put:n
- { \exp_not:n { \exp_after:wN \regex_replacement_exp_not:N \cs:w } }
}
-\cs_new:Npn \regex_replacement_exp_not:N #1 { \exp_not:n {#1} }
+\cs_new_protected:Npn \regex_replacement_u:w #1#2
+ {
+ \str_if_eq:xxTF { #1#2 } { \tl_build_one:n \c_lbrace_str }
+ {
+ \if_case:w \l_regex_replacement_csnames_int
+ \tl_build_one:n { \exp_not:n { \exp_after:wN \exp_not:V \cs:w } }
+ \else:
+ \tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:V \cs:w } }
+ \fi:
+ \int_incr:N \l_regex_replacement_csnames_int
+ }
+ { \regex_replacement_error:NNN u #1#2 }
+ }
+\cs_new_protected:Npn \regex_replacement_rbrace:N #1
+ {
+ \if_int_compare:w \l_regex_replacement_csnames_int > \c_zero
+ \tl_build_one:n \cs_end:
+ \int_decr:N \l_regex_replacement_csnames_int
+ \else:
+ \tl_build_one:n #1
+ \fi:
+ }
\group_begin:
-
- \char_set_catcode_math_superscript:N \^^@
- \cs_new_protected_nopar:Npn \regex_replacement_c_U:w
- { \regex_replacement_char:nNN { ^^@ } }
-
- \char_set_catcode_alignment:N \^^@
- \cs_new_protected_nopar:Npn \regex_replacement_c_T:w
+ \cs_new_protected:Npn \regex_replacement_char:nNN #1#2#3
+ {
+ \if_meaning:w \prg_do_nothing: #3
+ \msg_kernel_error:nn { regex } { replacement-catcode-end }
+ \else:
+ \tex_lccode:D \c_zero = `#3 \scan_stop:
+ \tl_to_lowercase:n { \tl_build_one:n {#1} }
+ \fi:
+ }
+ \char_set_catcode_active:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_A:w
+ { \regex_replacement_char:nNN { \exp_not:n { \exp_not:N ^^@ } } }
+ \char_set_catcode_group_begin:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_B:w
+ {
+ \if_num:w \l_regex_replacement_csnames_int = \c_zero
+ \int_incr:N \l_regex_balance_int
+ \fi:
+ \regex_replacement_char:nNN
+ { \exp_not:n { \exp_after:wN ^^@ \if_false: } \fi: } }
+ }
+ \cs_new_protected:Npn \regex_replacement_c_C:w #1#2
+ { \tl_build_one:n { \exp_not:N \exp_not:N \exp_not:c {#2} } }
+ \char_set_catcode_math_subscript:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_D:w
{ \regex_replacement_char:nNN { ^^@ } }
-
- \cs_new_protected:Npn \regex_replacement_c_S:w #1#2
+ \char_set_catcode_group_end:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_E:w
{
- \int_compare:nNnTF { `#2 } = \c_zero
- { \regex_replacement_error:NNN c #1#2 }
- {
- \char_set_lccode:nn {32} { `#2 }
- \tl_to_lowercase:n { \regex_replacement_put:n {~} }
- }
+ \if_num:w \l_regex_replacement_csnames_int = \c_zero
+ \int_decr:N \l_regex_balance_int
+ \fi:
+ \regex_replacement_char:nNN
+ { \exp_not:n { \if_false: { \fi: ^^@ } }
}
-
- \char_set_catcode_parameter:N \^^@
- \cs_new_protected_nopar:Npn \regex_replacement_c_P:w
- { \regex_replacement_char:nNN { ^^@^^@^^@^^@^^@^^@^^@^^@ } }
-
- \char_set_catcode_other:N \^^@
- \cs_new_protected_nopar:Npn \regex_replacement_c_O:w
+ \char_set_catcode_letter:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_L:w
{ \regex_replacement_char:nNN { ^^@ } }
-
\char_set_catcode_math_toggle:N \^^@
\cs_new_protected_nopar:Npn \regex_replacement_c_M:w
{ \regex_replacement_char:nNN { ^^@ } }
-
- \char_set_catcode_letter:N \^^@
- \cs_new_protected_nopar:Npn \regex_replacement_c_L:w
+ \char_set_catcode_other:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_O:w
{ \regex_replacement_char:nNN { ^^@ } }
-
- \char_set_catcode_group_end:N \^^@
- \cs_new_protected_nopar:Npn \regex_replacement_c_E:w
+ \char_set_catcode_parameter:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_P:w
{
- \int_decr:N \l_regex_nesting_int
- \regex_replacement_char:nNN { \if_false: { \fi: ^^@ }
+ \regex_replacement_char:nNN
+ { \exp_not:n { \exp_not:n { ^^@^^@^^@^^@ } } }
}
-
- \char_set_catcode_math_subscript:N \^^@
- \cs_new_protected_nopar:Npn \regex_replacement_c_D:w
- { \regex_replacement_char:nNN { ^^@ } }
-
- \char_set_catcode_group_begin:N \^^@
- \cs_new_protected_nopar:Npn \regex_replacement_c_B:w
+ \cs_new_protected:Npn \regex_replacement_c_S:w #1#2
{
- \int_incr:N \l_regex_nesting_int
- \regex_replacement_char:nNN { \exp_after:wN ^^@ \if_false: } \fi: }
+ \if_meaning:w \prg_do_nothing: #2
+ \msg_kernel_error:nn { regex } { replacement-catcode-end }
+ \else:
+ \if_num:w `#2 = \c_zero
+ \msg_kernel_error:nn { regex } { replacement-null-space }
+ \fi:
+ \tex_lccode:D 32 = `#2 \scan_stop:
+ \tl_to_lowercase:n { \tl_build_one:n {~} }
+ \fi:
}
-
- \char_set_catcode_active:N \^^@
- \cs_new_protected_nopar:Npn \regex_replacement_c_A:w
- { \regex_replacement_char:nNN { \exp_not:N ^^@ } }
-
+ \char_set_catcode_alignment:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_T:w
+ { \regex_replacement_char:nNN { ^^@ } }
+ \char_set_catcode_math_superscript:N \^^@
+ \cs_new_protected_nopar:Npn \regex_replacement_c_U:w
+ { \regex_replacement_char:nNN { ^^@ } }
\group_end:
-
-\cs_new_protected:Npn \regex_replacement_char:nNN #1#2#3
+\cs_new_protected:Npn \regex_replacement_error:NNN #1#2#3
{
- \char_set_lccode:nn \c_zero { `#3 }
- \tl_to_lowercase:n
- { \regex_replacement_put:n { \exp_not:n {#1} } }
+ \msg_kernel_error:nnx { regex } { replacement-#1 } {#3}
+ #2 #3
}
-\cs_new_protected_nopar:Npn \regex_set:Nn
- { \regex_set_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \regex_gset:Nn
- { \regex_set_aux:NNn \tl_gset:Nn }
-\cs_new_protected_nopar:Npn \regex_const:Nn
- { \regex_set_aux:NNn \tl_const:Nn }
-\cs_new_protected:Npn \regex_set_aux:NNn #1#2#3
+\cs_new_protected:Npn \regex_new:N #1
+ { \cs_new_eq:NN #1 \c_regex_no_match_regex }
+\cs_new_protected_nopar:Npn \regex_set:Nn #1#2
{
- \group_begin:
- \regex_build:n {#3}
- \use:x
- {
- \group_end:
- #1 \exp_not:N #2 { \regex_set_aux:N #2 }
- }
+ \regex_compile:n {#2}
+ \tl_set_eq:NN #1 \l_regex_internal_regex
}
-\cs_new:Npn \regex_set_aux:N #1
+\cs_new_protected_nopar:Npn \regex_gset:Nn #1#2
{
- \exp_not:n { \regex_nfa:Nw #1 }
- \l_regex_max_state_int
- = \int_use:N \l_regex_max_state_int
- \l_regex_capturing_group_int
- = \int_use:N \l_regex_capturing_group_int
- \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
- \c_zero \c_one {\l_regex_max_state_int - \c_one }
- \regex_set_aux:n
- \s_stop
+ \regex_compile:n {#2}
+ \tl_gset_eq:NN #1 \l_regex_internal_regex
+ }
+\cs_new_protected_nopar:Npn \regex_const:Nn #1#2
+ {
+ \regex_compile:n {#2}
+ \tl_const:Nx #1 { \exp_not:o \l_regex_internal_regex }
}
-\cs_new:Npn \regex_set_aux:n #1
- { \tex_toks:D #1 { \tex_the:D \tex_toks:D #1 } }
-\cs_new:Npn \regex_nfa:Nw #1
+\cs_new_protected:Npn \regex_show:n #1
{
- \msg_expandable_kernel_error:nnn { regex } { nfa-misused } {#1}
- \use_none_delimit_by_s_stop:w
+ \regex_compile:n {#1}
+ \regex_show_aux:Nx \l_regex_internal_regex
+ { { \tl_to_str:n {#1} } }
}
-\cs_new_protected_nopar:Npn \regex_use:N
- { \exp_last_unbraced:No \use_none:nn }
+\cs_new_protected:Npn \regex_show:N #1
+ { \regex_show_aux:Nx #1 { variable~\token_to_str:N #1 } }
+\prg_new_protected_conditional:Npnn \regex_match:nn #1#2 { T , F , TF }
+ {
+ \regex_match_aux:nn { \regex_build:n {#1} } {#2}
+ \regex_aux_return:
+ }
+\prg_new_protected_conditional:Npnn \regex_match:Nn #1#2 { T , F , TF }
+ {
+ \regex_match_aux:nn { \regex_build:N #1 } {#2}
+ \regex_aux_return:
+ }
+\cs_new_protected:Npn \regex_count:nnN #1
+ { \regex_count_aux:nnN { \regex_build:n {#1} } }
+\cs_new_protected:Npn \regex_count:NnN #1
+ { \regex_count_aux:nnN { \regex_build:N #1 } }
+\cs_set_protected:Npn \regex_tmp:w #1#2#3
+ {
+ \cs_new_protected:Npn #2 ##1 { #1 { \regex_build:n {##1} } }
+ \cs_new_protected:Npn #3 ##1 { #1 { \regex_build:N ##1 } }
+ \prg_new_protected_conditional:Npnn #2 ##1##2##3 { T , F , TF }
+ { #1 { \regex_build:n {##1} } {##2} ##3 \regex_aux_return: }
+ \prg_new_protected_conditional:Npnn #3 ##1##2##3 { T , F , TF }
+ { #1 { \regex_build:N ##1 } {##2} ##3 \regex_aux_return: }
+ }
+\regex_tmp:w \regex_extract_once_aux:nnN
+ \regex_extract_once:nnN \regex_extract_once:NnN
+\regex_tmp:w \regex_extract_all_aux:nnN
+ \regex_extract_all:nnN \regex_extract_all:NnN
+\regex_tmp:w \regex_replace_once_aux:nnN
+ \regex_replace_once:nnN \regex_replace_once:NnN
+\regex_tmp:w \regex_replace_all_aux:nnN
+ \regex_replace_all:nnN \regex_replace_all:NnN
+\regex_tmp:w \regex_split_aux:nnN \regex_split:nnN \regex_split:NnN
+\int_new:N \l_regex_match_count_int
+\flag_new:n { regex_begin }
+\flag_new:n { regex_end }
+\int_new:N \l_regex_submatch_int
+\int_new:N \l_regex_zeroth_submatch_int
\cs_new_protected_nopar:Npn \regex_aux_return:
{
\if_meaning:w \c_true_bool \g_regex_success_bool
@@ -2145,79 +2331,67 @@
\prg_return_false:
\fi:
}
-\cs_new_protected:Npn \regex_aux_build_match:nn #1#2
+\cs_new_protected:Npn \regex_match_aux:nn #1#2
{
- \regex_build:n {#1}
- \regex_match:n {#2}
- }
-\cs_new_protected:Npn \regex_aux_use_match:Nn #1#2
- {
- \exp_args:No \tl_if_head_eq_meaning:nNTF {#1} \regex_nfa:Nw
- {
- \regex_use:N #1
- \regex_match:n {#2}
- }
- {
- \msg_kernel_error:nnx { regex } { not-nfa } { \token_to_str:N #1 }
- \bool_gset_false:N \g_regex_success_bool
- }
+ \group_begin:
+ \regex_disable_submatches:
+ \regex_single_match:
+ #1
+ \regex_match:n {#2}
+ \group_end:
}
-\cs_set_protected:Npn \regex_tmp:w #1#2#3
+\cs_new_protected:Npn \regex_count_aux:nnN #1#2#3
{
- \cs_new_protected_nopar:Npn #1
- { #3 \regex_aux_build_match:nn }
- \cs_new_protected_nopar:Npn #2
- { #3 \regex_aux_use_match:Nn }
- \prg_new_protected_conditional:Npnn #1 ##1##2##3 { T , F , TF }
- {
- #3 \regex_aux_build_match:nn {##1} {##2} ##3
- \regex_aux_return:
- }
- \prg_new_protected_conditional:Npnn #2 ##1##2##3 { T , F , TF }
- {
- #3 \regex_aux_use_match:Nn {##1} {##2} ##3
- \regex_aux_return:
- }
+ \group_begin:
+ \regex_disable_submatches:
+ \int_zero:N \l_regex_match_count_int
+ \regex_multi_match:n { \int_incr:N \l_regex_match_count_int }
+ #1
+ \regex_match:n {#2}
+ \exp_args:NNNo
+ \group_end:
+ \int_set:Nn #3 { \int_use:N \l_regex_match_count_int }
}
-\tl_map_inline:nn
+\cs_new_protected:Npn \regex_extract_once_aux:nnN #1#2#3
{
- { extract_once } { extract_all }
- { replace_once } { replace_all }
- { split }
+ \group_begin:
+ \regex_single_match:
+ #1
+ \regex_match:n {#2}
+ \regex_extract:
+ \regex_group_end_extract_seq:N #3
}
+\cs_new_protected:Npn \regex_extract_all_aux:nnN #1#2#3
{
- \exp_args:Nccc \regex_tmp:w
- { regex_#1:nnN } { regex_#1:NnN } { regex_#1_aux:NnnN }
+ \group_begin:
+ \regex_multi_match:n { \regex_extract: }
+ #1
+ \regex_match:n {#2}
+ \regex_group_end_extract_seq:N #3
}
-\cs_new_protected_nopar:Npn \regex_extract:
+\cs_new_protected:Npn \regex_split_aux:nnN #1#2#3
{
- \int_set_eq:NN \l_regex_submatch_start_int \l_regex_submatch_int
- \if_meaning:w \c_true_bool \g_regex_success_bool
- \prg_replicate:nn \l_regex_capturing_group_int
- {
- \tex_skip:D \l_regex_submatch_int \c_zero sp \scan_stop:
- \int_incr:N \l_regex_submatch_int
- }
- \prop_map_inline:Nn \l_regex_success_submatches_prop
+ \group_begin:
+ \regex_multi_match:n
{
- \if_num:w ##1 \c_max_int
- \exp_after:wN \regex_extract_aux_b:wn \int_use:N
- \else:
- \exp_after:wN \regex_extract_aux_e:wn \int_use:N
+ \if_num:w \l_regex_start_pos_int < \l_regex_success_pos_int
+ \regex_extract:
+ \tex_skip:D \l_regex_zeroth_submatch_int
+ = \l_regex_start_pos_int sp
+ plus \tex_skip:D \l_regex_zeroth_submatch_int \scan_stop:
\fi:
- \int_eval:w \l_regex_submatch_start_int + ##1 {##2}
}
- \fi:
- }
-\cs_new_protected:Npn \regex_extract_aux_b:wn #1 < #2
- {
- \tex_skip:D #1 = #2 sp
- plus \etex_gluestretch:D \tex_skip:D #1 \scan_stop:
- }
-\cs_new_protected:Npn \regex_extract_aux_e:wn #1 > #2
- {
- \tex_skip:D #1
- = 1 \tex_skip:D #1 plus #2 sp \scan_stop:
+ #1
+ \regex_match:n {#2}
+ \tex_skip:D \l_regex_submatch_int
+ = \l_regex_start_pos_int sp plus \l_regex_max_pos_int sp \scan_stop:
+ \int_incr:N \l_regex_submatch_int
+ \if_meaning:w \c_true_bool \l_regex_empty_success_bool
+ \if_num:w \l_regex_start_pos_int = \l_regex_max_pos_int
+ \int_decr:N \l_regex_submatch_int
+ \fi:
+ \fi:
+ \regex_group_end_extract_seq:N #3
}
\cs_new_protected:Npn \regex_group_end_extract_seq:N #1
{
@@ -2227,7 +2401,7 @@
\tl_set:Nx \l_regex_internal_a_tl
{
\prg_stepwise_function:nnnN
- \l_regex_max_state_int
+ { \c_two * \l_regex_max_state_int }
\c_one
{ \l_regex_submatch_int - \c_one }
\regex_extract_seq_aux:n
@@ -2235,17 +2409,24 @@
\int_compare:nNnF
{ \flag_height:n { regex_begin } + \flag_height:n { regex_end } }
= \c_zero
- { \msg_kernel_error:nn { regex } { sequence-unbalanced } }
- \tl_set:Nx \l_regex_internal_a_tl { \l_regex_internal_a_tl }
- \exp_args:NNNo \group_end:
- \tl_set:Nn #1 \l_regex_internal_a_tl
+ {
+ \msg_kernel_error:nnxxx { regex } { result-unbalanced }
+ { splitting~or~extracting~submatches }
+ { \flag_height:n { regex_end } }
+ { \flag_height:n { regex_begin } }
+ }
+ \use:x
+ {
+ \group_end:
+ \tl_set:Nn \exp_not:N #1 { \l_regex_internal_a_tl }
+ }
}
\cs_new:Npn \regex_extract_seq_aux:n #1
{
\seq_item:n
{
\exp_after:wN \regex_extract_seq_aux:ww
- \int_value:w \regex_submatch_nesting_aux:n {#1} ; #1;
+ \int_value:w \regex_submatch_balance:n {#1} ; #1;
}
}
\cs_new:Npn \regex_extract_seq_aux:ww #1; #2;
@@ -2254,184 +2435,124 @@
\flag_raise:n { regex_end }
\prg_replicate:nn {-#1} { \exp_not:n { { \if_false: } \fi: } }
\fi:
- \regex_query_submatch:w #2;
+ \regex_query_submatch:n {#2}
\if_num:w #1 > \c_zero
\flag_raise:n { regex_begin }
\prg_replicate:nn {#1} { \exp_not:n { \if_false: { \fi: } } }
\fi:
}
-\prg_new_protected_conditional:Npnn \regex_match:nn #1#2 { T , F , TF }
- {
- \regex_match_aux:n
- { \regex_aux_build_match:nn {#1} {#2} }
- }
-\prg_new_protected_conditional:Npnn \regex_match:Nn #1#2 { T , F , TF }
- {
- \regex_match_aux:n
- { \regex_aux_use_match:Nn #1 {#2} }
- }
-\cs_new_protected:Npn \regex_match_aux:n #1
- {
- \group_begin:
- \tl_clear:N \l_regex_every_match_tl
- \regex_disable_submatches:
- #1
- \group_end:
- \regex_aux_return:
- }
-\cs_new_protected_nopar:Npn \regex_count:nnN
- { \regex_count_aux:NnnN \regex_aux_build_match:nn }
-\cs_new_protected_nopar:Npn \regex_count:NnN
- { \regex_count_aux:NnnN \regex_aux_use_match:Nn }
-\cs_new_protected:Npn \regex_count_aux:NnnN #1#2#3#4
+\cs_new_protected_nopar:Npn \regex_extract:
{
- \group_begin:
- \regex_disable_submatches:
- \int_zero:N \l_regex_match_count_int
- \tl_set:Nn \l_regex_every_match_tl
+ \if_meaning:w \c_true_bool \g_regex_success_bool
+ \int_set_eq:NN \l_regex_zeroth_submatch_int \l_regex_submatch_int
+ \prg_replicate:nn \l_regex_capturing_group_int
{
- \int_incr:N \l_regex_match_count_int
- \regex_match_once:
+ \tex_skip:D \l_regex_submatch_int \c_zero sp \scan_stop:
+ \int_incr:N \l_regex_submatch_int
}
- #1 {#2} {#3}
- \exp_args:NNNo
- \group_end:
- \int_set:Nn #4 { \int_use:N \l_regex_match_count_int }
- }
-\cs_new_protected:Npn \regex_extract_once_aux:NnnN #1#2#3#4
- {
- \group_begin:
- \tl_set:Nn \l_regex_every_match_tl { \regex_extract: }
- #1 {#2} {#3}
- \regex_group_end_extract_seq:N #4
+ \prop_map_inline:Nn \l_regex_success_submatches_prop
+ {
+ \if_num:w ##1 \c_minus_one
+ \exp_after:wN \regex_extract_aux_e:wn \int_value:w
+ \else:
+ \exp_after:wN \regex_extract_aux_b:wn \int_value:w
+ \fi:
+ \int_eval:w \l_regex_zeroth_submatch_int + ##1 {##2}
+ }
+ \tex_skip:D \l_regex_zeroth_submatch_int
+ = \tex_the:D \tex_skip:D \l_regex_zeroth_submatch_int
+ minus \l_regex_start_pos_int sp \scan_stop:
+ \fi:
}
-\cs_new_protected:Npn \regex_extract_all_aux:NnnN #1#2#3#4
+\cs_new_protected:Npn \regex_extract_aux_b:wn #1 < #2
{
- \group_begin:
- \tl_set:Nn \l_regex_every_match_tl
- { \regex_extract: \regex_match_once: }
- #1 {#2} {#3}
- \regex_group_end_extract_seq:N #4
+ \tex_skip:D #1 = #2 sp
+ plus \etex_gluestretch:D \tex_skip:D #1 \scan_stop:
}
-\cs_new_protected:Npn \regex_split_aux:NnnN #1#2#3#4
+\cs_new_protected:Npn \regex_extract_aux_e:wn #1 > #2
{
- \group_begin:
- \tl_set:Nn \l_regex_every_match_tl
- {
- \if_num:w \l_regex_start_index_int < \l_regex_success_index_int
- \regex_extract:
- \tex_skip:D \l_regex_submatch_start_int
- = \l_regex_start_index_int sp
- plus \tex_skip:D \l_regex_submatch_start_int \scan_stop:
- \fi:
- \regex_match_once:
- }
- #1 {#2} {#3}
- \tex_skip:D \l_regex_submatch_int
- = \l_regex_start_index_int sp
- plus \l_regex_current_index_int sp \scan_stop:
- \int_incr:N \l_regex_submatch_int
- \if_num:w \l_regex_start_index_int = \l_regex_current_index_int
- \if_meaning:w \c_true_bool \l_regex_success_empty_bool
- \int_decr:N \l_regex_submatch_int
- \fi:
- \fi:
- \regex_group_end_extract_seq:N #4
+ \tex_skip:D #1
+ = 1 \tex_skip:D #1 plus #2 sp \scan_stop:
}
-\cs_new_protected:Npn \regex_replace_once_aux:NnnN #1#2#3#4
+\cs_new_protected:Npn \regex_replace_once_aux:nnN #1#2#3
{
\group_begin:
- \tl_clear:N \l_regex_every_match_tl
- \regex_replacement:n {#3}
- \exp_args:Nno #1 {#2} #4
- \if_meaning:w \c_true_bool \g_regex_success_bool
+ \regex_single_match:
+ #1
+ \regex_replacement:n {#2}
+ \exp_args:No \regex_match:n { #3 }
+ \if_meaning:w \c_false_bool \g_regex_success_bool
+ \group_end:
+ \else:
\regex_extract:
- \int_set:Nn \l_regex_internal_a_int
- { \regex_nesting:n { \l_regex_submatch_start_int } }
- \if_num:w \l_regex_internal_a_int = \c_zero
- \else:
- \msg_kernel_error:nnx { regex } { replace-unbalanced }
- { \l_regex_internal_a_int }
- \fi:
+ \int_set:Nn \l_regex_balance_int
+ {
+ \regex_replacement_balance_one_match:n
+ { \l_regex_zeroth_submatch_int }
+ }
\tl_set:Nx \l_regex_internal_a_tl
{
- \if_num:w \l_regex_internal_a_int < \c_zero
- \prg_replicate:nn { - \l_regex_internal_a_int }
- { \exp_not:n { { \if_false: } \fi: } }
- \fi:
- \regex_toks_range:nn
- { \l_regex_min_index_int }
- { \tex_skip:D \l_regex_submatch_start_int }
- \regex_replacement_tl:n { \l_regex_submatch_start_int }
- \regex_toks_range:nn
- { \etex_gluestretch:D \tex_skip:D \l_regex_submatch_start_int }
- { \l_regex_max_index_int }
- \if_num:w \l_regex_internal_a_int > \c_zero
- \prg_replicate:nn { \l_regex_internal_a_int }
- { \exp_not:n { \if_false: { \fi: } } }
- \fi:
+ \regex_replacement_do_one_match:n { \l_regex_zeroth_submatch_int }
+ \regex_query_range:nn
+ { \etex_gluestretch:D \tex_skip:D \l_regex_zeroth_submatch_int }
+ { \l_regex_max_pos_int }
}
- \tl_set:Nx \l_regex_internal_a_tl { \l_regex_internal_a_tl }
- \exp_args:NNNo \group_end:
- \tl_set:Nn #4 \l_regex_internal_a_tl
- \else:
- \group_end:
+ \regex_group_end_replace:N #3
\fi:
}
-\cs_new_protected:Npn \regex_replace_all_aux:NnnN #1#2#3#4
+\cs_new_protected:Npn \regex_replace_all_aux:nnN #1#2#3
{
\group_begin:
- \tl_set:Nn \l_regex_every_match_tl
- {
- \regex_extract:
- \tex_skip:D \l_regex_submatch_start_int
- = \tex_the:D \tex_skip:D \l_regex_submatch_start_int
- minus \l_regex_start_index_int sp \scan_stop:
- \regex_match_once:
- }
- \regex_replacement:n {#3}
- \exp_args:Nno #1 {#2} #4
- \int_set:Nn \l_regex_internal_a_int
+ \regex_multi_match:n { \regex_extract: }
+ #1
+ \regex_replacement:n {#2}
+ \exp_args:No \regex_match:n {#3}
+ \int_set:Nn \l_regex_balance_int
{
0
\prg_stepwise_function:nnnN
- \l_regex_max_state_int
+ { \c_two * \l_regex_max_state_int }
\l_regex_capturing_group_int
{ \l_regex_submatch_int - \c_one }
- \regex_nesting:n
+ \regex_replacement_balance_one_match:n
}
- \if_num:w \l_regex_internal_a_int = \c_zero
- \else:
- \msg_kernel_error:nnx { regex } { replace-unbalanced }
- { \l_regex_internal_a_int }
- \fi:
\tl_set:Nx \l_regex_internal_a_tl
{
- \if_num:w \l_regex_internal_a_int < \c_zero
- \prg_replicate:nn { - \l_regex_internal_a_int }
- { \exp_not:n { { \if_false: } \fi: } }
- \fi:
\prg_stepwise_function:nnnN
- \l_regex_max_state_int
+ { \c_two * \l_regex_max_state_int }
\l_regex_capturing_group_int
{ \l_regex_submatch_int - \c_one }
- \regex_replace_all_aux:n
- \regex_toks_range:nn
- \l_regex_start_index_int \l_regex_max_index_int
- \if_num:w \l_regex_internal_a_int > \c_zero
- \prg_replicate:nn { \l_regex_internal_a_int }
- { \exp_not:n { \if_false: { \fi: } } }
- \fi:
+ \regex_replacement_do_one_match:n
+ \regex_query_range:nn
+ \l_regex_start_pos_int \l_regex_max_pos_int
}
- \tl_set:Nx \l_regex_internal_a_tl { \l_regex_internal_a_tl }
- \exp_args:NNNo \group_end:
- \tl_set:Nn #4 \l_regex_internal_a_tl
+ \regex_group_end_replace:N #3
}
-\cs_new:Npn \regex_replace_all_aux:n #1
+\cs_new_protected_nopar:Npn \regex_group_end_replace:N #1
{
- \regex_toks_range:nn
- { \etex_glueshrink:D \tex_skip:D #1 } { \tex_skip:D #1 }
- \regex_replacement_tl:n {#1}
+ \if_num:w \l_regex_balance_int = \c_zero
+ \else:
+ \msg_kernel_error:nnxxx { regex } { result-unbalanced }
+ { replacing }
+ { \int_max:nn { - \l_regex_balance_int } { \c_zero } }
+ { \int_max:nn { \l_regex_balance_int } { \c_zero } }
+ \fi:
+ \use:x
+ {
+ \group_end:
+ \tl_set:Nn \exp_not:N #1
+ {
+ \if_int_compare:w \l_regex_balance_int < \c_zero
+ \prg_replicate:nn { - \l_regex_balance_int }
+ { { \if_false: } \fi: }
+ \fi:
+ \l_regex_internal_a_tl
+ \if_int_compare:w \l_regex_balance_int > \c_zero
+ \prg_replicate:nn { \l_regex_balance_int }
+ { \if_false: { \fi: } }
+ \fi:
+ }
+ }
}
\msg_kernel_new:nnnn { regex } { trailing-backslash }
{ Trailing~escape~character~\iow_char:N\\. }
@@ -2453,6 +2574,13 @@
`\iow_char:N\\x\{\int_to_hexadecimal:n{#1}\}'.~
The~character~code~'#1'~is~larger~than~\int_use:N \c_max_char_int.
}
+\msg_kernel_new:nnnn { regex } { invalid-quantifier }
+ { Braced~quantifier~'#1'~may~not~be~followed~by~'#2'. }
+ {
+ The~character~'#2'~is~invalid~in~the~braced~quantifier~'#1'.~
+ The~only~valid~quantifiers~are~'*',~'?',~'+',~'{<int>}',~
+ '{<min>,}'~and~'{<min>,<max>}',~followed~or~not~by~'?'.
+ }
\msg_kernel_new:nnnn { regex } { missing-rbrack }
{ Missing~right~bracket~inserted~in~regular~expression. }
{
@@ -2475,19 +2603,29 @@
LaTeX~came~across~a~closing~parenthesis~when~no~submatch~group~
was~open.~The~parenthesis~will~be~ignored.
}
-\msg_kernel_new:nnnn { regex } { class-bad-escape }
- { Invalid~escape~\c_backslash_str #1~in~character~class. }
+\msg_kernel_new:nnnn { regex } { bad-escape }
{
- The~escape~sequence~\iow_char:N\\#1~may~not~appear~within~
- a~character~class.~For~instance,~assertions~(which~match~zero~
- characters)~would~not~make~sense~there.
+ Invalid~escape~\c_backslash_str #1~
+ \regex_if_in_cs:TF { within~a~control~sequence. }
+ {
+ \regex_if_in_class:TF
+ { in~a~character~class. }
+ { following~a~category~test. }
+ }
}
-\msg_kernel_new:nnnn { regex } { catcode-bad-escape }
- { Invalid~escape~\c_backslash_str #1~following~category~test. }
{
- The~escape~sequence~\iow_char:N\\#1~may~not~appear~following~
- a~category~test~such~as~\iow_char:N\\cL~or~
- \iow_char:N\\c[\iow_char:N\^BE].
+ The~escape~sequence~\iow_char:N\\#1~may~not~appear~
+ \regex_if_in_cs:TF
+ {
+ within~a~control~sequence~test~introduced~by~
+ \iow_char:N\\c\iow_char:N\{.
+ }
+ {
+ \regex_if_in_class:TF
+ { within~a~character~class~ }
+ { following~a~category~test~such~as~\iow_char:N\\cL~ }
+ because~it~does~not~match~exactly~one~character.
+ }
}
\msg_kernel_new:nnnn { regex } { range-missing-end }
{ Invalid~end-point~for~range~'#1-#2'~in~character~class. }
@@ -2525,7 +2663,7 @@
regular~expression,~but~the~closing~']'~is~not~present.
}
\msg_kernel_new:nnnn { regex } { c-missing-category }
- { Invalid~character~'#1'~following~\iow_char\\c~escape. }
+ { Invalid~character~'#1'~following~\iow_char:N\\c~escape. }
{
In~regular~expressions,~the~\iow_char:N\\c~escape~sequence~
may~only~be~followed~by~a~left~brace,~a~left~bracket,~or~a~
@@ -2547,78 +2685,102 @@
{ encountered~an~escaped~alphanumeric~character '\iow_char:N\\#2'~ }
when~parsing~the~argument~of~an~'\iow_char:N\\u\iow_char:N\{...\}'~escape.
}
-\msg_kernel_new:nnnn { regex } { sequence-unbalanced }
+\msg_kernel_new:nnnn { regex } { posix-unsupported }
+ { POSIX~collating~element~'[#1 ~ #1]'~not~supported. }
{
- Missing~
- \flag_if_raised:nTF { regex_end }
- {
- left~
- \flag_if_raised:nTF { regex_begin }
- { and~right~braces } { brace }
- }
- { right~brace }
- \ inserted~in~extracted~match.
+ 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 }
+ { POSIX~class~[:#1:]~unknown. }
{
- LaTeX~was~asked~to~extract~submatches~or~split~a~token~list~
- according~to~a~given~regular~expression,~but~some~of~the~resulting~
- items~were~not~balanced.
+ [:#1:]~is~not~among~the~known~POSIX~classes~
+ [:alnum:],~[:alpha:],~[:ascii:],~[:blank:],~
+ [:cntrl:],~[:digit:],~[:graph:],~[:lower:],~
+ [:print:],~[:punct:],~[:space:],~[:upper:],~
+ [:word:],~and~[:xdigit:].
}
-\msg_kernel_new:nnnn { regex } { replace-unbalanced }
- { The~result~of~a~replacement~does~not~have~balanced~braces. }
+\msg_kernel_new:nnnn { regex } { posix-missing-close }
+ { Missing~closing~':]'~for~POSIX~class. }
+ { The~POSIX~syntax~'#1'~must~be~followed~by~':]',~not~'#2'. }
+\msg_kernel_new:nnnn { regex } { result-unbalanced }
+ { Missing~brace~inserted~when~#1. }
{
- LaTeX~was~asked~to~do~some~regular~expression~replacement,~
+ LaTeX~was~asked~to~do~some~regular~expression~operation,~
and~the~resulting~token~list~would~not~have~the~same~number~
- of~begin-group~and~end-group~tokens. \\ \\
- \ \ \ \
- \prg_case_int:nnn {#1}
- {
- { -1 } { A~left~brace~was }
- { 1 } { A~right~brace~was }
- }
- {
- \int_abs:n {#1} ~
- \int_compare:nNnTF {#1} < \c_zero { left } { right } ~
- braces ~ were
- }
- \ inserted.
+ of~begin-group~and~end-group~tokens.~Braces~were~inserted:~
+ #2~left,~#3~right.
}
-\msg_kernel_new:nnnn { regex } { not-nfa }
- { This~is~not~a~regular~expression~variable. }
+\msg_kernel_new:nnnn { regex } { unknown-option }
+ { Unknown~option~`#1'~for~regular~expressions. }
{
- LaTeX~was~expecting~`#1'~to~be~a~regular~expression~variable.\\
- This~control~sequence~is~not~a~regex~variable.~It's~current~meaning~
- is~\\\\
- \ \ \ \ \token_to_str:N #1 = \token_to_meaning:N #1 .
+ The~only~available~option~is~'case-insensitive',~toggled~by~
+ '(?i)'~and~'(?-i)'.
}
-\msg_kernel_new:nnn { regex } { nfa-misused }
- { Automaton~#1 used~incorrectly. }
-\msg_kernel_new:nnnn { regex } { c-command }
- { Misused~\iow_char:N\\c~or\iow_char:N\\C~command~in~a~#1. }
+\msg_kernel_new:nnnn { regex } { replacement-c }
+ { Misused~\iow_char:N\\c~command~in~a~replacement~text. }
{
- In~a~#1,~the~\iow_char:N\\C~escape~sequence~
+ 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~'#2'.
- }
-\msg_kernel_new:nnnn { regex } { unknown-option }
- { Unknown~option~`#1'~for~regular~expressions. }
- {
- LaTeX~came~across~something~like~`(?#1)'~in~a~regular~expression,~
- but~the~option~`#1'~is~not~known.~It~will~be~ignored.
+ or~a~brace~group,~not~by~'#1'.
}
-\msg_kernel_new:nnnn { regex } { invalid-in-option }
- { Invalid~character~in~option~of~a~regular~expression. }
+\msg_kernel_new:nnnn { regex } { replacement-u }
+ { Misused~\iow_char:N\\u~command~in~a~replacement~text. }
{
- The~character~or~escape~sequence~`#1'~is~not~defined~
- as~an~option~within~regular~expressions.
+ 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 } { g-command }
+\msg_kernel_new:nnnn { regex } { replacement-g }
{ Missing~brace~for~the~\iow_char:N\\g~construction~in~a~replacement~text. }
{
In~the~replacement~text~for~a~regular~expression~search,~
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 }
+ {
+ Missing~character~for~the~\iow_char:N\\c<category><character>~
+ construction~in~a~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.~LaTeX~
+ reached~the~end~of~the~replacement~when~looking~for~that.
+ }
+\msg_kernel_new:nnnn { regex } { replacement-null-space }
+ { TeX~cannot~build~a~space~token~with~character~code~0. }
+ {
+ You~asked~for~a~character~token~with~category~'space',~
+ and~character~code~0,~for~instance~through~
+ '\iow_char:N\\cS\iow_char:N\\x00'.~
+ This~specific~case~is~impossible~and~will~be~replaced~
+ by~a~normal~space.
+ }
+\msg_kernel_new:nnnn { regex } { replacement-missing-rbrace }
+ { Missing~right~brace~inserted~in~replacement~text. }
+ {
+ There~were~\int_use:N \l_regex_replacement_csnames_int \
+ missing~right~braces.
+ }
+\cs_new:Npn \regex_msg_repeated:nnN #1#2#3
+ {
+ \str_if_eq:xxF { #1 #2 } { 1 0 }
+ {
+ , ~ repeated ~
+ \prg_case_int:nnn {#2}
+ {
+ { -1 } { #1~or~more~times,~\bool_if:NTF #3 { lazy } { greedy } }
+ { 0 } { #1~times }
+ }
+ {
+ between~#1~and~\int_eval:n {#1+#2}~times,~
+ \bool_if:NTF #3 { lazy } { greedy }
+ }
+ }
+ }
%%
%%
%% 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 d9ef6271899..88042a5337d 100644
--- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty
+++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty
@@ -46,13 +46,15 @@
%%
%% -----------------------------------------------------------------------
\RequirePackage{expl3}
-\GetIdInfo$Id: l3str.dtx 3257 2012-01-29 13:37:03Z bruno $
+\GetIdInfo$Id: l3str.dtx 3460 2012-02-26 12:16:41Z will $
{L3 Experimental Strings}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\RequirePackage{l3tl-analysis,l3flag}
+\RequirePackage{l3tl-analysis,l3tl-build,l3flag}
\cs_if_exist:NF \use_ii_i:nn
{ \cs_new:Npn \use_ii_i:nn #1#2 { #2 #1 } }
+\cs_new_eq:NN \str_new:N \tl_new:N
+\cs_generate_variant:Nn \str_new:N { c }
\tl_map_inline:nn
{
{ set }
@@ -435,15 +437,17 @@
\prg_return_true:
\fi:
}
+\cs_new_eq:NN \str_show:n \tl_show:n
+\cs_new_eq:NN \str_show:N \tl_show:N
+\cs_generate_variant:Nn \str_show:N { c }
\group_begin:
- \tl_clear:N \l_str_internal_tl
\char_set_catcode_other:n { \c_zero }
- \tl_gset:Nx \g_str_result_tl { \tl_to_str:n { 0123456789ABCDEF } }
- \exp_args:No \tl_map_inline:nn { \g_str_result_tl " }
+ \tl_set:Nx \l_str_internal_tl { \tl_to_str:n { 0123456789ABCDEF } }
+ \exp_args:No \tl_map_inline:nn { \l_str_internal_tl " }
{ \char_set_lccode:nn {`#1} { \c_zero } }
- \tl_map_inline:Nn \g_str_result_tl
+ \tl_map_inline:Nn \l_str_internal_tl
{
- \tl_map_inline:Nn \g_str_result_tl
+ \tl_map_inline:Nn \l_str_internal_tl
{
\char_set_lccode:nn { \c_zero } {"#1##1}
\tl_to_lowercase:n
@@ -451,12 +455,9 @@
\tl_const:cx
{ c_str_byte_ \int_eval:n {"#1##1} _tl }
{ ^^@ #1 ##1 }
- \tl_put_right:Nn \l_str_internal_tl { ^^@ }
}
}
}
- \tl_const:Nx \c_str_positive_bytes_tl
- { \exp_after:wN \use_none:n \l_str_internal_tl }
\group_end:
\tl_const:cn { c_str_byte_-1_tl } { { } \use_none:n { } }
\cs_new:Npn \str_output_byte:n #1
@@ -744,53 +745,20 @@
{
\cs_new_protected_nopar:Npn \str_convert_encode_:
{
- \tex_lccode:D \c_zero \c_zero
- \int_zero:N \l_str_internal_int
- \tl_set_eq:NN \l_str_internal_tl \g_str_result_tl
- \tl_gclear:N \g_str_result_tl
- \exp_after:wN \str_encode_native_loop:w
- \l_str_internal_tl \s_tl { \q_stop \prg_map_break: } \s_tl
- \prg_break_point:n { \str_encode_native_flush: }
+ \int_zero:N \l_tl_build_offset_int
+ \tl_gset_build_x:Nw \g_str_result_tl
+ \exp_after:wN \str_encode_native_loop:w
+ \g_str_result_tl \s_tl { \q_stop \prg_map_break: } \s_tl
+ \prg_break_point:n { }
+ \tl_build_end:
}
\cs_new_protected:Npn \str_encode_native_loop:w #1 \s_tl #2 \s_tl
{
\use_none_delimit_by_q_stop:w #2 \q_stop
- \if_num:w \l_str_internal_int = \c_two_hundred_fifty_five
- \str_encode_native_flush:
- \l_str_internal_int \c_zero
- \fi:
- \tex_advance:D \l_str_internal_int \c_one
\tex_lccode:D \l_str_internal_int \int_eval:w #2 \int_eval_end:
+ \tl_to_lowercase:n { \tl_build_one:n { ^^@ } }
\str_encode_native_loop:w
}
- \cs_new_protected_nopar:Npn \str_encode_native_flush:
- {
- \use:x
- {
- \tl_to_lowercase:n
- {
- \tl_gput_right:Nx \exp_not:N \g_str_result_tl
- {
- \exp_after:wN \str_encode_native_filter:N
- \c_str_positive_bytes_tl
- { ? = \c_zero \fi: \prg_map_break: }
- \prg_break_point:n { }
- }
- }
- }
- }
- \cs_new:Npn \str_encode_native_filter:N #1
- {
- \if_num:w `#1 > \l_str_internal_int
- \exp_after:wN \prg_map_break:
- \fi:
- \if_num:w \tex_lccode:D `#1 = \c_zero
- ^^@
- \else:
- #1
- \fi:
- \str_encode_native_filter:N
- }
}
\group_end:
\cs_new_protected:Npn \str_declare_eight_bit_encoding:nnn #1#2#3
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty
index 6f82415d186..545d7ce7069 100644
--- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty
+++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty
@@ -52,6 +52,7 @@
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
\RequirePackage{l3str}
\scan_new:N \s_tl
+\tl_new:N \l_tl_analysis_internal_tl
\cs_new_eq:NN \l_tl_analysis_token ?
\cs_new_eq:NN \l_tl_analysis_char_token ?
\int_new:N \l_tl_analysis_normal_int
@@ -370,8 +371,8 @@
}
\cs_new_protected:Npn \tl_show_analysis:n #1
{
- \tl_set:Nn \l_tl_tmpa_tl {#1}
- \tl_show_analysis:N \l_tl_tmpa_tl
+ \tl_set:Nn \l_tl_analysis_internal_tl {#1}
+ \tl_show_analysis:N \l_tl_analysis_internal_tl
}
\cs_new:Npn \tl_show_analysis_loop:wNw #1 \s_tl #2 #3 \s_tl
{
@@ -396,37 +397,55 @@
\exp_after:wN \token_to_str:N #1 ~
( \exp_after:wN \token_to_meaning:N #1 )
}
+\cs_new:Npn \tl_show_analysis_value:N #1
+ {
+ \token_if_expandable:NF #1
+ {
+ \token_if_chardef:NTF #1 \prg_map_break: { }
+ \token_if_mathchardef:NTF #1 \prg_map_break: { }
+ \token_if_dim_register:NTF #1 \prg_map_break: { }
+ \token_if_int_register:NTF #1 \prg_map_break: { }
+ \token_if_skip_register:NTF #1 \prg_map_break: { }
+ \token_if_toks_register:NTF #1 \prg_map_break: { }
+ \use_none:nnnn
+ \prg_break_point:n { }
+ \use:n { = \tex_the:D #1 }
+ }
+ }
\cs_new:Npn \tl_show_analysis_cs:n #1
{ \exp_args:No \tl_show_analysis_long:nn {#1} { control~sequence= } }
\cs_new:Npn \tl_show_analysis_active:n #1
{ \exp_args:No \tl_show_analysis_long:nn {#1} { active~character= } }
\cs_new:Npn \tl_show_analysis_long:nn #1
{
- \exp_args:Noo \tl_show_analysis_long_aux:nnn
+ \tl_show_analysis_long_aux:oofn
{ \token_to_str:N #1 }
{ \token_to_meaning:N #1 }
+ { \tl_show_analysis_value:N #1 }
}
-\cs_new:Npn \tl_show_analysis_long_aux:nnn #1#2#3
+\cs_new:Npn \tl_show_analysis_long_aux:nnnn #1#2#3#4
{
\int_compare:nNnTF
- { \str_length:n { #1 ~ ( #3 #2 ) } }
+ { \str_length:n { #1 ~ ( #4 #2 #3 ) } }
> { \l_iow_line_length_int - \c_three }
{
- \str_substr:nnn { #1 ~ ( #3 #2 ) } \c_zero
+ \str_substr:nnn { #1 ~ ( #4 #2 #3 ) } \c_zero
{
\l_iow_line_length_int - \c_three
- \str_length:N \c_tl_show_analysis_etc_str
}
\c_tl_show_analysis_etc_str
}
- { #1 ~ ( #3 #2 ) }
+ { #1 ~ ( #4 #2 #3 ) }
}
+\cs_generate_variant:Nn \tl_show_analysis_long_aux:nnnn { oof }
\tl_const:Nx \c_tl_show_analysis_etc_str % (
{ \token_to_str:N \ETC.) }
\msg_kernel_new:nnn { tl-analysis } { show }
{
The~token~list~
- \str_if_eq:nnF {#1} { \l_tl_tmpa_tl } { \token_to_str:N #1 ~ }
+ \str_if_eq:nnF {#1} { \l_tl_analysis_internal_tl }
+ { \token_to_str:N #1 ~ }
\tl_if_empty:NTF #1
{ is~empty }
{ contains~the~tokens: }
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-build.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-build.sty
new file mode 100644
index 00000000000..415a89f4897
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-build.sty
@@ -0,0 +1,120 @@
+%%
+%% This is file `l3tl-build.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% l3tl-build.dtx (with options: `package')
+%%
+%% EXPERIMENTAL CODE
+%%
+%% Do not distribute this file without also distributing the
+%% source files specified above.
+%%
+%% Do not distribute a modified version of this file.
+%%
+%% File: l3tl-build.dtx Copyright (C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3experimental bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The released version of this bundle is available from CTAN.
+%%
+%% -----------------------------------------------------------------------
+%%
+%% The development version of the bundle can be found at
+%%
+%% http://www.latex-project.org/svnroot/experimental/trunk/
+%%
+%% for those people who are interested.
+%%
+%%%%%%%%%%%
+%% NOTE: %%
+%%%%%%%%%%%
+%%
+%% Snapshots taken from the repository represent work in progress and may
+%% not work or may contain conflicting material! We therefore ask
+%% people _not_ to put them into distributions, archives, etc. without
+%% prior consultation with the LaTeX3 Project.
+%%
+%% -----------------------------------------------------------------------
+\RequirePackage{expl3}
+\GetIdInfo$Id: l3tl-build.dtx 3039 2011-12-08 09:22:35Z bruno $
+ {L3 Experimental Build of Token lists}
+\ProvidesExplPackage
+ {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
+\int_new:N \l_tl_build_start_index_int
+\int_new:N \l_tl_build_index_int
+\tl_new:N \l_tl_build_result_tl
+\cs_new_protected_nopar:Npn \tl_build_unpack:
+ {
+ \tl_put_right:Nx \l_tl_build_result_tl
+ {
+ \exp_after:wN \tl_build_unpack_loop:w
+ \int_use:N \l_tl_build_start_index_int ;
+ \prg_break_point:n { }
+ }
+ }
+\cs_new:Npn \tl_build_unpack_loop:w #1 ;
+ {
+ \if_num:w #1 = \l_tl_build_index_int
+ \exp_after:wN \prg_map_break:
+ \fi:
+ \tex_the:D \tex_toks:D #1 \exp_stop_f:
+ \exp_after:wN \tl_build_unpack_loop:w
+ \int_use:N \int_eval:w #1 + \c_one ;
+ }
+\cs_new_protected_nopar:Npn \tl_set_build:Nw
+ { \tl_set_build_aux:NNw \tl_set:Nn }
+\cs_new_protected_nopar:Npn \tl_set_build_x:Nw
+ { \tl_set_build_aux:NNw \tl_set:Nx }
+\cs_new_protected_nopar:Npn \tl_gset_build:Nw
+ { \tl_set_build_aux:NNw \tl_gset:Nn }
+\cs_new_protected_nopar:Npn \tl_gset_build_x:Nw
+ { \tl_set_build_aux:NNw \tl_gset:Nx }
+\cs_new_protected:Npn \tl_set_build_aux:NNw #1#2
+ {
+ \group_begin:
+ \cs_set_nopar:Npn \tl_build_end_assignment:n
+ { \group_end: #1 #2 }
+ \int_zero:N \l_tl_build_start_index_int
+ \int_zero:N \l_tl_build_index_int
+ \tl_clear:N \l_tl_build_result_tl
+ }
+\cs_new_protected_nopar:Npn \tl_build_end:
+ {
+ \tl_build_unpack:
+ \exp_args:No
+ \tl_build_end_assignment:n \l_tl_build_result_tl
+ }
+\cs_new_eq:NN \tl_build_end_assignment:n \use_none:n
+\cs_new_protected:Npn \tl_build_one:n #1
+ {
+ \tex_toks:D \l_tl_build_index_int {#1}
+ \tex_advance:D \l_tl_build_index_int \c_one
+ \if_num:w \l_tl_build_index_int > \c_max_register_int
+ \tl_build_unpack:
+ \l_tl_build_index_int \l_tl_build_start_index_int
+ \fi:
+ }
+\cs_new_protected:Npn \tl_build_one:o #1
+ {
+ \tex_toks:D \l_tl_build_index_int \exp_after:wN {#1}
+ \tex_advance:D \l_tl_build_index_int \c_one
+ \if_num:w \l_tl_build_index_int > \c_max_register_int
+ \tl_build_unpack:
+ \l_tl_build_index_int \l_tl_build_start_index_int
+ \fi:
+ }
+\cs_new_protected:Npn \tl_build_one:x #1
+ { \use:x { \tl_build_one:n {#1} } }
+%%
+%%
+%% End of file `l3tl-build.sty'.
diff --git a/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty b/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty
index 9d4a42407e3..ab210356d5c 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 2963 2011-11-15 22:06:41Z joseph $
+\GetIdInfo$Id: xcoffins.dtx 3385 2012-02-12 20:37:09Z bruno $
{L3 Experimental design-level coffins}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}