遞歸字串解析

遞歸字串解析

我一直致力於用 Latex 編寫一個遞歸流處理器,它將一組常用命令的速記版本轉換為更長的形式。下面的程式碼代表了我在意識到 xstrings 不允許嵌套巨集之前所做的事情。

該程式應該執行以下操作:

  • 檢查輸入的長度是否為 0。
  • 否則它會檢查第一組中是否有任何命令(現在只有旋轉)
  • 否則它會檢查第二組中是否有任何命令(其中 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 的命名法。同樣,對於“水平” ,意思是「沿水平軸翻轉」。

已編輯以處理空參數。重新編輯以展示如何對大於單一字元的參數進行遞歸操作。

\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

我認為除了輪換之外你不需要任何軟體包,但我可能誤解了

在此輸入影像描述

但我認為您沒有具體說明旋轉應該做什麼。 (我假設\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}

相關內容