Анализ плоской строки SGF (с пакетом listofitems)

Анализ плоской строки SGF (с пакетом listofitems)

Я пытаюсь проанализироватьСГФстрока с пакетомlistofitems. SGF — это деревья в текстовой форме, но сейчас для простоты я работаю только с одноветвистыми SGF.

Вот пример того, что я пытаюсь сделать:

\documentclass{article}

\usepackage{listofitems}
\usepackage{tikz}

\newcommand{\parseSgf}[1]{
  % From [this answer by @StevenB.Segletes](https://tex.stackexchange.com/a/429895/64441).
  \setsepchar{;}
  \defpair{[]}
  
  \readlist\Z{#1}

  \begin{itemize}
    \foreach \i in {\Z}{
      % TODO: if key is either `B` or `W`:
      \item Color: {\i}[0] and Coords: {\i}[1]
    }
  \end{itemize}
}

\begin{document}
  \def\sgfA{;B[ab];W[cd]}
  \def\sgfB{(;GM[1]FF[4]CA[UTF-8]AP[Sabaki:0.52.2]KM[6.5]SZ[19]DT[2024-02-05];B[as];W[bs];B[cs])}

  \parseSgf{\sgfA}
  \parseSgf{\sgfB}
\end{document}

sgfAне является правильным SGF, просто простой пример. Я хотел бы, чтобы он напечатал неупорядоченный список, как это:

  • Цвет: Bи Координаты:ab
  • Цвет: Wи Координаты:cd

Но я не смог понять, как правильно использовать \setsepcharи \defpairразделять вещи, или как использовать их в \foreach.

sgfBявляется правильной строкой SGF. И есть дополнительная проблема игнорирования ключей, которые не являются Bили W. Если кто-то знает, как это сделать с listofitems, это будет плюсом.

решение1

Я понимаю, что вас в первую очередь интересуют части строки, имеющие синтаксис B[xy]или W[xy](где xи y— некоторые отдельные буквы). Поэтому приведенный ниже код игнорирует все остальное.

Это, вероятно, не следует считать окончательной версией, но, возможно, что-то вроде этого подойдет. В этом случае я использовал последовательности expl, поскольку большинство вещей связано с разделением строк (обратите внимание, что может возникнуть ошибка «отсутствует элемент», если строка не содержит подходящего синтаксиса):

\documentclass{article}

\ExplSyntaxOn
\cs_generate_variant:Nn \tl_set:Nn { Ne } % You might need to add this if the version of your TeX installation is not the most recent one 
\cs_generate_variant:Nn \seq_set_split:Nnn { Nne }
\NewDocumentCommand{\parseSgf}{ m }{
  \tl_set:Ne \l_tmpa_tl { #1 }
  % remove ( and ) from string
  \tl_remove_all:Nn \l_tmpa_tl { ( }
  \tl_remove_all:Nn \l_tmpa_tl { ) }
  % store the contents of #1 in a sequence with ; as delimiter
  \seq_set_split:Nne \l_tmpa_seq { ; } { \l_tmpa_tl }
  \begin{itemize}
    % loop over all items in sequence
    \seq_map_inline:Nn \l_tmpa_seq {
      % split string at [ and store result in another sequence
      \seq_set_split:Nne \l_tmpb_seq { [ } { ##1 }
      \bool_if:nT { 
        % test if first part of sequence is B or W
        \str_if_eq_p:ee { \seq_item:Nn \l_tmpb_seq { 1 } } { B } ||
        \str_if_eq_p:ee { \seq_item:Nn \l_tmpb_seq { 1 } } { W } 
      } {
        \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_tmpb_seq { 1 } }
        \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \l_tmpb_seq { 2 } }
        % remove ] from string
        \tl_remove_all:Nn \l_tmpb_tl { ] }
        \item Color: ~ \l_tmpa_tl {} ~ and ~ Coords: ~ \l_tmpb_tl
      } 
   }
  \end{itemize}
}
\ExplSyntaxOff

\begin{document}

  \def\sgfA{;B[ab];W[cd]}
  \def\sgfB{(;GM[1]FF[4]CA[UTF-8]AP[Sabaki:0.52.2]KM[6.5]SZ[19]DT[2024-02-05];B[as];W[bs];B[cs])}

  \parseSgf{\sgfA}
  \parseSgf{\sgfB}
  
\end{document}

введите описание изображения здесь

решение2

Вот listofitemsподход. Однако он не будет проверять наличие неправильного синтаксиса в строке SGF, например ;B[ab[;W]cd], , который будет реагировать так же, как и тестовый случай \sgfA.

\documentclass{article}
\usepackage{listofitems,tikz}
\long\def\Firstof#1#2\endFirstof{#1}
\ignoreemptyitems
\newcommand{\parseSgf}[1]{%
  \setsepchar{;/[||]}%
  \readlist*\Z{#1}%
  \begin{itemize}
    \foreachitem \i \in \Z[]{%
      \itemtomacro\Z[\icnt,1]\tmp
      % TODO: if key is either `B` or `W`:
      \expandafter\if\expandafter\Firstof\tmp\endFirstof B
        \item Color: \tmp and Coords: \Z[\icnt,2]
      \else\expandafter\if\expandafter\Firstof\tmp\endFirstof W
        \item Color: \tmp and Coords: \Z[\icnt,2]
      \fi\fi
    }%
  \end{itemize}
}
\begin{document}
  \def\sgfA{;B[ab];W[cd]}
  \def\sgfB{(;GM[1]FF[4]CA[UTF-8]AP[Sabaki:0.52.2]KM[6.5]SZ[19]DT[2024-02-05];B[as];W[bs];B[cs])}
  \parseSgf{\sgfA}\bigskip
  \parseSgf{\sgfB}
\end{document}

введите описание изображения здесь

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