Команда с аргументом и несколькими результатами внутри команды (внутри команды...)

Команда с аргументом и несколькими результатами внутри команды (внутри команды...)

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

\documentclass{article}
\usepackage{xparse}
\usepackage{tikz}

\ExplSyntaxOn
\int_new:N \l_opt_number_int
\cs_new_protected:Npn \parsecommand #1#2#3#4#5 {
%\NewDocumentCommand{\parsecommand}{
%   m   % #1 expression to parse
%   m   % #2 */empty
%   m   % #3 +/-/empty
%   m   % #4 part before ! / 1
%   m   % #5 part after ! / empty
%}{
\int_zero:N \l_opt_number_int
\tl_clear:N #2
\tl_clear:N #3
\tl_clear:N #4
\tl_clear:N #5
\tl_if_in:NnTF #1 {!} {
  \tl_map_inline:Nn #1 {
    \bool_set_false:N \l_done_bool
    \tl_case:Nn ##1 {
    * {\int_compare:nT {\l_opt_number_int < 1}{
        \tl_set_eq:NN #2 ##1
        \bool_set_true:N \l_done_bool
        \int_set:Nn \l_opt_number_int {1}}}
    - {\int_compare:nT {\l_opt_number_int < 2}{
        \tl_set_eq:NN #3 ##1
        \bool_set_true:N \l_done_bool
        \int_set:Nn \l_opt_number_int {2}}}
    + {\int_compare:nT {\l_opt_number_int < 2}{
        \tl_set_eq:NN #3 ##1
        \bool_set_true:N \l_done_bool
        \int_set:Nn \l_opt_number_int {2}}}
    ! {\int_compare:nT {\l_opt_number_int < 3}{
        \bool_set_true:N \l_done_bool
        \int_set:Nn \l_opt_number_int {3}}}
      }
    \bool_if:NF \l_done_bool {
      \int_compare:nTF {\l_opt_number_int < 3}
        {\tl_put_right:Nn #4 {##1}}
        {\tl_put_right:Nn #5 {##1}}
      }
    }
  }
  {\tl_set_eq:NN #5 #1}
  \tl_if_empty:NT #4 {\tl_put_right:Nn #4 {1}}
}
\ExplSyntaxOff

