将带有不匹配括号的 token 存储在 token 寄存器中

将带有不匹配括号的 token 存储在 token 寄存器中

首先,这个问题不是现实世界的问题,它只是为了看看使用 TeX 是否可以实现以下操作。

考虑这个简短的代码:

\begingroup
\toks0={\def\foo<}
\toks1={>}
\edef\bar{\the\toks0 foo\the\toks1}
\show\bar
\endgroup

<是否可以分别用显式括号和替换>上述代码中的{},以便\bar扩展为\def\foo{foo}

我找到了一种使用两个 s 来获得所需结果的方法\edef

\begingroup
\toks0={\noexpand\def\noexpand\foo{\iffalse}\fi}
\toks1={\iffalse{\fi}}
\edef\bar{\the\toks0 foo\the\toks1}
\expandafter\edef\expandafter\bar\expandafter{\bar}
\show\bar
\endgroup

但这要求两个寄存器中的所有标记都为第二个做好准备\edef。我对一个解决方案感兴趣(如果有的话),该解决方案可以逐字使用两个寄存器的内容。

答案1

鉴于您不能在令牌寄存器中存储不平衡的括号,也许这是一种替代方法......<在寄存器中存储一个按照您想要的语法运行的活动字符,即:\toks0={\gdef\foo<}\toks1={>}

激活时,<表现为\gdef<#1>{{#1}}

\documentclass{article}
\def\tmpA#1#2{\expandafter#1\expandafter#2}
\def\tmpB#1{\expandafter\tmpA\the\toks0 #1}
\def\usethetoks#1{\def\tmpC{\tmpB #1}%
  \expandafter\tmpC\the\toks1}
\begingroup
\catcode`<=\active
\gdef<#1>{{#1}}
\endgroup
\begin{document}
\begingroup
\catcode`<=\active

\toks0={\gdef\foo<}
\toks1={>}
\usethetoks{bar}

\toks0={\gdef\foobar<Pre-}
\toks1={-post>}
\usethetoks{baz}

\endgroup

\foo{} and \foobar

Is $<$ restored? \ifnum1<2\relax True\else False\fi
\end{document}

在此处输入图片描述

答案2

您不能将不平衡的标记列表存储在定义文本中,也不能存储在标记列表寄存器中。

您可以使用特殊令牌来伪造它,在这里\BGROUP\EGROUP在最后进行替换。

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\splitdefbegin}{mO{0}}
 {
  \siracusa_splitdef_begin:nn { #1 } { #2 }
 }
\NewDocumentCommand{\splitdefadd}{m}
 {
  \siracusa_splitdef_add:n { #1 }
 }
\NewDocumentCommand{\splitdefend}{ }
 {
  \siracusa_splitdef_end:
 }

\tl_new:N \l__siracusa_splitdef_name_tl
\int_new:N \l__siracusa_splitdef_args_int
\prg_generate_conditional_variant:Nnn \regex_match:nn { nV } { T,F,TF }
\cs_generate_variant:Nn \cs_set:Nn { cV }

\cs_new_protected:Nn \siracusa_splitdef_begin:nn
 {
  \tl_set:Nn \l__siracusa_splitdef_name_tl { #1 }
  \int_set:Nn \l__siracusa_splitdef_args_int { #2 }
  \tl_build_begin:N \l__siracusa_splitdef_body_tl
 }
\cs_new_protected:Nn \siracusa_splitdef_add:n
 {
  \tl_build_put_right:Nn \l__siracusa_splitdef_body_tl { #1 }
 }
\cs_new_protected:Nn \siracusa_splitdef_end:
 {
  \tl_build_end:N \l__siracusa_splitdef_body_tl
  \__siracusa_splitdef_normalize:
  \cs_set:cV
   { __siracusa_splitdef_temp:\prg_replicate:nn { \l__siracusa_splitdef_args_int } { n } }
   \l__siracusa_splitdef_body_tl
  \cs_set_eq:cc
   { \l__siracusa_splitdef_name_tl }
   { __siracusa_splitdef_temp:\prg_replicate:nn { \l__siracusa_splitdef_args_int } { n } }
 }

\cs_new_protected:Nn \__siracusa_splitdef_normalize:
 {
  % recursively replace \BGROUP...\EGROUP with {...}
  \regex_match:nVT { \c{BGROUP} } \l__siracusa_splitdef_body_tl
   {
    \regex_replace_all:nnN
     { \c{BGROUP}(.*)\c{EGROUP} }  % search
     { \cB\{ \1 \cE\} }            % replace
     \l__siracusa_splitdef_body_tl % in
    \__siracusa_splitdef_normalize:
   }
 }

\ExplSyntaxOff

\splitdefbegin{foo}[2]

\splitdefadd{x\fbox\BGROUP#1}
\splitdefadd{y\fbox\BGROUP{#2}z\EGROUP}
\splitdefadd{!\EGROUP}

\splitdefend

\begin{document}

\texttt{\meaning\foo}

\foo{A}{B}

\end{document}

在此处输入图片描述

相关内容