Определить разделитель

Определить разделитель

Можно ли проверить, является ли токен разделителем, т. е (. , ), |, , \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, все проходит.

Связанный контент