\NewDocumentCommand{\othercommandone}{m}{
    \parsecommand{#1}{\a}{\b}{\c}{\d}
    \{#1\} $\rightarrow$ \{\a\}\{\b\}\{\c\}\{\d\}
}

\NewDocumentCommand{\othercommandtwo}{m}{
\def\incoming{#1}
    \parsecommand{\incoming}{\a}{\b}{\c}{\d}
    \{\incoming\} $\rightarrow$ \{\a\}\{\b\}\{\c\}\{\d\}
}

\NewDocumentCommand{\drawcommandone}{m}{
  \begin{tikzpicture}[baseline]
    \parsecommand{#1}{\douter}{\danchor}{\nthy}{\dlabel}
    \draw (-1,0) -- (1,0);
    \node at (0,\nthy*5mm) {\dlabel};
  \end{tikzpicture}
}

\NewDocumentCommand{\drawcommandtwo}{m}{
  \begin{tikzpicture}[baseline]
    \def\incoming{#1}
    \parsecommand{\incoming}{\douter}{\danchor}{\nthy}{\dlabel}
    \draw (-1,0) -- (1,0);
    \node at (0,\nthy*1cm) {\dlabel};
  \end{tikzpicture}
}

\begin{document}

\def\something{*+5!abc}
\def\somethingelse{+777}
\def\somethingmore{-!$\sqrt{\alpha}$}

Directly in the document command works\ldots

\parsecommand{\something}{\a}{\b}{\c}{\d}
\{\something\} $\rightarrow$ \{\a\}\{\b\}\{\c\}\{\d\}

\parsecommand{\somethingelse}{\a}{\b}{\c}{\d}
\{\somethingelse\} $\rightarrow$ \{\a\}\{\b\}\{\c\}\{\d\}

\parsecommand{\somethingmore}{\a}{\b}{\c}{\d}
\{\somethingmore\} $\rightarrow$ \{\a\}\{\b\}\{\c\}\{\d\}
\bigskip

If command is used directly with argument, there are no problems\ldots

\othercommandone{\something}

\othercommandone{\somethingelse}

\othercommandone{\somethingmore}
\bigskip

If command is used via intermediate macro, there are problems\ldots

\othercommandtwo{\something}

\othercommandtwo{\somethingelse}

\othercommandtwo{\somethingmore}
\bigskip

For purity of experiment, application inside \verb|tikzpicture| directly with argument, everything is fine\ldots

\drawcommandone{\something}
\hspace{1cm}
\drawcommandone{\somethingelse}
\hspace{1cm}
\drawcommandone{\somethingmore}
\bigskip

Finally, as it must be, with internal intermediate transformation (it is planned to split comma-separated values), problems arise again\ldots

\drawcommandtwo{\something}
\hspace{1cm}
\drawcommandtwo{\somethingelse}
\hspace{1cm}
\drawcommandtwo{\somethingmore}

\end{document}

При использовании команды в сложных ситуациях возникают различные ошибки, в том числе отсутствие некоторых значений анализируемого выражения. Команда используется внутри tikzpictureтретьей команды. Я хотел, чтобы она использовала, например, как результаты \pgfgettransformentries.

[02/05/2017] Пример заменен на более реалистичную ситуацию. Теперь он не работает так, как я хочу.

Скриншот

[04/05/2017] В любом случае, кое-что ускользает от моего понимания (вероятно, это неизбежно)...

\documentclass{article}
\usepackage{xparse}
\usepackage{tikz}

\ExplSyntaxOn

\NewDocumentCommand{\extractfirst}{mm}{\tl_set:Nx #1 {\clist_item:Nn #2 {1} }}

\NewDocumentCommand{\extractlast}{mm}{\tl_set:Nx #1 {\clist_item:Nn #2 {-1} }}

\int_new:N \l_opt_number_int
\cs_new_protected:Npn \parsecommand #1#2#3#4#5 {
%\NewDocumentCommand{\parsecommand}{
%   m   % #1 expression to parse
%   m   % #2 */empty
%   m   % #3 +/-/empty
%   m   % #4 part before ! / 1
%   m   % #5 part after ! / empty
%}{
\int_zero:N \l_opt_number_int
\tl_clear:N #2
\tl_clear:N #3
\tl_clear:N #4
\tl_clear:N #5
\tl_if_in:NnTF #1 {!} {
  \tl_map_inline:Nn #1 {
    \bool_set_false:N \l_done_bool
    \tl_case:Nn ##1 {
    * {\int_compare:nT {\l_opt_number_int < 1}{
        \tl_set_eq:NN #2 ##1
        \bool_set_true:N \l_done_bool
        \int_set:Nn \l_opt_number_int {1}}}
    - {\int_compare:nT {\l_opt_number_int < 2}{
        \tl_set_eq:NN #3 ##1
        \bool_set_true:N \l_done_bool
        \int_set:Nn \l_opt_number_int {2}}}
    + {\int_compare:nT {\l_opt_number_int < 2}{
        \tl_set_eq:NN #3 ##1
        \bool_set_true:N \l_done_bool
        \int_set:Nn \l_opt_number_int {2}}}
    ! {\int_compare:nT {\l_opt_number_int < 3}{
        \bool_set_true:N \l_done_bool
        \int_set:Nn \l_opt_number_int {3}}}
      }
    \bool_if:NF \l_done_bool {
      \int_compare:nTF {\l_opt_number_int < 3}
        {\tl_put_right:Nn #4 {##1}}
        {\tl_put_right:Nn #5 {##1}}
      }
    }
  }
  {\tl_set_eq:NN #5 #1}
  \tl_if_empty:NT #4 {\tl_put_right:Nn #4 {1}}
}
\ExplSyntaxOff

\NewDocumentCommand{\drawcommandone}{m}{%
\begin{tikzpicture}[baseline]
\extractfirst{\frstprt}{#1}
\extractlast{\lstprt}{#1}

\draw (-3,0) -- (-1,0);
\node [anchor=north] at (-2,0) {\frstprt};
\parsecommand{\frstprt}{\douter}{\danchor}{\nthy}{\dlabel}
\node at (-2,\nthy*4mm) {\dlabel};

\draw (1,0) -- (3,0);
\node [anchor=north] at (2,0) {\lstprt};
\parsecommand{\lstprt}{\douter}{\danchor}{\nthy}{\dlabel}
\node at (2,\nthy*4mm) {\dlabel};
\end{tikzpicture}%
}

\NewDocumentCommand{\drawcommandtwo}{m}{%
\begin{tikzpicture}[baseline]
\def\incoming{#1}%
\extractfirst{\frstprt}{\incoming}
\extractlast{\lstprt}{\incoming}

\draw (-3,0) -- (-1,0);
\node [anchor=north] at (-2,0) {\frstprt};
\expandafter\parsecommand\expandafter{\frstprt}{\douter}{\danchor}{\nthy}{\dlabel}
\node at (-2,\nthy*4mm) {\dlabel};

\draw (1,0) -- (3,0);
\node [anchor=north] at (2,0) {\lstprt};
\expandafter\parsecommand\expandafter{\lstprt}{\douter}{\danchor}{\nthy}{\dlabel}
\node at (2,\nthy*4mm) {\dlabel};
\end{tikzpicture}%
}

\begin{document}

%\def\something{*+5!first,+2!second}
%\def\something{+777,*!150}
\def\something{3!$\sqrt{\alpha}$,2!$\beta^2$}

\drawcommandone{\something}
\vspace{1cm}

\drawcommandtwo{\something}

\end{document}

Как в этом случае сделать так, чтобы результаты совпадали?

Скриншот

решение1

Как я уже сказал в своем комментарии, вам нужно расширить аргумент, прежде чем \parsecommandдействовать на его основе:

\NewDocumentCommand{\drawcommandtwo}{m}{%
  \begin{tikzpicture}[baseline]
    \def\incoming{#1}%
    \expandafter\parsecommand\expandafter{\incoming}{\douter}{\danchor}{\nthy}{\dlabel}
    \draw (-1,0) -- (1,0);
    \node at (0,\nthy*5mm) {\dlabel};
  \end{tikzpicture}%
}

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

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