Рекурсивный анализ строк

Рекурсивный анализ строк

Я работаю над написанием рекурсивного потокового процессора в latex, который преобразует сокращенную версию набора часто используемых команд в гораздо более длинную форму. Код ниже представляет то, что я сделал до сих пор, прежде чем понял, что xstrings не позволяет вам вкладывать макросы.

Программа должна выполнять следующие действия:

  • Проверяет, имеет ли входная информация нулевую длину.
  • в противном случае он проверяет, есть ли какие-либо команды в первом наборе (сейчас там только rotate)
  • в противном случае он проверяет, есть ли какие-либо команды во втором наборе (где находится 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, то пусть будет так. просто пытаюсь сделать это в LaTeX, прежде чем мне нужно будет изучить Lua

решение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

Я не думаю, что вам нужны какие-либо пакеты, кроме как для ротации, но я мог неправильно понять, поскольку я получаю

введите описание изображения здесь

Но я не думаю, что вы указали, что именно должна делать функция 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}

Связанный контент