
Можно ли проверить, является ли токен разделителем, т. е (
. , )
, |
, , \vert
, \langle
, \rangle
и т. д., не проверяя каждый из них напрямую в условии?
Структура разделителя хорошо описана здесь:https://tex.stackexchange.com/a/296650/213149. Кажется, он использует \delimiter
команду
Поэтому мой вопрос заключается в том, как я могу обнаружить такой разделитель достаточно универсальным способом, используя либо чистый TeX, либо LaTeX3.
Например, я хочу создать пользовательский макрос \isDelimiter{...}
для печати true
в false
документе, если его аргумент является разделителем или нет соответственно.
решение1
Я не уверен, что это может быть полезно для вашей \veca
проблемы. В любом случае…
\documentclass{article}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\isDelimiterTF}{mmm}
{
\antshar_isdel:Nnn #1 { #2 } { #3 }
}
% first check whether #1 is a control sequence
\cs_new:Nn \antshar_isdel:Nnn
{
\token_if_cs:NTF #1
{
\__antshar_isdel_cs:Nnn #1 { #2 } { #3 }
}
{
\__antshar_isdel_char:Nnn #1 { #2 } { #3 }
}
}
% it is a control sequence; first check the two exceptional cases \{ and \}
% which return true; otherwise go on: if the token is not expandable return false
\cs_new:Nn \__antshar_isdel_cs:Nnn
{
\str_case:nnF { #1 }
{
{\{}{#2}
{\}}{#2}
}
{
\token_if_expandable:NTF #1
{
\__antshar_isdel_csexp:Nnn #1 { #2 } { #3 }
}
{
#3
}
}
}
% the token is expandable, access its expansion
\cs_new:Nn \__antshar_isdel_csexp:Nnn
{
\__antshar_isdel_exp:onn { #1 } { #2 } { #3 }
}
% if the expansion begins with \delimiter return true, otherwise false
\cs_new:Nn \__antshar_isdel_exp:nnn
{
\__antshar_isdel_exp_aux:w #1 \q_nil \q_stop { #2 } { #3 }
}
\cs_generate_variant:Nn \__antshar_isdel_exp:nnn { o }
\cs_new:Npn \__antshar_isdel_exp_aux:w #1 #2 \q_stop #3 #4
{
\token_if_eq_meaning:NNTF #1 \delimiter { #3 } { #4 }
}
% when the token is a character, look at its \delcode;
% if positive return true, otherwise false
\cs_new:Nn \__antshar_isdel_char:Nnn
{
\int_compare:nTF { \delcode`#1 > 0 } { #2 } { #3 }
}
\ExplSyntaxOff
\begin{document}
\verb|a|: \isDelimiterTF{a}{T}{F}
\verb|(|: \isDelimiterTF{(}{T}{F}
\verb|]|: \isDelimiterTF{]}{T}{F}
\verb|\langle|: \isDelimiterTF{\langle}{T}{F}
\verb-\|-: \isDelimiterTF{\|}{T}{F}
\verb|\{|: \isDelimiterTF{\{}{T}{F}
\verb|\lbrace|: \isDelimiterTF{\lbrace}{T}{F}
\verb|\mbox|: \isDelimiterTF{\mbox}{T}{F}
\end{document}
Как распознать, когда управляющая последовательность является разделителем? Ее первый уровень расширения должен начинаться с \delimiter
или, если это символ, он \delcode
должен быть положительным.
Поэтому проверка на символ очевидна. Для управляющей последовательности нам нужно сначала посмотреть, является ли она расширяемой или нет. Но также нам нужно позаботиться о \{
и \}
, которые являются несколько особенными, поэтому эти случаи решаются сами собой.
Если последовательность управления, которую мы проверяем, не расширяема, она не является разделителем (возможно, есть и другие исключения, такие как \{
и \}
должны быть добавлены с некоторыми пакетами шрифтов). Если она расширяема, мы смотрим на ее расширение первого уровня, вызывая
\__antshar_isdel_exp:onn { #1 } { #2 } { #3 }
поэтому o
тип аргумента выполнит требуемое одноуровневое расширение. Это станет
\__antshar_isdel_exp_aux:w #1 \q_nil \q_stop { #2 } { #3 }
Определение \__antshar_isdel_exp_aux:w
есть
\cs_new:Npn \__antshar_isdel_exp_aux:w #1 #2 \q_stop #3 #4
{
\token_if_eq_meaning:NNTF #1 \delimiter { #3 } { #4 }
}
поэтому первый токен в расширении последовательности управления, которую мы рассматриваем, становится , #1
а остальные до \q_nil
становятся #2
. Остальные, то есть #3
и #4
являются истинным и ложным текстом для \isDelimiterTF
. Первый аргумент не имеет разделителей, поэтому он примет первый токен во входном потоке в качестве своего аргумента; второй аргумент заканчивается, когда TeX находит \q_stop
.
Странно \q_nil
, потому что если вы попробуете, \isDelimiter{\empty}{T}{F}
то в расширении ничего не будет; в этом случае \q_nil
берется как #1
и #2
пусто. Но, поскольку \q_nil
не является \delimiter
, все проходит.