LaTeX3 按顺序扩展标记列表

LaTeX3 按顺序扩展标记列表

我刚刚开始学习 expl3 编程,并尝试创建一个用于绘制 TikZ/PGF 图类型的解析器。基本上我想要

\begin{pck}
    plot node1 .3 .3;
    plot node2 .7 .7;
\end{pck}

扩展到

\begin{tikzpicture}
    \begin{axis}[xmin=0, xmax=1,
                 ymin=0, ymax=1]
        \node (node1) at (axis cs:.3, .3) [circle, draw] {};
        \node (node1) at (axis cs:.7, .7) [circle, draw] {};
    \end{axis}
\end{tikzpicture}

文本在环境中必须先完全解析,然后将其扩展为 TikZ 代码,因为我想对一些参数进行一些处理。

到目前为止我有以下代码。

\documentclass{article}

\usepackage[check-declarations]{expl3}
\usepackage{environ}
\usepackage{pgfplots}
\pgfplotsset{compat=1.15}

\ExplSyntaxOn

\tl_new:N \pck_objects_tl

\seq_new:N \pck_labels
\seq_new:N \pck_xs
\seq_new:N \pck_ys
\seq_new:N \pck_edgs_left
\seq_new:N \pck_edgs_right

\tl_new:N \pck_label
\tl_new:N \pck_x
\tl_new:N \pck_y
\tl_new:N \pck_edg_left
\tl_new:N \pck_edg_right

\cs_new:Npn \pck_draw {
    \bool_do_until:nn {\seq_if_empty_p:N \pck_labels} {
        \seq_pop_left:NN \pck_labels \pck_label
        \seq_pop_left:NN \pck_xs \pck_x
        \seq_pop_left:NN \pck_ys \pck_y 

        \node~(\pck_label)~at~(axis~cs\c_colon_str~\pck_x,~\pck_y)~[circle, draw]~\bgroup \egroup ; \par
    }
}

\NewEnviron{pck}[1][] {
    \pck_parse:V \BODY

    \begin{tikzpicture}
        \begin{axis}[xmin=0, xmax=1,
                     ymin=0, ymax=1]
            \pck_draw
        \end{axis}
    \end{tikzpicture}\par
}

\cs_new_protected:Npn \pck_parse:n #1{
    \tl_set:Nn \pck_objects_tl{#1}
    \tl_remove_all:Nn \pck_objects_tl{\par}
    \tl_replace_all:Nnn \pck_objects_tl{plot~}{\pck_parse_plot:w}
    \tl_use:N \pck_objects_tl 
}

\cs_generate_variant:Nn \pck_parse:n {V}

\cs_new_protected:Npn \pck_parse_plot:w #1 ~ #2 ~ #3 ; {
    \seq_put_right:Nn \pck_labels {#1}
    \seq_put_right:Nn \pck_xs {#2}
    \seq_put_right:Nn \pck_ys {#3}
}

\ExplSyntaxOff

\begin{document}
    \begin{pck}
        plot node1 .3 .3;
        plot node2 .7 .7;
    \end{pck}
\end{document}

但是,此代码将所有节点都绘制在彼此之上。我相信这是因为当序列(例如\pck_labels)弹出到标记列表时\pck_label,标记列表不会立即扩展为node1node2,但扩展发生在最后,因此全部扩展为node2等。我真的无法弄清楚如何以正确的方式扩展标记,我尝试使用和规格生成变体fx使用\exp_after\use。有什么建议吗?

此外,由于我对 expl3 完全陌生,我很高兴收到有关代码的任何反馈!

答案1

此代码将解决您的问题。我不会使用多个序列。通过进行一些 x 类型扩展,它将绘制您的点。请注意,您应该在 l3 名称中添加包含数据类型的后缀。

阴谋

\documentclass{article}

\usepackage[check-declarations]{expl3}
\usepackage{environ}
\usepackage{pgfplots}
\pgfplotsset{compat=1.15}

\ExplSyntaxOn

\tl_new:N \pck_objects_tl
\seq_new:N \pck_plot_seq

\cs_new:Npn \pck_node:nnn #1#2#3 {
    \node~(#1)~at~(axis~cs\c_colon_str#2,#3)~[circle, draw] { };
}
\cs_generate_variant:Nn \pck_node:nnn {xxx}


\cs_new:Npn \pck_draw {
    \seq_map_inline:Nn \pck_plot_seq
        {
            \clist_set:Nn \l_tmpa_clist { ##1 }
            \pck_node:xxx { \clist_item:Nn \l_tmpa_clist { 1 } }
                { \clist_item:Nn \l_tmpa_clist { 2 } }
                { \clist_item:Nn \l_tmpa_clist { 3 } }
        }
}

\NewEnviron{pck}[1][] {
    \pck_parse:V \BODY
    \begin{tikzpicture}
        \begin{axis}[xmin=0, xmax=1,
                     ymin=0, ymax=1]
            \pck_draw
        \end{axis}
    \end{tikzpicture}\par
}

\cs_new_protected:Npn \pck_parse:n #1{
    \tl_set:Nn \pck_objects_tl{#1}
    \tl_remove_all:Nn \pck_objects_tl{\par}
    \tl_replace_all:Nnn \pck_objects_tl{plot~}{\pck_parse_plot:w}
    \tl_use:N \pck_objects_tl 
}

\cs_generate_variant:Nn \pck_parse:n { V }

\cs_new_protected:Npn \pck_parse_plot:w #1 ~ #2 ~ #3 ; {
    \seq_put_right:Nn \pck_plot_seq {#1,#2,#3}
}

\ExplSyntaxOff

\begin{document}
    \begin{pck}
        plot node1 .3 .3;
        plot node2 .7 .7;
        plot node3 .5 .5;
    \end{pck}
\end{document}

相关内容