フラット SGF 文字列の解析 (パッケージ listofitems を使用)

フラット SGF 文字列の解析 (パッケージ listofitems を使用)

私は解析しようとしていますエスジーエフパッケージの文字列listofitemsSGF はテキスト形式のツリーですが、現在は単純化のため、単一分岐の 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

sgfBBは適切な SGF 文字列です。また、または以外のキーを無視するという追加の問題もありますW。 でこれを行う方法を知っている人がいればlistofitems、それはプラスになります。

答え1

主に興味があるのは、構文B[xy]またはW[xy](およびxy単一の文字) を持つ文字列の部分だと理解しています。したがって、以下のコードでは、他のすべてを無視します。

これはおそらく最終バージョンとは考えられませんが、おそらく次のようなもので十分でしょう。ほとんどのことは文字列の分割に関係しているので、この場合は 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}

ここに画像の説明を入力してください

関連情報