diff options
author | Karl Berry <karl@freefriends.org> | 2011-12-29 23:03:28 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2011-12-29 23:03:28 +0000 |
commit | 0bc9393ae50667d7ff769a76321a9548a70351fc (patch) | |
tree | 6da7cc8ebef423a4653c82a19be6d4e1c6652705 /Master/texmf-dist/tex/latex | |
parent | 56ecd0d3d0de54cebdeb29cc8a056001ee93b02e (diff) |
l3experimental 3109 (29dec11)
git-svn-id: svn://tug.org/texlive/trunk@24970 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex')
12 files changed, 1689 insertions, 837 deletions
diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3flag.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3flag.sty new file mode 100644 index 00000000000..40e2c899682 --- /dev/null +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3flag.sty @@ -0,0 +1,100 @@ +%% +%% This is file `l3flag.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3flag.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: l3flag.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: l3flag.dtx 3039 2011-12-08 09:22:35Z bruno $ + {L3 Experimental Flags} +\ProvidesExplPackage + {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} +\tl_new:N \g_flag_list_tl +\cs_new_protected:Npn \flag_new:N #1 + { + \tl_if_in:NnTF \g_flag_list_tl {#1} + { + \msg_kernel_error:nnx + { flag } { already-defined } + { \token_to_str:N #1 } + } + { + \tl_gput_right:Nn \g_flag_list_tl {#1} + \cs_new_eq:NN #1 \c_undefined:D + } + } +\cs_generate_variant:Nn \flag_new:N { c } +\prg_new_conditional:Npnn \flag_test:N #1 { p , T , F , TF } + { + \if_cs_exist:N #1 + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +\prg_new_conditional:Npnn \flag_test:c #1 { p , T , F , TF } + { + \if_cs_exist:w #1 \cs_end: + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +\cs_new:Npn \flag_raise:N #1 + { \exp_after:wN \use_none:n \cs:w \cs_to_str:N #1 \cs_end: } +\cs_new:Npn \flag_raise:c #1 + { \exp_after:wN \use_none:n \cs:w #1 \cs_end: } +\cs_new_protected:Npn \flag_lower:N #1 + { \cs_set_eq:NN #1 \c_undefined:D } +\cs_generate_variant:Nn \flag_lower:N { c } +\msg_kernel_new:nnnn { flag } { already-defined } + { The~control~sequence~#1~is~already~declared~as~a~flag. } + { + LaTeX~was~asked~to~define~the~flag~#1,~but~it~has~already~ + been~defined~as~a~flag.~The~flag~module~is~mostly~meant~ + for~kernel~use,~and~booleans~should~be~preferred. + } +%% +%% +%% End of file `l3flag.sty'. diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty index f3dc0b5a358..facf764c168 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty @@ -46,17 +46,19 @@ %% %% ----------------------------------------------------------------------- \RequirePackage{expl3} -\GetIdInfo$Id: l3regex.dtx 3017 2011-11-28 00:10:02Z bruno $ +\GetIdInfo$Id: l3regex.dtx 3073 2011-12-21 01:53:06Z bruno $ {L3 Experimental Regular Expressions} \ProvidesExplPackage {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} -\RequirePackage{l3str} +\RequirePackage{l3str, l3tl-analysis, l3flag} \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 +\tl_new:N \l_regex_tmpc_tl \int_new:N \l_regex_tmpa_int \int_new:N \l_regex_tmpb_int +\flag_new:N \l_regex_group_begin_flag +\flag_new:N \l_regex_group_end_flag \int_new:N \l_regex_max_state_int \int_new:N \l_regex_left_state_int \int_new:N \l_regex_right_state_int @@ -67,7 +69,10 @@ \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_build_or_class_tl \tl_new:N \l_regex_one_or_group_tl +\bool_new:N \l_regex_in_csname_bool +\tl_new:N \l_regex_tmpa_regex_tl \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 @@ -133,12 +138,16 @@ \regex_item_geq:n { \c_eleven } % > lf \regex_item_range:nn { \c_zero } { \c_nine } % < lf } -\tl_new:N \l_regex_query_other_str +\int_new:N \l_regex_nesting_int +\int_new:N \l_regex_min_step_int +\int_new:N \l_regex_max_step_int \int_new:N \l_regex_current_step_int \int_new:N \l_regex_start_step_int \int_new:N \l_regex_success_step_int -\int_new:N \l_regex_unique_step_int +\int_new:N \l_regex_unique_id_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 @@ -147,23 +156,23 @@ \prop_new:N \l_regex_success_submatches_prop \int_new:N \l_regex_max_index_int \tl_new:N \l_regex_every_match_tl -\bool_new:N \l_regex_success_bool +\bool_new:N \g_regex_success_bool +\bool_new:N \l_regex_saved_success_bool +\bool_new:N \l_regex_success_match_bool \cs_new_protected:Npn \regex_last_match_empty_no:F #1 {#1} \cs_new_protected:Npn \regex_last_match_empty_yes:F { \int_compare:nNnF \l_regex_start_step_int = \l_regex_current_step_int } \cs_new_eq:NN \regex_last_match_empty:F \regex_last_match_empty_no:F \bool_new:N \l_regex_success_empty_bool \bool_new:N \l_regex_fresh_thread_bool -\seq_new:N \g_regex_submatches_seq -\int_new:N \g_regex_match_count_int -\seq_new:N \g_regex_extract_all_seq -\seq_new:N \g_regex_split_seq -\tl_new:N \l_regex_replacement_tl -\tl_new:N \g_regex_replaced_str -\cs_new_eq:NN \s_regex_stop \scan_stop: +\int_new:N \l_regex_replacement_int +\int_new:N \l_regex_replacement_csnames_int +\int_new:N \l_regex_submatch_int +\int_new:N \l_regex_submatch_start_int +\int_new:N \l_regex_match_count_int \cs_new_protected:Npn \regex_toks_put_left:Nx #1#2 { - \cs_set_nopar:Npx \regex_tmp:w \s_regex_stop { \s_regex_stop #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 } } @@ -173,18 +182,24 @@ \tex_toks:D #1 \exp_after:wN { \tex_the:D \tex_toks:D \exp_after:wN #1 \regex_tmp:w } } -\cs_new_nopar:Npn \regex_query_substr:NN #1#2 +\cs_new:Npn \regex_query_substr:nn #1#2 { - \exp_after:wN \regex_query_substr_aux:NN - \exp_after:wN #1 - \exp_after:wN #2 - \l_regex_query_other_str - \q_stop + \if_num:w \int_eval:w #1 < \int_eval:w #2 \int_eval_end: + \str_aux_toks_range:nn {#1} {#2} + \fi: + } +\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_substr_aux:NN #1#2 +\cs_new:Npn \regex_query_submatch:w #1 ; { - \str_skip_do:nn {#1} - { \str_collect_do:nn { #2 - #1 } { \use_i_delimit_by_q_stop:nw } } + \regex_query_substr:nn + { \tex_skip:D #1 } + { \etex_gluestretch:D \tex_skip:D #1 } } \cs_new_protected:Npn \regex_seq_pop_int:NN #1#2 { @@ -208,8 +223,27 @@ \seq_get:NN #1 \l_regex_tmpa_tl \l_regex_tmpa_tl } +\cs_new:Npn \regex_seq_item:Nn #1#2 + { + \exp_after:wN \regex_seq_item_aux:wNn + \int_use:N \int_eval:w #2 \exp_after:wN ; + #1 { ? \prg_map_break: } { } + \prg_break_point:n { } + } +\cs_new:Npn \regex_seq_item_aux:wNn #1; #2#3 + { + \use_none:n #2 + \if_num:w #1 = \c_zero + \exp_after:wN \prg_map_break:n + \else: + \exp_after:wN \use_none:n + \fi: + { \exp_not:n {#3} } + \exp_after:wN \regex_seq_item_aux:wNn + \int_use:N \int_eval:w #1 - \c_one ; + } \cs_new_protected_nopar:Npn \regex_item_dot:T - { \int_compare:nNnF \l_regex_current_char_int = \c_minus_one } + { \int_compare:nNnF \l_regex_current_char_int < \c_minus_one } \cs_new_protected_nopar:Npn \regex_break_true:w #1 \regex_break_point:TF #2 #3 {#2} \cs_new_protected_nopar:Npn \regex_break_false:w @@ -283,6 +317,37 @@ \cs_set:Npn \regex_item_range:nn { \regex_item_caseful_range:nn } \cs_set:Npn \regex_item_geq:n { \regex_item_caseful_geq:n } } +\cs_new_protected_nopar:Npn \regex_item_catcode:n #1 + { + \if_num:w #1 = \l_regex_current_catcode_int + \exp_after:wN \regex_break_true:w + \fi: + } +\cs_new_protected_nopar:Npn \regex_item_catcode_neq:n #1 + { + \if_num:w #1 = \l_regex_current_catcode_int + \else: + \exp_after:wN \regex_break_true:w + \fi: + } +\cs_new_protected:Npn \regex_item_cs:n #1 + { + \int_compare:nNnT \l_regex_current_catcode_int = \c_zero + { + \tl_set:Nn \l_regex_tmpa_regex_tl {#1} + \bool_set_eq:NN \l_regex_saved_success_bool \g_regex_success_bool + \exp_args:NNx \regex_match:NnTF \l_regex_tmpa_regex_tl + { + \exp_after:wN \exp_after:wN + \exp_after:wN \cs_to_str:N \l_regex_current_token_tl + } + { + \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 } + } + } \cs_new_protected:Npn \regex_get_digits:nw #1 { \tex_afterassignment:D \regex_tmp:w @@ -362,14 +427,10 @@ } \cs_new_protected_nopar:Npn \regex_build_new_state: { - \int_compare:nNnTF \l_regex_max_state_int > { 32766 } - { \msg_error:nn { regex } { -997 } } - { - \int_incr:N \l_regex_max_state_int - \tex_toks:D \l_regex_max_state_int { \s_regex_stop } - } + \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 } \cs_new_protected_nopar:Npn \regex_build_transition_aux:NN #1#2 { @@ -388,16 +449,18 @@ } \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 } + \bool_set_false:N \l_regex_in_csname_bool + \regex_build:w + \regex_build_new_state: + \regex_toks_put_right:Nx \l_regex_left_state_int + { \regex_action_start_wildcard:nn {0} {1} } \regex_build_open_aux: - \g_str_result_tl \prg_do_nothing: \prg_do_nothing: - \regex_seq_push_int:NN \l_regex_capturing_group_seq \c_zero - \regex_build_close_aux: \regex_build_group_: + \str_escape_use:NNNn + \regex_build_i_unescaped:N + \regex_build_i_escaped:N + \regex_build_i_raw:N + { #1 } + \prg_do_nothing: \prg_do_nothing: \regex_build_end: } \cs_new_nopar:Npn \regex_build_i_unescaped:N #1 @@ -414,38 +477,39 @@ } \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_new_protected_nopar:Npn \regex_build_control:N #1 { - \cs_if_exist_use:cF { regex_build_#1: } - { \regex_build_default_raw:N #1 } + \cs_if_exist_use:cF { regex_ \l_regex_build_or_class_tl _#1: } + { \use:c { regex_ \l_regex_build_or_class_tl _default_raw:N } #1 } } -\cs_new_protected_nopar:Npn \regex_build_setup: +\cs_new_protected_nopar:Npn \regex_build:w { - \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 + \tl_set:Nn \l_regex_build_or_class_tl { build } \int_set_eq:NN \l_regex_capturing_group_int \c_zero \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 {0} {1} } } \cs_new_protected_nopar:Npn \regex_build_end: { + \regex_seq_push_int:NN \l_regex_capturing_group_seq \c_zero + \regex_build_close_aux: \regex_build_group_: \seq_if_empty:NF \l_regex_capturing_group_seq { - \msg_error:nn { regex } {22} + \msg_kernel_error:nnx { regex } { missing-rparen } + { \seq_length:N \l_regex_capturing_group_seq } \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: } + \int_incr:N \l_regex_capturing_group_int } \cs_new_protected_nopar:cpn { regex_build_^: } - { \regex_build_anchor_start:N \c_zero } + { \regex_build_anchor_start:N \l_regex_min_step_int } \cs_new_protected_nopar:Npn \regex_build_A: - { \regex_build_anchor_start:N \c_zero } + { \regex_build_anchor_start:N \l_regex_min_step_int } \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 @@ -453,7 +517,7 @@ \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 + \exp_not:N \int_compare:nNnT #1 = \l_regex_current_step_int { \regex_action_free:n { @@ -469,7 +533,7 @@ \regex_toks_put_right:Nx \l_regex_left_state_int { \exp_not:N \int_compare:nNnT - \c_minus_one = \l_regex_current_char_int + \l_regex_current_char_int < \c_minus_one { \regex_action_free:n { @@ -519,61 +583,52 @@ \int_set_eq:NN \l_regex_current_char_int \l_regex_last_char_int \c_regex_w_tl \regex_break_point:TF - { \group_end: \c_regex_W_tl \regex_item_equal:n { -1 } } + { \group_end: \c_regex_W_tl \regex_item_equal:n { -2 } } { \group_end: \c_regex_w_tl } \regex_break_point:TF } -\cs_new_protected_nopar:Npn \regex_build_default_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_set:Npx \regex_build_tmp_class:n ##1 + \cs_set_nopar:Npx \regex_build_tmp_class:n ##1 { - \regex_item_equal:n { \int_value:w `#1 ~ } - \regex_break_point:TF { \regex_action_cost:n { ##1 } } { } + \exp_not:N \exp_not:n {#1} + \regex_break_point:TF { \regex_action_cost:n {##1} } { } } \regex_build_one_quantifier: } +\cs_new_protected_nopar:Npn \regex_build_default_raw:N #1 + { \regex_build_one:x { \regex_item_equal:n { \int_value:w `#1 ~ } } } \cs_new_protected_nopar:cpn { regex_build_.: } { \cs_set:Npn \regex_build_tmp_class:n ##1 { \regex_item_dot:T { \regex_action_cost:n {##1} } } \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 - \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 } - } + { \regex_build_one:n \exp_not:c { c_regex_#1_tl } } } +\cs_new_protected:Npn \regex_class_one:n + { \tl_put_right:Nn \l_regex_class_tl } +\cs_new_protected:Npn \regex_class_one:x + { \tl_put_right:Nx \l_regex_class_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 + \cs_set_eq:NN \regex_build_raw:N \regex_class_default_raw:N + \tl_set:Nn \l_regex_build_or_class_tl { class } \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 ] } + { \regex_class_default_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 + \tl_set:Nn \l_regex_build_or_class_tl { build } \cs_set:Npn \regex_build_tmp_class:n ##1 { \exp_not:o \l_regex_class_tl @@ -593,7 +648,7 @@ #1 #2 } } -\cs_new_protected_nopar:Npn \regex_class_raw:N #1#2#3 +\cs_new_protected_nopar:Npn \regex_class_default_raw:N #1#2#3 { \str_if_eq:nnTF {#2#3} { \regex_build_control:N - } { \regex_class_range:Nw #1 } @@ -603,10 +658,7 @@ } } \cs_new_protected_nopar:Npn \regex_class_single:N #1 - { - \tl_put_right:Nx \l_regex_class_tl - { \regex_item_equal:n { \int_value:w `#1 } } - } + { \regex_class_one:x { \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 @@ -624,9 +676,9 @@ \cs_new_protected_nopar:Npn \regex_class_range_put:NN #1#2 { \if_num:w `#1 > `#2 \exp_stop_f: - \msg_error:nn { regex } {8} + \msg_kernel_error:nnxx { regex } { backwards-range } {#1} {#2} \else: - \tl_put_right:Nx \l_regex_class_tl + \regex_class_one:x { \if_num:w `#1 = `#2 \exp_stop_f: \regex_item_equal:n @@ -640,10 +692,93 @@ \tl_map_inline:nn { dDhHsSvVwWN } { \cs_new_protected_nopar:cpx { regex_class_#1: } + { \regex_class_one:n \exp_not:c { c_regex_#1_tl } } + } +\cs_new_protected_nopar:Npn \regex_build_c: + { \regex_aux_c:NNNN \regex_item_catcode:n \use_i:nn } +\cs_new_protected_nopar:Npn \regex_build_C: + { \regex_aux_c:NNNN \regex_item_catcode_neq:n \use_ii:nn } +\cs_new_eq:NN \regex_class_c: \regex_build_c: +\cs_new_eq:NN \regex_class_C: \regex_build_C: +\cs_new_protected:Npn \regex_aux_c:NNNN #1#2#3#4 + { + \token_if_eq_meaning:NNTF #3 \regex_build_raw:N + { + \regex_aux_c_test:NTF #4 + { + \use:c { regex_ \l_regex_build_or_class_tl _one:x } + { #1 { \int_use:N \l_regex_current_catcode_int } } + } + { + \msg_kernel_error:nnx { regex } { build-c } { #4 } + #3 #4 + } + } + { + \if_charcode:w \c_lbrace_str \exp_not:N #4 + \exp_after:wN #2 + \else: + \exp_after:wN \use_ii:nn + \fi: + { + \group_begin: + \bool_set_true:N \l_regex_in_csname_bool + \regex_build:w + } + { + \msg_kernel_error:nnx { regex } { build-c } { #4 } + #3 #4 + } + } + } +\cs_new_protected:Npn \regex_aux_c_test:NTF #1 + { + \int_set:Nn \l_regex_current_catcode_int + { + \if_case:w \int_eval:w `#1 - `A \int_eval_end: + \c_thirteen % Active + \or: \c_one % Begin-group + \or: \c_zero % Control sequence + \or: \c_eight % Down (subscript) + \or: \c_two % End-group + \else: + \if_case:w \int_eval:w `#1 - `L \int_eval_end: + \c_eleven % Letter + \or: \c_three % Math toggle + \or: \c_minus_one + \or: \c_twelve % Other + \or: \c_six % Parameter + \or: \c_minus_one + \or: \c_minus_one + \or: \c_ten % Space + \or: \c_four % Tab (alignment) + \or: \c_seven % Up (superscript) + \else: \c_minus_one + \fi: + \fi: + } + \if_num:w \l_regex_current_catcode_int = \c_minus_one + \exp_after:wN \use_ii:nn + \else: + \exp_after:wN \use_i:nn + \fi: + } +\cs_new_protected:cpn { regex_build_ \c_rbrace_str : } + { + \bool_if:NTF \l_regex_in_csname_bool { - \tl_put_right:Nn \exp_not:N \l_regex_class_tl - { \exp_not:c { c_regex_#1_tl } } + \regex_build_Z: + \regex_toks_put_right:Nx \l_regex_right_state_int + { \regex_action_success: } + \int_incr:N \l_regex_capturing_group_int + \use:x + { + \group_end: + \exp_not:n { \use:c { regex_ \l_regex_build_or_class_tl _one:n } } + { \regex_item_cs:n { \regex_set_aux:N ? } } + } } + { \exp_after:wN \regex_build_raw:N \c_rbrace_str } } \cs_new_protected_nopar:Npn \regex_build_quantifier:w #1#2 { @@ -711,12 +846,8 @@ { \tl_if_empty:nTF {#2} { \regex_build_quantifier_aux:nnNN { {#1} } { n* } } - { - \int_compare:nNnT {#1} > {#2} - { \msg_error:nn { regex } {4} } - \regex_build_quantifier_aux:nnNN { {#1} {#2} } { nn } - } - } + { \regex_build_quantifier_aux:nnNN { {#1} {#2} } { nn } } + } %^^A todo: catch the case m>n { \regex_build_quantifier_end:n { } \use:x @@ -833,7 +964,7 @@ \cs_new_protected_nopar:cpn { regex_build_): } { \seq_if_empty:NTF \l_regex_capturing_group_seq - { \msg_error:nn { regex } { 22 } } + { \msg_kernel_error:nn { regex } { extra-rparen } } { \regex_build_close_aux: \regex_build_group_quantifier: @@ -878,7 +1009,8 @@ { \cs_if_exist_use:cF { regex_build_special_group_\token_to_str:N #2 : } { - \msg_error:nn { regex } { -998 } + \msg_kernel_error:nnx { regex } { unsupported } + { (? \token_to_str:N #2 } %) \regex_build_control:N ( % ) \regex_build_raw:N ? #1 #2 @@ -990,7 +1122,7 @@ { \tex_toks:D \l_regex_tmpa_int { - \s_regex_stop + \s_stop #1 { \int_eval:n { \l_regex_right_state_int - \l_regex_tmpa_int } } } } @@ -1052,16 +1184,19 @@ \regex_toks_put_right:Nx \l_regex_right_state_int { \regex_action_free:n - { \int_eval:n { \l_regex_max_state_int - \l_regex_left_state_int } } + { + \int_eval:n %^^A todo: document why that value. + { \l_regex_max_state_int - \c_one - \l_regex_left_state_int } + } } \int_set_eq:NN \l_regex_tmpa_int \l_regex_left_state_int - \int_set:Nn \l_regex_tmpb_int { \l_regex_max_state_int + \c_one } + \int_set_eq:NN \l_regex_tmpb_int \l_regex_max_state_int \int_set:Nn \l_regex_max_state_int { - \l_regex_left_state_int - \c_one - + #1 * ( \l_regex_max_state_int - \l_regex_left_state_int + \c_one ) + \l_regex_left_state_int + + #1 * ( \l_regex_max_state_int - \l_regex_left_state_int ) } - \int_until_do:nNnn \l_regex_tmpb_int > \l_regex_max_state_int + \int_while_do:nNnn \l_regex_tmpb_int < \l_regex_max_state_int { \tex_toks:D \l_regex_tmpb_int = \tex_toks:D \l_regex_tmpa_int \int_incr:N \l_regex_tmpa_int @@ -1114,14 +1249,13 @@ \cs_new_protected_nopar:Npn \regex_state_use_with_submatches: { \regex_state_use_aux:n { } } \cs_new_protected_nopar:Npn \regex_state_use: - { \regex_state_use_aux:n { \exp_after:wN \regex_state_use_aux_ii:w } } -\cs_new_nopar:Npn \regex_state_use_aux_ii:w #1 \s_regex_stop { } + { \regex_state_use_aux:n { \exp_after:wN \use_none_delimit_by_s_stop:w } } \cs_new_protected_nopar:Npn \regex_state_use_aux:n #1 { \if_num:w \tex_dimen:D \l_regex_current_state_int - < \l_regex_unique_step_int + < \l_regex_unique_id_int \tex_dimen:D \l_regex_current_state_int - = \l_regex_unique_step_int sp \scan_stop: + = \l_regex_unique_id_int sp \scan_stop: #1 \tex_the:D \tex_toks:D \exp_after:wN \l_regex_current_state_int \fi: \scan_stop: @@ -1144,73 +1278,105 @@ \tex_the:D \tex_toks:D #1 } } -\cs_new_protected:Npn \regex_store_submatches_aux:w #1 \s_regex_stop +\cs_new_protected:Npn \regex_store_submatches_aux:w #1 \s_stop { \regex_store_submatches_aux_ii:Nnnw #1 \regex_state_submatches:nn \c_minus_one \q_prop - \s_regex_stop + \s_stop } \cs_new_protected:Npn \regex_store_submatches_aux_ii:Nnnw - \regex_state_submatches:nn #1 #2 #3 \s_regex_stop + \regex_state_submatches:nn #1 #2 #3 \s_stop { \exp_after:wN \c_zero \exp_after:wN \regex_state_submatches:nn \exp_after:wN { \int_value:w \int_eval:w - \l_regex_unique_step_int + \c_one + \l_regex_unique_id_int + \c_one \exp_after:wN } \exp_after:wN { \l_regex_current_submatches_prop } \regex_state_submatches:nn {#1} {#2} - \s_regex_stop + \s_stop } \cs_new_protected:Npn \regex_state_submatches:nn #1#2 { - \if_num:w #1 = \l_regex_unique_step_int + \if_num:w #1 = \l_regex_unique_id_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_other_str { \tl_to_other_str:n {#1} } + \tl_set_analysis:Nn \l_regex_tmpa_tl {#1} + + \int_zero:N \l_regex_nesting_int + \int_set_eq:NN \l_regex_current_step_int \l_regex_max_state_int + \regex_query_set:nnn { } { -1 } { -2 } + \int_set_eq:NN \l_regex_min_step_int \l_regex_current_step_int + \exp_after:wN \regex_query_set_loop:ww + \l_regex_tmpa_tl + \q_mark { ? \prg_map_break: } , + \prg_break_point:n { } + \int_set_eq:NN \l_regex_max_step_int \l_regex_current_step_int + \regex_query_set:nnn { } { -1 } { -2 } + \regex_match_initial_setup: \regex_match_once: } -\cs_new_protected_nopar:Npn \regex_match_once: +\cs_new:Npn \regex_query_set_loop:ww #1 \q_mark #2#3 , { - \regex_match_setup: - \exp_after:wN \regex_match_once_aux: \l_regex_query_other_str - \q_recursion_tail \q_recursion_stop - \bool_if:NT \l_regex_success_bool { \l_regex_every_match_tl } + \use_none:n #2 + \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: + \regex_query_set_loop:ww } -\cs_new_protected_nopar:Npn \regex_match_once_aux: +\cs_new_protected:Npn \regex_query_set:nnn #1#2#3 { - \int_compare:nNnTF \l_regex_start_step_int = \c_zero - { - \int_set_eq:NN \l_regex_current_char_int \c_minus_one - \regex_match_loop:N - } - { - \str_skip_do:nn - { \l_regex_start_step_int - \c_one } - { \regex_match_once_aux_ii:N } - } + \tex_muskip:D \l_regex_current_step_int + = \etex_gluetomu:D + #3 sp + plus #2 sp + minus \l_regex_nesting_int sp + \scan_stop: + \tex_toks:D \l_regex_current_step_int {#1} + \int_incr:N \l_regex_current_step_int } -\cs_new_protected_nopar:Npn \regex_match_once_aux_ii:N #1 +\cs_new_protected_nopar:Npn \regex_query_get: { - \int_set:Nn \l_regex_current_char_int { `#1 } - \regex_match_loop:N + \tl_set:Nx \l_regex_current_token_tl + { \tex_the:D \tex_toks:D \l_regex_current_step_int } + \l_regex_current_char_int + = \etex_mutoglue:D \tex_muskip:D \l_regex_current_step_int + \l_regex_current_catcode_int = \etex_gluestretch:D + \etex_mutoglue:D \tex_muskip:D \l_regex_current_step_int + } +\cs_new_protected_nopar:Npn \regex_match_once: + { + \regex_match_setup: + \regex_query_get: + \regex_match_loop: + \prg_break_point:n { } + \bool_if:NT \l_regex_success_match_bool + { + \bool_gset_true:N \g_regex_success_bool + \l_regex_every_match_tl + } } \cs_new_protected_nopar:Npn \regex_match_initial_setup: { - \prg_stepwise_inline:nnnn {1} {1} { \l_regex_max_state_int } + \prg_stepwise_inline:nnnn {0} {1} { \l_regex_max_state_int - \c_one } { \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 + \int_set_eq:NN \l_regex_unique_id_int \c_minus_one + \int_set:Nn \l_regex_start_step_int + { \l_regex_min_step_int - \c_one } + \int_set_eq:NN \l_regex_current_step_int \l_regex_min_step_int + \int_set_eq:NN \l_regex_success_step_int \l_regex_min_step_int + \int_set_eq:NN \l_regex_submatch_int \l_regex_max_state_int \bool_set_false:N \l_regex_success_empty_bool + \bool_gset_false:N \g_regex_success_bool } \cs_new_protected_nopar:Npn \regex_match_setup: { @@ -1219,33 +1385,44 @@ { \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_set:Nn \l_regex_current_step_int + { \l_regex_start_step_int - \c_one } + \bool_set_false:N \l_regex_success_match_bool \int_zero:N \l_regex_max_index_int - \regex_store_state:n {1} + \regex_store_state:n {0} %^^A _state_int! } -\cs_new_protected_nopar:Npn \regex_match_loop:N #1 +\cs_new_protected_nopar:Npn \regex_match_loop: { - \regex_match_loop_setup:N #1 + \int_incr:N \l_regex_current_step_int + \int_incr:N \l_regex_unique_id_int + \bool_set_false:N \l_regex_fresh_thread_bool + \int_set_eq:NN \l_regex_last_char_int \l_regex_current_char_int + \regex_query_get: + \regex_match_loop_case_hook: \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_match_one_index:w 1 ; \prg_break_point:n { } + \exp_not:N \prg_break_point:n { } } - \regex_tmp:w \prg_break_point:n { } + \regex_tmp:w + \if_num:w \l_regex_current_char_int < \c_minus_one + \exp_after:wN \prg_map_break: + \fi: \if_num:w \l_regex_max_index_int = \c_zero - \exp_after:wN \use_none_delimit_by_q_recursion_stop:w + \exp_after:wN \prg_map_break: \fi: - \quark_if_recursion_tail_stop:N #1 - \regex_match_loop:N + \regex_match_loop: } -\cs_new_nopar:Npn \regex_match_one_index:n #1 +\cs_new_nopar:Npn \regex_match_one_index:w #1; { + \if_num:w #1 > \l_regex_max_index_int + \exp_after:wN \prg_map_break: + \fi: \regex_match_one_index_aux:n { \int_value:w \tex_skip:D #1 } + \exp_after:wN \regex_match_one_index:w + \int_use:N \int_eval:w #1 + \c_one ; } \cs_new_protected_nopar:Npn \regex_match_one_index_aux:n #1 { @@ -1253,19 +1430,6 @@ \prop_clear:N \l_regex_current_submatches_prop \regex_state_use_with_submatches: } -\cs_new_protected_nopar:Npn \regex_match_loop_setup:N #1 - { - \int_incr:N \l_regex_current_step_int - \int_incr:N \l_regex_unique_step_int - \bool_set_false:N \l_regex_fresh_thread_bool - \int_set_eq:NN \l_regex_last_char_int \l_regex_current_char_int - \if_meaning:w #1 \q_recursion_tail - \int_set_eq:NN \l_regex_current_char_int \c_minus_one - \else: - \int_set:Nn \l_regex_current_char_int {`#1} - \fi: - \regex_match_loop_case_hook: - } \cs_new_protected_nopar:Npn \regex_match_loop_case_hook: { } \cs_new_protected_nopar:Npn \regex_match_loop_caseless_hook: { @@ -1293,18 +1457,17 @@ } \cs_new_protected_nopar:Npn \regex_action_cost:n #1 { - \exp_args:Nf \regex_store_state:n %^^A optimize! + \exp_args:Nf \regex_store_state:n { \int_eval:n { \l_regex_current_state_int + #1 } } } \cs_new_protected_nopar:Npn \regex_action_success: { \regex_last_match_empty:F { - \bool_set_true:N \l_regex_success_bool + \bool_set_true:N \l_regex_success_match_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 + \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 \prg_map_break: @@ -1328,504 +1491,668 @@ \prop_put:Nno \l_regex_current_submatches_prop {#1} { \int_use:N \l_regex_current_step_int } } -\cs_new_protected_nopar:Npn \regex_extract: +\cs_new_protected:Npn \regex_submatch_nesting_aux:n #1 { - \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 - { \regex_query_substr:NN \l_regex_tmpa_tl \l_regex_tmpb_tl } - } - { \seq_gput_right:Nn \g_regex_submatches_seq { } } - } + + \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_nopar:Npn \regex_extract_aux:nTF #1#2#3 +\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 { - \prop_get:NnNTF \l_regex_success_submatches_prop - { #1 < } \l_regex_tmpa_tl + \int_zero:N \l_regex_replacement_int + \int_zero:N \l_regex_nesting_int + \tl_clear:N \l_regex_nesting_tl + \str_escape_use:NNNn + \regex_replacement_unescaped:N + \regex_replacement_escaped:N + \regex_replacement_raw:N + {#1} + \prg_do_nothing: \prg_do_nothing: + \cs_set_nopar:Npx \regex_nesting:n ##1 + { + + \int_use:N \l_regex_nesting_int + \l_regex_nesting_tl + - \regex_submatch_nesting_aux:n {##1} + } + \use:x { - \prop_get:NnNTF \l_regex_success_submatches_prop - { #1 > } \l_regex_tmpb_tl - {#2} - {#3} + \exp_not:n { \cs_set_nopar:Npn \regex_replacement_tl:n ##1 } + { \str_aux_toks_range:nn \c_zero \l_regex_replacement_int } } - {#3} + % ^^A rename! Careful with \cP\#. } -\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 +\cs_new_protected:Npn \regex_replacement_raw:N #1 + { \regex_replacement_put:n {#1} } +\cs_new_protected:Npn \regex_replacement_put:n #1 { - \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 - \token_if_eq_meaning:NNT - \regex_match_loop_case_hook: - \regex_match_loop_caseless_hook: - { - \cs_set_eq:NN \regex_match_loop_case_hook: - \regex_match_loop_caseless_hook: - } - \prg_stepwise_function:nnnN - {1} {1} {\l_regex_max_state_int} - \regex_set_aux:n - \s_regex_stop - } - \group_end: - #1 #2 \g_regex_tmpa_tl + \tex_toks:D \l_regex_replacement_int {#1} + \int_incr:N \l_regex_replacement_int } -\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 \s_regex_stop - { \msg_expandable_kernel_error:nnn { regex } { nfa-misused } {#1} } -\cs_new_protected_nopar:Npn \regex_const:Nn - { \regex_set_aux:NNn \cs_new_eq:NN } -\prg_new_protected_conditional:Npnn \regex_check_nfa:N #1 { T , TF } - { \exp_after:wN \regex_check_nfa_aux:Nw #1 \q_stop } -\cs_new:Npn \regex_check_nfa_aux:Nw #1 #2 \q_stop +\cs_new_protected:Npn \regex_replacement_unescaped:N #1 { - \if_meaning:w \regex_nfa:Nw #1 - \prg_return_true: + \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 + \fi: \else: - \msg_error:nnx { regex } { not-nfa } { \token_to_str:N #1 } - \prg_return_false: + \regex_replacement_put:n #1 \fi: } -\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 +\cs_new_protected:Npn \regex_replacement_escaped: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_meaning:w \c_true_bool \l_regex_success_bool - \group_insert_after:N \prg_return_true: + \if_charcode:w c #1 + \exp_after:wN \regex_replacement_c:w \else: - \group_insert_after:N \prg_return_false: + \if_charcode:w g #1 + \exp_after:wN \exp_after:wN \exp_after:wN \regex_replacement_g:w + \else: + \if_num:w \c_one < 1#1 \exp_stop_f: + \regex_replacement_put_submatch:n {#1} + \else: + \regex_replacement_put:n #1 + \fi: + \fi: \fi: } -\cs_new_protected_nopar:Npn \regex_extract_after_group:N #1 +\cs_new_protected:Npn \regex_replacement_put_submatch:n #1 { - \if_meaning:w \c_true_bool \l_regex_success_bool - \regex_extract: - \group_insert_after:N \seq_set_eq:NN - \group_insert_after:N #1 - \group_insert_after:N \g_regex_submatches_seq + \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: + } \fi: } -\cs_new_protected_nopar:Npn \regex_count_after_group:N #1 +\cs_new_protected:Npn \regex_replacement_error:NNN #1#2#3 { - \group_insert_after:N \int_set_eq:NN - \group_insert_after:N #1 - \group_insert_after:N \g_regex_match_count_int + \msg_kernel_error:nn { regex } { replacement-#1 } + #2 #3 } -\prg_new_protected_conditional:Npnn \regex_match:nn #1#2 { T , F , TF } +\cs_new_protected:Npn \regex_replacement_g:w #1#2 { - \regex_user_aux:n + \str_if_eq:xxTF + { \exp_not:n { #1#2 } } + { \regex_replacement_unescaped:N \c_lbrace_str } { - \regex_disable_submatches: - \regex_build:n {#1} - \regex_match:n {#2} - \regex_return_after_group: + \int_zero:N \l_regex_tmpa_int + \regex_replacement_g_digits:NN } + { \regex_replacement_error:NNN g #1 #2 } } -\prg_new_protected_conditional:Npnn \regex_match:Nn #1#2 { T , F , TF } +\cs_new_protected:Npn \regex_replacement_g_digits:NN #1#2 { - \regex_check_nfa:NTF #1 + \token_if_eq_meaning:NNTF #1 \regex_replacement_unescaped:N { - \regex_user_aux:n - { - \regex_disable_submatches: - \regex_use:N #1 - \regex_match:n {#2} - \regex_return_after_group: - } + \if_num:w \c_one < 1#2 \exp_stop_f: + \int_set:Nn \l_regex_tmpa_int { \c_ten * \l_regex_tmpa_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_tmpa_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: + \fi: } - { \prg_return_false: } + { \regex_replacement_error:NNN g } + #1 #2 } -\cs_new_protected:Npn \regex_count:nnN #1#2#3 +\cs_new_protected_nopar:Npn \regex_replacement_c:w #1#2 { - \regex_user_aux:n + \token_if_eq_meaning:NNTF #1 \regex_replacement_unescaped: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_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:Npn \regex_count:NnN #1#2#3 +\cs_new_protected_nopar:cpn { regex_replacement_c_ \c_lbrace_str :w } { - \regex_check_nfa:NT #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 - } - } + \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_protected:Npn \regex_extract_once:nnN #1#2#3 - { - \regex_user_aux:n - { - \regex_build:n {#1} - \regex_match:n {#2} - \regex_extract_after_group:N #3 - } +\cs_new_nopar:Npn \regex_replacement_exp_not:N #1 { \exp_not:n {#1} } +\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 + { \regex_replacement_char:nNN { ^^@ } } + + \cs_new_protected_nopar:Npn \regex_replacement_c_S:w #1#2 + { + \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 {~} } + } + } + + \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 + { \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 + { \regex_replacement_char:nNN { ^^@ } } + + \char_set_catcode_group_end:N \^^@ + \cs_new_protected_nopar:Npn \regex_replacement_c_E:w + { + \int_decr:N \l_regex_nesting_int + \regex_replacement_char:nNN { \if_false: { \fi: ^^@ } + } + + \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 + { + \int_incr:N \l_regex_nesting_int + \regex_replacement_char:nNN { \exp_after:wN ^^@ \if_false: } \fi: } + } + + \char_set_catcode_active:N \^^@ + \cs_new_protected_nopar:Npn \regex_replacement_c_A:w + { \regex_replacement_char:nNN { \exp_not:N ^^@ } } + +\group_end: + +\cs_new_protected_nopar:Npn \regex_replacement_char:nNN #1#2#3 + { + \char_set_lccode:nn \c_zero { `#3 } + \tl_to_lowercase:n + { \regex_replacement_put:n { \exp_not:n {#1} } } } -\prg_new_protected_conditional:Npnn \regex_extract_once:nnN #1#2#3 - { T , F , TF } +\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 { - \regex_user_aux:n - { - \regex_build:n {#1} - \regex_match:n {#2} - \regex_extract_after_group:N #3 - \regex_return_after_group: - } + \group_begin: + \regex_build:n {#3} + \cs_set_nopar:Npx \regex_tmp:w + { #1 \exp_not:N #2 { \regex_set_aux:N #2 } } + \exp_after:wN + \group_end: + \regex_tmp:w } -\cs_new_protected:Npn \regex_extract_once:NnN #1#2#3 +\cs_new:Npn \regex_set_aux:N #1 { - \regex_check_nfa:NT #1 + \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: { - \regex_user_aux:n - { - \regex_use:N #1 - \regex_match:n {#2} - \regex_extract_after_group:N #3 - } + \cs_set_eq:NN \regex_match_loop_case_hook: + \regex_match_loop_caseless_hook: } + \prg_stepwise_function:nnnN + {0} {1} {\l_regex_max_state_int - \c_one } + \regex_set_aux:n + \s_stop } -\prg_new_protected_conditional:Npnn \regex_extract_once:NnN #1#2#3 - { T , F , TF } +\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 { - \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: } + \msg_expandable_kernel_error:nnn { regex } { nfa-misused } {#1} + \use_none_delimit_by_s_stop:w } -\cs_new_protected:Npn \regex_extract_all:nnN #1#2#3 +\cs_new_protected_nopar:Npn \regex_use:N + { \exp_last_unbraced:No \use_none:nn } +\cs_new_nopar:Npn \regex_to_str:N #1 { - \regex_user_aux:n - { - \seq_gclear:N \g_regex_extract_all_seq - \tl_set:Nn \l_regex_every_match_tl { \regex_extract_all_aux: } - \regex_build:n {#1} - \regex_match:n {#2} - \regex_extract_all_after_group:N #3 - } + \exp_after:wN \regex_to_str_aux:Nw #1 + \tex_toks:D \q_stop \prg_map_break: \tex_toks:D + \prg_break_point:n { } } -\cs_new_protected:Npn \regex_extract_all:NnN #1#2#3 +\cs_new_nopar:Npn \regex_to_str_aux:Nw #1#2\tex_toks:D { - \regex_check_nfa:NT #1 - { - \regex_user_aux:n - { - \seq_gclear:N \g_regex_extract_all_seq - \tl_set:Nn \l_regex_every_match_tl { \regex_extract_all_aux: } - \regex_use:N #1 - \regex_match:n {#2} - \regex_extract_all_after_group:N #3 - } - } + \use_none_delimit_by_q_stop:w #2 \q_stop + \tl_to_str:n {#1#2} \iow_newline: + \regex_to_str_aux:Nw \tex_toks:D } -\cs_new_protected_nopar:Npn \regex_extract_all_aux: +\cs_new_protected_nopar:Npn \regex_aux_return: { - \regex_extract: - \seq_gconcat:NNN \g_regex_extract_all_seq - \g_regex_extract_all_seq \g_regex_submatches_seq - \regex_match_once: + \if_meaning:w \c_true_bool \g_regex_success_bool + \prg_return_true: + \else: + \prg_return_false: + \fi: } -\cs_new_protected_nopar:Npn \regex_extract_all_after_group:N #1 +\cs_new_protected:Npn \regex_aux_build_match:nn #1#2 { - \seq_if_empty:NF \g_regex_extract_all_seq - { - \regex_extract: - \group_insert_after:N \seq_set_eq:NN - \group_insert_after:N #1 - \group_insert_after:N \g_regex_extract_all_seq - } + \regex_build:n {#1} + \regex_match:n {#2} } -\cs_new_protected:Npn \regex_split:nnN #1#2#3 +\cs_new_protected:Npn \regex_aux_use_match:Nn #1#2 { - \regex_user_aux:n + \exp_args:No \tl_if_head_eq_meaning:nNTF {#1} \regex_nfa:Nw { - \seq_gclear:N \g_regex_split_seq - \tl_set:Nn \l_regex_every_match_tl { \regex_split_aux: } - \regex_build:n {#1} + \regex_use: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:NT #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 - { - \regex_query_substr:NN - \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 + \msg_kernel_error:nnx { regex } { not-nfa } { \token_to_str:N #1 } + \bool_gset_false:N \g_regex_success_bool } - \regex_match_once: } -\cs_new_protected_nopar:Npn \regex_split_after_group:N #1 +\cs_set_protected:Npn \regex_tmp:w #1#2#3 { - \int_compare:nNnTF \l_regex_start_step_int = \l_regex_current_step_int + \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 } { - \bool_if:NF \l_regex_success_empty_bool - { \seq_gput_right:Nn \g_regex_split_seq { } } + #3 \regex_aux_build_match:nn {##1} {##2} ##3 + \regex_aux_return: } + \prg_new_protected_conditional:Npnn #2 ##1##2##3 { T , F , TF } { - \seq_gput_right:Nx \g_regex_split_seq - { - \regex_query_substr:NN - \l_regex_start_step_int \l_regex_current_step_int - } + #3 \regex_aux_use_match:Nn {##1} {##2} ##3 + \regex_aux_return: } - \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 +\tl_map_inline:nn { - \str_aux_escape:NNNn - \prg_do_nothing: - \regex_replacement_escaped:N - \prg_do_nothing: - {#1} - \tl_set_eq:NN \l_regex_replacement_tl \g_str_result_tl - \tl_set:Nx \l_regex_replacement_tl - { \l_regex_replacement_tl \prg_do_nothing: } + { extract_once } { extract_all } + { replace_once } { replace_all } + { split } } -\cs_new_nopar:Npn \regex_replacement_escaped:N #1 { - \regex_token_if_other_digit:NTF #1 - { - \exp_not:n - { \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } } {#1} - } - { - \token_if_eq_charcode:NNTF g #1 - { \exp_not:N \regex_replacement_submatch:w } - { #1 } - } + \exp_args:Nccc \regex_tmp:w + { regex_#1:nnN } { regex_#1:NnN } { regex_#1_aux:NnnN } } -\cs_new_nopar:Npn \regex_replacement_submatch:w #1 +\cs_new_protected_nopar:Npn \regex_extract: { - \exp_after:wN \token_if_eq_meaning:NNTF \c_lbrace_str #1 - { \regex_replacement_submatch_aux:nN { } } - { - \regex_token_if_other_digit:NTF #1 - { \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } } - { \msg_expandable_kernel_error:nn { regex } { g-misused } } - #1 - } + \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 + { + \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 + \fi: + \int_eval:w \l_regex_submatch_start_int + ##1 {##2} + } + \fi: } -\cs_new_nopar:Npn \regex_replacement_submatch_aux:nN #1 #2 +\cs_new_protected_nopar:Npn \regex_extract_aux_b:wn #1 < #2 { - \regex_token_if_other_digit:NTF #2 - { \regex_replacement_submatch_aux:nN {#1#2} } - { - \exp_not:n { \seq_item:Nn \g_regex_submatches_seq } {#1} - \exp_after:wN \token_if_eq_meaning:NNF \c_rbrace_str #2 - { - \msg_expandable_kernel_error:nn { regex } { g-misused } - #2 - } - } + \tex_skip:D #1 = #2 sp + plus \etex_gluestretch:D \tex_skip:D #1 \scan_stop: } -\cs_new_protected_nopar:Npn \regex_replace_after_group:N #1 +\cs_new_protected_nopar:Npn \regex_extract_aux_e:wn #1 > #2 { - \group_insert_after:N \tl_set:Nx - \group_insert_after:N #1 - \group_insert_after:N { - \group_insert_after:N \tl_to_str:N - \group_insert_after:N \g_regex_replaced_str - \group_insert_after:N } + \tex_skip:D #1 + = 1 \tex_skip:D #1 plus #2 sp \scan_stop: } -\cs_new_protected:Npn \regex_replace_once_aux:Nn #1#2 +\cs_new_protected:Npn \regex_group_end_extract_seq:N #1 { - \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} + \cs_set_eq:NN \seq_item:n \scan_stop: + \flag_lower:N \l_regex_group_begin_flag + \flag_lower:N \l_regex_group_end_flag + \tl_set:Nx \l_regex_tmpa_tl { - \cs_set_nopar:Npn \regex_tmp:w - { \str_skip_do:nn { \l_regex_tmpb_tl } { } } - \tl_gset:Nx \g_regex_replaced_str - { - \regex_query_substr:NN \c_zero \l_regex_tmpa_tl - \l_regex_replacement_tl - \exp_after:wN \regex_tmp:w \l_regex_query_other_str - } + \prg_stepwise_function:nnnN + \l_regex_max_state_int + \c_one + { \l_regex_submatch_int - \c_one } + \regex_extract_seq_aux:n } - { \tl_gset_eq:NN \g_regex_replaced_str \l_regex_query_other_str } - \group_end: + \flag_test:NF \l_regex_group_begin_flag + { \flag_test:NF \l_regex_group_end_flag { \use_none:nnn } } + \msg_kernel_error:nn { regex } { sequence-unbalanced } + \tl_set:Nx \l_regex_tmpa_tl { \l_regex_tmpa_tl } + \exp_args:NNNo \group_end: + \tl_set:Nn #1 \l_regex_tmpa_tl } -\cs_new_protected:Npn \regex_replace_once:nnN #1#2#3 +\cs_new_nopar:Npn \regex_extract_seq_aux:n #1 { - \regex_replace_once_aux:Nn #3 + \seq_item:n { - \regex_build:n {#1} - \regex_replacement:n {#2} + \exp_after:wN \regex_extract_seq_aux:ww + \int_value:w \regex_submatch_nesting_aux:n {#1} ; #1; } } -\cs_new_protected:Npn \regex_replace_once:NnN #1#2#3 +\cs_new_nopar:Npn \regex_extract_seq_aux:ww #1; #2; + { %^^A todo: use flags + \if_num:w #1 < \c_zero + \flag_raise:N \l_regex_group_end_flag + \prg_replicate:nn {-#1} { \exp_not:n { { \if_false: } \fi: } } + \fi: + \regex_query_submatch:w #2; + \if_num:w #1 > \c_zero + \flag_raise:N \l_regex_group_begin_flag + \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_replace_once_aux:Nn #3 - { - \regex_use:N #1 - \regex_replacement:n {#2} - } + \regex_match_aux:n + { \regex_aux_build_match:nn {#1} {#2} } } -\prg_new_protected_conditional:Npnn \regex_replace_once:nnN #1#2#3 {T,F,TF} +\prg_new_protected_conditional:Npnn \regex_match:Nn #1#2 { T , F , TF } { - \regex_replace_once_aux:Nn #3 - { - \regex_build:n {#1} - \regex_replacement:n {#2} - \regex_return_after_group: - } + \regex_match_aux:n + { \regex_aux_use_match:Nn #1 {#2} } } -\prg_new_protected_conditional:Npnn \regex_replace_once:NnN #1#2#3 {T,F,TF} +\cs_new_protected:Npn \regex_match_aux:n #1 { - \regex_replace_once_aux:Nn #3 - { - \regex_use:N #1 - \regex_replacement:n {#2} - \regex_return_after_group: - } + \group_begin: + \tl_clear:N \l_regex_every_match_tl + \regex_disable_submatches: + #1 + \group_end: + \regex_aux_return: } -\cs_new_protected:Npn \regex_replace_all_aux:Nn #1#2 +\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 { \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} - \cs_set_nopar:Npn \regex_tmp:w - { \str_skip_do:nn { \l_regex_start_step_int } { } } - \tl_gput_right:Nx \g_regex_replaced_str - { \exp_after:wN \regex_tmp:w \l_regex_query_other_str } + \regex_disable_submatches: + \int_zero:N \l_regex_match_count_int + \tl_set:Nn \l_regex_every_match_tl + { + \int_incr:N \l_regex_match_count_int + \regex_match_once: + } + #1 {#2} {#3} + \exp_args:NNNo \group_end: + \int_set:Nn #4 { \int_use:N \l_regex_match_count_int } } -\cs_new_protected_nopar:Npn \regex_replace_all_aux: +\cs_new_protected:Npn \regex_extract_once_aux:NnnN #1#2#3#4 { - \regex_extract: - \regex_extract_aux:nTF {0} - { - \tl_gput_right:Nx \g_regex_replaced_str + \group_begin: + \tl_set:Nn \l_regex_every_match_tl { \regex_extract: } + #1 {#2} {#3} + \regex_group_end_extract_seq:N #4 + } +\cs_new_protected:Npn \regex_extract_all_aux:NnnN #1#2#3#4 + { + \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 + } +\cs_new_protected:Npn \regex_split_aux:NnnN #1#2#3#4 + { + \group_begin: + \tl_set:Nn \l_regex_every_match_tl + { + \if_num:w \l_regex_start_step_int < \l_regex_success_step_int + \regex_extract: + \tex_skip:D \l_regex_submatch_start_int + = \l_regex_start_step_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_step_int sp + plus \l_regex_current_step_int sp \scan_stop: + \int_incr:N \l_regex_submatch_int + \if_num:w \l_regex_start_step_int = \l_regex_current_step_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 + } +\cs_new_protected:Npn \regex_replace_once_aux:NnnN #1#2#3#4 + { + \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_extract: + \int_set:Nn \l_regex_tmpa_int + { \regex_nesting:n { \l_regex_submatch_start_int } } + \if_num:w \l_regex_tmpa_int = \c_zero + \else: + \msg_kernel_error:nnx { regex } { replace-unbalanced } + { \l_regex_tmpa_int } + \fi: + \tl_set:Nx \l_regex_tmpa_tl { - \regex_query_substr:NN - \l_regex_start_step_int \l_regex_tmpa_tl - \l_regex_replacement_tl + \if_num:w \l_regex_tmpa_int < \c_zero + \prg_replicate:nn { - \l_regex_tmpa_int } + { \exp_not:n { { \if_false: } \fi: } } + \fi: + \regex_query_substr:nn + { \l_regex_min_step_int } + { \tex_skip:D \l_regex_submatch_start_int } + \regex_replacement_tl:n { \l_regex_submatch_start_int } + \regex_query_substr:nn + { \etex_gluestretch:D \tex_skip:D \l_regex_submatch_start_int } + { \l_regex_max_step_int } + \if_num:w \l_regex_tmpa_int > \c_zero + \prg_replicate:nn { \l_regex_tmpa_int } + { \exp_not:n { \if_false: { \fi: } } } + \fi: } - } - { \msg_error:nn { regex } { internal } } - \regex_match_once: + \tl_set:Nx \l_regex_tmpa_tl { \l_regex_tmpa_tl } + \exp_args:NNNo \group_end: + \tl_set:Nn #4 \l_regex_tmpa_tl + \else: + \group_end: + \fi: } -\cs_new_protected:Npn \regex_replace_all:nnN #1#2#3 +\cs_new_protected_nopar:Npn \regex_replace_once_aux:w #1; { - \regex_replace_all_aux:Nn #3 + } +\cs_new_protected:Npn \regex_replace_all_aux:NnnN #1#2#3#4 + { + \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_step_int sp \scan_stop: + \regex_match_once: + } + \regex_replacement:n {#3} + \exp_args:Nno #1 {#2} #4 + \int_set:Nn \l_regex_tmpa_int + { + 0 + \prg_stepwise_function:nnnN + \l_regex_max_state_int + \l_regex_capturing_group_int + { \l_regex_submatch_int - \c_one } + \regex_nesting:n + } + \if_num:w \l_regex_tmpa_int = \c_zero + \else: + \msg_kernel_error:nnx { regex } { replace-unbalanced } + { \l_regex_tmpa_int } + \fi: + \tl_set:Nx \l_regex_tmpa_tl + { + \if_num:w \l_regex_tmpa_int < \c_zero + \prg_replicate:nn { - \l_regex_tmpa_int } + { \exp_not:n { { \if_false: } \fi: } } + \fi: + \prg_stepwise_function:nnnN + \l_regex_max_state_int + \l_regex_capturing_group_int + { \l_regex_submatch_int - \c_one } + \regex_replace_all_aux:n + \regex_query_substr:nn + \l_regex_start_step_int \l_regex_max_step_int + \if_num:w \l_regex_tmpa_int > \c_zero + \prg_replicate:nn { \l_regex_tmpa_int } + { \exp_not:n { \if_false: { \fi: } } } + \fi: + } + \tl_set:Nx \l_regex_tmpa_tl { \l_regex_tmpa_tl } + \exp_args:NNNo \group_end: + \tl_set:Nn #4 \l_regex_tmpa_tl + } +\cs_new_nopar:Npn \regex_replace_all_aux:n #1 + { + \regex_query_substr:nn + { \etex_glueshrink:D \tex_skip:D #1 } { \tex_skip:D #1 } + \regex_replacement_tl:n {#1} + } +\msg_kernel_new:nnnn { regex } { sequence-unbalanced } + { + Missing~ + \flag_test:NTF \l_regex_group_end_flag { - \regex_build:n {#1} - \regex_replacement:n {#2} + left~ + \flag_test:NTF \l_regex_group_begin_flag + { and~right~braces } { brace } } + { right~brace } + \ inserted~in~extracted~match. } -\cs_new_protected:Npn \regex_replace_all:NnN #1#2#3 { - \regex_replace_all_aux:Nn #3 + 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. + } +\msg_kernel_new:nnnn { regex } { replace-unbalanced } + { The~result~of~a~replacement~does~not~have~balanced~braces. } + { + LaTeX~was~asked~to~do~some~regular~expression~replacement,~ + and~the~resulting~token~list~would~not~have~the~same~number~ + of~begin-group~and~end-group~tokens. \\ \\ + \ \ \ \ + \prg_case_int:nnn {#1} { - \regex_use:N #1 - \regex_replacement:n {#2} + { -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. + } +\msg_kernel_new:nnnn { regex } { missing-rparen } + { Missing~right~parenthesis~added~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_new:nnn { regex } { -998 } { Unsupported~construct } -\msg_new:nnn { regex } { -997 } - { The~regular~expression~is~too~large~(32768~states). } -\msg_new:nnn { regex } { 1 } { \iow_char:N\\~at~end~of~pattern } -\msg_new:nnn { regex } { 4 } - { Numbers~out~of~order~in~\iow_char:N\{\iow_char\}~quantifier. } -\msg_new:nnn { regex } { 6 } - { Missing~terminating~\iow_char:N\]~for~character~class } -\msg_new:nnn { regex } { 7 } - { Invalid~escape~sequence~in~character~class } -\msg_new:nnn { regex } { 8 } - { Range~out~of~order~in~character~class } -\msg_new:nnn { regex } { 22 } { Mismatched~parentheses } -\msg_new:nnn { regex } { 34 } - { Character~value~in~\iow_char:N\\x{...}~sequence~is~too~large } -\msg_new:nnn { regex } { not-nfa } - { - LaTeX~was~expecting~a~regular~expression~variable.\\ - Instead,~LaTeX~found~'#1'. +\msg_kernel_new:nnnn { regex } { backwards-range } + { 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 } { unsupported } + { Unsupported~construction~`#1'. } + { + The~construction~`#1'~is~not~supported~by~the~LaTeX~ + regular~expression~module.~Perhaps~some~character~should~ + have~been~escaped? + } +\msg_kernel_new:nnnn { regex } { not-nfa } + { This~is~not~a~regular~expression~variable. } + { + 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 . + } +\msg_kernel_new:nnnn { regex } { build-c } + { Misused~\iow_char:N\\c~or\iow_char:N\\C~command~in~regular~expression. } + { + The~\iow_char:N\\C~escape~sequence~can~be~followed~by~ + one~of~the~letters~ABCDELMOPSTU.~The~\iow_char:N\\c~ + escape~sequence~can~also~be~followed~by~a~brace~group. + } +\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. + } +\msg_kernel_new:nnnn { regex } { invalid-in-option } + { Invalid~character~in~option~of~a~regular~expression. } + { + The~character~or~escape~sequence~`#1'~is~not~defined~ + as~an~option~within~regular~expressions. + } +\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-c } + { Something~is~wrong~with~the~replacement~text. } + { + The~\iow_char:N\\c~escape~sequence~can~only~be~followed~by~ + ABCDELMN~or~by~a~brace. } \msg_kernel_new:nnn { regex } { nfa-misused } { Automaton~#1 used~incorrectly. } -\msg_kernel_new:nnn { regex } { g-misused } - { \g misused~in~replacement~text. } %% %% %% End of file `l3regex.sty'. diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-hex.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-hex.def index 9af2e4322ad..b24f29458a5 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-hex.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-hex.def @@ -47,13 +47,16 @@ %% ----------------------------------------------------------------------- \cs_new_protected_nopar:Npn \str_convert_input_hex: { - \tl_gset:Nx \g_str_result_tl - { - \str_output_byte:w " - \exp_after:wN \str_convert_input_hex_aux:N - \g_str_result_tl 0 { ? 0 - \c_one \prg_map_break: } - \prg_break_point:n { \str_output_end: } - } + \group_begin: + \int_set:Nn \tex_escapechar:D { 92 } + \tl_gset:Nx \g_str_result_tl + { + \str_output_byte:w " + \exp_after:wN \str_convert_input_hex_aux:N + \g_str_result_tl 0 { ? 0 - \c_one \prg_map_break: } + \prg_break_point:n { \str_output_end: } + } + \group_end: } \cs_new_nopar:Npn \str_convert_input_hex_aux:N #1 { diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-name.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-name.def index 8d378c87e3d..66e7dddb6b8 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-name.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-name.def @@ -49,12 +49,15 @@ { \cs_new_protected_nopar:Npn #2 { - \tl_gset:Nx \g_str_result_tl - { - \exp_after:wN #3 \g_str_result_tl - #1 ? { ? \prg_map_break: } - \prg_break_point:n { } - } + \group_begin: + \int_set:Nn \tex_escapechar:D { 92 } + \tl_gset:Nx \g_str_result_tl + { + \exp_after:wN #3 \g_str_result_tl + #1 ? { ? \prg_map_break: } + \prg_break_point:n { } + } + \group_end: } \cs_new_nopar:Npn #3 ##1#1##2##3 { diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-string.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-string.def index 7718a0d1b25..5e8fd099b25 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-string.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-string.def @@ -53,18 +53,21 @@ { \cs_new_protected_nopar:Npn \str_convert_input_string: { - \tl_gset:Nx \g_str_result_tl - { - \exp_after:wN \str_convert_input_string_aux:wN - \g_str_result_tl \prg_map_break: ^^M ? - \prg_break_point:n { } - } - \tl_gset:Nx \g_str_result_tl - { - \exp_after:wN \str_convert_input_string_aux:wNNN - \g_str_result_tl * ?? { ? \prg_map_break: } - \prg_break_point:n { } - } + \group_begin: + \int_set:Nn \tex_escapechar:D { 92 } + \tl_gset:Nx \g_str_result_tl + { + \exp_after:wN \str_convert_input_string_aux:wN + \g_str_result_tl \prg_map_break: ^^M ? + \prg_break_point:n { } + } + \tl_gset:Nx \g_str_result_tl + { + \exp_after:wN \str_convert_input_string_aux:wNNN + \g_str_result_tl * ?? { ? \prg_map_break: } + \prg_break_point:n { } + } + \group_end: } \cs_new_nopar:Npn \str_convert_input_string_aux:wNNN #1 *#2#3#4 } diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-url.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-url.def index bf6bf96514d..13cbde871fe 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-url.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-url.def @@ -49,12 +49,15 @@ { \cs_new_protected_nopar:Npn #2 { - \tl_gset:Nx \g_str_result_tl - { - \exp_after:wN #3 \g_str_result_tl - #1 ? { ? \prg_map_break: } - \prg_break_point:n { } - } + \group_begin: + \int_set:Nn \tex_escapechar:D { 92 } + \tl_gset:Nx \g_str_result_tl + { + \exp_after:wN #3 \g_str_result_tl + #1 ? { ? \prg_map_break: } + \prg_break_point:n { } + } + \group_end: } \cs_new_nopar:Npn #3 ##1#1##2##3 { diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf16.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf16.def index e2bea7ca224..001b955ac07 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf16.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf16.def @@ -127,13 +127,13 @@ \if_meaning:w \scan_stop: #2 \str_aux_from_utf_xvi_end:Nw #1 \fi: - \int_use:N \int_eval:w - \if_case:w - \int_eval:w ( \str_tmp:w #1#2 - "D6 ) / \c_four \int_eval_end: - \or: \exp_after:wN \str_aux_from_utf_xvi:wNNN - \or: \exp_after:wN \str_aux_from_utf_xvi_error:wNNw - \fi: - "100 * \str_tmp:w #1#2 + \str_tmp:w #2#1 , + \if_case:w + \int_eval:w ( \str_tmp:w #1#2 - "D6 ) / \c_four \int_eval_end: + \or: #1#2 \exp_after:wN \str_aux_from_utf_xvi:wNNN + \or: \exp_after:wN \str_aux_from_utf_xvi_error:wNNw + \else: #1#2 \exp_not:N \q_mark \int_use:N \int_eval:w + \fi: + "100 * \str_tmp:w #1#2 + \str_tmp:w #2#1 , \str_aux_from_utf_xvi:NN } \cs_new:Npn \str_aux_from_utf_xvi:wNNN #1, #2#3#4 @@ -142,8 +142,10 @@ \str_aux_from_utf_xvi_end:wNNww #1 , #3 \fi: \if_num:w \int_eval:w ( \str_tmp:w #3#4 - "DA ) / \c_four = \c_one - ( #1 - "D800 ) * "400 - + \str_tmp:w #3#4 * "100 + \str_tmp:w #4#3 - "DC00 , + #3 #4 + \int_use:N \int_eval:w + ( #1 - "D800 ) * "400 + + \str_tmp:w #3#4 * "100 + \str_tmp:w #4#3 - "DC00 , \exp_after:wN \use_i:nnn \else: \str_aux_from_utf_xvi_error:wNNw #1 , @@ -152,6 +154,7 @@ } \cs_new:Npn \str_aux_from_utf_xvi_error:wNNw #1 \str_tmp:w #2#3 #4, { + \exp_not:N \q_mark \msg_expandable_kernel_error:nnn { str } { utf16-surrogate } { #2#3 } \c_str_replacement_char_int , @@ -161,15 +164,17 @@ \fi: \if_meaning:w \scan_stop: #1 \else: + #1 \exp_not:N \q_mark \msg_expandable_kernel_error:nnn { str } { utf16-odd } {#1} - \c_str_replacement_char_int , + \int_use:N \c_str_replacement_char_int , \fi: \prg_map_break: } \cs_new:Npn \str_aux_from_utf_xvi_end:wNNww #1 `#2#3 #4, #5 \fi: { \fi: + \exp_not:N \q_mark \if_meaning:w \scan_stop: #5 \msg_expandable_kernel_error:nnn { str } { utf16-surrogate } { #2#3 } @@ -177,7 +182,7 @@ \msg_expandable_kernel_error:nnn { str } { utf16-odd } { #2#3#5 } \fi: - \c_str_replacement_char_int , + \int_use:N \c_str_replacement_char_int , \prg_map_break: } \group_end: diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf32.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf32.def index 7c56d2e3929..8251d8c44fe 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf32.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf32.def @@ -107,31 +107,33 @@ \cs_new:Npn \str_aux_from_utf_xxxii:NNNN #1#2#3#4 { \if_meaning:w \scan_stop: #4 - \str_aux_from_utf_xxxii_end:ww #1#2#3#4 + \exp_after:wN \str_aux_from_utf_xxxii_end:w + \fi: + #1#2#3#4 \exp_not:N \q_mark + \if_num:w \int_eval:w + \str_tmp:w #1#4 * \c_two_hundred_fifty_six + + \str_tmp:w #2#3 + > \c_sixteen + \msg_expandable_kernel_error:nnn + { str } { utf32-overflow } { #1#2#3#4 } + \int_use:N \c_str_replacement_char_int + \else: + \int_use:N \int_eval:w + \str_tmp:w #2#3*"10000 + + \str_tmp:w #3#2 * \c_two_hundred_fifty_six + + \str_tmp:w #4#1 \fi: - \int_use:N \int_eval:w - \if_num:w \int_eval:w - \str_tmp:w #1#4 * \c_two_hundred_fifty_six - + \str_tmp:w #2#3 - > \c_sixteen - \msg_expandable_kernel_error:nnn - { str } { utf32-overflow } { #1#2#3#4 } - \c_str_replacement_char_int - \else: - \str_tmp:w #2#3*"10000 - + \str_tmp:w #3#2 * \c_two_hundred_fifty_six - + \str_tmp:w #4#1 - \fi: , \str_aux_from_utf_xxxii:NNNN } - \cs_new:Npn \str_aux_from_utf_xxxii_end:ww #1 \scan_stop: #2 \fi: + \cs_new:Npn \str_aux_from_utf_xxxii_end:w #1 \scan_stop: { - \fi: \tl_if_empty:nF {#1} { \msg_expandable_kernel_error:nnn { str } { utf32-truncated } { #1 } + #1 \exp_not:N \q_mark + \int_use:N \c_str_replacement_char_int , } \prg_map_break: } diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf8.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf8.def index 9e0f26c2346..d6233f22557 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf8.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-utf8.def @@ -74,32 +74,33 @@ \tl_gset:Nx \g_str_result_tl { \exp_after:wN \str_aux_from_utf_viii:N \g_str_result_tl - { ? \prg_map_break: \q_stop \str_aux_from_utf_viii_error: } + { \prg_map_break: \str_aux_from_utf_viii_error: } \prg_break_point:n { } } } \cs_new_nopar:Npn \str_aux_from_utf_viii:N #1 { - \use_none:n #1 - \int_use:N \int_eval:w - \if_num:w `#1 < "C0 \exp_stop_f: - \if_num:w `#1 < "80 \exp_stop_f: - `#1 - \else: - \msg_expandable_kernel_error:nnn - { str } { utf8-extra-conti } {#1} - \c_str_replacement_char_int - \fi: + #1 + \if_num:w `#1 < "C0 \exp_stop_f: + \exp_not:N \q_mark + \if_num:w `#1 < "80 \exp_stop_f: + \int_value:w `#1 \else: - \if_num:w `#1 < "F5 \exp_stop_f: - \exp_after:wN \str_aux_from_utf_viii:wwNN - \int_use:N \int_eval:w `#1 - "C0 - \else: - \msg_expandable_kernel_error:nnn - { str } { utf8-invalid-byte } {#1} - \c_str_replacement_char_int - \fi: + \msg_expandable_kernel_error:nnn + { str } { utf8-extra-conti } {#1} + \int_use:N \c_str_replacement_char_int \fi: + \else: + \if_num:w `#1 < "F5 \exp_stop_f: + \exp_after:wN \str_aux_from_utf_viii:wwNN + \int_use:N \int_eval:w `#1 - "C0 + \else: + \exp_not:N \q_mark + \msg_expandable_kernel_error:nnn + { str } { utf8-invalid-byte } {#1} + \int_use:N \c_str_replacement_char_int + \fi: + \fi: , \use_none_delimit_by_q_stop:w "80 , "800 , "10000 , "10FFFF , @@ -108,7 +109,7 @@ } \cs_new_nopar:Npn \str_aux_from_utf_viii:wwNN #1 , #2 \q_stop #3#4 { - \use_none_delimit_by_q_stop:w #4 \q_stop + \use_none:n #4 \exp_after:wN \str_aux_from_utf_viii:wNNww \int_use:N \int_eval:w #1 * "40 + `#4 - "80 , #4 @@ -121,8 +122,9 @@ \if_num:w #1 < #4 \exp_stop_f: \str_aux_from_utf_viii_error:w #1 , \else: + #2 \if_num:w #1 < #5 \exp_stop_f: - #1 + \exp_not:N \q_mark #1 \else: \exp_after:wN \str_aux_from_utf_viii:wwNN \int_use:N \int_eval:w #1 - #5 @@ -136,12 +138,14 @@ } \cs_new_nopar:Npn \str_aux_from_utf_viii_error:w #1 , { + \exp_not:N \q_mark \msg_expandable_kernel_error:nnn { str } { utf8-overlong } {#1} \c_str_replacement_char_int } \cs_new_nopar:Npn \str_aux_from_utf_viii_error:NwN #1 #2 \q_stop #3 { + \exp_not:N \q_mark \msg_expandable_kernel_error:nnn { str } { utf8-missing-conti } {#1} \c_str_replacement_char_int , @@ -149,6 +153,7 @@ } \cs_new_nopar:Npn \str_aux_from_utf_viii_error: { + \exp_not:N \q_mark \msg_expandable_kernel_error:nn { str } { utf8-premature-end } \c_str_replacement_char_int , diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty index c49601841e0..7d527b6d264 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str.sty @@ -46,23 +46,10 @@ %% %% ----------------------------------------------------------------------- \RequirePackage{expl3} -\GetIdInfo$Id: l3str.dtx 3035 2011-12-07 11:48:46Z bruno $ +\GetIdInfo$Id: l3str.dtx 3088 2011-12-23 02:00:14Z bruno $ {L3 Experimental Strings} \ProvidesExplPackage {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} -\cs_if_exist:NF \use_i:nnnnnnnn - { \cs_new:Npn \use_i:nnnnnnnn #1#2#3#4#5#6#7#8 {#1} } -\int_const:Nn \c_forty_eight { 48 } -\int_const:Nn \c_fifty_eight { 58 } -\int_const:Nn \c_sixty_five { 65 } -\int_const:Nn \c_ninety_one { 91 } -\int_const:Nn \c_ninety_seven { 97 } -\int_const:Nn \c_one_hundred_twenty_three { 123 } -\int_const:Nn \c_one_hundred_twenty_seven { 127 } -\pdftex_if_engine:TF - { \int_const:Nn \c_max_char_int { 255 } } - { \int_const:Nn \c_max_char_int { 1114111 } } -\int_const:Nn \c_str_replacement_char_int { "FFFD } \group_begin: \cs_set_protected_nopar:Npn \str_tmp:w #1 { @@ -80,8 +67,19 @@ \group_end: \cs_new_protected_nopar:Npn \str_tmp:w { } \tl_new:N \l_str_tmpa_tl +\int_new:N \l_str_tmpa_int \tl_new:N \g_str_result_tl \int_new:N \l_str_char_int +\int_const:Nn \c_forty_eight { 48 } +\int_const:Nn \c_fifty_eight { 58 } +\int_const:Nn \c_sixty_five { 65 } +\int_const:Nn \c_ninety_one { 91 } +\int_const:Nn \c_ninety_seven { 97 } +\int_const:Nn \c_one_hundred_twenty_three { 123 } +\int_const:Nn \c_one_hundred_twenty_seven { 127 } +\int_const:Nn \c_max_char_int + { \pdftex_if_engine:TF { 255 } { 1114111 } } +\int_const:Nn \c_str_replacement_char_int { "FFFD } \tl_const:Nx \c_backslash_str { \cs_to_str:N \\ } \tl_const:Nx \c_lbrace_str { \cs_to_str:N \{ } \tl_const:Nx \c_rbrace_str { \cs_to_str:N \} } @@ -100,7 +98,6 @@ \prop_gput:Nnn \g_str_aliases_prop { latin9 } { iso885915 } \prop_gput:Nnn \g_str_aliases_prop { latin10 } { iso885916 } \prop_gput:Nnn \g_str_aliases_prop { hexadecimal } { hex } -\prop_gput:Nnn \g_str_aliases_prop { percent } { url } \group_begin: \char_set_lccode:nn { `\* } { `\ } \char_set_lccode:nn { `\A } { `\A } @@ -124,72 +121,53 @@ \cs_new_nopar:Npn \tl_to_other_str_end:w \fi: #1 \q_mark #2 * A #3 \q_stop { \fi: #2 } } -\cs_new_nopar:Npn \tl_to_other_str:N { \exp_args:No \tl_to_other_str:n } -\cs_new:Npn \str_sanitize_args:Nn #1#2 - { \exp_args:Nf #1 { \tl_to_other_str:n {#2} } } -\cs_new:Npn \str_sanitize_args:Nnn #1#2#3 - { - \exp_args:Nff #1 - { \tl_to_other_str:n {#2} } - { \tl_to_other_str:n {#3} } - } \group_begin: \char_set_lccode:nn { `\* } { `\ } \char_set_lccode:nn { `\A } { `\A } \tl_to_lowercase:n { \group_end: - \cs_new_protected:Npn \str_aux_gset_other:Nn #1#2 + \cs_new_protected:Npn \str_gset_other:Nn #1#2 { \tl_gset:Nx #1 { - \exp_after:wN \str_aux_gset_other_loop:w \tl_to_str:n {#2} ~ % + \exp_after:wN \str_gset_other_loop:w \tl_to_str:n {#2} ~ % A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_mark \q_stop } } - \cs_new_nopar:Npn \str_aux_gset_other_loop:w + \cs_new_nopar:Npn \str_gset_other_loop:w #1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 ~ { \if_meaning:w A #9 - \str_aux_gset_other_end:w + \str_gset_other_end:w \fi: #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * #9 - \str_aux_gset_other_loop:w * + \str_gset_other_loop:w * } - \cs_new_nopar:Npn \str_aux_gset_other_end:w \fi: #1 * A #2 \q_stop + \cs_new_nopar:Npn \str_gset_other_end:w \fi: #1 * A #2 \q_stop { \fi: #1 } } -\cs_new_nopar:Npn \str_map_tokens:Nn - { \exp_args:No \str_map_tokens:nn } -\cs_new:Npn \str_map_tokens:nn #1 - { \exp_args:No \str_map_tokens_aux:nn { \tl_to_str:n {#1} } } -\cs_new:Npn \str_map_tokens_aux:nn #1#2 +\cs_if_exist:NF \use_i:nnnnnnnn + { \cs_new:Npn \use_i:nnnnnnnn #1#2#3#4#5#6#7#8 {#1} } +\cs_new:Npn \str_aux_toks_range:nn #1#2 { - \str_map_tokens_loop:nw {#2} #1 - { ? \use_none_delimit_by_q_recursion_stop:w } - ?~ ?~ ?~ ?~ ?~ ?~ ?~ ?~ \q_recursion_stop + \exp_after:wN \str_aux_toks_range:ww + \int_use:N \int_eval:w #1 \exp_after:wN ; + \int_use:N \int_eval:w #2 ; + \prg_break_point:n { } } -\group_begin: - \char_set_lccode:nn { `* } { `\ } - \tl_to_lowercase:n - { - \group_end: - \cs_new:Npn \str_map_tokens_loop:nw #1 #2~ #3~ #4~ #5~ #6~ #7~ #8~ #9~ - { - \str_map_tokens_loop:nN {#1} #2* #3* #4* #5* #6* #7* #8* #9* - { ? \use_none_delimit_by_q_stop:w } \q_stop - \str_map_tokens_loop:nw {#1} - } - } -\cs_new:Npn \str_map_tokens_loop:nN #1#2 +\cs_new:Npn \str_aux_toks_range:ww #1 ; #2 ; { - \use_none:n #2 - #1 #2 - \str_map_tokens_loop:nN {#1} + \if_num:w #1 = #2 \exp_stop_f: + \exp_after:wN \prg_map_break: + \fi: + \tex_the:D \tex_toks:D #1 \exp_stop_f: + \exp_after:wN \str_aux_toks_range:ww + \int_use:N \int_eval:w #1 + \c_one ; #2 ; } -\cs_new_eq:NN \str_map_break_do:n \use_i_delimit_by_q_recursion_stop:nw \cs_new_nopar:Npn \str_length:N { \exp_args:No \str_length:n } -\cs_new:Npn \str_length:n { \str_sanitize_args:Nn \str_length_unsafe:n } +\cs_new:Npn \str_length:n #1 + { \exp_args:Nf \str_length_unsafe:n { \tl_to_other_str:n {#1} } } \cs_new_nopar:Npn \str_length_unsafe:n #1 { \str_length_aux:n { \str_length_loop:NNNNNNNNN #1 } } \cs_new:Npn \str_length_ignore_spaces:n #1 @@ -308,7 +286,7 @@ \cs_new:Npn \str_item:nn #1#2 { \exp_args:Nf \tl_to_str:n - { \str_sanitize_args:Nn \str_item_unsafe:nn {#1} {#2} } + { \exp_args:Nf \str_item_unsafe:nn { \tl_to_other_str:n {#1} } {#2} } } \cs_new:Npn \str_item_ignore_spaces:nn #1 { \exp_args:No \str_item_unsafe:nn { \tl_to_str:n {#1} } } @@ -344,26 +322,31 @@ \cs_new:Npn \str_substr:nnn #1#2#3 { \exp_args:Nf \tl_to_str:n - { \str_sanitize_args:Nn \str_substr_unsafe:nnn {#1} {#2} {#3} } + { + \exp_args:Nf \str_substr_unsafe:nnn + { \tl_to_other_str:n {#1} } {#2} {#3} + } } \cs_new:Npn \str_substr_ignore_spaces:nnn #1 { \exp_args:No \str_substr_unsafe:nnn { \tl_to_str:n {#1} } } \cs_new:Npn \str_substr_unsafe:nnn #1#2#3 { - \str_aux_eval_args:Nnnn \str_substr_aux:nnnw - { \str_length_unsafe:n {#1} } - {#2} - {#3} + \exp_after:wN \str_substr_aux:www + \int_value:w \str_length_unsafe:n {#1} \exp_after:wN ; + \int_use:N \int_eval:w #2 + \c_zero \exp_after:wN ; + \int_use:N \int_eval:w \exp_args:Nf \str_substr_unsafe:nN {#3} \c_max_int ; #1 \q_stop } -\cs_new:Npn \str_substr_aux:nnnw #1#2#3 +\cs_new:Npn \str_substr_unsafe:nN #1 #2 + { \tl_if_empty:nTF {#1} {#2} {#1} } +\cs_new:Npn \str_substr_aux:www #1; #2; #3; { - \exp_args:Nf \str_substr_aux_ii:nnw + \exp_args:Nf \str_substr_aux:nnw { \str_aux_normalize_range:nn {#2} {#1} } { \str_aux_normalize_range:nn {#3} {#1} } } -\cs_new:Npn \str_substr_aux_ii:nnw #1#2 +\cs_new:Npn \str_substr_aux:nnw #1#2 { \str_skip_do:nn {#1} { @@ -372,13 +355,6 @@ { \use_i_delimit_by_q_stop:nw } } } -\cs_new:Npn \str_aux_eval_args:Nnnn #1#2#3#4 - { - \exp_after:wN #1 - \exp_after:wN { \int_value:w \int_eval:w #2 \exp_after:wN } - \exp_after:wN { \int_value:w \int_eval:w #3 \exp_after:wN } - \exp_after:wN { \int_value:w \int_eval:w #4 } - } \cs_new:Npn \str_aux_normalize_range:nn #1#2 { \int_eval:n @@ -403,69 +379,32 @@ \if_int_compare:w \pdftex_strcmp:D { \tl_to_str:N #1 } { \tl_to_str:N #2 } = \c_zero \prg_return_true: \else: \prg_return_false: \fi: } -\prg_new_conditional:Npnn \str_if_contains_char:NN #1#2 { p , T , F , TF } +\prg_new_conditional:Npnn \str_if_contains_char:NN #1#2 { T , TF } { - \str_map_tokens:Nn #1 { \str_if_contains_char_aux:NN #2 } + \exp_after:wN \str_if_contains_char_aux:NN \exp_after:wN #2 + #1 { \prg_map_break:n { ? \fi: } } + \prg_break_point:n { } \prg_return_false: } -\prg_new_conditional:Npnn \str_if_contains_char:nN #1#2 { p , T , F , TF } +\prg_new_conditional:Npnn \str_if_contains_char:nN #1#2 { TF } { - \str_map_tokens:nn {#1} { \str_if_contains_char_aux:NN #2 } + \exp_after:wN \str_if_contains_char_aux:NN \exp_after:wN #2 + \tl_to_str:n {#1} { \prg_map_break:n { ? \fi: } } + \prg_break_point:n { } \prg_return_false: } \cs_new_nopar:Npn \str_if_contains_char_aux:NN #1#2 { - \if_num:w `#1 = `#2 \exp_stop_f: - \str_if_contains_char_end:w + \if_charcode:w #1 #2 + \exp_after:wN \str_if_contains_char_end: \fi: + \str_if_contains_char_aux:NN #1 } -\cs_new_nopar:Npn \str_if_contains_char_end:w \fi: #1 \prg_return_false: - { \fi: \prg_return_true: } -\pdftex_if_engine:TF - { - \cs_new_eq:NN \str_if_bytes_p:N \c_true_bool - \cs_new_eq:NN \str_if_bytes:NT \use_ii:nn - \cs_new_eq:NN \str_if_bytes:NF \use_none:nn - \cs_new_eq:NN \str_if_bytes:NTF \use_ii:nnn - } - { - \prg_new_conditional:Npnn \str_if_bytes:N #1 { p , T , F , TF } - { - \exp_args:Nf \tl_map_function:nN - { \tl_to_str:N #1 } - \str_if_bytes_aux:N - \prg_return_true: - } - \cs_new_nopar:Npn \str_if_bytes_aux:N #1 - { - \if_num:w `#1 > \c_two_hundred_fifty_five - \exp_after:wN \str_if_bytes_aux: - \fi: - } - \cs_new_nopar:Npn \str_if_bytes_aux: - { \tl_map_break:n { \prg_return_false: \use_none:n } } - } -\prg_new_protected_conditional:Npnn \str_aux_hexadecimal_test:N #1 { TF } - { - \tl_if_in:onTF { \tl_to_str:n { abcdef } } {#1} - { - \int_set:Nn \l_str_char_int - { \c_sixteen * \l_str_char_int + `#1 - 87 } - \prg_return_true: - } - { - \if_num:w \c_fifteen < "1 \exp_not:N #1 \exp_stop_f: - \int_set:Nn \l_str_char_int - { \c_sixteen * \l_str_char_int + "#1 } - \prg_return_true: - \else: - \prg_return_false: - \fi: - } - } +\cs_new_nopar:Npn \str_if_contains_char_end: + { \prg_map_break:n { \prg_return_true: \use_none:n } } \prg_new_conditional:Npnn \str_aux_octal_use:N #1 { TF } { - \if_num:w \c_one < '1 #1 \exp_stop_f: + \if_num:w \c_one < '1 \token_to_str:N #1 \exp_stop_f: #1 \prg_return_true: \else: \prg_return_false: @@ -473,21 +412,27 @@ } \prg_new_conditional:Npnn \str_aux_hexadecimal_use:N #1 { TF } { - \if_num:w \c_two < "1 #1 \exp_stop_f: + \if_num:w \c_two < "1 \token_to_str:N #1 \exp_stop_f: #1 \prg_return_true: \else: - \if_case:w \int_eval:w `#1 - `a \int_eval_end: - A \prg_return_true: - \or: B \prg_return_true: - \or: C \prg_return_true: - \or: D \prg_return_true: - \or: E \prg_return_true: - \or: F \prg_return_true: - \else: \prg_return_false: + \if_case:w \int_eval:w + \exp_after:wN ` \token_to_str:N #1 - `a + \int_eval_end: + A + \or: B + \or: C + \or: D + \or: E + \or: F + \else: + \prg_return_false: + \exp_after:wN \use_none:n \fi: + \prg_return_true: \fi: } \group_begin: + \tl_clear:N \l_str_tmpa_tl \char_set_catcode_other:n { \c_zero } \tl_gset:Nx \g_str_result_tl { \tl_to_str:n { 0123456789ABCDEF } } \tl_map_inline:Nn \g_str_result_tl @@ -496,15 +441,18 @@ { \tl_map_inline:Nn \g_str_result_tl { - \char_set_lccode:nn { \c_zero } {"##1#1} + \char_set_lccode:nn { \c_zero } {"#1##1} \tl_to_lowercase:n { \tl_const:cx - { c_str_byte_ \int_eval:n {"##1#1} _tl } - { ^^@ ##1 #1 } + { c_str_byte_ \int_eval:n {"#1##1} _tl } + { ^^@ #1 ##1 } + \tl_put_right:Nn \l_str_tmpa_tl { ^^@ } } } } + \tl_const:Nx \c_str_positive_bytes_tl + { \exp_after:wN \use_none:n \l_str_tmpa_tl } \group_end: \tl_const:cn { c_str_byte_-1_tl } { { } \use_none:n { } } \cs_new:Npn \str_output_byte:n #1 @@ -545,17 +493,17 @@ { \tl_gset:Nx \g_str_result_tl { - \exp_after:wN \str_aux_gmap_internal_result_loop:Nw + \exp_after:wN \str_aux_gmap_internal_result_loop:Nww \exp_after:wN #1 - \g_str_result_tl \q_stop \prg_map_break: , + \g_str_result_tl \q_mark \q_stop \prg_map_break: , \prg_break_point:n { } } } -\cs_new_nopar:Npn \str_aux_gmap_internal_result_loop:Nw #1#2, +\cs_new_nopar:Npn \str_aux_gmap_internal_result_loop:Nww #1#2\q_mark #3, { - \use_none_delimit_by_q_stop:w #2 \q_stop - #1 {#2} - \str_aux_gmap_internal_result_loop:Nw #1 + \use_none_delimit_by_q_stop:w #3 \q_stop + #1 {#3} + \str_aux_gmap_internal_result_loop:Nww #1 } \cs_new_protected:Npn \str_input:Nn #1#2 { @@ -567,9 +515,11 @@ \str_aux_escape:NNNn \token_to_str:N \token_to_str:N \token_to_str:N {#2} \tl_gset_eq:NN #1 \g_str_result_tl } -\cs_new_eq:NN \str_aux_escape_unescaped:N \use:n -\cs_new_eq:NN \str_aux_escape_escaped:N \use:n -\cs_new_eq:NN \str_aux_escape_raw:N \use:n +\cs_new_protected:Npn \str_escape_use:NNNn #1#2#3#4 + { + \str_aux_escape:NNNn #1#2#3 {#4} + \g_str_result_tl + } \cs_new_protected:Npn \str_aux_escape:NNNn #1#2#3#4 { \group_begin: @@ -577,12 +527,15 @@ \cs_set_nopar:Npn \str_aux_escape_escaped:N { #2 } \cs_set_nopar:Npn \str_aux_escape_raw:N { #3 } \int_set:Nn \tex_escapechar:D { 92 } - \str_aux_gset_other:Nn \g_str_result_tl {#4} + \str_gset_other:Nn \g_str_result_tl {#4} + \int_zero:N \l_str_tmpa_int \tl_gset:Nx \g_str_result_tl { \exp_after:wN \str_aux_escape_loop:N \g_str_result_tl \q_recursion_tail \q_recursion_stop } + \tl_gput_left:Nx \g_str_result_tl + { \str_aux_toks_range:nn \c_zero \l_str_tmpa_int } \group_end: } \cs_new_nopar:Npn \str_aux_escape_loop:N #1 @@ -598,6 +551,9 @@ { \str_aux_escape_escaped:N #1 } \str_aux_escape_loop:N } +\cs_new_eq:NN \str_aux_escape_unescaped:N \prg_do_nothing: +\cs_new_eq:NN \str_aux_escape_escaped:N \prg_do_nothing: +\cs_new_eq:NN \str_aux_escape_raw:N \prg_do_nothing: \cs_new_eq:cN { str_aux_escape_ \c_backslash_str q_recursion_tail :w } \use_none_delimit_by_q_recursion_stop:w @@ -620,6 +576,8 @@ \cs_new_nopar:cpn { str_aux_escape_/x:w } \str_aux_escape_loop:N { \if_false: { \fi: } + \tex_toks:D \l_str_tmpa_int \exp_after:wN { \g_str_result_tl } + \int_incr:N \l_str_tmpa_int \int_zero:N \l_str_char_int \str_aux_escape_x_test:N } @@ -628,35 +586,36 @@ \exp_not:N \token_if_eq_charcode:NNTF \c_space_token #1 { \exp_not:N \str_aux_escape_x_test:N } { - \exp_not:N \token_if_eq_charcode:NNTF \c_lbrace_str #1 - { \exp_not:N \str_aux_escape_x_braced_loop:N } - { \exp_not:N \str_aux_escape_x_unbraced_i:N #1 } + \l_str_char_int = "0 + \exp_not:N \token_if_eq_charcode:NNTF \c_lbrace_str #1 + { \exp_not:N \str_aux_escape_x_braced_loop:N } + { \exp_not:N \str_aux_escape_x_unbraced_i:N #1 } } } -\cs_new_protected_nopar:Npn \str_aux_escape_x_unbraced_i:N #1 +\cs_new_nopar:Npn \str_aux_escape_x_unbraced_i:N #1 { - \str_aux_hexadecimal_test:NTF #1 + \str_aux_hexadecimal_use:NTF #1 { \str_aux_escape_x_unbraced_ii:N } - { \str_aux_escape_x_end: #1 } + { \exp_stop_f: \str_aux_escape_x_end: #1 } } -\cs_new_protected_nopar:Npn \str_aux_escape_x_unbraced_ii:N #1 +\cs_new_nopar:Npn \str_aux_escape_x_unbraced_ii:N #1 { \token_if_eq_charcode:NNTF \c_space_token #1 { \str_aux_escape_x_unbraced_ii:N } { - \str_aux_hexadecimal_test:NTF #1 - { \str_aux_escape_x_end: } - { \str_aux_escape_x_end: #1 } + \str_aux_hexadecimal_use:NTF #1 + { \exp_stop_f: \str_aux_escape_x_end: } + { \exp_stop_f: \str_aux_escape_x_end: #1 } } } -\cs_new_protected_nopar:Npn \str_aux_escape_x_braced_loop:N #1 +\cs_new_nopar:Npn \str_aux_escape_x_braced_loop:N #1 { \token_if_eq_charcode:NNTF \c_space_token #1 { \str_aux_escape_x_braced_loop:N } { - \str_aux_hexadecimal_test:NTF #1 + \str_aux_hexadecimal_use:NTF #1 { \str_aux_escape_x_braced_loop:N } - { \str_aux_escape_x_braced_end:N #1 } + { \exp_stop_f: \str_aux_escape_x_braced_end:N #1 } } } \cs_new_protected_nopar:Npx \str_aux_escape_x_braced_end:N #1 @@ -675,7 +634,7 @@ \tex_lccode:D \c_zero \l_str_char_int \tl_to_lowercase:n { - \tl_gput_right:Nx \g_str_result_tl + \tl_gset:Nx \g_str_result_tl { \if_false: } \fi: \str_aux_escape_raw:N ^^@ \str_aux_escape_loop:N @@ -683,13 +642,13 @@ } \group_end: \cs_new_protected:Npn \str_set_convert:Nnnn - { \str_convert_aux_i:NNnnn \str_set:Nx } + { \str_convert_aux_i:NNnnn \tl_set_eq:NN } \cs_new_protected:Npn \str_gset_convert:Nnnn - { \str_convert_aux_i:NNnnn \str_gset:Nx } + { \str_convert_aux_i:NNnnn \tl_gset_eq:NN } \cs_new_protected:Npn \str_convert_aux_i:NNnnn #1#2#3#4#5 { \group_begin: - \str_aux_gset_other:Nn \g_str_result_tl {#5} + \str_gset_other:Nn \g_str_result_tl {#5} \exp_after:wN \str_convert_aux_ii:wwwnn \tl_to_str:n {#3} /// \q_stop @@ -831,11 +790,10 @@ \char_set_catcode_comment:N \% \int_set:Nn \tex_endlinechar:D {32} } -\int_new:N \l_str_encoding_int \cs_new_protected:Npn \str_convert_from_eight_bit:n #1 { \group_begin: - \int_zero:N \l_str_encoding_int + \int_zero:N \l_str_tmpa_int \exp_last_unbraced:Nx \str_convert_from_eight_bit_load:nn { \tl_use:c { c_str_encoding_#1_tl } } { \q_stop \prg_map_break: } { } @@ -850,24 +808,25 @@ \cs_new_protected_nopar:Npn \str_convert_from_eight_bit_load:nn #1#2 { \use_none_delimit_by_q_stop:w #1 \q_stop - \tex_dimen:D "#1 = \l_str_encoding_int sp \scan_stop: - \tex_skip:D \l_str_encoding_int = "#1 sp \scan_stop: - \tex_toks:D \l_str_encoding_int \exp_after:wN { \int_value:w "#2 } - \tex_advance:D \l_str_encoding_int \c_one + \tex_dimen:D "#1 = \l_str_tmpa_int sp \scan_stop: + \tex_skip:D \l_str_tmpa_int = "#1 sp \scan_stop: + \tex_toks:D \l_str_tmpa_int \exp_after:wN { \int_value:w "#2 } + \tex_advance:D \l_str_tmpa_int \c_one \str_convert_from_eight_bit_load:nn } \cs_new_protected_nopar:Npn \str_convert_from_eight_bit_load_missing:n #1 { \use_none_delimit_by_q_stop:w #1 \q_stop - \tex_dimen:D "#1 = \l_str_encoding_int sp \scan_stop: - \tex_skip:D \l_str_encoding_int = "#1 sp \scan_stop: - \tex_toks:D \l_str_encoding_int \exp_after:wN { \int_value:w "FFFD } - \tex_advance:D \l_str_encoding_int \c_one + \tex_dimen:D "#1 = \l_str_tmpa_int sp \scan_stop: + \tex_skip:D \l_str_tmpa_int = "#1 sp \scan_stop: + \tex_toks:D \l_str_tmpa_int \exp_after:wN { \int_value:w "FFFD } + \tex_advance:D \l_str_tmpa_int \c_one \str_convert_from_eight_bit_load_missing:n } \cs_new:Npn \str_convert_from_eight_bit_aux:N #1 { - \if_num:w \tex_dimen:D `#1 < \l_str_encoding_int + #1 \exp_not:N \q_mark + \if_num:w \tex_dimen:D `#1 < \l_str_tmpa_int \if_num:w \tex_skip:D \tex_dimen:D `#1 = `#1 \exp_stop_f: \tex_the:D \tex_toks:D \tex_dimen:D \fi: @@ -877,7 +836,7 @@ \cs_new_protected:Npn \str_convert_to_eight_bit:n #1 { \group_begin: - \int_zero:N \l_str_encoding_int + \int_zero:N \l_str_tmpa_int \exp_last_unbraced:Nx \str_convert_to_eight_bit_load:nn { \tl_use:c { c_str_encoding_#1_tl } } { \q_stop \prg_map_break: } { } @@ -888,17 +847,17 @@ \cs_new_protected_nopar:Npn \str_convert_to_eight_bit_load:nn #1#2 { \use_none_delimit_by_q_stop:w #1 \q_stop - \tex_dimen:D "#2 = \l_str_encoding_int sp \scan_stop: - \tex_skip:D \l_str_encoding_int = "#2 sp \scan_stop: - \exp_args:NNf \tex_toks:D \l_str_encoding_int + \tex_dimen:D "#2 = \l_str_tmpa_int sp \scan_stop: + \tex_skip:D \l_str_tmpa_int = "#2 sp \scan_stop: + \exp_args:NNf \tex_toks:D \l_str_tmpa_int { \str_output_byte:n { "#1 } } - \tex_advance:D \l_str_encoding_int \c_one + \tex_advance:D \l_str_tmpa_int \c_one \str_convert_to_eight_bit_load:nn } \cs_new:Npn \str_convert_to_eight_bit_aux:n #1 { \if_num:w #1 < "8000 \exp_stop_f: - \if_num:w \tex_dimen:D #1 < \l_str_encoding_int + \if_num:w \tex_dimen:D #1 < \l_str_tmpa_int \if_num:w \tex_skip:D \tex_dimen:D #1 = #1 \exp_stop_f: \tex_the:D \tex_toks:D \tex_dimen:D #1 \exp_stop_f: \exp_after:wN \exp_after:wN \exp_after:wN \use_none:nn @@ -907,7 +866,7 @@ \str_convert_to_eight_bit_aux_ii:n {#1} \else: \msg_expandable_kernel_error:nnn - { str } { eight_bit-to-byte-overflow } {#1} + { str } { eight-bit-to-byte-overflow } {#1} \fi: } \cs_new:Npn \str_convert_to_eight_bit_aux_ii:n #1 @@ -956,30 +915,73 @@ \cs_new_protected_nopar:Npn \str_convert_from_native: { \str_aux_gmap_result:N \str_convert_from_native_aux:N } \cs_new:Npn \str_convert_from_native_aux:N #1 - { \int_value:w `#1 , } + { #1 \exp_not:N \q_mark \int_value:w `#1 , } \cs_new_protected_nopar:Npn \str_convert_to_native: { \tl_set_eq:NN \l_str_tmpa_tl \g_str_result_tl + \str_aux_convert_to_native:n + { + \exp_after:wN \str_convert_to_native_aux:w + \l_str_tmpa_tl \q_mark { \q_stop \prg_map_break: } , + } + } +\cs_new_protected_nopar:Npn \str_convert_to_native_aux:w #1\q_mark #2, + { + \use_none_delimit_by_q_stop:w #2 \q_stop + \str_aux_convert_to_native_step:n {#2} + \str_convert_to_native_aux:w + } +\cs_new_protected_nopar:Npn \str_aux_convert_to_native:n #1 + { + \tex_lccode:D \c_zero \c_zero + \int_zero:N \l_str_tmpa_int \tl_gclear:N \g_str_result_tl - \tex_afterassignment:D \str_convert_to_native_aux:w - \l_str_char_int = \l_str_tmpa_tl \c_zero \prg_map_break: , - \prg_break_point:n { } + #1 + \prg_break_point:n { \str_aux_convert_to_native_flush: } + } +\cs_new_protected_nopar:Npn \str_aux_convert_to_native_step:n #1 + { + \if_num:w \l_str_tmpa_int = \c_two_hundred_fifty_five + \str_aux_convert_to_native_flush: + \l_str_tmpa_int \c_zero + \fi: + \tex_advance:D \l_str_tmpa_int \c_one + \if_int_compare:w #1 > \c_max_char_int + \msg_kernel_error:nnx { str } { overflow } {#1} + \tex_lccode:D \l_str_tmpa_int \c_str_replacement_char_int + \else: + \tex_lccode:D \l_str_tmpa_int \int_eval:w #1 \int_eval_end: + \fi: + } +\cs_new_protected_nopar:Npn \str_aux_convert_to_native_flush: + { + \use:x + { + \tl_to_lowercase:n + { + \tl_gput_right:Nx \exp_not:N \g_str_result_tl + { + \exp_after:wN \str_aux_convert_to_native_filter:N + \c_str_positive_bytes_tl + { ? = \c_zero \fi: \prg_map_break: } + \prg_break_point:n { } + } + } + } } \group_begin: - \char_set_catcode_other:n { `\^^@ } - \cs_new_protected_nopar:Npn \str_convert_to_native_aux:w #1 , + \char_set_catcode_other:n { 0 } + \cs_new:Npn \str_aux_convert_to_native_filter:N #1 { - #1 - \if_int_compare:w \l_str_char_int > \c_max_char_int - \msg_kernel_error:nnx { str } { overflow } - { \int_use:N \l_str_char_int } + \if_num:w `#1 > \l_str_tmpa_int + \exp_after:wN \prg_map_break: + \fi: + \if_num:w \tex_lccode:D `#1 = \c_zero + ^^@ \else: - \tex_lccode:D \c_zero \l_str_char_int - \tl_to_lowercase:n - { \tex_xdef:D \g_str_result_tl { \g_str_result_tl ^^@ } } + #1 \fi: - \tex_afterassignment:D \str_convert_to_native_aux:w - \l_str_char_int = + \str_aux_convert_to_native_filter:N } \group_end: \msg_kernel_new:nnnn { str } { x-missing-brace } diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty new file mode 100644 index 00000000000..84479cc1543 --- /dev/null +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty @@ -0,0 +1,402 @@ +%% +%% This is file `l3tl-analysis.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3tl-analysis.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-analysis.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: l3tl-analysis.dtx 3039 2011-12-08 09:22:35Z bruno $ + {L3 Experimental Analysis of Token lists} +\ProvidesExplPackage + {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} +\RequirePackage{l3str} +\int_new:N \l_tl_analysis_normal_int +\int_new:N \l_tl_analysis_index_int +\int_new:N \l_tl_analysis_nesting_int +\int_new:N \l_tl_analysis_char_int +\int_new:N \l_tl_analysis_type_int +\tl_new:N \g_tl_analysis_result_tl +\cs_new_protected_nopar:Npn \tl_analysis_extract_charcode: + { + \exp_after:wN \tl_analysis_extract_charcode_aux:w + \token_to_meaning:N \l_tl_analysis_token + } +\cs_new_protected_nopar:Npn \tl_analysis_extract_charcode_aux:w #1 ~ #2 ~ { ` } +\cs_new:Npn \tl_analysis_cs_space_count:NN #1 #2 + { + \exp_after:wN #1 + \int_value:w \int_eval:w \c_zero + \exp_after:wN \tl_analysis_cs_space_count:w + \token_to_str:N #2 + \fi: \tl_analysis_cs_space_count_end:w ; ~ ! + } +\cs_new:Npn \tl_analysis_cs_space_count:w #1 ~ + { + \if_false: #1 #1 \fi: + + \c_one + \tl_analysis_cs_space_count:w + } +\cs_new:Npn \tl_analysis_cs_space_count_end:w ; #1 \fi: #2 ! + { \exp_after:wN ; \int_value:w \str_length_ignore_spaces:n {#1} ; } +\cs_new_protected:Npn \tl_analysis:n #1 + { + \group_begin: + \group_align_safe_begin: + \tl_analysis_setup:n {#1} + \tl_analysis_i:n {#1} + \tl_analysis_ii:n {#1} + \group_align_safe_end: + \group_end: + } +\cs_new_protected:Npn \tl_set_analysis:Nn #1#2 + { + \tl_analysis:n {#2} + \tl_set_eq:NN #1 \g_tl_analysis_result_tl + } +\cs_new_protected:Npn \tl_analysis_setup:n #1 + { + \int_set:Nn \tex_escapechar:D { 92 } + \exp_after:wN \tl_analysis_disable_loop:N + \tl_to_str:n {#1} { ~ } { ? ~ \prg_map_break: } + \prg_break_point:n { } + } +\group_begin: + \char_set_catcode_active:N \^^@ + \cs_new_protected_nopar:Npn \tl_analysis_disable_loop:N #1 + { + \tex_lccode:D \c_zero `#1 ~ + \tl_to_lowercase:n { \tex_let:D ^^@ } \c_undefined:D + \tl_analysis_disable_loop:N + } +\group_end: +\cs_new_protected:Npn \tl_analysis_i:n #1 + { + \int_zero:N \l_tl_analysis_normal_int + \int_zero:N \l_tl_analysis_index_int + \int_zero:N \l_tl_analysis_nesting_int + \if_false: { \fi: \tl_analysis_i_loop:w #1 } + \int_decr:N \l_tl_analysis_index_int + } +\cs_new_protected_nopar:Npn \tl_analysis_i_loop:w + { \tex_futurelet:D \l_tl_analysis_token \tl_analysis_i_type:w } +\cs_new_protected_nopar:Npn \tl_analysis_i_type:w + { + \l_tl_analysis_type_int = + \if_meaning:w \l_tl_analysis_token \c_space_token + \c_zero + \else: + \if_catcode:w \exp_not:N \l_tl_analysis_token \c_group_begin_token + \c_one + \else: + \if_catcode:w \exp_not:N \l_tl_analysis_token \c_group_end_token + \c_minus_one + \else: + \c_two + \fi: + \fi: + \fi: + \if_case:w \l_tl_analysis_type_int + \exp_after:wN \tl_analysis_i_space:w + \or: \exp_after:wN \tl_analysis_i_bgroup:w + \or: \exp_after:wN \tl_analysis_i_safe:N + \else: \exp_after:wN \tl_analysis_i_egroup:w + \fi: + } +\cs_new_protected:Npn \tl_analysis_i_safe:N #1 + { + \if_charcode:w + \scan_stop: + \exp_after:wN \use_none:n \token_to_str:N #1 \prg_do_nothing: + \scan_stop: + \int_incr:N \l_tl_analysis_normal_int + \else: + \tl_analysis_cs_space_count:NN \tl_analysis_i_cs:ww #1 + \fi: + \tl_analysis_i_loop:w + } +\cs_new_protected:Npn \tl_analysis_i_cs:ww #1; #2; + { + \if_num:w #1 > \c_zero + \tex_skip:D \l_tl_analysis_index_int + = \int_eval:w \l_tl_analysis_normal_int + \c_one sp \scan_stop: + \tex_advance:D \l_tl_analysis_index_int #1 \exp_stop_f: + \l_tl_analysis_normal_int #2 \exp_stop_f: + \else: + \tex_advance:D \l_tl_analysis_normal_int #2 \exp_stop_f: + \fi: + } +\cs_new_protected_nopar:Npn \tl_analysis_i_space:w + { + \tex_afterassignment:D \tl_analysis_i_space_test:w + \exp_after:wN \cs_set_eq:NN + \exp_after:wN \l_tl_analysis_token + \token_to_str:N + } +\cs_new_protected_nopar:Npn \tl_analysis_i_space_test:w + { + \if_meaning:w \l_tl_analysis_token \c_space_token + \tex_toks:D \l_tl_analysis_index_int { \exp_not:n { ~ } } + \tl_analysis_i_store: + \else: + \int_incr:N \l_tl_analysis_normal_int + \fi: + \tl_analysis_i_loop:w + } +\group_begin: + \char_set_catcode_group_begin:N \^^@ + \char_set_catcode_group_end:N \^^E + \cs_new_protected_nopar:Npn \tl_analysis_i_bgroup:w + { \tl_analysis_i_group:nw { \exp_after:wN ^^@ \if_false: ^^E \fi: } } + \char_set_catcode_group_begin:N \^^B + \char_set_catcode_group_end:N \^^@ + \cs_new_protected_nopar:Npn \tl_analysis_i_egroup:w + { \tl_analysis_i_group:nw { \if_false: ^^B \fi: ^^@ } } +\group_end: +\cs_new_protected_nopar:Npn \tl_analysis_i_group:nw #1 + { + \l_tl_analysis_char_int = \tl_analysis_extract_charcode: \scan_stop: + \tex_lccode:D \c_zero \l_tl_analysis_char_int + \tl_to_lowercase:n { \tex_toks:D \l_tl_analysis_index_int {#1} } + \if_num:w \l_tl_analysis_char_int = \tex_escapechar:D + \int_set:Nn \tex_escapechar:D { 139 - \tex_escapechar:D } + \fi: + \tex_afterassignment:D \tl_analysis_i_group_test:w + \exp_after:wN \cs_set_eq:NN + \exp_after:wN \l_tl_analysis_token + \token_to_str:N + } +\cs_new_protected_nopar:Npn \tl_analysis_i_group_test:w + { + \if_num:w \tl_analysis_extract_charcode: = \l_tl_analysis_char_int + \tl_analysis_i_store: + \else: + \int_incr:N \l_tl_analysis_normal_int + \fi: + \tl_analysis_i_loop:w + } +\cs_new_protected_nopar:Npn \tl_analysis_i_store: + { + \tex_advance:D \l_tl_analysis_nesting_int \l_tl_analysis_type_int + \if_num:w \l_tl_analysis_char_int = \c_thirty_two + \tex_multiply:D \l_tl_analysis_type_int \c_two + \fi: + \tex_skip:D \l_tl_analysis_index_int + = \l_tl_analysis_normal_int sp plus \l_tl_analysis_type_int sp \scan_stop: + \int_incr:N \l_tl_analysis_index_int + \int_zero:N \l_tl_analysis_normal_int + \if_num:w \l_tl_analysis_nesting_int = \c_minus_one + \cs_set_eq:NN \tl_analysis_i_loop:w \scan_stop: + \fi: + } +\cs_new_protected:Npn \tl_analysis_ii:n #1 + { + \tl_gset:Nx \g_tl_analysis_result_tl + { + \tl_analysis_ii_loop:w 0; #1 + \prg_break_point:n { } + } + } +\cs_new:Npn \tl_analysis_ii_loop:w #1; + { + \exp_after:wN \tl_analysis_ii_normals:ww + \int_value:w \tex_skip:D #1 ; #1 ; + } +\cs_new:Npn \tl_analysis_ii_normals:ww #1; + { + \if_num:w #1 = \c_zero + \tl_analysis_ii_special:w + \fi: + \tl_analysis_ii_normal:wwN #1; + } +\cs_new:Npn \tl_analysis_ii_normal:wwN #1; #2; #3 + { + \exp_not:n { \exp_not:n { #3 } } \exp_not:N \q_mark + \if_charcode:w + \scan_stop: + \exp_after:wN \use_none:n \token_to_str:N #3 \prg_do_nothing: + \scan_stop: + \exp_after:wN \tl_analysis_ii_char:Nww + \else: + \exp_after:wN \tl_analysis_ii_cs:Nww + \fi: + #3 #1; #2; + } +\cs_new:Npn \tl_analysis_ii_char:Nww #1 + { + \if_meaning:w #1 \c_undefined:D D \else: + \if_catcode:w #1 \c_catcode_other_token C \else: + \if_catcode:w #1 \c_catcode_letter_token B \else: + \if_catcode:w #1 \c_math_toggle_token 3 \else: + \if_catcode:w #1 \c_alignment_token 4 \else: + \if_catcode:w #1 \c_math_superscript_token 7 \else: + \if_catcode:w #1 \c_math_subscript_token 8 \else: + 6 + \fi: \fi: \fi: \fi: \fi: \fi: \fi: + \int_value:w `#1 , + \exp_after:wN \tl_analysis_ii_normals:ww + \int_use:N \int_eval:w \c_minus_one + + } +\cs_new:Npn \tl_analysis_ii_cs:Nww #1 + { + 0 -1 , + \tl_analysis_cs_space_count:NN \tl_analysis_ii_cs_test:ww #1 + } +\cs_new:Npn \tl_analysis_ii_cs_test:ww #1 ; #2 ; #3; #4; + { + \exp_after:wN \tl_analysis_ii_normals:ww + \int_use:N \int_eval:w + \if_num:w #1 = \c_zero + #3 + \else: + \tex_skip:D \int_eval:w #4 + #1 \int_eval_end: + \fi: + - #2 + \exp_after:wN ; + \int_use:N \int_eval:w #4 + #1; + } +\cs_new:Npn \tl_analysis_ii_special:w \fi: \tl_analysis_ii_normal:wwN 0; #1; + { + \fi: + \if_num:w #1 = \l_tl_analysis_index_int + \exp_after:wN \prg_map_break: + \fi: + \tex_the:D \tex_toks:D #1 \exp_stop_f: \exp_not:N \q_mark + \if_case:w \etex_gluestretch:D \tex_skip:D #1 \exp_stop_f: + A + \or: 1 + \or: 1 + \else: 2 + \fi: + \if_int_odd:w \etex_gluestretch:D \tex_skip:D #1 \exp_stop_f: + \exp_after:wN \tl_analysis_ii_special_char:wN \int_use:N + \else: + \exp_after:wN \tl_analysis_ii_special_space:w \int_use:N + \fi: + \int_eval:w \c_one + #1 \exp_after:wN ; + \token_to_str:N + } +\cs_new:Npn \tl_analysis_ii_special_char:wN #1 ; #2 + { + \int_value:w `#2 , + \tl_analysis_ii_loop:w #1 ; + } +\cs_new:Npn \tl_analysis_ii_special_space:w #1 ; ~ + { + 32 , + \tl_analysis_ii_loop:w #1 ; + } +\cs_new_protected:Npn \tl_show_analysis:N #1 + { + \exp_args:No \tl_analysis:n {#1} + \msg_aux_show:Nnx #1 + { tl-analysis } + { + \exp_after:wN \tl_show_analysis_loop:wNw \g_tl_analysis_result_tl + \q_mark { ? \prg_map_break: } , + \prg_break_point:n { } + } + } +\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 + } +\cs_new:Npn \tl_show_analysis_loop:wNw #1 \q_mark #2 #3, + { + \use_none:n #2 + \iow_newline: > \c_space_tl \c_space_tl + \if_num:w "#2 = \c_zero + \exp_after:wN \tl_show_analysis_cs:n + \else: + \if_num:w "#2 = \c_thirteen + \exp_after:wN \exp_after:wN + \exp_after:wN \tl_show_analysis_active:n + \else: + \exp_after:wN \exp_after:wN + \exp_after:wN \tl_show_analysis_normal:n + \fi: + \fi: + {#1} + \tl_show_analysis_loop:wNw + } +\cs_new:Npn \tl_show_analysis_normal:n #1 + { + \exp_after:wN \token_to_str:N #1 ~ + ( \exp_after:wN \token_to_meaning:N #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 + { \token_to_str:N #1 } + { \token_to_meaning:N #1 } + } +\cs_new_nopar:Npn \tl_show_analysis_long_aux:nnn #1#2#3 + { + \int_compare:nNnTF + { \str_length:n { >>> #1 ~ ( #3 #2 ) } } + > { \l_iow_line_length_int } + { + \str_substr:nnn { >>> #1 ~ ( #3 #2 ) } \c_three + { \l_iow_line_length_int - \str_length:N \c_tl_show_analysis_etc_str } + \c_tl_show_analysis_etc_str + } + {#1~(#3#2)} + } +\str_const:Nx \c_tl_show_analysis_etc_str % ( + { \iow_char:N \\ETC. ) } +\msg_kernel_new:nnn { tl-analysis } { show } + { + Token~list~ + \str_if_eq:nnF {#1} { \l_tl_tmpa_tl } { \token_to_str:N #1~} + \tl_if_empty:NTF #1 + { is~empty } + { contains~the~tokens: } + } +%% +%% +%% End of file `l3tl-analysis.sty'. diff --git a/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty b/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty index e8a3345204f..28bc6b50dc5 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty @@ -48,14 +48,11 @@ %% ----------------------------------------------------------------------- %% \RequirePackage{l3names} -\GetIdInfo$Id: l3galley.dtx 2938 2011-10-25 18:41:20Z joseph $ +\GetIdInfo$Id: l3galley.dtx 3071 2011-12-20 20:14:00Z bruno $ {L3 Experimental galley code} \ProvidesExplPackage {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} \package_check_loaded_expl: -\cs_new_protected:Npn \scan_marker_new:N #1 - { \cs_new_eq:NN #1 \scan_stop: } -\cs_generate_variant:Nn \scan_marker_new:N { c } \cs_new_protected_nopar:Npn \galley_leave_vmode: { \tex_unhbox:D \c_empty_box } \clist_new:N \l_galley_parshape_left_indent_clist @@ -193,7 +190,7 @@ \galley_restore_parameters: \group_end: } -\scan_marker_new:N \s_par_omit +\scan_new:N \s_par_omit \cs_new_protected_nopar:Npn \galley_std_par: { \s_par_omit |