创建我自己的 NSD

创建我自己的 NSD

我正在尝试为普通的 [Xe]TeX 创建一组宏,以便能够创建 Nassi-Shneidermann 图表来生成表格 ( \halign)。(我会注意到不同案例的倾斜线不同,我们可以忽略这个问题。)

要创建表格,我需要知道最终 NSD 的列数,因此我需要累积命令。但如果我累积命令,我还必须输入我在调用宏时无法知道的信息,即列数。

所以问题是,我如何制作某种容器,它可以积累标记,并且在使用参数扩展时,它会放入正确的最终结果?例如,如果我们忽略这种图表的边界,并且我想在图表中的 if-then-else 结构之前放置一个命令结构,它将\span\omit在命令的单元格中生成一对,或者使用 5 个案例结构,它将放置 4 个\span\omit宏对。


我不知道我希望它在最后阶段是什么样的,但对于一个确切的具体例子,我想要这样的东西:

\beginstruct
\command{i:=1}
\strutif i≠5
\then
j:=j-1
\else
SKIP
\strutfi
\endstruct

得到如下结果:

\halign{
&#\vrule&\hfil#\hfil\cr
\noalign{\hrule}
&i:=1\multispan2&\cr
\noalign{\hrule}
&\char`\\\hfill i≠5\hfill/\multispan2&\cr
\noalign{\hrule}
&j:=j-1&&SKIP&\cr
\noalign{\hrule}
}

但如果我只写:

\beginstruct
\command{i:=1}
\endstruct

会产生如下结果:

\halign{
&#\vrule&\hfil#\hfil\cr
\noalign{\hrule}
&i:=1&\cr
\noalign{\hrule}
}

这里的问题是,我需要知道有 2 列(不包括边框),然后才能向其中写入任何数字\multispan。在我的第一个示例中,\multispan后面i:=1有 2 作为参数,但在第二个示例之后不存在。

答案1

TeX 语言中用于水平对齐的原语\halign具有前导重复属性,可能在这里有用。\halign将内容(如果前导中没有另行说明)设置为\hboxes。以下是其使用的几个示例:

\halign{&\ThisColumnGetsRepeated{#}\cr...}

上述以“与”符号 ( &) 开头的序言重复了列定义 ( \ThisColumnGetsRepeated{#},IE,对每一列重复运行针对给定输入调用的宏\ThisColumnGetsRepeated),因此您可以给它(通过替换上面的点)无限数量的列:

foo& bar& baz& foo& bar& baz& ... \cr

但是,如果你想要对第一列(比如说)进行一些特殊处理,同时仍然重复其他列,该怎么办?无限地稍后再说?还有另一种形式:

\halign{\SomethingDifferentForThisColumn{#}&&\ThisColumnGetsRepeated{#}\cr ...}

之后的列定义&&重复。

一旦你爱上了的重复功能,你就会欣赏到在最后一列中\halign关闭其中的粘性的可能性。 Bruno Le Floch 在\tabskip他对上一个问题的回答


另一个问题询问如何重复调用序列\omit\span。恰巧,plain-tex 格式有一个宏,就是这个。\multispan\multispan它应该的列数作为参数\span,因此\multispan3跨越三列,而\multispan{13}跨越十三列。


为了找出要输入的数字\multispan,您可以通过两次排版表格来计算列数;第一次只计算列数,尽管我敢打赌计算输入会更容易。在这里我做了困难的方法:

\newcount\colcount
\newcount\maxcolcount
\long\def\maxcols#1{
  \global\maxcolcount=0
  \everycr={\noalign{\global\colcount=1}}
  \setbox0=\vbox{\halign{&##\ifnum\colcount>\maxcolcount
    \global\maxcolcount=\colcount\fi\global\advance\colcount by 1\cr#1\cr}}
  \the\maxcolcount}
\maxcols{&&\cr&&&\cr&&&&&&&\cr}

^输出:8

然后我尝试从我找到的图像中重现 NSD:

\newdimen\boxitspace\boxitspace=0pt
\long\def\boxit#1{\vbox{\hrule\hbox{\vrule\kern\boxitspace\vbox{%
  \kern\boxitspace\parindent0pt#1\kern\boxitspace}%
  \kern\boxitspace\vrule}\hrule}}
\offinterlineskip
\boxit{\vbox{\halign{\quad\vphantom{$\Big)$}$#$\hfil&&
  \vrule\quad\vphantom{$\Big)$}$#$\hfil\quad\cr
  a \gets 1 \cr
  \multispan3\hrulefill\cr
  b \gets 1 \cr
  \multispan3\hrulefill\cr
  do~while~a < 12 \hidewidth\cr
  \omit& \multispan2\hrulefill\cr
  \omit& b \gets a*a \cr
  \omit& \multispan2\hrulefill\cr
  \omit& output~a,b \hidewidth\cr
  \omit& \multispan2\hrulefill\cr
  \omit& if~b < 100 \cr
  \omit& \multispan2\hrulefill\cr
  \omit& T & F \cr
  \omit& \multispan2\hrulefill\cr
  \omit& a\gets a+1 & a\gets a+2 \cr}}}
\bye

它看起来像这样:
在此处输入图片描述

但将所有这些放在一个宏中有点超出我现在的可用时间。也许我以后会再回来做这件事。

TeXing 快乐!:-)

相关内容