diff options
author | Karl Berry <karl@freefriends.org> | 2011-10-10 21:53:20 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2011-10-10 21:53:20 +0000 |
commit | 8fdc0d5c9ee743261c162302bdafbb83f9cfb542 (patch) | |
tree | 05e2062f23f57880ed2e0a26ad898e81b9d813be /Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty | |
parent | d2d088ff389655c2c3aad324760138895af2a9d3 (diff) |
l3experimental 2900 (10oct11)
git-svn-id: svn://tug.org/texlive/trunk@24258 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty')
-rw-r--r-- | Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty | 1637 |
1 files changed, 1637 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty new file mode 100644 index 00000000000..5da00fdd3d0 --- /dev/null +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty @@ -0,0 +1,1637 @@ +%% +%% This is file `l3regex.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3regex.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: l3regex.dtx Copyright (C) 2011 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 2895 2011-10-09 15:58:19Z joseph $ + {L3 Experimental Regular Expressions} +\ProvidesExplPackage + {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} +\RequirePackage{l3str} +\cs_new:Npn \regex_tmp:w { } +\tl_new:N \g_regex_tmpa_tl +\tl_new:N \l_regex_tmpa_tl +\tl_new:N \l_regex_tmpb_tl +\int_new:N \l_regex_tmpa_int +\tl_new:N \l_regex_pattern_str +\int_new:N \l_regex_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 +\seq_new:N \l_regex_capturing_group_seq +\tl_new:N \l_regex_one_or_group_tl +\int_new:N \l_regex_repetition_int +\bool_new:N \l_regex_look_behind_bool +\tl_new:N \l_regex_look_behind_str +\cs_new_eq:NN \regex_build_tmp_class:n \use_none:n +\bool_new:N \l_regex_class_bool +\tl_new:N \l_regex_class_tl +\tl_const:Nn \c_regex_d_tl + { + \regex_item_range:nn {48} {57} % 0--9 + } +\tl_const:Nn \c_regex_D_tl + { + \regex_item_more:n {57} % 9 + \regex_item_range:nn {0} {47} % 0 + } +\tl_const:Nn \c_regex_h_tl + { + \regex_item_equal:n {32} % space + \regex_item_equal:n {9} % tab + } +\tl_const:Nn \c_regex_H_tl + { + \regex_item_neq:n {32} % space + \regex_item_neq:n {9} % tab + \regex_break_true:w + } +\tl_const:Nn \c_regex_s_tl + { + \regex_item_equal:n {32} % space + \regex_item_neq:n {11} % vtab + \regex_item_range:nn {9} {13} % tab, lf, vtab, ff, cr + } +\tl_const:Nn \c_regex_S_tl + { + \regex_item_more:n {32} % > space + \regex_item_range:nn {14} {31} % tab < ... < space + \regex_item_range:nn {0} {8} % < tab + \regex_item_equal:n {11} % vtab + } +\tl_const:Nn \c_regex_v_tl + { + \regex_item_range:nn {10} {13} % lf, vtab, ff, cr + } +\tl_const:Nn \c_regex_V_tl + { + \regex_item_more:n {13} % cr + \regex_item_range:nn {0} {9} % < lf + } +\tl_const:Nn \c_regex_w_tl + { + \regex_item_range:nn {97} {122} % a--z + \regex_item_range:nn {65} {90} % A--Z + \regex_item_range:nn {48} {57} % 0--9 + \regex_item_equal:n {95} % _ + } +\tl_const:Nn \c_regex_W_tl + { + \regex_item_range:nn {0} {47} % <`0 + \regex_item_range:nn {58} {64} % (`9+1)--(`A-1) + \regex_item_range:nn {91} {94} % (`Z+1)--(`_-1) + \regex_item_equal:n {96} % ` + \regex_item_more:n {122} % z + } +\tl_const:Nn \c_regex_N_tl + { + \regex_item_neq:n {10} % lf + \regex_break_true:w + } +\tl_new:N \l_regex_query_str +\int_new:N \l_regex_start_step_int +\int_new:N \l_regex_current_char_int +\int_new:N \l_regex_current_step_int +\int_new:N \l_regex_unique_step_int +\int_new:N \l_regex_current_state_int +\prop_new:N \l_regex_current_submatches_prop +\int_new:N \l_regex_max_index_int +\tl_new:N \l_regex_every_match_tl +\cs_new_protected:Npn \regex_last_match_empty_no:F #1 {#1} +\cs_new_protected:Npn \regex_last_match_empty_yes:F + { \int_compare:nNnF \l_regex_start_step_int = \l_regex_current_step_int } +\cs_new_eq:NN \regex_last_match_empty:F \regex_last_match_empty_no:F +\bool_new:N \l_regex_success_bool +\bool_new:N \l_regex_success_empty_bool +\int_new:N \l_regex_success_step_int +\prop_new:N \l_regex_success_submatches_prop +\bool_new:N \l_regex_fresh_thread_bool +\seq_new:N \g_regex_submatches_seq +\int_new:N \g_regex_match_count_int +\seq_new:N \g_regex_split_seq +\tl_new:N \l_regex_replacement_tl +\tl_new:N \g_regex_replaced_str +\cs_new_eq:NN \s_regex_toks \scan_stop: +\cs_new_protected:Npn \regex_toks_put_left:Nx #1#2 + { + \cs_set_nopar:Npx \regex_tmp:w \s_regex_toks { \s_regex_toks #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_eq:NN \regex_if_tail_stop:N \quark_if_recursion_tail_stop:N +\cs_new_protected_nopar:Npn \regex_if_tail_error:Nn #1#2 + { \quark_if_recursion_tail_stop_do:Nn #1 { \regex_build_error:n {#2} } } +\cs_new_protected_nopar:Npn \regex_build_error:n #1 + { + \msg_error:nnxx { regex } { build-error } {\int_eval:n{#1}} + { + \prg_case_int:nnn {#1} + { + {-999} {File~not~found} + {-998} {Unsupported~construct} + {-997} {The~regular~expression~is~too~large~(32768~states).} + {1} {\iow_char:N\\~at~end~of~pattern } + {4} {Numbers~out~of~order~in~\iow_char:N\{\iow_char\}~quantifier.} + {6} {Missing~terminating~\iow_char:N\]~for~character~class } + {7} {Invalid~escape~sequence~in~character~class} + {8} {Range~out~of~order~in~character~class} + {22} {Mismatched~parentheses} + {34} {Character~value~in~\iow_char:N\\x{...}~sequence~is~too~large} + } + { Internal~bug. } + } + } +\msg_new:nnn { regex } { build-error } { (error~#1): ~ #2 } +\cs_new_nopar:Npn \regex_break_true:w #1 \regex_break_point:TF #2 #3 {#2} +\cs_new_nopar:Npn \regex_break_false:w #1 \regex_break_point:TF #2 #3 {#3} +\cs_new_eq:NN \regex_break_point:TF \use_ii:nn +\cs_new_nopar:Npn \regex_item_equal:n #1 + { + \if_num:w #1 = \l_regex_current_char_int + \exp_after:wN \regex_break_true:w + \fi: + } +\cs_new_nopar:Npn \regex_item_range:nn #1 #2 + { + \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_nopar:Npn \regex_item_less:n #1 + { + \if_num:w #1 > \l_regex_current_char_int + \exp_after:wN \regex_break_true:w + \fi: + } +\cs_new_nopar:Npn \regex_item_more:n #1 + { + \if_num:w #1 < \l_regex_current_char_int + \exp_after:wN \regex_break_true:w + \fi: + } +\cs_new_nopar:Npn \regex_item_neq:n #1 + { + \if_num:w #1 = \l_regex_current_char_int + \exp_after:wN \regex_break_false:w + \fi: + } +\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:N + } +\cs_new_nopar:Npn \regex_get_digits_aux:N #1 + { + \if_num:w 9 < 1 \exp_not:N #1 \exp_stop_f: + \else: + \if_charcode:w \c_space_token \exp_not:N #1 + \else: + \regex_get_digits_end:w + \fi: + \fi: + #1 \regex_get_digits_aux:N + } +\cs_new_nopar:Npn \regex_get_digits_end:w + \fi: \fi: #1 \regex_get_digits_aux:N + { + \fi: \fi: + \if_false: { { \fi: } } + #1 + } +\prg_new_conditional:Npnn \regex_aux_char_if_special:N #1 { TF } + { + \if_num:w `#1 < 97 \exp_stop_f: + \if_num:w `#1 < 58 \exp_stop_f: + \if_num:w \int_eval:w (`#1 - \c_eight)/\c_sixteen = \c_two + \prg_return_true: + \else: + \prg_return_false: + \fi: + \else: + \if_num:w \int_eval:w `#1 / 26 = \c_three + \prg_return_false: + \else: + \prg_return_true: + \fi: + \fi: + \else: + \if_num:w \int_eval:w `#1 / \c_five = 25 \exp_stop_f: + \prg_return_true: + \else: + \prg_return_false: + \fi: + \fi: + } +\prg_new_conditional:Npnn \regex_aux_char_if_alphanumeric:N #1 { TF } + { + \if_num:w `#1 < 91 \exp_stop_f: + \if_num:w `#1 < 65 \exp_stop_f: + \if_num:w \c_nine < 1 #1 \exp_stop_f: + \prg_return_true: + \else: + \prg_return_false: + \fi: + \else: + \prg_return_true: + \fi: + \else: + \if_num:w \int_eval:w (`#1-\c_six)/26 = \c_four + \prg_return_true: + \else: + \prg_return_false: + \fi: + \fi: + } +\cs_new_protected_nopar:Npn \regex_build_new_state: + { + \int_compare:nNnTF \l_regex_max_state_int > {32766} + { \regex_build_error:n {-997} } + { + \int_incr:N \l_regex_max_state_int + \tex_toks:D \l_regex_max_state_int { \s_regex_toks } + } + \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 + } +\cs_new_protected_nopar:Npn \regex_build_transition_aux:NN #1#2 + { + \regex_build_new_state: + \regex_toks_put_right:Nx \l_regex_left_state_int + { #1 { \int_use:N #2 } } + } +\cs_new_protected_nopar:Npn \regex_build_transitions_aux:NNNN #1#2#3#4 + { + \regex_build_new_state: + \regex_toks_put_right:Nx \l_regex_left_state_int + { + #1 { \int_use:N #2 } + #3 { \int_use:N #4 } + } + } +\cs_new_protected:Npn \regex_build:n #1 + { + \regex_build_setup: + \str_aux_escape:NNNn + \regex_build_i_unescaped:N + \regex_build_i_escaped:N + \regex_build_i_raw:N + { #1 } + \regex_build_open_aux: + \g_str_result_tl \prg_do_nothing: \prg_do_nothing: + \seq_push:Nn \l_regex_capturing_group_seq { 0 } + \regex_build_close_aux: \regex_build_group_: + \regex_build_end: + } +\cs_new_nopar:Npn \regex_build_i_unescaped:N #1 + { + \regex_aux_char_if_special:NTF #1 + { \exp_not:N \regex_build_control:N #1 } + { \exp_not:N \regex_build_raw:N #1 } + } +\cs_new_nopar:Npn \regex_build_i_escaped:N #1 + { + \regex_aux_char_if_alphanumeric:NTF #1 + { \exp_not:N \regex_build_control:N #1 } + { \exp_not:N \regex_build_raw:N #1 } + } +\cs_new_nopar:Npn \regex_build_i_raw:N #1 + { \exp_not:N \regex_build_raw:N #1 } +\cs_new_protected_nopar:Npn \regex_build_default_control:N #1 + { + \cs_if_exist_use:cF { regex_build_#1: } + { \regex_build_default_raw:N #1 } + } +\cs_new_protected_nopar:Npn \regex_build_setup: + { + \cs_set_eq:NN \regex_build_control:N \regex_build_default_control:N + \cs_set_eq:NN \regex_build_raw:N \regex_build_default_raw:N + \int_set_eq:NN \l_regex_capturing_group_int \c_zero + \int_zero:N \l_regex_left_state_int + \int_zero:N \l_regex_right_state_int + \int_zero:N \l_regex_max_state_int + \regex_build_new_state: + \regex_build_new_state: + \regex_toks_put_right:Nx \l_regex_left_state_int + { + \regex_action_start_wildcard:nn + { \int_use:N \l_regex_left_state_int } + { \int_use:N \l_regex_right_state_int } + } + } +\cs_new_protected_nopar:Npn \regex_build_end: + { + \seq_if_empty:NF \l_regex_capturing_group_seq + { + \regex_build_error:n {22} + \prg_replicate:nn + { \seq_length:N \l_regex_capturing_group_seq } % ( + { \regex_build_close_aux: \regex_build_group_: } + } + \regex_toks_put_right:Nx \l_regex_right_state_int + { \regex_action_success: } + } +\cs_new_protected_nopar:cpn { regex_build_^: } + { \regex_build_anchor_start:N \c_zero } +\cs_new_protected_nopar:Npn \regex_build_A: + { \regex_build_anchor_start:N \c_zero } +\cs_new_protected_nopar:Npn \regex_build_G: + { \regex_build_anchor_start:N \l_regex_start_step_int } +\cs_new_protected_nopar:Npn \regex_build_anchor_start:N #1 + { + \regex_build_new_state: + \regex_toks_put_right:Nx \l_regex_left_state_int + { + \exp_not:N \int_compare:nNnT {#1} = \l_regex_current_step_int + { \regex_action_free:n { \int_use:N \l_regex_right_state_int } } + } + } +\cs_new_protected_nopar:cpn { regex_build_$: } % $ + { + \regex_build_new_state: + \regex_toks_put_right:Nx \l_regex_left_state_int + { + \exp_not:N \int_compare:nNnT + \c_minus_one = \l_regex_current_char_int + { \regex_action_free:n { \int_use:N \l_regex_right_state_int } } + } + } +\cs_new_eq:Nc \regex_build_Z: { regex_build_$: } %$ +\cs_new_eq:Nc \regex_build_z: { regex_build_$: } %$ +\cs_new_protected_nopar:Npn \regex_build_b: + { + \bool_set_true:N \l_regex_look_behind_bool + \regex_build_new_state: + \regex_toks_put_right:Nx \l_regex_left_state_int + { + \exp_not:N \regex_if_word_boundary:TF + { \regex_action_free:n { \int_use:N \l_regex_right_state_int } } + { } + } + } +\cs_new_protected_nopar:Npn \regex_build_B: + { + \bool_set_true:N \l_regex_look_behind_bool + \regex_build_new_state: + \regex_toks_put_right:Nx \l_regex_left_state_int + { + \exp_not:N \regex_if_word_boundary:TF + { } + { \regex_action_free:n { \int_use:N \l_regex_right_state_int } } + } + } +\cs_new_protected_nopar:Npn \regex_if_word_boundary:TF + { + \tl_if_empty:NTF \l_regex_look_behind_str + { \c_regex_w_tl } + { + \group_begin: + \cs_set_nopar:Npx \regex_tmp:w + { + \int_set:Nn \l_regex_current_char_int + { ` \str_head:N \l_regex_look_behind_str } + } + \regex_tmp:w + \c_regex_w_tl + \regex_break_point:TF + { \group_end: \c_regex_W_tl } + { \group_end: \c_regex_w_tl } + } + \regex_break_point:TF + } +\cs_new_protected_nopar:Npn \regex_build_default_raw:N #1 + { + \cs_set:Npx \regex_build_tmp_class:n ##1 + { + \exp_not:n { \exp_not:N \if_num:w } + \int_value:w `#1 = \l_regex_current_char_int + \regex_action_cost:n { ##1 } + \exp_not:n { \exp_not:N \fi: } + } + \regex_build_one_quantifier: + } +\cs_new_protected_nopar:cpn { regex_build_.: } + { + \cs_set:Npn \regex_build_tmp_class:n ##1 + { + \exp_not:N \if_num:w \c_minus_one < \l_regex_current_char_int + \regex_action_cost:n {##1} + \exp_not:N \fi: + } + \regex_build_one_quantifier: + } +\cs_new_protected_nopar:Npn \regex_build_char_type:N #1 + { + \cs_set:Npn \regex_build_tmp_class:n ##1 + { + \exp_not:N #1 + \exp_not:N \regex_break_point:TF + { \regex_action_cost:n {##1} } + { } + } + \regex_build_one_quantifier: + } +\tl_map_inline:nn { dDhHsSvVwWN } + { + \cs_new_protected_nopar:cpx { regex_build_#1: } + { + \exp_not:N \regex_build_char_type:N + \exp_not:c { c_regex_#1_tl } + } + } +\cs_new_protected_nopar:cpn { regex_build_[: } + { + \tl_clear:N \l_regex_class_tl + \cs_set_eq:NN \regex_build_control:N \regex_class_control:N + \cs_set_eq:NN \regex_build_raw:N \regex_class_raw:N + \regex_class_first:NN + } +\cs_new_protected_nopar:Npn \regex_class_control:N #1 + { + \cs_if_exist_use:cF { regex_class_#1: } + { \regex_class_raw:N #1 } + } +\cs_new_protected_nopar:cpn { regex_class_]: } + { + \tl_if_empty:NTF \l_regex_class_tl %[ + { \regex_class_raw:N ] } + { + \cs_set_eq:NN \regex_build_control:N \regex_build_default_control:N + \cs_set_eq:NN \regex_build_raw:N \regex_build_default_raw:N + \cs_set:Npn \regex_build_tmp_class:n ##1 + { + \exp_not:o \l_regex_class_tl + \bool_if:NTF \l_regex_class_bool + { + \exp_not:N \regex_break_point:TF + { \regex_action_cost:n {##1} } + { } + } + { + \exp_not:N \regex_break_point:TF + { } + { \regex_action_cost:n {##1} } + } + } + \regex_build_one_quantifier: + } + } +\cs_new_protected_nopar:Npn \regex_class_first:NN #1#2 + { + \str_if_eq:nnTF {#1#2} { \regex_build_control:N ^ } + { \bool_set_false:N \l_regex_class_bool } + { + \bool_set_true:N \l_regex_class_bool + #1 #2 + } + } +\cs_new_protected_nopar:Npn \regex_class_raw:N #1#2#3 + { + \str_if_eq:nnTF {#2#3} { \regex_build_control:N - } + { \regex_class_range:Nw #1 } + { + \regex_class_single:N #1 + #2 #3 + } + } +\cs_new_protected_nopar:Npn \regex_class_single:N #1 + { + \tl_put_right:Nx \l_regex_class_tl + { \exp_not:N \regex_item_equal:n { \int_value:w `#1 } } + } +\cs_new_protected_nopar:Npn \regex_class_range:Nw #1#2#3 + { + \token_if_eq_meaning:NNTF #2 \regex_build_control:N + { + \cs_if_exist:cTF { regex_class_#3: } + { + \regex_class_single:N #1 + \regex_class_single:N - + #2#3 + } + { \regex_class_range_put:NN #1#3 } + } + { \regex_class_range_put:NN #1#3 } + } +\cs_new_protected_nopar:Npn \regex_class_range_put:NN #1#2 + { + \if_num:w `#1 > `#2 \exp_stop_f: + \regex_build_error:n {8} + \else: + \tl_put_right:Nx \l_regex_class_tl + { + \if_num:w `#1 = `#2 \exp_stop_f: + \exp_not:N \regex_item_equal:n + \else: + \exp_not:N \regex_item_range:nn { \int_value:w `#1 } + \fi: + { \int_value:w `#2 } + } + \fi: + } +\tl_map_inline:nn { dDhHsSvVwWN } + { + \cs_new_protected_nopar:cpx { regex_class_#1: } + { + \tl_put_right:Nn \exp_not:N \l_regex_class_tl + { \exp_not:c { c_regex_#1_tl } } + } + } +\cs_new_protected_nopar:Npn \regex_build_quantifier:w #1#2 + { + \token_if_eq_meaning:NNTF #1 \regex_build_control:N + { + \cs_if_exist_use:cF { regex_build_quantifier_#2:w } + { + \regex_build_quantifier_end:n { } + #1 #2 + } + } + { + \regex_build_quantifier_end:n { } + #1 #2 + } + } +\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_nopar:Npn \regex_build_quantifier_aux:nnNN #1#2#3#4 + { + \str_if_eq:nnTF { #3 #4 } { \regex_build_control:N ? } + { \regex_build_quantifier_end:n { #2 #4 } #1 } + { + \regex_build_quantifier_end:n { #2 } #1 + #3 #4 + } + } +\cs_new_protected_nopar:cpn { regex_build_quantifier_ \c_lbrace_str :w } + { \regex_get_digits:nw { \regex_build_quantifier_lbrace:n } } +\cs_new_protected_nopar:Npn \regex_build_quantifier_lbrace:n #1 + { + \tl_if_empty:nTF {#1} + { + \regex_build_quantifier_end:n { } + \exp_after:wN \regex_build_raw:N \c_lbrace_str + } + { \regex_build_quantifier_lbrace:nw {#1} } + } +\cs_new_protected_nopar:Npx \regex_build_quantifier_lbrace:nw #1#2#3 + { + \exp_not:N \prg_case_str:nnn { #2 #3 } + { + { \exp_not:N \regex_build_control:N , } + { + \exp_not:N \regex_get_digits:nw + { \exp_not:N \regex_build_quantifier_lbrace:nnw {#1} } + } + { \exp_not:N \regex_build_control:N \c_rbrace_str } + { \exp_not:N \regex_build_quantifier_end:n {n} {#1} } + } + { + \exp_not:N \regex_build_quantifier_end:n { } + \exp_not:N \regex_build_raw:N \c_lbrace_str #1#2 + } + } +\cs_new_protected_nopar:Npn \regex_build_quantifier_lbrace:nnw #1#2#3 + { + \str_if_eq:xxTF { \exp_not:N #3 } { \c_rbrace_str } + { + \tl_if_empty:nTF {#2} + { \regex_build_quantifier_aux:nnN { {#1} {\c_max_int} } {nn} } + { + \int_compare:nNnT {#1} > {#2} + { \regex_build_error:n {4} } + \regex_build_quantifier_aux:nnN { {#1} {#2} } {nn} + } + } + { + \regex_build_quantifier_end:n { } + \use:x + { + \exp_not:n { \exp_args:No \tl_map_function:nN } + { \c_lbrace_str #1 #2 , } + \regex_build_raw:N + } + } + } +\cs_new_protected_nopar:Npn \regex_build_quantifier_end:n #1 + { \use:c { regex_build_ \l_regex_one_or_group_tl _ #1 : } } +\cs_new_protected_nopar:Npn \regex_build_one_quantifier: + { + \tl_set:Nx \l_regex_one_or_group_tl { one } + \regex_build_quantifier:w + } +\cs_new_protected_nopar:Npn \regex_build_one_: + { + \regex_build_transition_aux:NN + \regex_build_tmp_class:n \l_regex_right_state_int + } +\cs_new_protected_nopar:cpn { regex_build_one_?: } + { + \regex_build_transitions_aux:NNNN + \regex_build_tmp_class:n \l_regex_right_state_int + \regex_action_free:n \l_regex_right_state_int + } +\cs_new_protected_nopar:cpn { regex_build_one_??: } + { + \regex_build_transitions_aux:NNNN + \regex_action_free:n \l_regex_right_state_int + \regex_build_tmp_class:n \l_regex_right_state_int + } +\cs_new_protected_nopar:cpn { regex_build_one_*: } + { + \regex_build_transitions_aux:NNNN + \regex_build_tmp_class:n \l_regex_left_state_int + \regex_action_free:n \l_regex_right_state_int + } +\cs_new_protected_nopar:cpn { regex_build_one_*?: } + { + \regex_build_transitions_aux:NNNN + \regex_action_free:n \l_regex_right_state_int + \regex_build_tmp_class:n \l_regex_left_state_int + } +\cs_new_protected_nopar:cpn { regex_build_one_+: } + { + \regex_build_one_: + \int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int + \regex_build_transitions_aux:NNNN + \regex_action_free:n \l_regex_tmpa_int + \regex_action_free:n \l_regex_right_state_int + } +\cs_new_protected_nopar:cpn { regex_build_one_+?: } + { + \regex_build_one_: + \int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int + \regex_build_transitions_aux:NNNN + \regex_action_free:n \l_regex_right_state_int + \regex_action_free:n \l_regex_tmpa_int + } +\cs_new_protected_nopar:Npn \regex_build_one_n: #1 + { + \int_set_eq:NN \l_regex_tmpa_int \l_regex_right_state_int + \regex_build_new_state: + \regex_build_new_state: + \regex_toks_put_right:Nx \l_regex_tmpa_int + { %^^A safe \if nesting? + \exp_not:N \if_num:w #1 > \l_regex_repetition_int + \regex_action_repeat_move:n + { \int_use:N \l_regex_left_state_int } + \exp_not:N \else: + \regex_action_no_repeat_move:n + { \int_use:N \l_regex_right_state_int } + \exp_not:N \fi: + } + \regex_toks_put_right:Nx \l_regex_left_state_int + { + \regex_build_tmp_class:n + { \int_use:N \l_regex_tmpa_int } + } + } +\cs_new_eq:cN { regex_build_one_n?: } \regex_build_one_n: +\cs_new_protected_nopar:Npn \regex_build_one_nn: #1#2 + { + \regex_build_one_nn_aux:nn {#1} + { + \exp_not:N \if_num:w #2 > \l_regex_repetition_int + \regex_action_repeat_copy:n + { \int_use:N \l_regex_left_state_int } + \exp_not:N \fi: + \regex_action_no_repeat_move:n + { \int_use:N \l_regex_right_state_int } + } + } +\cs_new_protected_nopar:cpn { regex_build_one_nn?: } #1#2 + { + \regex_build_one_nn_aux:nn {#1} + { + \regex_action_no_repeat_copy:n + { \int_use:N \l_regex_right_state_int } + \exp_not:N \if_num:w #2 > \l_regex_repetition_int + \regex_action_repeat_move:n + { \int_use:N \l_regex_left_state_int } + \exp_not:N \fi: + } + } +\cs_new_protected_nopar:Npn \regex_build_one_nn_aux:nn #1#2 + { + \int_set_eq:NN \l_regex_tmpa_int \l_regex_right_state_int + \regex_build_new_state: + \regex_build_new_state: + \regex_toks_put_right:Nx \l_regex_tmpa_int + { + \exp_not:N \if_num:w #1 > \l_regex_repetition_int + \regex_action_repeat_move:n + { \int_use:N \l_regex_left_state_int } + \exp_not:N \else: + #2 + \exp_not:N \fi: + } + \regex_toks_put_right:Nx \l_regex_left_state_int + { + \regex_build_tmp_class:n + { \int_use:N \l_regex_tmpa_int } + } + } +\cs_new_protected_nopar:cpn { regex_build_(: } #1#2 + { + \str_if_eq:nnTF { #1 #2 } { \regex_build_control:N ? } + { \regex_build_special_group:NN } + { + \int_incr:N \l_regex_capturing_group_int + \seq_push:Nx \l_regex_capturing_group_seq + { \int_use:N \l_regex_capturing_group_int } + \regex_build_open_aux: + #1 #2 + } + } +\cs_new_protected_nopar:Npn \regex_build_open_aux: + { + \regex_build_new_state: + \seq_push:Nx \l_regex_left_state_seq + { \int_use:N \l_regex_left_state_int } + \seq_push:Nx \l_regex_right_state_seq + { \int_use:N \l_regex_right_state_int } + \regex_build_begin_alternation: + } +\cs_new_protected_nopar:cpn { regex_build_|: } + { + \regex_build_end_alternation: + \regex_build_begin_alternation: + } +\cs_new_protected_nopar:cpn { regex_build_): } + { + \seq_if_empty:NTF \l_regex_capturing_group_seq + { \regex_build_error:n {22} } + { + \regex_build_close_aux: + \regex_build_group_quantifier: + } + } +\cs_new_protected_nopar:Npn \regex_build_close_aux: + { + \regex_build_end_alternation: + \seq_pop:NN \l_regex_left_state_seq \l_regex_tmpa_tl + \int_set:Nn \l_regex_left_state_int \l_regex_tmpa_tl + \seq_pop:NN \l_regex_right_state_seq \l_regex_tmpa_tl + \int_set:Nn \l_regex_right_state_int \l_regex_tmpa_tl + } +\cs_new_protected_nopar:Npn \regex_build_begin_alternation: + { + \regex_build_new_state: + \seq_get:NN \l_regex_left_state_seq \l_regex_tmpa_tl + \int_set:Nn \l_regex_left_state_int \l_regex_tmpa_tl + \regex_toks_put_right:Nx \l_regex_left_state_int + { \regex_action_free:n { \int_use:N \l_regex_right_state_int } } + } +\cs_new_protected_nopar:Npn \regex_build_end_alternation: + { + \seq_get:NN \l_regex_right_state_seq \l_regex_tmpa_tl + \regex_toks_put_right:Nx \l_regex_right_state_int + { \regex_action_free:n { \l_regex_tmpa_tl } } + } +\cs_new_protected_nopar:Npn \regex_build_special_group:NN #1#2 + { + \cs_if_exist_use:cF { regex_build_special_group_\token_to_str:N #2 : } + { + \regex_build_error:n { -998 } + \regex_build_control:N ( % ) + \regex_build_raw:N ? + #1 #2 + } + } +\cs_new_protected_nopar:cpn { regex_build_special_group_:: } + { + \seq_push:Nx \l_regex_capturing_group_seq { * } + \regex_build_open_aux: + } +\cs_new_protected_nopar:Npn \regex_build_group_quantifier: + { + \tl_set:Nn \l_regex_one_or_group_tl { group } + \regex_build_quantifier:w + } +\cs_new_protected_nopar:Npn \regex_build_group_submatches:NN #1#2 + { + \seq_pop:NN \l_regex_capturing_group_seq \l_regex_tmpa_tl + \str_if_eq:xxF { \l_regex_tmpa_tl } { * } + { + \regex_toks_put_left:Nx #1 + { \regex_action_submatch:n { \l_regex_tmpa_tl < } } + \regex_toks_put_left:Nx #2 + { \regex_action_submatch:n { \l_regex_tmpa_tl > } } + } + } +\cs_new_protected_nopar:Npn \regex_build_group_: + { + \regex_build_group_submatches:NN + \l_regex_left_state_int \l_regex_right_state_int + \regex_build_transition_aux:NN + \regex_action_free:n \l_regex_right_state_int + } +\cs_new_protected_nopar:Npn \regex_build_group_shift:N #1 + { + \int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int + \regex_build_new_state: + \tex_toks:D \l_regex_right_state_int = \tex_toks:D \l_regex_tmpa_int + \use:x + { + \tex_toks:D \l_regex_tmpa_int + { \s_regex_toks #1 { \int_use:N \l_regex_right_state_int } } + } + \regex_build_group_submatches:NN + \l_regex_right_state_int \l_regex_left_state_int + \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int + } +\cs_new_protected_nopar:Npn \regex_build_group_qs_aux:NN #1#2 + { + \regex_build_group_shift:N \regex_action_free:n + \regex_build_transition_aux:NN \regex_action_free:n #1 + #2 \l_regex_tmpa_int + { \regex_action_free:n { \int_use:N \l_regex_right_state_int } } + } +\cs_new_protected_nopar:cpn { regex_build_group_?: } + { + \regex_build_group_qs_aux:NN + \l_regex_right_state_int \regex_toks_put_right:Nx + } +\cs_new_protected_nopar:cpn { regex_build_group_??: } + { + \regex_build_group_qs_aux:NN + \l_regex_right_state_int \regex_toks_put_left:Nx + } +\cs_new_protected_nopar:cpn { regex_build_group_*: } + { + \regex_build_group_qs_aux:NN + \l_regex_tmpa_int \regex_toks_put_right:Nx + } +\cs_new_protected_nopar:cpn { regex_build_group_*?: } + { + \regex_build_group_qs_aux:NN + \l_regex_tmpa_int \regex_toks_put_left:Nx + } +\cs_new_protected_nopar:cpn { regex_build_group_+: } + { + \regex_build_group_submatches:NN + \l_regex_left_state_int \l_regex_right_state_int + \int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int + \regex_build_transitions_aux:NNNN + \regex_action_free:n \l_regex_tmpa_int + \regex_action_free:n \l_regex_right_state_int + } +\cs_new_protected_nopar:cpn { regex_build_group_+?: } + { + \regex_build_group_submatches:NN + \l_regex_left_state_int \l_regex_right_state_int + \int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int + \regex_build_transitions_aux:NNNN + \regex_action_free:n \l_regex_right_state_int + \regex_action_free:n \l_regex_tmpa_int + } +\cs_new_protected_nopar:Npn \regex_build_group_n: #1 + { + \regex_build_group_shift:N \regex_action_repeat_move:n + \regex_build_transition_aux:NN + \regex_action_free:n \l_regex_tmpa_int + \use:x + { + \tex_toks:D \l_regex_tmpa_int + { + \s_regex_toks + \exp_not:N \if_num:w #1 > \l_regex_repetition_int + \tex_the:D \tex_toks:D \l_regex_tmpa_int + \exp_not:N \else: + \regex_action_no_repeat_move:n + { \int_use:N \l_regex_right_state_int } + \exp_not:N \fi: + } + } + } +\cs_new_eq:cN { regex_build_group_n?: } \regex_build_group_n: +\cs_new_protected_nopar:Npn \regex_build_group_nn: #1#2 + { + \regex_build_group_shift:N \regex_action_repeat_move:n + \regex_build_transition_aux:NN + \regex_action_free:n \l_regex_tmpa_int + \use:x + { + \tex_toks:D \l_regex_tmpa_int + { + \s_regex_toks + \exp_not:N \if_num:w #1 > \l_regex_repetition_int + \tex_the:D \tex_toks:D \l_regex_tmpa_int + \exp_not:N \else: + \exp_not:N \if_num:w #2 > \l_regex_repetition_int + \tex_the:D \tex_toks:D \l_regex_tmpa_int + \exp_not:N \fi: + \regex_action_no_repeat_copy:n + { \int_use:N \l_regex_right_state_int } + \exp_not:N \fi: + } + } + } +\cs_new_protected_nopar:cpn { regex_build_group_nn?: } #1#2 + { + \regex_build_group_shift:N \regex_action_repeat_move:n + \regex_build_transition_aux:NN + \regex_action_free:n \l_regex_tmpa_int + \use:x + { + \tex_toks:D \l_regex_tmpa_int + { + \s_regex_toks + \exp_not:N \if_num:w #1 > \l_regex_repetition_int + \tex_the:D \tex_toks:D \l_regex_tmpa_int + \exp_not:N \else: + \regex_action_no_repeat_copy:n + { \int_use:N \l_regex_right_state_int } + \exp_not:N \if_num:w #2 > \l_regex_repetition_int + \tex_the:D \tex_toks:D \l_regex_tmpa_int + \exp_not:N \fi: + \exp_not:N \fi: + } + } + } +\cs_new_protected:Npn \regex_if_state_free:nT #1 + { + \if_num:w \tex_dimen:D #1 = \l_regex_unique_step_int + \exp_after:wN \use_none:n + \else: + \exp_after:wN \use:n + \fi: + } +\cs_new_protected:Npn \regex_store_state:n #1 + { + \int_incr:N \l_regex_max_index_int + \tex_skip:D \l_regex_max_index_int #1 sp \scan_stop: + \regex_store_submatches:n {#1} + } +\cs_new_protected_nopar:Npn \regex_state_use_submatches: + { \regex_state_use_aux:n { } } +\cs_new_protected_nopar:Npn \regex_state_use: + { \regex_state_use_aux:n { \exp_after:wN \regex_state_use_aux_ii:w } } +\cs_new:Npn \regex_state_use_aux_ii:w #1 \s_regex_toks { } +\cs_new_protected:Npn \regex_state_use_aux:n #1 + { + \regex_if_state_free:nT { \l_regex_current_state_int } + { + \tex_dimen:D \l_regex_current_state_int + = \l_regex_unique_step_int sp \scan_stop: + #1 \tex_the:D \tex_toks:D \l_regex_current_state_int \scan_stop: + } + } +\cs_new_protected_nopar:Npn \regex_disable_submatches: + { + \cs_set_eq:NN \regex_state_use_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 + } +\cs_new_protected:Npn \regex_protected_use_none:n #1 { } +\cs_new_protected:Npn \regex_store_submatches:n #1 + { + \exp_after:wN \regex_store_submatches_aux:Nw + \exp_after:wN \l_regex_current_submatches_prop + \tex_the:D \tex_toks:D #1 \scan_stop: \q_stop + { #1 } + } +\cs_new_protected:Npn \regex_store_submatches_aux:Nw #1 #2 \s_regex_toks + { + \exp_args:No \regex_store_submatches_aux_ii:wnnwwn { #1 } + #2 + \regex_state_submatches:nn { \c_minus_one } { \q_prop } + \s_regex_toks + } +\cs_new_protected:Npn \regex_store_submatches_aux_ii:wnnwwn + #1 \regex_state_submatches:nn #2#3 #4 \s_regex_toks #5 \q_stop #6 + { + \tex_toks:D #6 \exp_after:wN + { + \exp_after:wN \regex_state_submatches:nn \exp_after:wN + { \int_value:w \int_eval:w \l_regex_unique_step_int + \c_one } + { #1 } + \regex_state_submatches:nn {#2} {#3} + \s_regex_toks + #5 + } + } +\cs_new_protected:Npn \regex_state_submatches:nn #1#2 + { + \if_num:w #1 = \l_regex_unique_step_int + \tl_set:Nn \l_regex_current_submatches_prop {#2} + \fi: + } +\cs_new_protected:Npn \regex_match:n #1 + { + \tl_set:Nx \l_regex_query_str { \tl_to_other_str:n {#1} } + \regex_match_initial_setup: + \regex_match_once: + } +\cs_new_protected_nopar:Npn \regex_match_once: + { + \regex_match_setup: + \exp_after:wN \regex_match_once_aux: \l_regex_query_str + \q_recursion_tail \q_recursion_stop + \bool_if:NT \l_regex_success_bool { \l_regex_every_match_tl } + } +\cs_new_protected_nopar:Npn \regex_match_once_aux: + { \str_skip_do:nn { \l_regex_start_step_int } { \regex_match_loop:N } } +\cs_new_protected_nopar:Npn \regex_match_initial_setup: + { + \tl_clear:N \l_regex_look_behind_str + \prg_stepwise_inline:nnnn {1} {1} { \l_regex_max_state_int } + { \tex_dimen:D ##1 \c_minus_one sp \scan_stop: } + \int_set_eq:NN \l_regex_unique_step_int \c_minus_one + \int_set_eq:NN \l_regex_start_step_int \c_minus_one + \int_set_eq:NN \l_regex_current_step_int \c_zero + \int_set_eq:NN \l_regex_success_step_int \c_zero + \bool_set_false:N \l_regex_success_empty_bool + } +\cs_new_protected_nopar:Npn \regex_match_setup: + { + \prop_clear:N \l_regex_current_submatches_prop + \bool_if:NTF \l_regex_success_empty_bool + { \cs_set_eq:NN \regex_last_match_empty:F \regex_last_match_empty_yes:F } + { \cs_set_eq:NN \regex_last_match_empty:F \regex_last_match_empty_no:F } + \int_set_eq:NN \l_regex_start_step_int \l_regex_success_step_int + \int_set_eq:NN \l_regex_current_step_int \l_regex_start_step_int + \int_decr:N \l_regex_current_step_int + \bool_set_false:N \l_regex_success_bool + \int_zero:N \l_regex_max_index_int + \regex_store_state:n {1} + } +\cs_new_protected_nopar:Npn \regex_match_loop_setup: + { + \int_incr:N \l_regex_current_step_int + \int_incr:N \l_regex_unique_step_int + \bool_set_false:N \l_regex_fresh_thread_bool + } +\cs_new_eq:NN \s_regex_step \scan_stop: +\cs_new:Npn \regex_break_step:w #1 \s_regex_step { } +\cs_new_protected_nopar:Npn \regex_match_loop:N #1 + { + \regex_match_loop_setup: + \token_if_eq_meaning:NNTF #1 \q_recursion_tail + { \int_set_eq:NN \l_regex_current_char_int \c_minus_one } + { \int_set:Nn \l_regex_current_char_int {`#1} } + \cs_set_nopar:Npx \regex_tmp:w + { + \int_zero:N \l_regex_max_index_int + \prg_stepwise_function:nnnN + {1} {1} { \l_regex_max_index_int } + \regex_match_one_index:n + } + \regex_tmp:w + \s_regex_step + \if_num:w \l_regex_max_index_int = \c_zero + \exp_after:wN \use_none_delimit_by_q_recursion_stop:w + \fi: + \quark_if_recursion_tail_stop:N #1 + \bool_if:NT \l_regex_look_behind_bool + { \tl_put_left:Nx \l_regex_look_behind_str {#1} } + \regex_match_loop:N + } +\cs_new_nopar:Npn \regex_match_one_index:n #1 + { + \regex_match_one_index_aux:n { \int_value:w \tex_skip:D #1 } + } +\cs_new_protected_nopar:Npn \regex_match_one_index_aux:n #1 + { + \int_set:Nn \l_regex_current_state_int {#1} + \prop_clear:N \l_regex_current_submatches_prop + \regex_state_use_submatches: + } +\cs_new_protected_nopar:Npn \regex_action_start_wildcard:nn #1#2 + { + \bool_set_true:N \l_regex_fresh_thread_bool + \regex_action_free:n {#2} + \bool_set_false:N \l_regex_fresh_thread_bool + \regex_action_cost:n {#1} + } +\cs_new_protected_nopar:Npn \regex_action_cost:n #1 + { \regex_store_state:n {#1} } +\cs_new_protected_nopar:Npn \regex_action_success: + { + \regex_last_match_empty:F + { + \bool_set_true:N \l_regex_success_bool + \bool_set_eq:NN \l_regex_success_empty_bool + \l_regex_fresh_thread_bool + \int_set_eq:NN \l_regex_success_step_int + \l_regex_current_step_int + \prop_set_eq:NN \l_regex_success_submatches_prop + \l_regex_current_submatches_prop + \regex_break_step:w + } + } +\cs_new_protected_nopar:Npn \regex_action_free:n #1 + { + \regex_if_state_free:nT {#1} + { + \use:x + { + \int_set:Nn \l_regex_current_state_int {#1} + \regex_store_submatches:n { \l_regex_current_state_int } + \regex_state_use: + \int_set:Nn \l_regex_current_state_int + { \int_use:N \l_regex_current_state_int } + \tl_set:Nn \exp_not:N \l_regex_current_submatches_prop + { \exp_not:o \l_regex_current_submatches_prop } + } + } + } +\cs_new_protected_nopar:Npn \regex_action_submatch:n #1 + { + \prop_put:Nno \l_regex_current_submatches_prop {#1} + { \int_use:N \l_regex_current_step_int } + \regex_store_submatches:n { \l_regex_current_state_int } + } +\cs_new_protected_nopar:Npn \regex_action_repeat_copy:n { \ERROR } +\cs_new_protected_nopar:Npn \regex_action_repeat_move:n { \ERROR } +\cs_new_protected_nopar:Npn \regex_action_no_repeat_copy:n { \ERROR } +\cs_new_protected_nopar:Npn \regex_action_no_repeat_move:n { \ERROR } +\cs_new_protected_nopar:Npn \regex_extract: + { + \seq_gclear:N \g_regex_submatches_seq + \prg_stepwise_inline:nnnn + {0} {1} { \l_regex_capturing_group_int } + { + \regex_extract_aux:nTF { ##1 } + { + \seq_gput_right:Nx \g_regex_submatches_seq + { + \str_from_to:Nnn \l_regex_query_str + { \l_regex_tmpa_tl } + { \l_regex_tmpb_tl } + } + } + { \seq_gput_right:Nn \g_regex_submatches_seq { } } + } + } +\cs_new_protected_nopar:Npn \regex_extract_aux:nTF #1#2#3 + { + \prop_get:NnNTF \l_regex_success_submatches_prop + { #1 < } \l_regex_tmpa_tl + { + \prop_get:NnNTF \l_regex_success_submatches_prop + { #1 > } \l_regex_tmpb_tl + {#2} + {#3} + } + {#3} + } +\cs_new_protected_nopar:Npn \regex_set:Nn + { \regex_set_aux:NNn \tl_set_eq:NN } +\cs_new_protected_nopar:Npn \regex_gset:Nn + { \regex_set_aux:NNn \tl_gset_eq:NN } +\cs_new_protected:Npn \regex_set_aux:NNn #1#2#3 + { + \group_begin: + \regex_build:n {#3} + \tl_gset:Nx \g_regex_tmpa_tl + { + \exp_not:N \regex_nfa:Nw \exp_not:N #2 + \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 + \bool_if:NTF \l_regex_look_behind_bool + { \bool_set_true:N \l_regex_look_behind_bool } + { \bool_set_false:N \l_regex_look_behind_bool } + \prg_stepwise_function:nnnN + {1} {1} {\l_regex_max_state_int} + \regex_set_aux:n + \regex_nfa_end: + } + \group_end: + #1 #2 \g_regex_tmpa_tl + } +\cs_new_nopar:Npn \regex_set_aux:n #1 + { \tex_toks:D #1 { \tex_the:D \tex_toks:D #1 } } +\cs_new:Npn \regex_nfa:Nw #1 #2 \regex_nfa_end: + { \msg_expandable_error:n { Automaton~#1 used~incorrectly. } } +\cs_new_eq:NN \regex_nfa_end: \scan_stop: +\prg_new_protected_conditional:Npnn \regex_check_nfa:N #1 { TF } + { \exp_after:wN \regex_check_nfa_aux:Nw #1 \q_stop } +\cs_new:Npn \regex_check_nfa_aux:Nw #1 #2 \q_stop + { + \if_meaning:w \regex_nfa:Nw #1 + \prg_return_true: + \else: + \msg_error:nnx { regex } { not-nfa } { \token_to_str:N #1 } + \prg_return_false: + \fi: + } +\msg_new:nnn { regex } { not-nfa } + { + I~was~expecting~a~regular~expression~variable.\\ + Instead,~I~got~#1. + } +\cs_new_protected_nopar:Npn \regex_use:N #1 + { \exp_after:wN \use_none:nn #1 } +\cs_new_protected:Npn \regex_user_aux:n #1 + { + \group_begin: + \tl_clear:N \l_regex_every_match_tl + #1 + \group_end: + } +\cs_new_protected_nopar:Npn \regex_return_after_group: + { + \if_bool:N \l_regex_success_bool + \group_insert_after:N \prg_return_true: + \else: + \group_insert_after:N \prg_return_false: + \fi: + } +\cs_new_protected_nopar:Npn \regex_extract_after_group:N #1 + { + \if_bool:N \l_regex_success_bool + \regex_extract: + \group_insert_after:N \seq_set_eq:NN + \group_insert_after:N #1 + \group_insert_after:N \g_regex_submatches_seq + \fi: + } +\cs_new_protected_nopar:Npn \regex_count_after_group:N #1 + { + \group_insert_after:N \int_set_eq:NN + \group_insert_after:N #1 + \group_insert_after:N \g_regex_match_count_int + } +\prg_new_protected_conditional:Npnn \regex_match:nn #1#2 { T , F , TF } + { + \regex_user_aux:n + { + \regex_disable_submatches: + \regex_build:n {#1} + \regex_match:n {#2} + \regex_return_after_group: + } + } +\prg_new_protected_conditional:Npnn \regex_match:Nn #1#2 { T , F , TF } + { + \regex_check_nfa:NTF #1 + { + \regex_user_aux:n + { + \regex_disable_submatches: + \regex_use:N #1 + \regex_match:n {#2} + \regex_return_after_group: + } + } + { \prg_return_false: } + } +\cs_new_protected:Npn \regex_count:nnN #1#2#3 + { + \regex_user_aux:n + { + \regex_disable_submatches: + \int_gzero:N \g_regex_match_count_int + \tl_set:Nn \l_regex_every_match_tl + { + \int_gincr:N \g_regex_match_count_int + \regex_match_once: + } + \regex_build:n {#1} + \regex_match:n {#2} + \regex_count_after_group:N #3 + } + } +\cs_new_protected:Npn \regex_count:NnN #1#2#3 + { + \regex_check_nfa:NTF #1 + { + \regex_user_aux:n + { + \regex_disable_submatches: + \int_gzero:N \g_regex_match_count_int + \tl_set:Nn \l_regex_every_match_tl + { + \int_gincr:N \g_regex_match_count_int + \regex_match_once: + } + \regex_use:N #1 + \regex_match:n {#2} + \regex_count_after_group:N #3 + } + } + { } + } +\cs_new_protected:Npn \regex_extract:nnN #1#2#3 + { + \regex_user_aux:n + { + \regex_build:n {#1} + \regex_match:n {#2} + \regex_extract_after_group:N #3 + } + } +\prg_new_protected_conditional:Npnn \regex_extract:nnN #1#2#3 { T , F , TF } + { + \regex_user_aux:n + { + \regex_build:n {#1} + \regex_match:n {#2} + \regex_extract_after_group:N #3 + \regex_return_after_group: + } + } +\cs_new_protected:Npn \regex_extract:NnN #1#2#3 + { + \regex_check_nfa:NTF #1 + { + \regex_user_aux:n + { + \regex_use:N #1 + \regex_match:n {#2} + \regex_extract_after_group:N #3 + } + } + { } + } +\prg_new_protected_conditional:Npnn \regex_extract:NnN #1#2#3 { T , F , TF } + { + \regex_check_nfa:NTF #1 + { + \regex_user_aux:n + { + \regex_use:N #1 + \regex_match:n {#2} + \regex_extract_after_group:N #3 + \regex_return_after_group: + } + } + { \prg_return_false: } + } +\cs_new_protected:Npn \regex_split:nnN #1#2#3 + { + \regex_user_aux:n + { + \seq_gclear:N \g_regex_split_seq + \tl_set:Nn \l_regex_every_match_tl { \regex_split_aux: } + \regex_build:n {#1} + \regex_match:n {#2} + \regex_split_after_group:N #3 + } + } +\cs_new_protected:Npn \regex_split:NnN #1#2#3 + { + \regex_check_nfa:NTF #1 + { + \regex_user_aux:n + { + \seq_gclear:N \g_regex_split_seq + \tl_set:Nn \l_regex_every_match_tl { \regex_split_aux: } + \regex_use:N #1 + \regex_match:n {#2} + \regex_split_after_group:N #3 + } + } + { } + } +\cs_new_protected_nopar:Npn \regex_split_aux: + { + \int_compare:nNnF \l_regex_start_step_int = \l_regex_success_step_int + { + \regex_extract: + \seq_pop:NN \g_regex_submatches_seq \l_regex_tmpa_tl + \regex_extract_aux:nTF {0} + { + \seq_gput_left:Nx \g_regex_submatches_seq + { + \str_from_to:Nnn \l_regex_query_str + { \int_use:N \l_regex_start_step_int } + { \l_regex_tmpa_tl } + } + } + { \msg_error:nn { regex } { internal } } + \seq_gconcat:NNN \g_regex_split_seq + \g_regex_split_seq \g_regex_submatches_seq + } + \regex_match_once: + } +\cs_new_protected_nopar:Npn \regex_split_after_group:N #1 + { + \int_compare:nNnTF \l_regex_start_step_int = \l_regex_current_step_int + { + \bool_if:NF \l_regex_success_empty_bool + { \seq_gput_right:Nn \g_regex_split_seq { } } + } + { + \seq_gput_right:Nx \g_regex_split_seq + { + \str_from_to:Nnn \l_regex_query_str + { \int_use:N \l_regex_start_step_int } + { \int_use:N \l_regex_current_step_int } + } + } + \group_insert_after:N \seq_set_eq:NN + \group_insert_after:N #1 + \group_insert_after:N \g_regex_split_seq + } +\cs_new_protected:Npn \regex_replacement:n #1 + { + \str_aux_escape:NNNn + \prg_do_nothing: + \regex_replacement_escaped:N + \regex_replacement_raw:N + {#1} + \tl_set_eq:NN \l_regex_replacement_tl \g_str_result_tl + \tl_set:Nx \l_regex_replacement_tl + { \l_regex_replacement_tl \prg_do_nothing: } + } +\cs_new_nopar:Npn \regex_replacement_raw:N { \exp_not:N \prg_do_nothing: } +\cs_new_nopar:Npn \regex_replacement_escaped:N #1 + { + \if_num:w 9 < 1 #1 \exp_stop_f: + \exp_not:N \regex_replacement_escaped_ii:nN {#1} + \else: + #1 + \fi: + } +\cs_new_nopar:Npn \regex_replacement_escaped_ii:nN #1#2 + { + \regex_token_if_other_digit:NTF #2 + { \regex_replacement_escaped_ii:nN {#1#2} } + { \exp_not:N \seq_item:Nn \exp_not:N \g_regex_submatches_seq {#1} #2 } + } +\prg_new_conditional:Npnn \regex_token_if_other_digit:N #1 { TF } + { + \if_num:w 9 < 1 \exp_not:N #1 \exp_stop_f: + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +\cs_new_protected_nopar:Npn \regex_replace_after_group:N #1 + { + \group_insert_after:N \tl_set_eq:NN + \group_insert_after:N #1 + \group_insert_after:N \g_regex_replaced_str + } +\cs_new_protected:Npn \regex_replace_once_aux:Nn #1#2 + { + \group_begin: + \regex_replace_after_group:N #1 + \tl_clear:N \l_regex_every_match_tl + #2 + \exp_args:No \regex_match:n {#1} + \regex_extract: + \regex_extract_aux:nTF {0} + { + \tl_gset:Nx \g_regex_replaced_str + { + \str_from_to:Nnn \l_regex_query_str {0} { \l_regex_tmpa_tl } + \l_regex_replacement_tl + \str_from_to:Nnn \l_regex_query_str + { \l_regex_tmpb_tl } { \c_max_int } + } + } + { \tl_gset_eq:NN \g_regex_replaced_str \l_regex_query_str } + \group_end: + } +\cs_new_protected:Npn \regex_replace_once:nnN #1#2#3 + { + \regex_replace_once_aux:Nn #3 + { + \regex_build:n {#1} + \regex_replacement:n {#2} + } + } +\cs_new_protected:Npn \regex_replace_once:NnN #1#2#3 + { + \regex_replace_once_aux:Nn #3 + { + \regex_use:N #1 + \regex_replacement:n {#2} + } + } +\prg_new_protected_conditional:Npnn \regex_replace_once:nnN #1#2#3 {T,F,TF} + { + \regex_replace_once_aux:Nn #3 + { + \regex_build:n {#1} + \regex_replacement:n {#2} + \regex_return_after_group: + } + } +\prg_new_protected_conditional:Npnn \regex_replace_once:NnN #1#2#3 {T,F,TF} + { + \regex_replace_once_aux:Nn #3 + { + \regex_use:N #1 + \regex_replacement:n {#2} + \regex_return_after_group: + } + } +\cs_new_protected:Npn \regex_replace_all_aux:Nn #1#2 + { + \group_begin: + \regex_replace_after_group:N #1 + \tl_set:Nn \l_regex_every_match_tl { \regex_replace_all_aux: } + \tl_gclear:N \g_regex_replaced_str + #2 + \exp_args:No \regex_match:n {#1} + \tl_gput_right:Nx \g_regex_replaced_str + { + \str_from_to:Nnn \l_regex_query_str + { \int_use:N \l_regex_start_step_int } + { \c_max_int } + } + \group_end: + } +\cs_new_protected_nopar:Npn \regex_replace_all_aux: + { + \regex_extract: + \regex_extract_aux:nTF {0} + { + \tl_gput_right:Nx \g_regex_replaced_str + { + \str_from_to:Nnn \l_regex_query_str + { \int_use:N \l_regex_start_step_int } + { \l_regex_tmpa_tl } + \l_regex_replacement_tl + } + } + { \msg_error:nn { regex } { internal } } + \regex_match_once: + } +\cs_new_protected:Npn \regex_replace_all:nnN #1#2#3 + { + \regex_replace_all_aux:Nn #3 + { + \regex_build:n {#1} + \regex_replacement:n {#2} + } + } +\cs_new_protected:Npn \regex_replace_all:NnN #1#2#3 + { + \regex_replace_all_aux:Nn #3 + { + \regex_use:N #1 + \regex_replacement:n {#2} + } + } +%% +%% +%% End of file `l3regex.sty'. |