Pesquisando uma lista de palavras usando operadores booleanos

Pesquisando uma lista de palavras usando operadores booleanos

No projeto em que estou trabalhando atualmente, o usuário pode definir, dentro de um ambiente definido pelo projeto, uma lista de tags, armazenadas internamente em uma macro (por exemplo, \tags). Cada item nesta lista consiste em uma ou mais palavras e espaços e números supérfluos (por exemplo, \tagspoderia ser {foo, bar, baz qux , quux2, Corge Grault}).

Gostaria de saber como definir um \mytestcomando que teste se uma ou mais palavras fornecidas pelo usuário pertencem ou não à \tagslista e execute um código de acordo com o resultado do teste. O usuário deve ser capaz de usar operadores booleanos (e, ou, não), quaisquer espaços supérfluos devem ser eliminados e pode haver uma opção para determinar se a pesquisa deve ou não levar em consideração as maiúsculas e minúsculas.

Por exemplo, if \tags={foo, bar, baz qux , quux2, Corge Grault} e if \userinput=(foo && BAR ) || garplythen \mytest{\userinput}{\tags}{true}{false}retornaria truewhile \mytest[1]{\userinput}{\tags}{true}{false} retornaria false, assumindo que o parâmetro opcional [1]fornecido significa que a pesquisa diferencia maiúsculas de minúsculas.

Tenho a sensação de que o LaTeX3 poderia ser particularmente útil para resolver este problema, mas infelizmente não sou competente o suficiente para alcançar o resultado desejado.

Qualquer ajuda seria muito bem-vinda.

Responder1

O comando \mytesttem um opcional *para diferenciar maiúsculas de minúsculas.

Ele usa \str_map_inline:nnpara fazer um loop no segundo argumento.

Em cada item deste loop, \tl_set_rescan:Nnné executado. Então é verificado se este elemento é |, &, (ou ).

A função \__searching_if_in:começa com \tl_trim_spaces:N. Ele constrói \l__searching_boolean_expression_tl. No final, isso é interpretado por \bool_if:nTF.

insira a descrição da imagem aqui

\documentclass[border=6pt]{standalone}
\ExplSyntaxOn
\clist_new:N \l__searching_tags_clist
\tl_new:N \l__searching_accumulate_text_tl
\tl_new:N \l__searching_boolean_expression_tl
\tl_new:N \l__searching_text_item_tl
\cs_new:Npn \__searching_if_in:
  {
    \tl_trim_spaces:N \l__searching_accumulate_text_tl
    \tl_if_empty:NF \l__searching_accumulate_text_tl
      {
        \clist_if_in:NVTF \l__searching_tags_clist \l__searching_accumulate_text_tl
          { \tl_put_right:Nn \l__searching_boolean_expression_tl { \c_true_bool } }
          { \tl_put_right:Nn \l__searching_boolean_expression_tl { \c_false_bool } }
      }
    \tl_clear:N \l__searching_accumulate_text_tl
  }
\NewDocumentCommand { \mytest } { s m m m m }
  {
    \clist_set:NV \l__searching_tags_clist #3
    \tl_clear:N \l__searching_accumulate_text_tl
    \tl_clear:N \l__searching_boolean_expression_tl
    \str_map_inline:nn {#2}
      {
        \tl_set_rescan:Nnn \l__searching_text_item_tl {} {##1}
        \tl_if_in:nVTF { | & ( ) } \l__searching_text_item_tl
          {
            \__searching_if_in:
            \tl_put_right:NV \l__searching_boolean_expression_tl \l__searching_text_item_tl
          }
          {
            \IfBooleanTF {#1}
              { \tl_put_right:NV \l__searching_accumulate_text_tl \l__searching_text_item_tl }
              { \tl_put_right:Ne \l__searching_accumulate_text_tl { \text_lowercase:n { \l__searching_text_item_tl } } }
          }
      }
    \__searching_if_in:
    \bool_if:nTF { \l__searching_boolean_expression_tl } {#4} {#5}
  }
\ExplSyntaxOff
\newcommand{\tags}{foo , bar , baz qux , quux2 , Corge Grault}
\begin{document}
\mytest{(foo && BAR ) || garply}{\tags}{true}{false}
\mytest*{(foo && BAR ) || garply}{\tags}{true}{false}
\mytest{ bAr & & foO }{\tags}{true}{false}
\mytest{   baz qux   }{\tags}{true}{false}
\end{document}

informação relacionada