upLaTeX で l3regex の 16 進コードによるマッチができない

Re: upLaTeX で l3regex の 16 進コードによるマッチができない

- wryz77 の投稿
返信数: 1

同様のケースに遭遇したので,私の理解の範囲で調べてみました。結論としてはやはり,ユーザー側で対応できる範疇ではなさそうですが・・・

以下,expl3-code.tex の中身を見ていきます。まず,該当のメッセージは次のように定義されています。

\msg_new:nnn { regex } { x-overflow }
  {
    Character~code~##1~too~large~in~
    \iow_char:N\\x\iow_char:N\{##2\iow_char:N\}~regex.
  }

このエラーが呼び出されるのは,\__regex_escape_x_end:w という関数の内部です。

\cs_new:Npn \__regex_escape_x_end:w #1 ;
  {
    \int_compare:nNnTF {#1} > \c_max_char_int
      {
        \msg_expandable_error:nnff { regex } { x-overflow }
          {#1} { \int_to_Hex:n {#1} }
      }
      {
        \exp_last_unbraced:Nf \__regex_escape_raw:N
          { \char_generate:nn {#1} { 12 } }
      }
  }

この関数の中に\c_max_char_int という整数値がありますが,その定義は「LuaTeX/XeTeX の場合は "10FFFF,そうでない場合は "FF」というものです。よって,upTeX では文字コードが "FF より大きい文字に対して関数 \__regex_escape_x_end:w はエラーを返すことになります。

では,expl3 のコードを修正し,\c_max_char_int の定義を upTeX に対応するように変更すればよいのかというと,そうでもありません。

\__regex_escape_x_end:w の定義の中に \char_generate:nn {#1} { 12 } とありますが,これは実質的には \Ucharcat #1 12 ,つまり文字コード #1,カテゴリーコード 12 の文字トークンに展開される,というものです。

しかし,pTeX では \Ucharcat は欧文文字しか生成できません。また,upTeX では \Ucharcat で和文文字を生成できますが,\Ucharcat で指定できるカテゴリーコードは 16 ~ 20 に限られます。一方,\char_generate:nn では 13 以上のカテゴリーコードは指定できません。

つまり,今回のケースは最終的に,pTeX/upTeX と expl3 との間での文字トークンの扱いの齟齬,という点に行き着くと思っています。

【余談】私が今回のケースを発見したのは,TeX Live 2024 において pTeX/upTeX 上で glossaries.sty を読み込もうとしたときに同様のエラーが出たのがきっかけでした。

wryz77 への返信

Re: upLaTeX で l3regex の 16 進コードによるマッチができない

- 本田 知亮 の投稿
処理を通すために下のようにその場限りの書き換えをすると

\regex_match:nnTF
{ \x{3042}い }
{ あいうえお }
{ True }
{ False }

はTrueに,「あかいうえお」すると Falseになって
なんとなく正しく動いている雰囲気にはなります.

\__regex_escape_x_end:w の最後でカテゴリコード12決め打ちのところを
#1の範囲に応じて12以外にできれば
もしかすると突破できる?
いまのupTeXのこのあたりのkcatcodeの設定がどうなってるのか分かってないですし,
このあたりのexpl3のコードもまるで読めないので
なんで通るのかもさっぱりです(正しい?偶然?)

%----------------------------------------
\documentclass{article}

\ExplSyntaxOn

\cs_set_eq:NN \c_max_char_int \relax
\int_const:Nn \c_max_char_int {"10FFFF}%%範囲を広げる

\cs_set:Npn \__regex_escape_x_end:w #1 ;
  {
    \int_compare:nNnTF {#1} > \c_max_char_int
      {
        \msg_expandable_error:nnff { regex } { x-overflow }
          {#1} { \int_to_Hex:n {#1} }
      }
      {
% #1 には文字コードがdecimalで入ってきている
        \exp_last_unbraced:Nf \__regex_escape_raw:N
          { \char_generate:nn {#1} { 17 } } %%ここを12以外にしてみる
      }
  }

\cs_set:Npn \__char_generate_aux:w #1 ; #2 ;
  {
    \if_int_odd:w 0
        \if_int_compare:w #2 < 1  \exp_stop_f: 1 \fi:
        \if_int_compare:w #2 = 5  \exp_stop_f: 1 \fi:
        \if_int_compare:w #2 = 9  \exp_stop_f: 1 \fi:
        \if_int_compare:w #2 > 20 \exp_stop_f: 1 \fi: \exp_stop_f:%%カテゴリコードの範囲を20まで広げてみる
      \msg_expandable_error:nn { char }
        { invalid-catcode }
    \else:
      \if_int_odd:w 0
        \if_int_compare:w #1 < \c_zero_int 1 \fi:
        \if_int_compare:w #1 > \c_max_char_int 1 \fi: \exp_stop_f:
        \msg_expandable_error:nn { char }
          { out-of-range }
      \else:
        \if_int_compare:w #2#1 = 100 \exp_stop_f:
          \msg_expandable_error:nn { char } { null-space }
        \else:
          \__char_generate_aux:nnw {#1} {#2}
        \fi:
      \fi:
    \fi:
    \exp_end:
  }

\begin{document}

\regex_match:nnTF
{ \x{3042}い }
{ あいうえお }
{ True }
{ False }

\end{document}