.png)
Я пытаюсь проанализироватьСГФстрока с пакетом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}