![再帰的な文字列解析](https://rvso.com/image/305748/%E5%86%8D%E5%B8%B0%E7%9A%84%E3%81%AA%E6%96%87%E5%AD%97%E5%88%97%E8%A7%A3%E6%9E%90.png)
私は、頻繁に使用される一連のコマンドの短縮形を、より長い形式に変換する再帰ストリーム プロセッサを LaTeX で作成することに取り組んでいます。以下のコードは、xstring ではマクロをネストできないことに気付く前に、私が行っていた処理を表しています。
このプログラムは、次のことを実行することになっています。
- 入力の長さが 0 かどうかを確認します。
- それ以外の場合は、最初のセットにコマンドがあるかどうかを確認します(現在は rotate のみ)
- それ以外の場合は、2番目のセット(flipがある)にコマンドがあるかどうかを確認します。
- それ以外の場合は、シンボルを返すだけです
シンボルが見つかった場合は、入力ストリーム内の残りの文字をネストして再帰的に呼び出します。それ以外の場合は、現在の文字に再帰呼び出しを追加するだけです。
プログラムの再帰的な性質を維持したいのは、入れ子になる可能性があるため、それが最も論理的な意味を持つからです。
\newcommand{\processSymbol}[1]{
\IfEq{0}{\StrLen{#1}}{}{\CheckRotate{\firstChar{#1}}{\restChars{#1}}}
}
\newcommand{\AECheckRotate}[2]{
\begin{switch}{#1}
\case{c}{\AEccwRotate{\processSymbol{#2}}}
\AECheckFlip{#1}{#2}
\end{switch}
}
\newcommand{\AECheckFlip}[2]{
\begin{switch}
\case{v}{\flipv{\processSymbol{#2}}}
#1\processSymbol{#2}
\end{switch}
}
コマンド セットは任意ですが、私が書いたサンプル コードのサンプル入力は次のようになります。
vccb
完全なコードでは、次のような結果が返されるはずです。
P
なぜなら、文字 b が回転し、回転して、垂直に反転するからです。
私はこのようにネストされた文字列解析を行う別の方法を見つけようとしています。そして、xstrings ではそれができないような気がします。LuaTex に切り替える必要があるなら、そうしましょう。Lua を学ぶ前に、これを LaTeX で実行しようとしています。
答え1
ここでは、水平反転、垂直反転、時計回り回転のマクロを定義します。まず、これらを としてネストする方法を示します。次に、マクロを使用してショートカットを取得し、同じことを再帰的に実行する方法を\myvreflect{\myrotate{\myrotate{b}}}
示します。\mytransform
vccb
(私の MWE では、「垂直」は「垂直軸を横切って反転する」と定義されており、「水平軸を横切って垂直に反転する」とは定義されていないことに注意してください。これは、OP の命名法と一致できるようにするためです。「水平」も同様で、「水平軸を横切って反転する」という意味です。)
null 引数を処理するように編集されました。 1 文字より大きい引数を再帰的に操作する方法を示すように再編集されました。
\documentclass{article}
\usepackage{graphicx}
\def\myhreflect#1{\scalebox{1}[-1]{#1}}
\def\myvreflect#1{\scalebox{-1}[1]{#1}}
\def\myrotate#1{\rotatebox{90}{#1}}
\newcommand\mytransform[1]{\mytransformhelp#1\relax\relax}
\def\mytransformhelp#1#2\relax{%
\if\relax#2\relax#1\else%
\if v#1\myvreflect{\mytransformhelp#2\relax}\else%
\if h#1\myhreflect{\mytransformhelp#2\relax}\else%
\if c#1\myrotate{\mytransformhelp#2\relax}%
\fi%
\fi%
\fi%
\fi%
}
\begin{document}
b \myvreflect{\myrotate{\myrotate{b}}}
\mytransform{vccb}\quad
\mytransform{vcb}\quad
\mytransform{hccb}\quad
\mytransform{hcb}
\def\x{test}
\mytransform{vcc\x}
\end{document}
答え2
以下は xstring を使用したメソッドです。
\documentclass{article}
\usepackage{xstring,graphicx}
\def\nestcommand#1#2{%
\ifx#1\relax \StrSubstitute#1\relax{#2\relax}[#1]%
\else \StrSubstitute#1\relax{#2{\relax}}[#1]%
\fi
}
\def\processSymbol#1{%
\def\processcommand{\relax}%
\edef\tempcommandset{,\unexpanded\expandafter{\commandcharlist},}%
\def\remaining{#1}%
\saveexpandmode\expandarg\saveexploremode\exploregroups
\processSymbolRecurse
}
\def\processSymbolRecurse{%
\unless\ifx\remaining\empty
\StrSplit\remaining 1\firstchar\tempremaining
\IfSubStr\tempcommandset{\expandafter,\firstchar=}
{\let\remaining=\tempremaining
\StrBehind\tempcommandset{\expandafter,\firstchar=}[\currentcommand]%
\StrBefore\currentcommand,[\currentcommand]%
\nestcommand\processcommand\currentcommand
\expandafter\processSymbolRecurse
}
{\StrSubstitute\processcommand\relax\remaining[\processcommand]%
\restoreexpandmode\restoreexploremode
\expandafter\processcommand
}%
\fi
}
\begin{document}
\def\commandcharlist{r=\rotatebox{90},h=\scalebox{1}[-1],v=\scalebox{-1}[1],f=\fbox,b=\bfseries}%
\processSymbol{rhfy}% same as \rotate{90}{\scalebox{1}[-1]{\fbox{y}}}
\def\test{Test}
\processSymbol{fb\test} or \processSymbol{fbTest}
\def\test{b}
\processSymbol{hrr\test}
\end{document}
答え3
ここにexpl3
バージョンがあります。何を達成したいのかよくわからないので、これは単なる試みです。
解釈されるのではなく印刷されるシンボルは、二重の中括弧で囲む必要があります。
\documentclass{article}
\usepackage{xparse}
\usepackage{graphicx}
\ExplSyntaxOn
\NewDocumentCommand\processSymbol{m}
{
\fallon_process_symbol:n { #1 }
}
\tl_new:N \l__fallon_head_tl
\tl_new:N \l__fallon_tail_tl
\tl_const:Nn \c_fallon_bgroup_tl { \if_true: { \else: } \fi: }
\tl_const:Nn \c_fallon_egroup_tl { \if_false: { \else: } \fi: }
\cs_new_protected:Npn \fallon_process_symbol:n #1
{
\tl_clear:N \l__fallon_head_tl
\tl_clear:N \l__fallon_tail_tl
\tl_map_inline:nn { #1 }
{
\str_case:nnF { ##1 }
{
{v}{ \__fallon_addto_head:N \fhreflect }
{h}{ \__fallon_addto_head:N \fvreflect }
{c}{ \__fallon_addto_head:N \frotate }
}
{
\fallon_output:n { ##1 }
}
}
}
\cs_new_protected:Npn \__fallon_addto_head:N #1
{
\tl_put_right:Nn \l__fallon_head_tl { #1 \c_fallon_bgroup_tl }
\tl_put_left:Nn \l__fallon_tail_tl { \c_fallon_egroup_tl }
}
\cs_new_protected:Npn \fallon_output:n #1
{
\tl_put_right:Nn \l__fallon_head_tl { \exp_not:n { #1 } }
\tl_put_right:NV \l__fallon_head_tl \l__fallon_tail_tl
\tl_set:Nx \l__fallon_head_tl { \l__fallon_head_tl }
\tl_use:N \l__fallon_head_tl
\tl_clear:N \l__fallon_head_tl
\tl_clear:N \l__fallon_tail_tl
}
\ExplSyntaxOff
\NewDocumentCommand\fhreflect{m}{\scalebox{1}[-1]{#1}}
\NewDocumentCommand\fvreflect{m}{\scalebox{-1}[1]{#1}}
\NewDocumentCommand\frotate{m}{\rotatebox{90}{#1}}
\begin{document}
\processSymbol{vccb}\quad
\processSymbol{vcb}\quad
\processSymbol{hccb}\quad
\processSymbol{hc{{v}}}
\def\x{test}
\processSymbol{vcc\x}
\processSymbol{vccbvccy}
\end{document}
さまざまなコマンド文字は、暗黙的な開き中括弧とともにトークン リストに追加されるコマンドに変換され、一致する暗黙的な開き中括弧が別のトークン リストに追加されます。コマンド文字に含まれていないシンボルが見つかると、トークン リストが結合され、完全に展開されて配信され、プロセスが最初からやり直されます。
答え4
ローテーション以外のパッケージは必要ないと思いますが、私が誤解している可能性があります
しかし、 rotate が具体的に何をするのか指定していないと思います。(\rotatebox{90}
ここでは推測しました。)
\documentclass{article}
\usepackage{graphicx}
\def\zz#1{\zzz#1\zzz}
\def\zzz#1{%
\expandafter\ifx\csname\string#1!\endcsname\relax
#1%
\expandafter\zzz
\else
\csname\string#1!\expandafter\endcsname
\fi}
\expandafter\def\csname\string\zzz!\endcsname{}
\expandafter\def\csname c!\endcsname#1\zzz{%
\rotatebox{90}{\zz{#1}}}
\expandafter\def\csname v!\endcsname#1\zzz{%
\scalebox{1}[-1]{\zz{#1}}}
\begin{document}
\zz{vccb}
\end{document}