%%
%% This is file `l3regex.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% l3regex.dtx  (with options: `package')
%% 
%% EXPERIMENTAL CODE
%% 
%% Do not distribute this file without also distributing the
%% source files specified above.
%% 
%% Do not distribute a modified version of this file.
%% 
%% File: l3regex.dtx Copyright (C) 2011-2012 The LaTeX3 Project
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
%% license or (at your option) any later version.  The latest version
%% of this license is in the file
%%
%%    http://www.latex-project.org/lppl.txt
%%
%% This file is part of the "l3experimental bundle" (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX3 Project.
%%
%% -----------------------------------------------------------------------
\RequirePackage{expl3}
\GetIdInfo$Id: l3regex.dtx 3326 2012-02-07 00:39:44Z bruno $
  {L3 Experimental Regular Expressions}
\ProvidesExplPackage
  {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
\RequirePackage{l3str, l3tl-analysis, l3flag}
\cs_new:Npn \regex_tmp:w { }
\tl_new:N   \l_regex_internal_a_tl
\tl_new:N   \l_regex_internal_b_tl
\int_new:N  \l_regex_internal_a_int
\int_new:N  \l_regex_internal_b_int
\int_new:N  \l_regex_internal_c_int
\tl_new:N   \g_regex_internal_tl
\tl_const:Nn \c_regex_d_tl
  { \regex_item_range:nn \c_forty_eight { 57 } } % 0--9
\tl_const:Nn \c_regex_h_tl
  {
    \regex_item_equal:n \c_thirty_two % space
    \regex_item_equal:n \c_nine       % tab
  }
\tl_const:Nn \c_regex_s_tl
  {
    \regex_item_equal:n \c_thirty_two % space
    \regex_item_equal:n \c_nine       % tab
    \regex_item_equal:n \c_ten        % lf
    \regex_item_equal:n \c_twelve     % ff
    \regex_item_equal:n \c_thirteen   % cr
  }
\tl_const:Nn \c_regex_v_tl
  { \regex_item_range:nn \c_ten \c_thirteen } % lf, vtab, ff, cr
\tl_const:Nn \c_regex_w_tl
  {
    \regex_item_range:nn \c_ninety_seven { 122 } % a--z
    \regex_item_range:nn \c_sixty_five   {  90 } % A--Z
    \regex_item_range:nn \c_forty_eight  {  57 } % 0--9
    \regex_item_equal:n  { 95 } % _
  }
\tl_const:Nn \c_regex_D_tl
  { \c_regex_d_tl \regex_break_point:TF { } \regex_break_true:w }
\tl_const:Nn \c_regex_H_tl
  { \c_regex_h_tl \regex_break_point:TF { } \regex_break_true:w }
\tl_const:Nn \c_regex_S_tl
  { \c_regex_s_tl \regex_break_point:TF { } \regex_break_true:w }
\tl_const:Nn \c_regex_V_tl
  { \c_regex_v_tl \regex_break_point:TF { } \regex_break_true:w }
\tl_const:Nn \c_regex_W_tl
  { \c_regex_w_tl \regex_break_point:TF { } \regex_break_true:w }
\tl_const:Nn \c_regex_N_tl
  {
    \regex_item_equal:n \c_ten
    \regex_break_point:TF { } { \regex_break_true:w }
  }
\tl_const:cn { c_regex_._tl }
  {
    \if_num:w \l_regex_current_char_int > - \c_two
      \exp_after:wN \regex_break_true:w
    \fi:
  }
\int_new:N \l_regex_build_mode_int
\int_new:N  \l_regex_max_state_int
\int_new:N  \l_regex_left_state_int
\int_new:N  \l_regex_right_state_int
\seq_new:N  \l_regex_left_state_seq
\seq_new:N  \l_regex_right_state_seq
\seq_new:N  \l_regex_end_group_seq
\seq_new:N  \l_regex_end_alternation_seq
\int_new:N  \l_regex_capturing_group_int
\seq_new:N  \l_regex_capturing_group_seq
\int_new:N  \l_regex_capturing_group_max_int
\tl_new:N   \l_regex_one_or_group_tl
\int_new:N \l_regex_catcodes_int
\int_new:N \l_regex_catcodes_default_int
\int_const:Nn \c_regex_catcode_C_int { "1 }
\int_const:Nn \c_regex_catcode_B_int { "4 }
\int_const:Nn \c_regex_catcode_E_int { "10 }
\int_const:Nn \c_regex_catcode_M_int { "40 }
\int_const:Nn \c_regex_catcode_T_int { "100 }
\int_const:Nn \c_regex_catcode_P_int { "1000 }
\int_const:Nn \c_regex_catcode_U_int { "4000 }
\int_const:Nn \c_regex_catcode_D_int { "10000 }
\int_const:Nn \c_regex_catcode_S_int { "100000 }
\int_const:Nn \c_regex_catcode_L_int { "400000 }
\int_const:Nn \c_regex_catcode_O_int { "1000000 }
\int_const:Nn \c_regex_catcode_A_int { "4000000 }
\int_const:Nn \c_regex_catcodes_all_int { "5515155 }
\bool_new:N \l_regex_catcodes_bool
\bool_new:N \l_regex_tests_bool
\tl_new:N   \l_regex_tests_tl
\bool_new:N \l_regex_tests_saved_bool
\tl_new:N   \l_regex_tests_saved_tl
\int_new:N  \l_regex_catcodes_saved_int
\int_new:N \l_regex_min_index_int
\int_new:N \l_regex_max_index_int
\int_new:N \l_regex_nesting_int
\int_new:N \l_regex_current_index_int
\int_new:N \l_regex_start_index_int
\int_new:N \l_regex_success_index_int
\int_new:N \l_regex_current_char_int
\int_new:N \l_regex_current_catcode_int
\tl_new:N  \l_regex_current_token_tl
\int_new:N \l_regex_last_char_int
\int_new:N \l_regex_case_changed_char_int
\bool_new:N \l_regex_caseless_bool
\int_new:N \l_regex_current_state_int
\prop_new:N \l_regex_current_submatches_prop
\prop_new:N \l_regex_success_submatches_prop
\int_new:N \l_regex_step_int
\int_new:N \l_regex_max_active_int
\tl_new:N \l_regex_every_match_tl
\bool_new:N \l_regex_fresh_thread_bool
\bool_new:N \l_regex_success_empty_bool
\cs_new_eq:NN \regex_if_two_empty_matches:F \use:n
\bool_new:N \g_regex_success_bool
\bool_new:N \l_regex_saved_success_bool
\bool_new:N \l_regex_success_match_bool
\tl_const:Nn \c_regex_no_match_regex
  {
    \regex_nfa:Nw \c_regex_no_match_regex
      \l_regex_max_state_int = \c_one
      \l_regex_capturing_group_int = \c_zero
      \tex_toks:D \c_zero { \s_stop }
    \s_stop
  }
\cs_new_protected:Npn \regex_new:N #1
  {
    \chk_if_free_cs:N #1
    \cs_gset_eq:NN #1 \c_regex_no_match_regex
  }
\regex_new:N \l_regex_internal_regex
\int_new:N \l_regex_replacement_csnames_int
\int_new:N \l_regex_replacement_int
\int_new:N \l_regex_submatch_int
\int_new:N \l_regex_submatch_start_int
\int_new:N \l_regex_match_count_int
\flag_new:n { regex_begin }
\flag_new:n { regex_end }
\cs_new_protected:Npn \regex_toks_put_left:Nx #1#2
  {
    \cs_set_nopar:Npx \regex_tmp:w \s_stop { \s_stop #2 }
    \tex_toks:D #1 \exp_after:wN \exp_after:wN \exp_after:wN
      { \exp_after:wN \regex_tmp:w \tex_the:D \tex_toks:D #1 }
  }
\cs_new_protected:Npn \regex_toks_put_right:Nx #1#2
  {
    \cs_set_nopar:Npx \regex_tmp:w {#2}
    \tex_toks:D #1 \exp_after:wN
      { \tex_the:D \tex_toks:D \exp_after:wN #1 \regex_tmp:w }
  }
\cs_new:Npn \regex_toks_range:nn #1#2
  {
    \exp_after:wN \regex_toks_range:ww
    \int_use:N \int_eval:w #1 \exp_after:wN ;
    \int_use:N \int_eval:w #2 ;
    \prg_break_point:n { }
  }
\cs_new:Npn \regex_toks_range:ww #1 ; #2 ;
  {
    \if_num:w #1 < #2 \exp_stop_f:
    \else:
      \exp_after:wN \prg_map_break:
    \fi:
    \tex_the:D \tex_toks:D #1 \exp_stop_f:
    \exp_after:wN \regex_toks_range:ww
      \int_use:N \int_eval:w #1 + \c_one ; #2 ;
  }
\cs_new:Npn \regex_query_submatch:nn #1#2
  {
    \if_num:w #1 < \l_regex_capturing_group_int
      \exp_after:wN \regex_query_submatch:w
      \int_use:N \int_eval:w #1 + #2 ;
    \fi:
  }
\cs_new:Npn \regex_query_submatch:w #1 ;
  {
    \regex_toks_range:nn
      { \tex_skip:D #1 }
      { \etex_gluestretch:D \tex_skip:D #1 }
  }
\cs_new_protected:Npn \regex_seq_pop_int:NN #1#2
  {
    \seq_pop:NN #1 \l_regex_internal_a_tl
    \int_set:Nn #2 \l_regex_internal_a_tl
  }
\cs_new_protected:Npn \regex_seq_get_int:NN #1#2
  {
    \seq_get:NN #1 \l_regex_internal_a_tl
    \int_set:Nn #2 \l_regex_internal_a_tl
  }
\cs_new_protected:Npn \regex_seq_push_int:NN #1#2
  { \seq_push:No #1 { \int_use:N #2 } }
\cs_new_protected:Npn \regex_seq_pop_use:N #1
  {
    \seq_pop:NN #1 \l_regex_internal_a_tl
    \l_regex_internal_a_tl
  }
\cs_new_protected:Npn \regex_seq_get_use:N #1
  {
    \seq_get:NN #1 \l_regex_internal_a_tl
    \l_regex_internal_a_tl
  }
\cs_new_protected:Npn \regex_get_digits:nw #1
  {
    \tex_afterassignment:D \regex_tmp:w
    \cs_set_nopar:Npx \regex_tmp:w
      {
        \exp_not:n {#1}
        { \if_false: } } \fi:
        \regex_get_digits_aux:NN
  }
\cs_new:Npn \regex_get_digits_aux:NN #1#2
  {
    \if_meaning:w \regex_build_raw:N #1
      \if_num:w 9 < 1 \exp_not:N #2 \exp_stop_f:
        #2
      \else:
        \regex_get_digits_end:w #1 #2
      \fi:
    \else:
      \regex_get_digits_end:w #1 #2
    \fi:
    \regex_get_digits_aux:NN
  }
\cs_new:Npn \regex_get_digits_end:w #1 \fi: #2 \regex_get_digits_aux:NN
  {
    \fi: #2
    \if_false: { { \fi: } }
    #1
  }
\cs_new_protected:Npn \regex_break_true:w
   #1 \regex_break_point:TF #2 #3 {#2}
\cs_new_protected:Npn \regex_break_point:TF #1 #2 { #2 }
\cs_new_protected:Npn \regex_item_caseful_equal:n #1
  {
    \if_num:w #1 = \l_regex_current_char_int
      \exp_after:wN \regex_break_true:w
    \fi:
  }
\cs_new_protected:Npn \regex_item_caseful_range:nn #1 #2
  {
    \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
      \reverse_if:N \if_num:w #2 < \l_regex_current_char_int
        \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
      \fi:
    \fi:
  }
\cs_new_protected:Npn \regex_item_caseful_geq:n #1
  {
    \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
      \exp_after:wN \regex_break_true:w
    \fi:
  }
\cs_new_protected:Npn \regex_item_caseless_equal:n #1
  {
    \if_num:w #1 = \l_regex_current_char_int
      \exp_after:wN \regex_break_true:w
    \fi:
    \if_num:w #1 = \l_regex_case_changed_char_int
      \exp_after:wN \regex_break_true:w
    \fi:
  }
\cs_new_protected:Npn \regex_item_caseless_range:nn #1 #2
  {
    \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
      \reverse_if:N \if_num:w #2 < \l_regex_current_char_int
        \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
      \fi:
    \fi:
    \reverse_if:N \if_num:w #1 > \l_regex_case_changed_char_int
      \reverse_if:N \if_num:w #2 < \l_regex_case_changed_char_int
        \exp_after:wN \exp_after:wN \exp_after:wN \regex_break_true:w
      \fi:
    \fi:
  }
\cs_new_protected:Npn \regex_item_caseless_geq:n #1
  {
    \reverse_if:N \if_num:w #1 > \l_regex_current_char_int
      \exp_after:wN \regex_break_true:w
    \fi:
    \reverse_if:N \if_num:w #1 > \l_regex_case_changed_char_int
      \exp_after:wN \regex_break_true:w
    \fi:
  }
\cs_new:Npn \regex_item_equal:n  { \regex_item_caseful_equal:n }
\cs_new:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
\cs_new:Npn \regex_item_geq:n    { \regex_item_caseful_geq:n }
\cs_new_protected_nopar:Npn \regex_build_caseless:
  {
    \bool_set_true:N \l_regex_caseless_bool
    \cs_set:Npn \regex_item_equal:n  { \regex_item_caseless_equal:n }
    \cs_set:Npn \regex_item_range:nn { \regex_item_caseless_range:nn }
    \cs_set:Npn \regex_item_geq:n    { \regex_item_caseless_geq:n }
  }
\cs_new_protected_nopar:Npn \regex_build_caseful:
  {
    \bool_set_false:N \l_regex_caseless_bool
    \cs_set:Npn \regex_item_equal:n  { \regex_item_caseful_equal:n }
    \cs_set:Npn \regex_item_range:nn { \regex_item_caseful_range:nn }
    \cs_set:Npn \regex_item_geq:n    { \regex_item_caseful_geq:n }
  }
\cs_new_protected:Npn \regex_item_catcode_aux:
  {
    "
    \if_case:w \l_regex_current_catcode_int
         1       \or: 4       \or: 10      \or: 40
    \or: 100     \or:         \or: 1000    \or: 4000
    \or: 10000   \or:         \or: 100000  \or: 400000
    \or: 1000000 \or: 4000000 \else: 1*\c_zero
    \fi:
  }
\cs_new_protected:Npn \regex_item_catcode:nT #1
  {
    \if_int_odd:w \int_eval:w #1 / \regex_item_catcode_aux: \int_eval_end:
      \exp_after:wN \use:n
    \else:
      \exp_after:wN \use_none:n
    \fi:
  }
\cs_new_protected:Npn \regex_item_cs:n #1
  {
    \int_compare:nNnT \l_regex_current_catcode_int = \c_zero
      {
        \tl_set:Nn \l_regex_internal_regex {#1}
        \bool_set_eq:NN \l_regex_saved_success_bool \g_regex_success_bool
        \exp_args:NNx \regex_match:NnTF \l_regex_internal_regex
          {
            \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_escape_use:nnnn #1#2#3#4
  {
    \group_begin:
      \cs_set_nopar:Npn \regex_escape_unescaped:N ##1 { #1 }
      \cs_set_nopar:Npn \regex_escape_escaped:N ##1 { #2 }
      \cs_set_nopar:Npn \regex_escape_raw:N ##1 { #3 }
      \int_set:Nn \tex_escapechar:D { 92 }
      \str_gset_other:Nn \g_regex_internal_tl {#4}
      \int_zero:N \l_regex_internal_a_int
      \tl_set:Nx \l_regex_internal_a_tl
        {
          \exp_after:wN \regex_escape_loop:N \g_regex_internal_tl
          { break } \prg_break_point:n { }
        }
      \use:x
        {
          \group_end:
          \regex_toks_range:nn \c_zero \l_regex_internal_a_int
          \exp_not:o \l_regex_internal_a_tl
        }
  }
\cs_new:Npn \regex_escape_loop:N #1
  {
    \cs_if_exist_use:cF { regex_escape_\token_to_str:N #1:w }
      { \regex_escape_unescaped:N #1 }
    \regex_escape_loop:N
  }
\cs_new_nopar:cpn { regex_escape_ \c_backslash_str :w }
    \regex_escape_loop:N #1
  {
    \cs_if_exist_use:cF { regex_escape_/\token_to_str:N #1:w }
      { \regex_escape_escaped:N #1 }
    \regex_escape_loop:N
  }
\cs_new_eq:NN \regex_escape_unescaped:N ?
\cs_new_eq:NN \regex_escape_escaped:N   ?
\cs_new_eq:NN \regex_escape_raw:N       ?
\cs_new_eq:NN \regex_escape_break:w \prg_map_break:
\cs_new_nopar:cpn { regex_escape_/break:w }
  {
    \if_false: { \fi: }
    \msg_kernel_error:nn { regex } { trailing-backslash }
    \exp_after:wN \use_none:n \exp_after:wN { \if_false: } \fi:
  }
\cs_new_nopar:cpn { regex_escape_~:w } { }
\cs_new_nopar:cpx { regex_escape_/a:w }
  { \exp_not:N \regex_escape_raw:N \iow_char:N \^^G }
\cs_new_nopar:cpx { regex_escape_/t:w }
  { \exp_not:N \regex_escape_raw:N \iow_char:N \^^I }
\cs_new_nopar:cpx { regex_escape_/n:w }
  { \exp_not:N \regex_escape_raw:N \iow_char:N \^^J }
\cs_new_nopar:cpx { regex_escape_/f:w }
  { \exp_not:N \regex_escape_raw:N \iow_char:N \^^L }
\cs_new_nopar:cpx { regex_escape_/r:w }
  { \exp_not:N \regex_escape_raw:N \iow_char:N \^^M }
\cs_new_nopar:cpx { regex_escape_/e:w }
  { \exp_not:N \regex_escape_raw:N \iow_char:N \^^[ }
\cs_new_nopar:cpn { regex_escape_/x:w } \regex_escape_loop:N
  {
    \if_false: { \fi: }
    \tex_toks:D \l_regex_internal_a_int
      \exp_after:wN { \l_regex_internal_a_tl }
    \int_incr:N \l_regex_internal_a_int
    \int_zero:N \l_regex_current_char_int
    \regex_escape_x_test:N
  }
\cs_new_protected:Npx \regex_escape_x_test:N #1
  {
    \exp_not:N \token_if_eq_charcode:NNTF \c_space_token #1
      { \exp_not:N \regex_escape_x_test:N }
      {
        \l_regex_current_char_int = "0
          \exp_not:N \token_if_eq_charcode:NNTF \c_lbrace_str #1
            { \exp_not:N \regex_escape_x_braced_loop:N }
            { \exp_not:N \regex_escape_x_unbraced_i:N #1 }
      }
  }
\cs_new:Npn \regex_escape_x_unbraced_i:N #1
  {
    \str_aux_hexadecimal_use:NTF #1
      { \regex_escape_x_unbraced_ii:N }
      { \exp_stop_f: \regex_escape_x_end: #1 }
  }
\cs_new:Npn \regex_escape_x_unbraced_ii:N #1
  {
    \token_if_eq_charcode:NNTF \c_space_token #1
      { \regex_escape_x_unbraced_ii:N }
      {
        \str_aux_hexadecimal_use:NTF #1
          { \exp_stop_f: \regex_escape_x_end: }
          { \exp_stop_f: \regex_escape_x_end: #1 }
      }
  }
\cs_new:Npn \regex_escape_x_braced_loop:N #1
  {
    \token_if_eq_charcode:NNTF \c_space_token #1
      { \regex_escape_x_braced_loop:N }
      {
        \str_aux_hexadecimal_use:NTF #1
          { \regex_escape_x_braced_loop:N }
          { \exp_stop_f: \regex_escape_x_braced_end:N #1 }
      }
  }
\cs_new_protected:Npx \regex_escape_x_braced_end:N #1
  {
    \exp_not:N \token_if_eq_charcode:NNTF \c_rbrace_str #1
      { \exp_not:N \regex_escape_x_end: }
      {
        \msg_kernel_error:nnx { regex } { x-missing-rbrace }
          { \int_use:N \l_regex_current_char_int }
        \exp_not:N \regex_escape_x_end: #1
      }
  }
\group_begin:
  \char_set_catcode_other:N \^^@
  \cs_new_protected_nopar:Npn \regex_escape_x_end:
    {
      \if_num:w \l_regex_current_char_int > \c_max_char_int
        \msg_kernel_error:nnx { regex } { x-overflow }
          { \int_use:N \l_regex_current_char_int }
        \exp_after:wN \use:n
      \else:
        \tex_lccode:D \c_zero \l_regex_current_char_int
        \exp_after:wN \tl_to_lowercase:n
      \fi:
        {
          \tl_set:Nx \l_regex_internal_a_tl
            { \if_false: } \fi:
            \regex_escape_raw:N ^^@
            \regex_escape_loop:N
        }
    }
\group_end:
\prg_new_conditional:Npnn \regex_char_if_special:N #1 { TF }
  {
    \if_num:w `#1 < \c_ninety_one
      \if_num:w `#1 < \c_fifty_eight
        \if_num:w `#1 < \c_forty_eight
          \if_num:w `#1 < \c_thirty_two
            \prg_return_false: \else: \prg_return_true: \fi:
        \else: \prg_return_false: \fi:
      \else:
        \if_num:w `#1 < \c_sixty_five
          \prg_return_true: \else: \prg_return_false: \fi:
      \fi:
    \else:
      \if_num:w `#1 < \c_one_hundred_twenty_three
        \if_num:w `#1 < \c_ninety_seven
          \prg_return_true: \else: \prg_return_false: \fi:
      \else:
        \if_num:w `#1 < \c_one_hundred_twenty_seven
          \prg_return_true: \else: \prg_return_false: \fi:
      \fi:
    \fi:
  }
\prg_new_conditional:Npnn \regex_char_if_alphanumeric:N #1 { TF }
  {
    \if_num:w `#1 < \c_ninety_one
      \if_num:w `#1 < \c_fifty_eight
        \if_num:w `#1 < \c_forty_eight
          \prg_return_false: \else: \prg_return_true: \fi:
      \else:
        \if_num:w `#1 < \c_sixty_five
          \prg_return_false: \else: \prg_return_true: \fi:
      \fi:
    \else:
      \if_num:w `#1 < \c_one_hundred_twenty_three
        \if_num:w `#1 < \c_ninety_seven
          \prg_return_false: \else: \prg_return_true: \fi:
      \else:
        \prg_return_false:
      \fi:
    \fi:
  }
\cs_new_nopar:Npn \regex_build_if_in_class:TF
  {
    \if_int_odd:w \l_regex_build_mode_int
      \exp_after:wN \use_i:nn
    \else:
      \exp_after:wN \use_ii:nn
    \fi:
  }
\cs_new_nopar:Npn \regex_build_if_assertions_forbidden:TF
  {
    \if_int_odd:w \l_regex_build_mode_int
      \exp_after:wN \use_i:nn
    \else:
      \if_int_compare:w \l_regex_build_mode_int > \c_zero
        \exp_after:wN \exp_after:wN \exp_after:wN \use_i:nn
      \else:
        \exp_after:wN \exp_after:wN \exp_after:wN \use_ii:nn
      \fi:
    \fi:
  }
\cs_new_protected_nopar:Npn \regex_build_new_state:
  {
    \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:Npn \regex_build_transition:NN #1#2
  {
    \regex_build_new_state:
    \regex_toks_put_right:Nx \l_regex_left_state_int
      { #1 { \int_eval:n { #2 - \l_regex_left_state_int } } }
  }
\cs_new_protected:Npn \regex_build_transitions:NNNN #1#2#3#4
  {
    \regex_build_new_state:
    \regex_toks_put_right:Nx \l_regex_left_state_int
      {
        #1 { \int_eval:n { #2 - \l_regex_left_state_int } }
        #3 { \int_eval:n { #4 - \l_regex_left_state_int } }
      }
  }
\cs_new_protected_nopar:Npn \regex_build:w
  {
    \int_set_eq:NN \l_regex_catcodes_default_int \c_regex_catcodes_all_int
    \int_set_eq:NN \l_regex_catcodes_int \l_regex_catcodes_default_int
    \int_set_eq:NN \l_regex_capturing_group_int \c_zero
    \seq_clear:N \l_regex_capturing_group_seq
    \tl_clear:N \l_regex_tests_tl
    \bool_set_true:N \l_regex_tests_bool
    \int_zero:N \l_regex_max_state_int
    \regex_build_new_state:
  }
\cs_new_protected_nopar:Npn \regex_build_end:
  {
    \regex_build_exit_class:
    \regex_build_exit_groups:
    \regex_toks_put_right:Nx \l_regex_right_state_int
      { \regex_action_success: }
    \int_incr:N \l_regex_capturing_group_int
  }
\cs_new_protected_nopar:Npn \regex_build_exit_class:
  {
    \regex_build_if_in_class:TF
      {
        \msg_kernel_error:nn { regex } { missing-rbrack }
        \use:c { regex_build_]: }
      }
      { }
  }
\cs_new_protected_nopar:Npn \regex_build_exit_groups:
  {
    \seq_if_empty:NF \l_regex_capturing_group_seq
      {
        \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_: }
      }
  }
\cs_new_protected:Npn \regex_build:n #1
  {
    \regex_build:w
      \int_set_eq:NN \l_regex_build_mode_int \c_zero
      \regex_build_new_state:
      \regex_toks_put_right:Nx \l_regex_left_state_int
        { \regex_action_start_wildcard: }
      \regex_build_open_aux:
        \regex_escape_use:nnnn
          {
            \regex_char_if_special:NTF ##1
              \regex_build_special:N \regex_build_raw:N ##1
          }
          {
            \regex_char_if_alphanumeric:NTF ##1
              \regex_build_escaped:N \regex_build_raw:N ##1
          }
          { \regex_build_raw:N ##1 }
          { #1 }
        \prg_do_nothing: \prg_do_nothing:
        \prg_do_nothing: \prg_do_nothing:
      \int_compare:nNnT \l_regex_build_mode_int < \c_zero
        {
          \msg_kernel_error:nn { regex } { c-missing-rbrace }
          \exp_after:wN \regex_build_special:N \c_rbrace_str
        }
      \seq_put_right:Nn \l_regex_capturing_group_seq {0}
      \regex_build_close_aux: \regex_build_group_:
    \regex_build_end:
  }
\cs_new_protected:Npn \regex_build_special:N #1
  {
    \cs_if_exist_use:cF { regex_build_#1: }
      { \regex_build_raw:N #1 }
  }
\cs_new_protected:Npn \regex_build_escaped:N #1
  {
    \cs_if_exist_use:cF { regex_build_/#1: }
      { \regex_build_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
  {
    \tl_put_right:Nx \l_regex_tests_tl
      {
        \if_num:w \l_regex_catcodes_int < \c_regex_catcodes_all_int
          \regex_item_catcode:nT { \int_use:N \l_regex_catcodes_int }
        \else:
          \exp_after:wN \use:n
        \fi:
        {#1}
      }
    \int_set_eq:NN \l_regex_catcodes_int \l_regex_catcodes_default_int
    \if_num:w \l_regex_build_mode_int = \c_two
      \l_regex_build_mode_int = \c_zero
    \else:
      \if_num:w \l_regex_build_mode_int = \c_six
        \l_regex_build_mode_int = \c_three
      \fi:
    \fi:
    \if_int_odd:w \l_regex_build_mode_int \else:
      \exp_after:wN \regex_build_one_quantifier:
    \fi:
  }
\cs_new:Npn \regex_tests_action_cost:n #1
  {
    \exp_not:o \l_regex_tests_tl
    \bool_if:NTF \l_regex_tests_bool
      { \regex_break_point:TF { \regex_action_cost:n {#1} } { } }
      { \regex_break_point:TF { } { \regex_action_cost:n {#1} } }
  }
\cs_new_protected:Npn \regex_build_raw_error:N #1
  {
    \if_int_odd:w \l_regex_build_mode_int
      \msg_kernel_error:nnx { regex } { class-bad-escape } {#1}
    \else:
      \msg_kernel_error:nnx { regex } { catcode-bad-escape } {#1}
    \fi:
    \regex_build_raw:N #1
  }
\cs_new_protected:Npn \regex_build_raw:N #1#2#3
  {
    \regex_build_if_in_class:TF
      { \str_if_eq:nnTF {#2#3} { \regex_build_special:N - } }
      { \use_ii:nn }
      { \regex_class_range:Nw #1 }
      {
        \regex_build_one:x { \regex_item_equal:n { \int_value:w `#1 ~ } }
        #2 #3
      }
  }
\cs_new_protected:Npn \regex_class_range:Nw #1#2#3
  {
    \token_if_eq_meaning:NNTF #2 \regex_build_escaped:N % [
      { \use_i:nn } { \str_if_eq:nnTF { #2#3 } { \regex_build_special:N ] } }
      {
        \msg_kernel_warning:nnxx { regex } { range-missing-end } % [
          {#1} { \token_if_eq_charcode:NNF #3 ] { \c_backslash_str } #3 }
        \tl_put_right:Nx \l_regex_tests_tl
          {
            \regex_item_equal:n { \int_value:w `#1 ~ }
            \regex_item_equal:n { \int_value:w `- ~ }
          }
        #2#3
      }
      {
        \if_num:w `#1 > `#3 \exp_stop_f:
          \msg_kernel_error:nnxx { regex } { range-backwards } {#1} {#3}
        \else:
          \tl_put_right:Nx \l_regex_tests_tl
            {
              \if_num:w `#1 = `#3 \exp_stop_f:
                \regex_item_equal:n
              \else:
                \regex_item_range:nn { \int_value:w `#1 ~ }
              \fi:
              { \int_value:w `#3 ~ }
            }
        \fi:
      }
  }
\cs_new_protected_nopar:cpx { regex_build_.: }
  {
    \exp_not:N \regex_build_if_in_class:TF
      { \regex_build_raw:N . }
      { \regex_build_one:n \exp_not:c { c_regex_._tl } }
  }
\tl_map_inline:nn { dDhHsSvVwWN }
  {
    \cs_new_protected_nopar:cpx { regex_build_/#1: }
      { \regex_build_one:n \exp_not:c { c_regex_#1_tl } }
  }
\cs_new_protected:Npn \regex_build_simple_assertion:nn #1#2
  {
    \regex_build_if_assertions_forbidden:TF {#1}
      {
        \regex_build_new_state:
        \regex_toks_put_right:Nx \l_regex_left_state_int
          {
            \exp_not:n {#2}
              {
                \regex_action_free:n
                  {
                    \int_eval:n
                      { \l_regex_right_state_int - \l_regex_left_state_int }
                  }
              }
          }
        %^^A todo: add \regex_assertion_quantifier:
      }
  }
\cs_new_protected_nopar:cpn { regex_build_^: }
  {
    \regex_build_simple_assertion:nn { \regex_build_raw:N ^ }
      { \int_compare:nNnT \l_regex_min_index_int = \l_regex_current_index_int }
  }
\cs_new_protected_nopar:cpn { regex_build_/A: }
  {
    \regex_build_simple_assertion:nn { \regex_build_raw_error:N A }
      { \int_compare:nNnT \l_regex_min_index_int = \l_regex_current_index_int }
  }
\cs_new_protected_nopar:cpn { regex_build_/G: }
  {
    \regex_build_simple_assertion:nn { \regex_build_raw_error:N G }
      { \int_compare:nNnT \l_regex_start_index_int = \l_regex_current_index_int }
  }
\group_begin:
  \char_set_catcode_other:N \$
  \cs_new_protected_nopar:cpn { regex_build_$: } % $
    {
      \regex_build_simple_assertion:nn { \regex_build_raw:N $ } % $
        { \int_compare:nNnT \l_regex_current_char_int < \c_minus_one }
    }
\group_end:
\cs_new_protected_nopar:cpn { regex_build_/Z: }
  {
    \regex_build_simple_assertion:nn { \regex_build_raw_error:N Z }
      { \int_compare:nNnT \l_regex_current_char_int < \c_minus_one }
  }
\cs_new_protected_nopar:cpn { regex_build_/z: }
  {
    \regex_build_simple_assertion:nn { \regex_build_raw_error:N z }
      { \int_compare:nNnT \l_regex_current_char_int < \c_minus_one }
  }
\cs_new_protected_nopar:cpn { regex_build_/b: }
  {
    \regex_build_simple_assertion:nn { \regex_build_raw_error:N b }
      { \regex_if_word_boundary:T }
  }
\cs_new_protected_nopar:cpn { regex_build_/B: }
  {
    \regex_build_simple_assertion:nn { \regex_build_raw_error:N B }
      { \regex_if_word_boundary:TF { } }
  }
\cs_new_protected_nopar:Npn \regex_if_word_boundary:TF
  {
    \group_begin:
      \int_set_eq:NN \l_regex_current_char_int \l_regex_last_char_int
      \c_regex_w_tl
      \regex_break_point:TF
        { \group_end: \c_regex_W_tl \regex_item_equal:n { -2 } }
        { \group_end: \c_regex_w_tl }
    \regex_break_point:TF
  }
\cs_new_protected_nopar:Npn \regex_if_word_boundary:T
  { \regex_if_word_boundary:TF \use:n \use_none:n }
\cs_new_protected_nopar:cpn { regex_build_[: }
  {
    \regex_build_if_in_class:TF
      { \regex_build_raw:N [ }
      { \regex_class_first:NNNN }
  }
\cs_new_protected:cpn { regex_build_]: }
  {
    \regex_build_if_in_class:TF
      {
        \if_num:w \l_regex_build_mode_int > \c_sixteen
          \tl_set:Nx \l_regex_tests_tl
            {
              \exp_not:o \l_regex_tests_saved_tl
              \if_num:w \l_regex_catcodes_saved_int < \c_regex_catcodes_all_int
                \regex_item_catcode:nT
                  { \int_use:N \l_regex_catcodes_saved_int }
              \else:
                \exp_after:wN \use:n
              \fi:
                {
                  \exp_not:o \l_regex_tests_tl
                  \bool_if:NF \l_regex_tests_bool
                    { \regex_break_point:TF { } \regex_break_true:w }
                }
            }
          \bool_set_eq:NN \l_regex_tests_bool \l_regex_tests_saved_bool
        \fi:
        \tex_advance:D \l_regex_build_mode_int - \c_fifteen
        \tex_divide:D \l_regex_build_mode_int \c_thirteen
        \if_int_odd:w \l_regex_build_mode_int \else:
          \exp_after:wN \regex_build_one_quantifier:
        \fi:
      }
      { \regex_build_raw:N ] }
  }
\cs_new_protected:Npn \regex_class_first:NNNN #1#2#3#4
  {
    \l_regex_build_mode_int = \int_value:w \l_regex_build_mode_int 3 ~ %
    \if_num:w \l_regex_build_mode_int > \c_sixteen
      \tl_set_eq:NN   \l_regex_tests_saved_tl     \l_regex_tests_tl
      \bool_set_eq:NN \l_regex_tests_saved_bool   \l_regex_tests_bool
      \int_set_eq:NN  \l_regex_catcodes_saved_int \l_regex_catcodes_int
      \int_set_eq:NN  \l_regex_catcodes_int       \c_regex_catcodes_all_int
    \fi:
    \token_if_eq_meaning:NNTF #1 \regex_build_special:N
      {
        \token_if_eq_charcode:NNTF #2 ^
          {
            \bool_set_false:N \l_regex_tests_bool % [
            \str_if_eq:nnTF {#3#4} { \regex_build_special:N ] }
              { \regex_build_raw:N }
          }
          { % [
            \token_if_eq_charcode:NNTF #2 ]
              { \regex_build_raw:N #2 }
              { #1 #2 }
          }
      }
      { #1 #2 }
    #3 #4
  }
\cs_new_protected:cpn { regex_build_/c: }
  {
    \if_case:w \l_regex_build_mode_int
      \exp_after:wN \regex_build_c_aux:wNN
    \or: \or: \or: \exp_after:wN \regex_build_c_aux:wNN
    \fi:
    \msg_kernel_error:nn { regex } { c-bad-mode }
    \s_stop
  }
\cs_new_protected:Npn \regex_build_c_aux:wNN #1 \s_stop #2#3
  {
    \token_if_eq_meaning:NNTF #2 \regex_build_raw:N
      {
        \cs_if_exist:cTF { c_regex_catcode_#3_int }
          {
            \int_set_eq:Nc \l_regex_catcodes_int { c_regex_catcode_#3_int }
            \l_regex_build_mode_int
              = \if_case:w \l_regex_build_mode_int \c_two \else: \c_six \fi:
          }
      }
      { \cs_if_exist_use:cF { regex_build_c_#3: } }
          {
            \msg_kernel_error:nnx { regex } { c-missing-category } {#3}
            #2 #3
          }
  }
\cs_new_protected:cpn { regex_build_c_ \c_lbrace_str : }
  {
    \group_begin:
      \l_regex_build_mode_int
        = - \if_case:w \l_regex_build_mode_int \c_two \else: \c_six \fi:
      \regex_build:w
  }
\cs_new_protected:cpn { regex_build_c_[: } #1#2
  {
    \int_zero:N \l_regex_catcodes_int
    \str_if_eq:nnTF { #1 #2 } { \regex_build_special:N ^ }
      {
        \bool_set_false:N \l_regex_catcodes_bool
        \regex_build_c_lbrack_loop:NN
      }
      {
        \bool_set_true:N \l_regex_catcodes_bool
        \regex_build_c_lbrack_loop:NN
        #1#2
      }
  }
\cs_new_protected:Npn \regex_build_c_lbrack_loop:NN #1#2
  {
    \token_if_eq_meaning:NNTF #1 \regex_build_raw:N
      {
        \cs_if_exist:cTF { c_regex_catcode_#2_int }
          {
            \exp_args:Nc \regex_build_c_lbrack_add:N
              { c_regex_catcode_#2_int }
            \regex_build_c_lbrack_loop:NN
          }
      }
      { % [
        \token_if_eq_charcode:NNTF #2 ]
          { \regex_build_c_lbrack_end: }
      }
          {
            \msg_kernel_error:nnx { regex } { c-missing-rbrack } {#2}
            \regex_build_c_lbrack_end:
          }
  }
\cs_new_protected_nopar:Npn \regex_build_c_lbrack_end:
  {
    \l_regex_build_mode_int
      = \if_case:w \l_regex_build_mode_int \c_two \else: \c_six \fi:
    \if_meaning:w \c_false_bool \l_regex_catcodes_bool
      \int_set:Nn \l_regex_catcodes_int
        { \c_regex_catcodes_all_int - \l_regex_catcodes_int }
    \fi:
  }
\cs_new_protected:Npn \regex_build_c_lbrack_add:N #1
  {
    \if_int_odd:w \int_eval:w \l_regex_catcodes_int / #1 \int_eval_end:
    \else:
      \tex_advance:D \l_regex_catcodes_int #1
    \fi:
  }
\cs_new_protected:cpn { regex_build_ \c_rbrace_str : }
  {
    \int_compare:nNnTF \l_regex_build_mode_int < \c_zero
      {
        \regex_build_exit_class:
        \regex_build_exit_groups:
        \regex_build_escaped:N Z
        \regex_build_end:
        \use:x
          {
            \group_end:
              \regex_build_one:n
                {
                  \regex_item_cs:n
                    { \regex_set_aux:N \l_regex_internal_regex }
                }
          }
      }
      { \exp_after:wN \regex_build_raw:N \c_rbrace_str }
  }
\cs_new_protected:Npn \regex_build_quantifier:w #1#2
  {
    \token_if_eq_meaning:NNTF #1 \regex_build_special:N
      {
        \cs_if_exist_use:cF { regex_build_quantifier_#2:w }
          {
            \regex_build_quantifier_end:nn { } { }
            #1 #2
          }
      }
      {
        \regex_build_quantifier_end:nn { } { }
        #1 #2
      }
  }
\cs_new_protected_nopar:cpn { regex_build_quantifier_?:w }
  { \regex_build_quantifier_aux:nnNN { } { ? } }
\cs_new_protected_nopar:cpn { regex_build_quantifier_*:w }
  { \regex_build_quantifier_aux:nnNN { } { * } }
\cs_new_protected_nopar:cpn { regex_build_quantifier_+:w }
  { \regex_build_quantifier_aux:nnNN { } { + } }
\cs_new_protected:Npn \regex_build_quantifier_aux:nnNN #1#2#3#4
  {
    \str_if_eq:nnTF { #3 #4 } { \regex_build_special:N ? }
      { \regex_build_quantifier_end:nn { #2 #4 } {#1} }
      {
        \regex_build_quantifier_end:nn { #2 } {#1}
        #3 #4
      }
  }
\cs_new_protected_nopar:cpn { regex_build_quantifier_ \c_lbrace_str :w }
  { \regex_get_digits:nw { \regex_build_quantifier_lbrace:n } }
\cs_new_protected:Npn \regex_build_quantifier_lbrace:n #1
  {
    \tl_if_empty:nTF {#1}
      {
        \regex_build_quantifier_end:nn { } { }
        \exp_after:wN \regex_build_raw:N \c_lbrace_str
      }
      { \regex_build_quantifier_lbrace:nw {#1} }
  }
\cs_new_protected:Npx \regex_build_quantifier_lbrace:nw #1#2#3
  {
    \exp_not:N \prg_case_str:nnn { #2 #3 }
      {
        { \exp_not:N \regex_build_special:N , }
          {
            \exp_not:N \regex_get_digits:nw
              { \exp_not:N \regex_build_quantifier_lbrace:nnw {#1} }
          }
        { \exp_not:N \regex_build_special:N \c_rbrace_str }
          { \exp_not:N \regex_build_quantifier_end:nn {n} { {#1} } }
      }
      {
        \exp_not:N \regex_build_quantifier_end:nn { } { }
        \exp_not:N \regex_build_raw:N \c_lbrace_str #1#2
      }
  }
\cs_new_protected:Npn \regex_build_quantifier_lbrace:nnw #1#2#3#4
  {
    \str_if_eq:xxTF
      { \exp_not:n {#3#4} }
      { \exp_not:N \regex_build_special:N \c_rbrace_str }
      {
        \tl_if_empty:nTF {#2}
          { \regex_build_quantifier_aux:nnNN { {#1} } { n* } }
          { \regex_build_quantifier_aux:nnNN { {#1} {#2} } { nn } }
      }
      {
        \regex_build_quantifier_end:nn { } { }
        \use:x
          {
            \exp_args:No \tl_map_function:nN
              { \c_lbrace_str #1 , #2 }
              \regex_build_raw:N
          }
        #3 #4
      }
  }
\cs_new_protected:Npn \regex_build_quantifier_end:nn #1#2
  {
    \use:c { regex_build_ \l_regex_one_or_group_tl _ #1 : } #2
    \tl_clear:N \l_regex_tests_tl
    \bool_set_true:N \l_regex_tests_bool
  }
\cs_new_protected_nopar:Npn \regex_build_one_quantifier:
  {
    \tl_set:Nx \l_regex_one_or_group_tl { one }
    \regex_build_quantifier:w
  }
\cs_new_protected:Npn \regex_build_one_n: #1
  {
    \prg_replicate:nn {#1}
      {
        \regex_build_transition:NN
          \regex_tests_action_cost:n \l_regex_right_state_int
      }
  }
\cs_new_eq:cN { regex_build_one_n?: } \regex_build_one_n:
\cs_new_protected_nopar:Npn \regex_build_one_:
  { \regex_build_one_n: \c_one }
\cs_new_protected:cpn { regex_build_one_n*: } #1
  {
    \int_compare:nNnTF {#1} = \c_zero
      {
        \regex_build_transitions:NNNN
          \regex_tests_action_cost:n \l_regex_left_state_int
          \regex_action_free:n       \l_regex_right_state_int
      }
      {
        \regex_build_one_n: {#1}
        \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
        \regex_build_transitions:NNNN
          \regex_action_free:n \l_regex_internal_a_int
          \regex_action_free:n \l_regex_right_state_int
      }
  }
\cs_new_protected:cpn { regex_build_one_n*?: } #1
  {
    \int_compare:nNnTF {#1} = \c_zero
      {
        \regex_build_transitions:NNNN
          \regex_action_free:n       \l_regex_right_state_int
          \regex_tests_action_cost:n \l_regex_left_state_int
      }
      {
        \regex_build_one_n: {#1}
        \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
        \regex_build_transitions:NNNN
          \regex_action_free:n \l_regex_right_state_int
          \regex_action_free:n \l_regex_internal_a_int
      }
  }
\cs_new_protected_nopar:cpx { regex_build_one_*: }
  { \exp_not:c { regex_build_one_n*: } \c_zero }
\cs_new_protected_nopar:cpx { regex_build_one_*?: }
  { \exp_not:c { regex_build_one_n*?: } \c_zero }
\cs_new_protected_nopar:cpx { regex_build_one_+: }
  { \exp_not:c { regex_build_one_n*: } \c_one }
\cs_new_protected_nopar:cpx { regex_build_one_+?: }
  { \exp_not:c { regex_build_one_n*?: } \c_one }
\cs_new_protected_nopar:Npn \regex_build_one_nn:
  {
    \regex_build_one_nn_aux:nnnn { }
      {
        \regex_build_transitions:NNNN
          \regex_tests_action_cost:n \l_regex_right_state_int
          \regex_action_free:n       \l_regex_internal_a_int
      }
  }
\cs_new_protected_nopar:cpn { regex_build_one_nn?: }
  {
    \regex_build_one_nn_aux:nnnn {?}
      {
        \regex_build_transitions:NNNN
          \regex_action_free:n       \l_regex_internal_a_int
          \regex_tests_action_cost:n \l_regex_right_state_int
      }
  }
\cs_new_protected:Npn \regex_build_one_nn_aux:nnnn #1#2#3#4
  {
    \regex_build_one_n: {#3}
    \int_compare:nNnTF {#3} > {#4}
      {
        \msg_kernel_error:nnxxx
          { regex } { quantifier-backwards } {#3} {#4} {#1}
      }
      {
        \int_set:Nn \l_regex_internal_a_int
          { \l_regex_right_state_int + #4 - #3 }
        \prg_replicate:nn { #4 - #3 } { #2 }
      }
  }
\cs_new_protected_nopar:cpn { regex_build_one_?: }
  { \regex_build_one_nn: \c_zero \c_one }
\cs_new_protected_nopar:cpx { regex_build_one_??: }
  { \exp_not:c { regex_build_one_nn?: } \c_zero \c_one }
\cs_new_protected:cpn { regex_build_(: } #1#2
  {
    \regex_build_if_in_class:TF
      {
        \regex_build_raw:N (
        #1 #2
      }
      {
        \str_if_eq:nnTF { #1 #2 } { \regex_build_special:N ? }
          { \regex_build_special_group:NN }
          {
            \int_incr:N \l_regex_capturing_group_int
            \regex_seq_push_int:NN
              \l_regex_capturing_group_seq \l_regex_capturing_group_int
            \regex_build_open_aux:
            #1 #2
          }
      }
  }
\cs_new_protected_nopar:Npn \regex_build_open_aux:
  {
    \regex_build_new_state:
    \regex_seq_push_int:NN \l_regex_left_state_seq  \l_regex_left_state_int
    \regex_seq_push_int:NN \l_regex_right_state_seq \l_regex_right_state_int
    \bool_if:NTF \l_regex_caseless_bool
      { \seq_push:Nn \l_regex_end_group_seq \regex_build_caseless: }
      { \seq_push:Nn \l_regex_end_group_seq \regex_build_caseful: }
    \seq_push:Nn \l_regex_end_alternation_seq { }
    \regex_build_begin_alternation:
  }
\cs_new_protected_nopar:cpn { regex_build_|: }
  {
    \regex_build_if_in_class:TF { \regex_build_raw:N | }
      {
        \regex_build_end_alternation:
        \regex_build_begin_alternation:
      }
  }
\cs_new_protected_nopar:cpn { regex_build_): }
  {
    \regex_build_if_in_class:TF { \regex_build_raw:N ) }
      {
        \seq_if_empty:NTF \l_regex_capturing_group_seq
          { \msg_kernel_error:nn { regex } { extra-rparen } }
          {
            \regex_build_close_aux:
            \regex_build_group_quantifier:
          }
      }
  }
\cs_new_protected_nopar:Npn \regex_build_close_aux:
  {
    \regex_build_end_alternation:
    \regex_seq_pop_int:NN \l_regex_left_state_seq  \l_regex_left_state_int
    \regex_seq_pop_int:NN \l_regex_right_state_seq \l_regex_right_state_int
    \regex_seq_pop_use:N \l_regex_end_group_seq
    \seq_pop:NN \l_regex_end_alternation_seq \l_regex_internal_a_tl
  }
\cs_new_protected_nopar:Npn \regex_build_begin_alternation:
  {
    \regex_build_new_state:
    \regex_seq_get_int:NN \l_regex_left_state_seq \l_regex_left_state_int
    \regex_toks_put_right:Nx \l_regex_left_state_int
      {
        \regex_action_free:n
          {
            \int_eval:n
              { \l_regex_right_state_int - \l_regex_left_state_int }
          }
      }
  }
\cs_new_protected_nopar:Npn \regex_build_end_alternation:
  {
    \int_set_eq:NN \l_regex_left_state_int \l_regex_right_state_int
    \regex_seq_get_int:NN \l_regex_right_state_seq \l_regex_right_state_int
    \regex_toks_put_right:Nx \l_regex_left_state_int
      {
        \regex_action_free:n
          {
            \int_eval:n
              { \l_regex_right_state_int - \l_regex_left_state_int }
          }
      }
    \regex_seq_get_use:N \l_regex_end_alternation_seq
  }
\cs_new_protected:Npn \regex_build_special_group:NN #1#2
  {
    \cs_if_exist_use:cF { regex_build_special_group_\token_to_str:N #2 : }
      {
        \msg_kernel_error:nnx { regex } { special-group-unknown }
          { (? \token_to_str:N #2 } %)
        \regex_build_special:N ( % )
        \regex_build_raw:N ?
        #1 #2
      }
  }
\cs_new_protected_nopar:cpn { regex_build_special_group_:: }
  {
    \regex_seq_push_int:NN \l_regex_capturing_group_seq \c_minus_one
    \regex_build_open_aux:
  }
\cs_new_protected_nopar:cpn { regex_build_special_group_|: }
  {
    \regex_seq_push_int:NN \l_regex_capturing_group_seq \c_minus_one
    \regex_build_new_state:
    \regex_seq_push_int:NN \l_regex_left_state_seq  \l_regex_left_state_int
    \regex_seq_push_int:NN \l_regex_right_state_seq \l_regex_right_state_int
    \seq_push:Nx \l_regex_end_alternation_seq
      {
        \exp_not:N \int_compare:nNnT
          \l_regex_capturing_group_int
          > \l_regex_capturing_group_max_int
          {
            \int_set_eq:NN
              \l_regex_capturing_group_max_int
              \l_regex_capturing_group_int
          }
        \int_set:Nn \l_regex_capturing_group_int
          { \int_use:N \l_regex_capturing_group_int }
      }
    \seq_push:Nx \l_regex_end_group_seq
      {
        \bool_if:NTF \l_regex_caseless_bool
          \regex_build_caseless:
          \regex_build_caseful:
        \int_set_eq:NN
          \l_regex_capturing_group_int
          \l_regex_capturing_group_max_int
      }
    \regex_build_begin_alternation:
  }
\cs_new_protected_nopar:Npn \regex_build_special_group_i:
  {
    \regex_build_options:NNN +
    \regex_build_raw:N i
  }
\cs_new_protected_nopar:cpn { regex_build_special_group_-: }
  {
    \regex_build_options:NNN -
  }
\cs_new_protected:Npn \regex_build_options:NNN #1#2#3
  {
    \token_if_eq_meaning:NNTF \regex_build_raw:N #2
      {
        \cs_if_exist_use:cF { regex_build_option_#1#3: }
          { \msg_kernel_error:nnx { regex } { unknown-option } { #3 } }
        \regex_build_options:NNN #1
      }
      {
        \prg_case_str:nnn { #3 }
          { % (
            { ) } { }
            { - } { \regex_build_options:NNN - }
          }
          { \msg_kernel_error:nnx { regex } { invalid-in-option } { #3 } }
      }
  }
\cs_new_protected_nopar:cpn { regex_build_option_+i: }
  {
    \regex_build_caseless:
    \cs_set_eq:NN \regex_match_loop_case_hook:
      \regex_match_loop_caseless_hook:
  }
\cs_new_protected_nopar:cpn { regex_build_option_-i: }
  { \regex_build_caseful: }
\cs_new_protected_nopar:Npn \regex_build_group_quantifier:
  {
    \tl_set:Nn \l_regex_one_or_group_tl { group }
    \regex_build_quantifier:w
  }
\cs_new_protected:Npn \regex_build_group_submatches:NN #1#2
  {
    \seq_pop:NN \l_regex_capturing_group_seq \l_regex_internal_a_tl
    \int_compare:nNnF { \l_regex_internal_a_tl } < \c_zero
      {
        \regex_toks_put_left:Nx #1
          { \regex_action_submatch:n { \l_regex_internal_a_tl < } }
        \regex_toks_put_left:Nx #2
          { \regex_action_submatch:n { \l_regex_internal_a_tl > } }
      }
  }
\cs_new_protected_nopar:Npn \regex_build_group_qs_aux:
  {
    \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
    \regex_build_new_state:
    \tex_toks:D \l_regex_right_state_int = \tex_toks:D \l_regex_internal_a_int
    \regex_toks_put_left:Nx \l_regex_right_state_int
      {
        \int_sub:Nn \l_regex_current_state_int
          {
            \int_eval:n % ^^A here we lie!
              { \l_regex_right_state_int - \l_regex_internal_a_int }
          }
      }
    \use:x
      {
        \tex_toks:D \l_regex_internal_a_int
          {
            \s_stop
            \regex_action_free:n
              {
                \int_eval:n
                  { \l_regex_right_state_int - \l_regex_internal_a_int }
              }
          }
      }
    \regex_build_group_submatches:NN
      \l_regex_right_state_int \l_regex_left_state_int
  }
\cs_new_protected:Npn \regex_build_group_qs_aux:NN #1#2
  {
    \regex_build_group_qs_aux:
    \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
    \regex_build_transition:NN \regex_action_free:n #1
    #2 \l_regex_internal_a_int
      {
        \regex_action_free:n
          { \int_eval:n { \l_regex_right_state_int - \l_regex_internal_a_int } }
      }
  }
\cs_new_protected_nopar:cpn { regex_build_group_?: }
  {
    \regex_build_group_qs_aux:NN
      \l_regex_right_state_int \regex_toks_put_right:Nx
  }
\cs_new_protected_nopar:cpn { regex_build_group_??: }
  {
    \regex_build_group_qs_aux:NN
      \l_regex_right_state_int \regex_toks_put_left:Nx
  }
\cs_new_protected:Npn \regex_build_group_transition_right_max:
  {
    \regex_toks_put_right:Nx \l_regex_right_state_int
      {
        \regex_action_free:n
          { \int_eval:n { \l_regex_max_state_int - \l_regex_right_state_int } }
      }
  }
\cs_new_protected:Npn \regex_build_group_n_aux:n #1
  {
    \int_set_eq:NN \l_regex_internal_a_int \l_regex_left_state_int
    \int_set_eq:NN \l_regex_internal_b_int \l_regex_max_state_int
    \int_add:Nn \l_regex_right_state_int
      { ( #1 - 1 ) * ( \l_regex_max_state_int - \l_regex_left_state_int ) }
    \int_set:Nn \l_regex_max_state_int
      {
        \l_regex_left_state_int
        + (#1) * ( \l_regex_max_state_int - \l_regex_left_state_int )
      }
    \int_while_do:nNnn \l_regex_internal_b_int < \l_regex_max_state_int
      {
        \tex_toks:D \l_regex_internal_b_int
          = \tex_toks:D \l_regex_internal_a_int
        \int_incr:N \l_regex_internal_a_int
        \int_incr:N \l_regex_internal_b_int
      }
  }
\cs_new_protected:Npn \regex_build_group_n: #1
  {
    \regex_build_group_transition_right_max:
    \regex_build_group_n_aux:n {#1}
    \regex_build_new_state:
    \int_compare:nNnF {#1} = \c_zero
      {
        \regex_build_group_submatches:NN
          \l_regex_internal_a_int \l_regex_left_state_int
      }
  }
\cs_new_eq:cN { regex_build_group_n?: } \regex_build_group_n:
\cs_new_protected_nopar:Npn \regex_build_group_:
  { \regex_build_group_n: \c_one }
\cs_new_protected_nopar:cpn { regex_build_group_n*: }
  {
    \regex_build_group_n_star_aux:NNn
      \regex_toks_put_right:Nx \regex_toks_put_left:Nx
  }
\cs_new_protected_nopar:cpn { regex_build_group_n*?: }
  {
    \regex_build_group_n_star_aux:NNn
      \regex_toks_put_left:Nx \regex_toks_put_right:Nx
  }
\cs_new_protected:Npn \regex_build_group_n_star_aux:NNn #1#2#3
  {
    \int_compare:nNnTF {#3} = \c_zero
      { \regex_build_group_qs_aux:NN \l_regex_internal_a_int #1 }
      {
        \regex_build_group_transition_right_max:
        \regex_build_group_n_aux:n {#3}
        \regex_build_new_state:
        #2 \l_regex_left_state_int
          {
            \regex_action_free:n
              {
                \int_eval:n
                  { \l_regex_internal_a_int - \l_regex_left_state_int }
              }
          }
        \regex_build_group_submatches:NN
          \l_regex_internal_a_int \l_regex_left_state_int
      }
  }
\cs_new_protected_nopar:cpx { regex_build_group_*: }
  { \exp_not:c { regex_build_group_n*: } \c_zero }
\cs_new_protected_nopar:cpx { regex_build_group_*?: }
  { \exp_not:c { regex_build_group_n*?: } \c_zero }
\cs_new_protected_nopar:cpx { regex_build_group_+: }
  { \exp_not:c { regex_build_group_n*: } \c_one }
\cs_new_protected_nopar:cpx { regex_build_group_+?: }
  { \exp_not:c { regex_build_group_n*?: } \c_one }
\cs_new_protected_nopar:Npn \regex_build_group_nn:
  {
    \regex_build_group_nn_aux:nnnn { }
      \regex_build_group_transition_right_max:
  }
\cs_new_protected_nopar:cpn { regex_build_group_nn?: }
  {
    \regex_build_group_nn_aux:nnnn { }
      {
        \use:x
          {
            \tex_toks:D \l_regex_right_state_int
              {
                \exp_after:wN \regex_build_group_nn_aux_ii:w
                \tex_the:D \tex_toks:D \l_regex_right_state_int
              }
          }
      }
  }
\cs_new_protected:Npn \regex_build_group_nn_aux:nnnn #1#2#3#4
  {
    \int_compare:nNnTF {#3} > {#4}
      {
        \msg_kernel_error:nnxxx
          { regex } { quantifier-backwards } {#3} {#4} {#1}
      }
      {
        \int_compare:nNnTF {#3} = \c_zero
          {
            \regex_build_group_qs_aux:
            \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
            \int_set_eq:NN \l_regex_left_state_int  \l_regex_internal_a_int
            \regex_build_group_transition_right_max:
            \regex_build_group_n_aux:n { #4 - #3 }
            \int_set_eq:NN \l_regex_internal_c_int \l_regex_right_state_int
            \int_set_eq:NN \l_regex_right_state_int \l_regex_left_state_int
            \prg_replicate:nn { #4 - #3 }
              {
                #2
                \int_add:Nn \l_regex_right_state_int
                  { \l_regex_internal_b_int - \l_regex_internal_a_int }
              }
            \int_set_eq:NN \l_regex_right_state_int \l_regex_internal_c_int
            \int_set_eq:NN \l_regex_left_state_int \l_regex_internal_a_int
            \regex_build_new_state:
          }
          {
            \regex_build_group_transition_right_max:
            \regex_build_group_n_aux:n {#3}
            \int_set_eq:NN \l_regex_left_state_int \l_regex_internal_a_int
            \regex_build_group_submatches:NN
              \l_regex_left_state_int \l_regex_right_state_int
            \regex_build_group_n_aux:n { #4 - #3 + \c_one }
            \int_sub:Nn \l_regex_right_state_int
              { \l_regex_internal_a_int - \l_regex_left_state_int }
            \prg_replicate:nn { #4 - #3 }
              {
                #2
                \int_add:Nn \l_regex_right_state_int
                  { \l_regex_internal_b_int - \l_regex_internal_a_int }
              }
            \int_set_eq:NN \l_regex_left_state_int \l_regex_internal_a_int
            \regex_build_new_state:
          }
      }
  }
\cs_new_protected:Npn \regex_build_group_nn_aux_ii:w #1 \regex_action_free:n
  {
    #1
    \regex_action_free:n
      {
        \int_eval:n
          { \l_regex_max_state_int - \l_regex_right_state_int }
      }
    \regex_action_free:n
  }
\cs_new_protected:cpn { regex_build_/u: } #1#2
  {
    \regex_build_if_assertions_forbidden:TF
      { \regex_build_raw_error:N u #1#2 }
      {
        \str_if_eq:xxTF {#1#2} { \regex_build_special:N \c_lbrace_str }
          {
            \tl_set:Nx \l_regex_internal_a_tl { \if_false: } \fi:
            \regex_build_u_loop:NN
          }
          {
            \msg_kernel_error:nn { regex } { u-missing-lbrace }
            #1#2
          }
      }
  }
\cs_new:Npn \regex_build_u_loop:NN #1#2
  {
    \token_if_eq_meaning:NNTF #1 \regex_build_raw:N
      { #2 \regex_build_u_loop:NN }
      {
        \token_if_eq_meaning:NNTF #1 \regex_build_special:N
          {
            \exp_after:wN \token_if_eq_charcode:NNTF \c_rbrace_str #2
              { \if_false: { \fi: } \regex_build_u_end: }
              { #2 \regex_build_u_loop:NN }
          }
          {
            \if_false: { \fi: }
            \msg_kernel_error:nnx { regex } { u-missing-rbrace } {#2}
            \regex_build_u_end:
            #1#2
          }
      }
  }
\cs_new_protected:Npn \regex_build_u_end:
  {
    \tl_set:Nv \l_regex_internal_a_tl \l_regex_internal_a_tl
    \if_num:w \l_regex_build_mode_int = \c_zero
      \regex_build_u_not_cs:
    \else:
      \regex_build_u_in_cs:
    \fi:
    \tl_clear:N \l_regex_tests_tl
  }
\cs_new_protected:Npn \regex_build_u_in_cs:
  {
    \exp_args:NNo \str_gset_other:Nn \g_regex_internal_tl
      { \l_regex_internal_a_tl }
    \tl_map_inline:Nn \g_regex_internal_tl
      {
        \tl_set:Nx \l_regex_tests_tl { \regex_item_equal:n { `##1 } }
        \regex_build_one_:
      }
  }
\cs_new_protected:Npn \regex_build_u_not_cs:
  {
    \exp_args:No \tl_analysis_map_inline:nn { \l_regex_internal_a_tl }
      {
        \tl_set:Nx \l_regex_tests_tl
          {
            \exp_not:N \int_compare:nNnT
              \l_regex_current_catcode_int = { \int_value:w "##2 }
              {
                \int_compare:nNnTF { "##2 } = \c_zero
                  {
                    \exp_not:n
                      { \str_if_eq:xxT { \l_regex_current_token_tl } {##1} }
                      { \regex_break_true:w }
                  }
                  { \regex_item_equal:n {##3} }
              }
          }
        \regex_build_one_:
      }
  }
\cs_new_protected:Npn \regex_store_state:n #1
  {
    \int_incr:N \l_regex_max_active_int
    \tex_skip:D \l_regex_max_active_int #1 sp \scan_stop:
    \regex_store_submatches:n {#1}
  }
\cs_new_protected_nopar:Npn \regex_state_use_with_submatches:
  { \regex_state_use_aux:n { } }
\cs_new_protected_nopar:Npn \regex_state_use:
  { \regex_state_use_aux:n { \exp_after:wN \use_none_delimit_by_s_stop:w } }
\cs_new_protected:Npn \regex_state_use_aux:n #1
  {
    \if_num:w \tex_dimen:D \l_regex_current_state_int < \l_regex_step_int
      \tex_dimen:D \l_regex_current_state_int
        = \l_regex_step_int sp \scan_stop:
      #1 \tex_the:D \tex_toks:D \exp_after:wN \l_regex_current_state_int
    \fi:
    \scan_stop:
  }
\cs_new_protected_nopar:Npn \regex_disable_submatches:
  {
    \cs_set_eq:NN \regex_state_use_with_submatches: \regex_state_use:
    \cs_set_eq:NN \regex_store_submatches:n
      \regex_protected_use_none:n
    \cs_set_eq:NN \regex_action_submatches:n
      \regex_protected_use_none:n
  }
\cs_new_protected:Npn \regex_protected_use_none:n #1 { }
\cs_new_protected:Npn \regex_store_submatches:n #1
  {
    \tex_toks:D #1 \exp_after:wN
      {
        \tex_romannumeral:D
        \exp_after:wN \regex_store_submatches_aux:w
        \tex_the:D \tex_toks:D #1
      }
  }
\cs_new_protected:Npn \regex_store_submatches_aux:w #1 \s_stop
  {
    \regex_store_submatches_aux_ii:Nnnw
      #1
      \regex_state_submatches:nn \c_minus_one \q_prop
    \s_stop
  }
\cs_new_protected:Npn \regex_store_submatches_aux_ii:Nnnw
    \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_step_int + \c_one \exp_after:wN }
      \exp_after:wN { \l_regex_current_submatches_prop }
    \regex_state_submatches:nn {#1} {#2}
    \s_stop
  }
\cs_new_protected:Npn \regex_state_submatches:nn #1#2
  {
    \if_num:w #1 = \l_regex_step_int
      \tl_set:Nn \l_regex_current_submatches_prop { #2 }
    \fi:
  }
\cs_new_protected:Npn \regex_match:n #1
  {
    \int_zero:N \l_regex_nesting_int
    \int_set_eq:NN \l_regex_current_index_int \l_regex_max_state_int
    \regex_query_set:nnn { } { -1 } { -2 }
    \int_set_eq:NN \l_regex_min_index_int \l_regex_current_index_int
    \tl_analysis_map_inline:nn {#1}
      {
        \regex_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:
      }
    \int_set_eq:NN \l_regex_max_index_int \l_regex_current_index_int
    \regex_query_set:nnn { } { -1 } { -2 }
    \regex_match_initial_setup:
    \regex_match_once:
  }
\cs_new_protected:Npn \regex_query_set:nnn #1#2#3
  {
    \tex_muskip:D \l_regex_current_index_int
      = \etex_gluetomu:D
        #3 sp
        plus #2 sp
        minus \l_regex_nesting_int sp
      \scan_stop:
    \tex_toks:D \l_regex_current_index_int {#1}
    \int_incr:N \l_regex_current_index_int
  }
\cs_new_protected_nopar:Npn \regex_query_get:
  {
    \tl_set:Nx \l_regex_current_token_tl
      { \tex_the:D \tex_toks:D \l_regex_current_index_int }
    \l_regex_current_char_int
      = \etex_mutoglue:D \tex_muskip:D \l_regex_current_index_int
    \l_regex_current_catcode_int = \etex_gluestretch:D
      \etex_mutoglue:D \tex_muskip:D \l_regex_current_index_int
  }
\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:
  {
    \int_set_eq:NN \l_regex_step_int \c_minus_one
    \prg_stepwise_inline:nnnn
      \c_zero \c_one { \l_regex_max_state_int - \c_one }
      { \tex_dimen:D ##1 \l_regex_step_int sp }
    \int_set:Nn \l_regex_start_index_int
      { \l_regex_min_index_int - \c_one }
    \int_set_eq:NN \l_regex_current_index_int \l_regex_min_index_int
    \int_set_eq:NN \l_regex_success_index_int \l_regex_min_index_int
    \int_set_eq:NN \l_regex_submatch_int \l_regex_max_state_int
    \bool_set_false:N \l_regex_success_empty_bool
    \bool_gset_false:N \g_regex_success_bool
  }
\cs_new_protected_nopar:Npn \regex_match_setup:
  {
    \prop_clear:N \l_regex_current_submatches_prop
    \bool_if:NTF \l_regex_success_empty_bool
      { \cs_set_eq:NN \regex_if_two_empty_matches:F \regex_if_match_empty:F }
      { \cs_set_eq:NN \regex_if_two_empty_matches:F \use:n }
    \int_set_eq:NN \l_regex_start_index_int \l_regex_success_index_int
    \int_set:Nn \l_regex_current_index_int
      { \l_regex_start_index_int - \c_one }
    \bool_set_false:N \l_regex_success_match_bool
    \int_zero:N \l_regex_max_active_int
    \regex_store_state:n {0} %^^A _state_int!
  }
\cs_new_protected_nopar:Npn \regex_match_loop:
  {
    \int_incr:N \l_regex_current_index_int
    \int_incr:N \l_regex_step_int
    \bool_set_false:N \l_regex_fresh_thread_bool
    \int_set_eq:NN \l_regex_last_char_int \l_regex_current_char_int
    \regex_query_get:
    \regex_match_loop_case_hook:
    \use:x
      {
        \int_zero:N \l_regex_max_active_int
        \regex_match_one_active:w 1 ; \prg_break_point:n { }
        \exp_not:N \prg_break_point:n { }
      }
    \if_num:w \l_regex_current_char_int < \c_minus_one
      \exp_after:wN \prg_map_break:
    \fi:
    \if_num:w \l_regex_max_active_int = \c_zero
      \exp_after:wN \prg_map_break:
    \fi:
    \regex_match_loop:
  }
\cs_new:Npn \regex_match_one_active:w #1;
  {
    \if_num:w #1 > \l_regex_max_active_int
      \exp_after:wN \prg_map_break:
    \fi:
    \regex_match_one_active_aux:n
      { \int_value:w \tex_skip:D #1 }
    \exp_after:wN \regex_match_one_active:w
    \int_use:N \int_eval:w #1 + \c_one ;
  }
\cs_new_protected:Npn \regex_match_one_active_aux:n #1
  {
    \int_set:Nn \l_regex_current_state_int {#1}
    \prop_clear:N \l_regex_current_submatches_prop
    \regex_state_use_with_submatches:
  }
\cs_new_protected_nopar:Npn \regex_match_loop_case_hook: { }
\cs_new_protected_nopar:Npn \regex_match_loop_caseless_hook:
  {
    \int_set_eq:NN \l_regex_case_changed_char_int \l_regex_current_char_int
    \if_num:w \l_regex_current_char_int < \c_ninety_one
      \if_num:w \l_regex_current_char_int < \c_sixty_five
      \else:
        \int_add:Nn \l_regex_case_changed_char_int { \c_thirty_two }
      \fi:
    \else:
      \if_num:w \l_regex_current_char_int < \c_one_hundred_twenty_three
        \if_num:w \l_regex_current_char_int < \c_ninety_seven
        \else:
          \int_sub:Nn \l_regex_case_changed_char_int { \c_thirty_two }
        \fi:
      \fi:
    \fi:
  }
\cs_new_protected_nopar:Npn \regex_action_start_wildcard:
  {
    \bool_set_true:N \l_regex_fresh_thread_bool
    \regex_action_free:n {1}
    \bool_set_false:N \l_regex_fresh_thread_bool
    \regex_action_cost:n {0}
  }
\cs_new_protected:Npn \regex_action_cost:n #1
  {
    \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_if_two_empty_matches:F
      {
        \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_index_int \l_regex_current_index_int
        \prop_set_eq:NN \l_regex_success_submatches_prop
          \l_regex_current_submatches_prop
        \prg_map_break:
      }
  }
\cs_new_protected:Npn \regex_action_free:n #1
  {
    \use:x
      {
        \int_add:Nn \l_regex_current_state_int {#1}
        \regex_state_use:
        \int_set:Nn \l_regex_current_state_int
          { \int_use:N \l_regex_current_state_int }
        \tl_set:Nn \exp_not:N \l_regex_current_submatches_prop
          { \exp_not:o \l_regex_current_submatches_prop }
      }
  }
\cs_new_protected:Npn \regex_action_submatch:n #1
  {
    \prop_put:Nno \l_regex_current_submatches_prop {#1}
      { \int_use:N \l_regex_current_index_int }
  }
\cs_new:Npn \regex_if_match_empty:T
  { \int_compare:nNnT \l_regex_start_index_int = \l_regex_current_index_int }
\cs_new:Npn \regex_if_match_empty:F
  { \int_compare:nNnF \l_regex_start_index_int = \l_regex_current_index_int }
\cs_new_protected:Npn \regex_submatch_nesting_aux:n #1
  {
    + \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:Npn \regex_nesting:n #1 { } %^^A move. Rename?
\tl_new:N \l_regex_nesting_tl
\cs_new_protected:Npn \regex_replacement:n #1
  {
    \int_zero:N \l_regex_replacement_int
    \int_zero:N \l_regex_nesting_int
    \tl_clear:N \l_regex_nesting_tl
    \regex_escape_use:nnnn
      { \regex_replacement_unescaped:N ##1 }
      { \regex_replacement_escaped:N ##1 }
      { \regex_replacement_raw:N ##1 }
      {#1}
    \prg_do_nothing: \prg_do_nothing:
    \cs_set:Npx \regex_nesting:n ##1
      {
        + \int_use:N \l_regex_nesting_int
        \l_regex_nesting_tl
        - \regex_submatch_nesting_aux:n {##1}
      }
    \use:x
      {
        \exp_not:n { \cs_set:Npn \regex_replacement_tl:n ##1 }
          { \regex_toks_range:nn \c_zero \l_regex_replacement_int }
      }
      % ^^A rename!
  }
\cs_new_protected:Npn \regex_replacement_raw:N #1
  { \regex_replacement_put:n {#1} }
\cs_new_protected:Npn \regex_replacement_put:n #1
  {
    \tex_toks:D \l_regex_replacement_int {#1}
    \int_incr:N \l_regex_replacement_int
  }
\cs_new_protected:Npn \regex_replacement_unescaped:N #1
  {
    \if_charcode:w \c_rbrace_str #1
      \if_num:w \l_regex_replacement_csnames_int > \c_zero
        \regex_replacement_put:n \cs_end:
      \else:
        \regex_replacement_put:n #1
      \fi:
    \else:
      \regex_replacement_put:n #1
    \fi:
  }
\cs_new_protected:Npn \regex_replacement_escaped:N #1
  {
    \cs_if_exist_use:cF { regex_replacement_#1:w }
      {
        \if_num:w \c_one < 1#1 \exp_stop_f:
          \regex_replacement_put_submatch:n {#1}
        \else:
          \regex_replacement_put:n #1
        \fi:
      }
  }
\cs_new_protected:Npn \regex_replacement_put_submatch:n #1
  {
    \regex_replacement_put:n
      { \regex_query_submatch:nn {#1} {##1} }
    \if_num:w \l_regex_replacement_csnames_int = \c_zero
      \tl_put_right:Nn \l_regex_nesting_tl
        {
          \exp_not:N \if_num:w #1 < \l_regex_capturing_group_int
            \regex_submatch_nesting_aux:n { \int_eval:w #1+##1 \int_eval_end: }
          \exp_not:N \fi:
        }
    \fi:
  }
\cs_new_protected:Npn \regex_replacement_error:NNN #1#2#3
  {
    \msg_kernel_error:nnxx { regex } { #1-command }
      { replacement~text } {#3}
    #2 #3
  }
\cs_new_protected:Npn \regex_replacement_g:w #1#2
  {
    \str_if_eq:xxTF
      { \exp_not:n { #1#2 } }
      { \regex_replacement_unescaped:N \c_lbrace_str }
      {
        \int_zero:N \l_regex_internal_a_int
        \regex_replacement_g_digits:NN
      }
      { \regex_replacement_error:NNN g #1 #2 }
  }
\cs_new_protected:Npn \regex_replacement_g_digits:NN #1#2
  {
    \token_if_eq_meaning:NNTF #1 \regex_replacement_unescaped:N
      {
        \if_num:w \c_one < 1#2 \exp_stop_f:
          \int_set:Nn \l_regex_internal_a_int { \c_ten * \l_regex_internal_a_int + #2 }
          \exp_after:wN \use_i:nnn
          \exp_after:wN \regex_replacement_g_digits:NN
        \else:
          \if_charcode:w \c_rbrace_str #2
            \exp_args:No \regex_replacement_put_submatch:n
              { \int_use:N \l_regex_internal_a_int }
            \exp_after:wN \exp_after:wN \exp_after:wN \use_none:nn
          \else:
            \exp_after:wN \exp_after:wN
            \exp_after:wN \regex_replacement_error:NNN
            \exp_after:wN \exp_after:wN \exp_after:wN g
          \fi:
        \fi:
      }
      { \regex_replacement_error:NNN g }
    #1 #2
  }
\cs_new_protected:Npn \regex_replacement_u:w #1#2
  {
    \str_if_eq:xxTF { #1#2 } { \regex_replacement_unescaped:N \c_lbrace_str }
      {
        \int_incr:N \l_regex_replacement_csnames_int
        \regex_replacement_put:n
          { \exp_not:n { \exp_after:wN \exp_not:V \cs:w } }
      }
      { \regex_replacement_error:NNN u #1#2 }
  }
\cs_new_protected:Npn \regex_replacement_c:w #1#2
  {
    \token_if_eq_meaning:NNTF #1 \regex_replacement_unescaped:N
      {
        \cs_if_exist_use:cF { regex_replacement_c_#2:w }
          { \regex_replacement_error:NNN c #1#2 }
      }
      { \regex_replacement_error:NNN c #1#2 }
  }
\cs_new_protected_nopar:cpn { regex_replacement_c_ \c_lbrace_str :w }
  {
    \int_incr:N \l_regex_replacement_csnames_int
    \regex_replacement_put:n
      { \exp_not:n { \exp_after:wN \regex_replacement_exp_not:N \cs:w } }
  }
\cs_new:Npn \regex_replacement_exp_not:N #1 { \exp_not:n {#1} }
\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: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: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} } }
  }
\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
  {
    \group_begin:
      \regex_build:n {#3}
      \use:x
        {
          \group_end:
          #1 \exp_not:N #2 { \regex_set_aux:N #2 }
        }
  }
\cs_new:Npn \regex_set_aux:N #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:
      {
        \cs_set_eq:NN \regex_match_loop_case_hook:
          \regex_match_loop_caseless_hook:
      }
    \prg_stepwise_function:nnnN
      \c_zero \c_one {\l_regex_max_state_int - \c_one }
      \regex_set_aux:n
    \s_stop
  }
\cs_new:Npn \regex_set_aux:n #1
  { \tex_toks:D #1 { \tex_the:D \tex_toks:D #1 } }
\cs_new:Npn \regex_nfa:Nw #1
  {
    \msg_expandable_kernel_error:nnn { regex } { nfa-misused } {#1}
    \use_none_delimit_by_s_stop:w
  }
\cs_new_protected_nopar:Npn \regex_use:N
  { \exp_last_unbraced:No \use_none:nn }
\cs_new_protected_nopar:Npn \regex_aux_return:
  {
    \if_meaning:w \c_true_bool \g_regex_success_bool
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
\cs_new_protected:Npn \regex_aux_build_match:nn #1#2
  {
    \regex_build:n {#1}
    \regex_match:n {#2}
  }
\cs_new_protected:Npn \regex_aux_use_match:Nn #1#2
  {
    \exp_args:No \tl_if_head_eq_meaning:nNTF {#1} \regex_nfa:Nw
      {
        \regex_use:N #1
        \regex_match:n {#2}
      }
      {
        \msg_kernel_error:nnx { regex } { not-nfa } { \token_to_str:N #1 }
        \bool_gset_false:N \g_regex_success_bool
      }
  }
\cs_set_protected:Npn \regex_tmp:w #1#2#3
  {
    \cs_new_protected_nopar:Npn #1
      { #3 \regex_aux_build_match:nn }
    \cs_new_protected_nopar:Npn #2
      { #3 \regex_aux_use_match:Nn }
    \prg_new_protected_conditional:Npnn #1 ##1##2##3 { T , F , TF }
      {
        #3 \regex_aux_build_match:nn {##1} {##2} ##3
        \regex_aux_return:
      }
    \prg_new_protected_conditional:Npnn #2 ##1##2##3 { T , F , TF }
      {
        #3 \regex_aux_use_match:Nn {##1} {##2} ##3
        \regex_aux_return:
      }
  }
\tl_map_inline:nn
  {
    { extract_once } { extract_all }
    { replace_once } { replace_all }
    { split }
  }
  {
    \exp_args:Nccc \regex_tmp:w
      { regex_#1:nnN } { regex_#1:NnN } { regex_#1_aux:NnnN }
  }
\cs_new_protected_nopar:Npn \regex_extract:
  {
    \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_protected:Npn \regex_extract_aux_b:wn #1 < #2
  {
    \tex_skip:D #1 = #2 sp
      plus \etex_gluestretch:D \tex_skip:D #1 \scan_stop:
  }
\cs_new_protected:Npn \regex_extract_aux_e:wn #1 > #2
  {
    \tex_skip:D #1
      = 1 \tex_skip:D #1 plus #2 sp \scan_stop:
  }
\cs_new_protected:Npn \regex_group_end_extract_seq:N #1
  {
      \cs_set_eq:NN \seq_item:n \scan_stop:
      \flag_clear:n { regex_begin }
      \flag_clear:n { regex_end }
      \tl_set:Nx \l_regex_internal_a_tl
        {
          \prg_stepwise_function:nnnN
            \l_regex_max_state_int
            \c_one
            { \l_regex_submatch_int - \c_one }
            \regex_extract_seq_aux:n
        }
      \int_compare:nNnF
        { \flag_height:n { regex_begin } + \flag_height:n { regex_end } }
        = \c_zero
        { \msg_kernel_error:nn { regex } { sequence-unbalanced } }
      \tl_set:Nx \l_regex_internal_a_tl { \l_regex_internal_a_tl }
    \exp_args:NNNo \group_end:
    \tl_set:Nn #1 \l_regex_internal_a_tl
  }
\cs_new:Npn \regex_extract_seq_aux:n #1
  {
    \seq_item:n
      {
        \exp_after:wN \regex_extract_seq_aux:ww
        \int_value:w \regex_submatch_nesting_aux:n {#1} ; #1;
      }
  }
\cs_new:Npn \regex_extract_seq_aux:ww #1; #2;
  {
    \if_num:w #1 < \c_zero
      \flag_raise:n { regex_end }
      \prg_replicate:nn {-#1} { \exp_not:n { { \if_false: } \fi: } }
    \fi:
    \regex_query_submatch:w #2;
    \if_num:w #1 > \c_zero
      \flag_raise:n { regex_begin }
      \prg_replicate:nn {#1} { \exp_not:n { \if_false: { \fi: } } }
    \fi:
  }
\prg_new_protected_conditional:Npnn \regex_match:nn #1#2 { T , F , TF }
  {
    \regex_match_aux:n
      { \regex_aux_build_match:nn {#1} {#2} }
  }
\prg_new_protected_conditional:Npnn \regex_match:Nn #1#2 { T , F , TF }
  {
    \regex_match_aux:n
      { \regex_aux_use_match:Nn #1 {#2} }
  }
\cs_new_protected:Npn \regex_match_aux:n #1
  {
    \group_begin:
      \tl_clear:N \l_regex_every_match_tl
      \regex_disable_submatches:
      #1
    \group_end:
    \regex_aux_return:
  }
\cs_new_protected_nopar:Npn \regex_count:nnN
  { \regex_count_aux:NnnN \regex_aux_build_match:nn }
\cs_new_protected_nopar:Npn \regex_count:NnN
  { \regex_count_aux:NnnN \regex_aux_use_match:Nn }
\cs_new_protected:Npn \regex_count_aux:NnnN #1#2#3#4
  {
    \group_begin:
      \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:Npn \regex_extract_once_aux:NnnN #1#2#3#4
  {
    \group_begin:
      \tl_set:Nn \l_regex_every_match_tl { \regex_extract: }
      #1 {#2} {#3}
      \regex_group_end_extract_seq:N #4
  }
\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_index_int < \l_regex_success_index_int
            \regex_extract:
            \tex_skip:D \l_regex_submatch_start_int
              = \l_regex_start_index_int sp
                plus \tex_skip:D \l_regex_submatch_start_int \scan_stop:
          \fi:
          \regex_match_once:
        }
      #1 {#2} {#3}
      \tex_skip:D \l_regex_submatch_int
        = \l_regex_start_index_int sp
          plus \l_regex_current_index_int sp \scan_stop:
      \int_incr:N \l_regex_submatch_int
      \if_num:w \l_regex_start_index_int = \l_regex_current_index_int
        \if_meaning:w \c_true_bool \l_regex_success_empty_bool
          \int_decr:N \l_regex_submatch_int
        \fi:
      \fi:
      \regex_group_end_extract_seq:N #4
  }
\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_internal_a_int
          { \regex_nesting:n { \l_regex_submatch_start_int } }
        \if_num:w \l_regex_internal_a_int = \c_zero
        \else:
          \msg_kernel_error:nnx { regex } { replace-unbalanced }
            { \l_regex_internal_a_int }
        \fi:
        \tl_set:Nx \l_regex_internal_a_tl
          {
            \if_num:w \l_regex_internal_a_int < \c_zero
              \prg_replicate:nn { - \l_regex_internal_a_int }
                { \exp_not:n { { \if_false: } \fi: } }
            \fi:
            \regex_toks_range:nn
              { \l_regex_min_index_int }
              { \tex_skip:D \l_regex_submatch_start_int }
            \regex_replacement_tl:n { \l_regex_submatch_start_int }
            \regex_toks_range:nn
              { \etex_gluestretch:D \tex_skip:D \l_regex_submatch_start_int }
              { \l_regex_max_index_int }
            \if_num:w \l_regex_internal_a_int > \c_zero
              \prg_replicate:nn { \l_regex_internal_a_int }
                { \exp_not:n { \if_false: { \fi: } } }
            \fi:
          }
        \tl_set:Nx \l_regex_internal_a_tl { \l_regex_internal_a_tl }
        \exp_args:NNNo \group_end:
        \tl_set:Nn #4 \l_regex_internal_a_tl
      \else:
        \group_end:
      \fi:
  }
\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_index_int sp \scan_stop:
          \regex_match_once:
        }
      \regex_replacement:n {#3}
      \exp_args:Nno #1 {#2} #4
      \int_set:Nn \l_regex_internal_a_int
        {
          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_internal_a_int = \c_zero
      \else:
        \msg_kernel_error:nnx { regex } { replace-unbalanced }
          { \l_regex_internal_a_int }
      \fi:
      \tl_set:Nx \l_regex_internal_a_tl
        {
          \if_num:w \l_regex_internal_a_int < \c_zero
            \prg_replicate:nn { - \l_regex_internal_a_int }
              { \exp_not:n { { \if_false: } \fi: } }
          \fi:
          \prg_stepwise_function:nnnN
            \l_regex_max_state_int
            \l_regex_capturing_group_int
            { \l_regex_submatch_int - \c_one }
            \regex_replace_all_aux:n
          \regex_toks_range:nn
            \l_regex_start_index_int \l_regex_max_index_int
          \if_num:w \l_regex_internal_a_int > \c_zero
            \prg_replicate:nn { \l_regex_internal_a_int }
              { \exp_not:n { \if_false: { \fi: } } }
          \fi:
        }
      \tl_set:Nx \l_regex_internal_a_tl { \l_regex_internal_a_tl }
    \exp_args:NNNo \group_end:
    \tl_set:Nn #4 \l_regex_internal_a_tl
  }
\cs_new:Npn \regex_replace_all_aux:n #1
  {
    \regex_toks_range:nn
      { \etex_glueshrink:D \tex_skip:D #1 } { \tex_skip:D #1 }
    \regex_replacement_tl:n {#1}
  }
\msg_kernel_new:nnnn { regex } { trailing-backslash }
  { Trailing~escape~character~\iow_char:N\\. }
  {
    A~regular~expression~or~its~replacement~text~ends~with~
    the~escape~character~\iow_char:N\\.~It~will~be~ignored.
  }
\msg_kernel_new:nnnn { regex } { x-missing-rbrace }
  { Missing~closing~brace~in~\iow_char:N\\x~hexadecimal~sequence. }
  {
    You~wrote~something~like~
    `\iow_char:N\\x\{\int_to_hexadecimal:n{#1}'.~
    The~closing~brace~is~missing.
  }
\msg_kernel_new:nnnn { regex } { x-overflow }
  { Character~code~'#1'~too~large~in~\iow_char:N\\x~hexadecimal~sequence. }
  {
    You~wrote~something~like~
    `\iow_char:N\\x\{\int_to_hexadecimal:n{#1}\}'.~
    The~character~code~'#1'~is~larger~than~\int_use:N \c_max_char_int.
  }
\msg_kernel_new:nnnn { regex } { missing-rbrack }
  { Missing~right~bracket~inserted~in~regular~expression. }
  {
    LaTeX~was~given~a~regular~expression~where~a~character~class~
    was~started~with~'[',~but~the~matching~']'~is~missing.
  }
\msg_kernel_new:nnnn { regex } { missing-rparen }
  {
    Missing~right~parenthes\int_compare:nTF{#1=1}{i}{e}s~
    inserted~in~regular~expression.
  }
  {
    LaTeX~was~given~a~regular~expression~with~\int_eval:n{#1}~
    more~left~parenthes\int_compare:nTF{#1=1}{i}{e}s~than~right~
    parenthes\int_compare:nTF{#1=1}{i}{e}s.
  }
\msg_kernel_new:nnnn { regex } { extra-rparen }
  { Extra~right~parenthesis~ignored~in~regular~expression. }
  {
    LaTeX~came~across~a~closing~parenthesis~when~no~submatch~group~
    was~open.~The~parenthesis~will~be~ignored.
  }
\msg_kernel_new:nnnn { regex } { class-bad-escape }
  { Invalid~escape~\c_backslash_str #1~in~character~class. }
  {
    The~escape~sequence~\iow_char:N\\#1~may~not~appear~within~
    a~character~class.~For~instance,~assertions~(which~match~zero~
    characters)~would~not~make~sense~there.
  }
\msg_kernel_new:nnnn { regex } { catcode-bad-escape }
  { Invalid~escape~\c_backslash_str #1~following~category~test. }
  {
    The~escape~sequence~\iow_char:N\\#1~may~not~appear~following~
    a~category~test~such~as~\iow_char:N\\cL~or~
    \iow_char:N\\c[\iow_char:N\^BE].
  }
\msg_kernel_new:nnnn { regex } { range-missing-end }
  { Invalid~end-point~for~range~'#1-#2'~in~character~class. }
  {
    The~end-point~'#2'~of~the~range~'#1-#2'~may~not~serve~as~an~
    end-point~for~a~range:~alphanumeric~characters~should~not~be~
    escaped,~and~non-alphanumeric~characters~should~be~escaped.
  }
\msg_kernel_new:nnnn { regex } { range-backwards }
  { Range~[#1-#2]~out~of~order~in~character~class. }
  {
    In~ranges~of~characters~[x-y]~appearing~in~character~classes,~
    the~first~character~code~must~not~be~larger~than~the~second.~
    Here,~#1~has~character~code~\int_eval:n {`#1},~while~#2~has~
    character~code~\int_eval:n {`#2}.
  }
\msg_kernel_new:nnnn { regex } { c-bad-mode }
  { Invalid~nested~\iow_char:N\\c~escape~in~regular~expression. }
  {
    The~\iow_char:N\\c~escape~cannot~be~used~within~
    a~control~sequence~test~'\iow_char:N\\c{...}'.~
    To~combine~several~category~tests,~use~'\iow_char:N\\c[...]'.
  }
\msg_kernel_new:nnnn { regex } { c-missing-rbrace }
  { Missing~right~brace~inserted~for~\iow_char:N\\c~escape. }
  {
    LaTeX~was~given~a~regular~expression~where~a~
    '\iow_char:N\\c\iow_char:N\{...'~construction~was~not~ended~
    with~a~closing~brace~'\iow_char:N\}'.
  }
\msg_kernel_new:nnnn { regex } { c-missing-rbrack }
  { Missing~right~bracket~inserted~for~\iow_char:N\\c~escape. }
  {
    A~construction~'\iow_char:N\\c[...'~appears~in~a~
    regular~expression,~but~the~closing~']'~is~not~present.
  }
\msg_kernel_new:nnnn { regex } { c-missing-category }
  { Invalid~character~'#1'~following~\iow_char\\c~escape. }
  {
    In~regular~expressions,~the~\iow_char:N\\c~escape~sequence~
    may~only~be~followed~by~a~left~brace,~a~left~bracket,~or~a~
    capital~letter~representing~a~character~category,~namely~
    one~of~ABCDELMOPSTU.
  }
\msg_kernel_new:nnnn { regex } { u-missing-lbrace }
  { Missing~left~brace~following~\iow_char:N\\u~escape. }
  {
    The~\iow_char:N\\u~escape~sequence~must~be~followed~by~
    a~brace~group~with~the~name~of~the~variable~to~use.
  }
\msg_kernel_new:nnnn { regex } { u-missing-rbrace }
  { Missing~right~brace~inserted~for~\iow_char:N\\u~escape. }
  {
    LaTeX~
    \tl_if_empty:xTF {#2}
      { reached~the~end~of~the~string~ }
      { encountered~an~escaped~alphanumeric~character '\iow_char:N\\#2'~ }
    when~parsing~the~argument~of~an~'\iow_char:N\\u\iow_char:N\{...\}'~escape.
  }
\msg_kernel_new:nnnn { regex } { sequence-unbalanced }
  {
    Missing~
    \flag_if_raised:nTF { regex_end }
      {
        left~
        \flag_if_raised:nTF { regex_begin }
          { and~right~braces } { brace }
      }
      { right~brace }
    \ inserted~in~extracted~match.
  }
  {
    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}
      {
        { -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 } { 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:nnn { regex } { nfa-misused }
  { Automaton~#1 used~incorrectly. }
\msg_kernel_new:nnnn { regex } { c-command }
  { Misused~\iow_char:N\\c~or\iow_char:N\\C~command~in~a~#1. }
  {
    In~a~#1,~the~\iow_char:N\\C~escape~sequence~
    can~be~followed~by~one~of~the~letters~ABCDELMOPSTU~
    or~a~brace~group,~not~by~'#2'.
  }
\msg_kernel_new:nnnn { regex } { unknown-option }
  { Unknown~option~`#1'~for~regular~expressions. }
  {
    LaTeX~came~across~something~like~`(?#1)'~in~a~regular~expression,~
    but~the~option~`#1'~is~not~known.~It~will~be~ignored.
  }
\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 } { g-command }
  { 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.
  }
%% 
%%
%% End of file `l3regex.sty'.
