現在のカウンター値をスタックデータ構造に渡す

現在のカウンター値をスタックデータ構造に渡す

スタック データ構造と\newcounter{}定義を組み合わせて、テキスト全体に散在するポイントのコレクションを自動的にペアにできるようにしたいと考えています。

\openbracket各ポイントはまたはとしてマークされ\closebracket、反対に定義されたポイントと自動的にペアになって\openbracket-\closebracketペアを形成します。閉じたペアは他の閉じた括弧のペア内にネストすることができ、開いた/閉じたポイントの各ペアはそれぞれ tikz ノードと でマークされます\node(openX) {};[\node(closeX) {};ここで、X は外部カウンターによって定義された整数です]。

例えば:

\openbraket First tier
    \openbraket Second tier A
        \openbraket Third tier
        \closebracket 
    \closebracket 
    \openbracket Second tier B
    \closebracket 
\closebracket 

上記のポイントは、自動的に 4 つの閉じた括弧のペアにペアリングされます\openbracket \closebracket。1 つの第 1 層の括弧には 2 つの第 2 層の括弧が含まれ、最初の括弧 (A) には 1 つの第 3 層の括弧が含まれます。私の MWE は、スタック構造からデータもポップして、上記の例の tikz ノードが次のように定義されるようにする必要があります。

(open0) First tier (open1) Second tier A (open2) Third tier 
(close2) (close1) (open3)  Second tier B (close3) (close0)

の助けを借りてプッシュ/ポップ、または長さ/寸法を保存しますか?コマンドでカウンターの現在の値を保存する、 そしてスタックデータをtikzノード名に渡す、私は機能するスタック データ構造を定義し、スタック データをマクロに正しく渡す方法を見つけました\tikzmark

ただし、以下の MWE は、 の現在の値を に明示的にプッシュせずbracketpairingcounterbracketpairingstack必要な整数ではなく、コマンド文字列をそのままプッシュします。したがって、各\node(closeX) {};tikz マークがデータ スタックからポップされると、各ノード番号は、スタックに順番にプッシュされる異なる整数ではなく、 の最後の値で評価されますbracketpairingcounter

番号付けの問題を解決するには、LaTeX コードに以下の値を直ちに評価させるように強制する必要がありますが、この場合は\openbracketnameどうしても実行できません\expandafter...\edef{}

ムウェ

\documentclass[openany]{article}
\usepackage{tikz}

%Define stack data structure commands (\push, \pop, \splitstack)
\newtoks\braketpairingstack
\braketpairingstack={\empty}

    \def\push#1#2{%
        \def\tmp{{#1}}% 
        \expandafter\expandafter\expandafter%
        #2\expandafter\expandafter\expandafter{\expandafter\tmp\the#2}%
    \ignorespaces}

    \def\pop#1#2{%
        \expandafter\splitstack\the#1\stop{#1}{#2}%
    }

    \def\splitstack#1#2\stop#3#4{% 
        \def\tmp{#1}
        \ifx\tmp\empty 
        \else
            \def#4{#1}\global#3={#2}%
        \fi
    } 

%Define \tikzmark command
\def\tikzmark#1{%
    \tikz[remember picture, overlay]\node[red](#1) {#1};%
}

%Define bracket pair counting commands (\openbracket, \closebracket)
\newcounter{bracketpairingcounter}

    \newcommand{\openbraket}{%
        \expandafter\edef\csname openbracketname\endcsname{\thebracketpairingcounter}%
        \push{\openbracketname}{\braketpairingstack}%
        \tikzmark{open\openbracketname}%
        \stepcounter{bracketpairingcounter}%
    }

    \newcommand{\closebraket}{%
        \pop{\braketpairingstack}{\closebracketname}%
        \tikzmark{close\closebracketname}%
    }

%Begin MWE document
\begin{document}
    \openbraket Open first bracket.\\ %Correctly marked as open0
    \openbraket Open second bracket.\\ %Correctly marked as open1

    Close second bracket. \closebraket\\ %Correctly marked as close1 
    Close first bracket. \closebraket\\ %Incorrectly marked as close1
\end{document}

答え1

を実行したいのです\edef\temp{{#1}}が、 の定義\pushやコードの他の部分も簡略化できます。

\documentclass[openany]{article}
\usepackage{tikz}

%Define stack data structure commands (\push, \pop, \splitstack)
\newtoks\braketpairingstack
\braketpairingstack={\empty}

\def\push#1#2{%
  \edef\tmp{{#1}\the#2}%
  #2=\expandafter{\tmp}%
}

\def\pop#1#2{%
  \expandafter\splitstack\the#1\stop{#1}{#2}%
}

\def\splitstack#1#2\stop#3#4{% 
  \def\tmp{#1}%
  \ifx\tmp\empty
  \else
    \def#4{#1}\global#3={#2}%
  \fi
} 

%Define \tikzmark command
\def\tikzmark#1{%
  \tikz[remember picture, overlay]\node[red](#1) {#1};%
}

%Define bracket pair counting commands (\openbracket, \closebracket)
\newcounter{bracketpairingcounter}

\newcommand{\openbraket}{%
   \edef\openbracketname{\thebracketpairingcounter}%
   \push{\openbracketname}{\braketpairingstack}%
   \tikzmark{open\openbracketname}%
   \stepcounter{bracketpairingcounter}%
}

\newcommand{\closebraket}{%
  \pop{\braketpairingstack}{\closebracketname}%
  \tikzmark{close\closebracketname}%
}

%Begin MWE document
\begin{document}

\openbraket Open first bracket. %Correctly marked as open0

\openbraket Open second bracket. %Correctly marked as open1

Close second bracket. \closebraket %Correctly marked as close1 

Close first bracket. \closebraket %Correctly marked as close0
\end{document}

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

では、\edef\tmp{{#1}\the#2}が完全に拡張され#1、トークン レジスタ #2 の拡張されていない内容が追加されます。これは、 がレジスタの内容の配信を行った\the\tokenregister後は拡張が続かないためです。次に、を の拡張 (1 レベルのみ) を含むように\the設定します。#2\tmp

\ignorespacesの呼び出しで\pushが見つかることから、は不要であることに注意してください\tikzmark。実際には、 は予期しない展開を引き起こす可能性があります (この場合はそうではありません)。

関連情報