解析函数参数和括号

解析函数参数和括号

我一直尝试让宏发挥作用,但没有成功。

我想要一个函数\graf{}接受以分号分隔的参数列表。这些参数需要传递给\xygraph具有特定语法的函数。

我正在使用xparse,它去掉了语法所需的括号,所以我做了以下事情

\NewDocumentCommand{\graf}{ >{ \SplitList{;} } m }{%
    {%
        \NewDocumentCommand{\func}{ m }{%
            !\{##1\}*+\{\thenewcounter \}="\thenewcounter"%
            \addtocounter{newcounter}{1}

            }% 

            \ProcessList{#1}{\func}%

    }%
}

的输出\graf{(0,0);(1,1)}是完美的:它被处理为

!{(0,0)}*+{0}="0"
!{(1,1)}*+{1}="1"

不幸的是,当我尝试将所有这些传递给时\xygraph,事情进展不顺利,我得到了错误"argument of \graf has an extra }"

\NewDocumentCommand{\graf}{ >{ \SplitList{;} } m }{%
{%
    \NewDocumentCommand{\func}{ m }{%
        !\{##1\}*+\{\thenewcounter \}="\thenewcounter"%
        \addtocounter{newcounter}{1}

        }% 
    \xygraph{!{<0cm,0cm>;<1cm,0cm>:<0cm,1cm>::}
        \ProcessList{#1}{\func}%
        }
}


}

我该如何解决这个问题?

PS:如果我根本不想做任何处理,它确实有效

\DeclareDocumentCommand \gra {m}{
\xygraph{%
!{<0cm,0cm>;<1cm,0cm>:<0cm,1cm>::}%
#1 }

但这违背了简化语法的目的。

编辑:

还需要为图添加一个边列表。它应该看起来像

\graf{(0,0);(1,1);(1,2)}{0-1;0-2;1-2}

应该翻译为

\xygraph{ !{<0cm,0cm>;<1cm,0cm>:<0cm,1cm>::} !{(0,0)}*+{0}="0" !{(1,1)}*+{1}="1" !{(1,2)}*+{2}="2" "0"-"1" "0"-"2" "1"-"2"}

但我还不够好,无法expl3独自做出改变。

答案1

您不应该\func在 的定义内进行定义\graf。另一方面,问题有点复杂,因为\xygraph希望看到其论点已经形成。

这是一种方法expl3

\documentclass{article}
\usepackage{xparse}
\usepackage[all,cmtip]{xy}

\ExplSyntaxOn
\NewDocumentCommand{\graf}{m}
 {
  \andy_graf_input:n { #1 }
 }

\seq_new:N \l_andy_graf_input_seq
\tl_new:N \l_andy_graf_output_tl

\cs_new_protected:Nn \andy_graf_input:n
 {
  \seq_set_split:Nnn \l_andy_graf_input_seq { ; } { #1 }
  \tl_clear:N \l_andy_graf_output_tl
  \int_step_inline:nnnn { 0 } { 1 } { \seq_count:N \l_andy_graf_input_seq - 1 }
   {
    \tl_put_right:Nx \l_andy_graf_output_tl
     {
      !{\seq_item:Nn \l_andy_graf_input_seq { ##1 + 1 }}*+{##1}="##1"
     }
   }
  \andy_graf_make:V \l_andy_graf_output_tl
 }

\cs_new_protected:Nn \andy_graf_make:n
 {% some trickery because of the colons
  \exp_args:Nx \xygraph { !{ \tl_to_str:n { <0cm,0cm>;<1cm,0cm>:<0cm,1cm>:: } \exp_not:n { #1 } } }
 }
\cs_generate_variant:Nn \andy_graf_make:n { V }
\ExplSyntaxOff

\begin{document}

With \texttt{\string\xygraph}: \xygraph{!{<0cm,0cm>;<1cm,0cm>:<0cm,1cm>::!{(0,0)}*+{0}="0"!{(1,1)}*+{1}="1"}}

With \texttt{\string\graf}: \graf{(0,0);(1,1)}

With \texttt{\string\graf}: \graf{(0,0);(1,0);(1,1)}

\end{document}

首先用分号分隔输入,然后准备所需的列表并传递给\xygraph

有一个小问题,因为后面的冒号\ExplSyntaxOn不是通常的冒号(它们被视为字母,因为它们必须是函数名称的一部分。

在此处输入图片描述

新版本的边缘规范如下:

\documentclass{article}
\usepackage{xparse}
\usepackage[all,cmtip]{xy}

\ExplSyntaxOn
\NewDocumentCommand{\graf}{mm}
 {
  \andy_graf_input:nn { #1 } { #2 }
 }

\seq_new:N \l_andy_graf_vertices_seq
\seq_new:N \l_andy_graf_edges_seq
\tl_new:N \l_andy_graf_vertices_tl
\tl_new:N \l_andy_graf_edges_tl
\tl_const:Nx \c_andy_graf_start_tl { !{ \tl_to_str:n { <0cm,0cm>;<1cm,0cm>:<0cm,1cm>:: } } }

\cs_new_protected:Nn \andy_graf_input:nn
 {
  % the vertices
  \seq_set_split:Nnn \l_andy_graf_vertices_seq { ; } { #1 }
  \tl_clear:N \l_andy_graf_vertices_tl
  \int_step_inline:nnnn { 0 } { 1 } { \seq_count:N \l_andy_graf_vertices_seq - 1 }
   {
    \tl_put_right:Nx \l_andy_graf_vertices_tl
     {~ % a space
      !{\seq_item:Nn \l_andy_graf_vertices_seq { ##1 + 1 }}*+{##1}="##1"
     }
   }
  % the edges
  \seq_set_split:Nnn \l_andy_graf_edges_seq { ; } { #2 }
  \tl_clear:N \l_andy_graf_edges_tl
  \seq_map_function:NN \l_andy_graf_edges_seq \__andy_graf_edge:n
  % make the graph
  \andy_graf_make:VVV \c_andy_graf_start_tl \l_andy_graf_vertices_tl \l_andy_graf_edges_tl
 }

\cs_new_protected:Nn \andy_graf_make:nnn
 {% some trickery because of the colons
  \xygraph
   {
    #1 % the start
    #2 % the vertices
    #3 % the edges
   }
 }
\cs_generate_variant:Nn \andy_graf_make:nnn { VVV }

\cs_new_protected:Nn \__andy_graf_edge:n
 {
  \tl_set:Nn \l__andy_graf_edge_tl { #1 }
  \regex_replace_all:nnN { ([^\-]*) - (.*) \Z } { \ "\1"-"\2" } \l__andy_graf_edge_tl
  \tl_put_right:NV \l_andy_graf_edges_tl \l__andy_graf_edge_tl
 }
\ExplSyntaxOff

\begin{document}

With \texttt{\string\xygraph}:
  \xygraph{
    !{<0cm,0cm>;<1cm,0cm>:<0cm,1cm>::}
    !{(0,0)}*+{0}="0"
    !{(1,1)}*+{1}="1"
    "0"-"1"
  }

With \texttt{\string\graf}: \graf{(0,0);(1,1)}{0-1}

With \texttt{\string\graf}: \graf{(0,0);(1,0);(1,1)}{0-1;1-2;2-0}

\end{document}

在此处输入图片描述

相关内容