我正在尝试创建一个宏 \AST(或者一个环境,如果有帮助的话),它将允许我以以下方式排版抽象语法树:
\AST{A}{\AST{B}{C\逗号 D}\逗号 E\逗号 \AST{F}{G}}
应该产生输出
A(B(C,
D),
E,
F(G))
具体来说,\AST 节点应与其左侧的基线对齐(参见“A(B”),而逗号和右括号应与最后的内容的基线(参见“D)”),最后逗号和右括号应该紧靠左侧的内容(例如,E 和逗号之间没有空格,就好像它会与 D 后的逗号对齐一样)。
为了获得额外的加分,逗号不会有如果下一个内容可以容纳在一行中,则换行...但我只需使用“,”而不是 \comma 宏就可以了。
我尝试过使用 parboxes 和 minipages,并使用 [t] 和 [b] 对齐,但这会导致一侧或两侧的垂直对齐出现错误,并且无法获得正确的水平对齐。
我认为我可以使用 TikZ 来做到这一点,使用“聪明”的节点和锚点位置,但这个问题似乎只是基于文本的,而 TikZ 可能会有点矫枉过正。
我知道我可以使用具有大量“列”的 alignat* 环境来伪造它,但是 LateX 标记与我尝试排版的逻辑结构不太匹配。
那么,有没有办法构建一个(或多个)行为与上述类似的盒子?或者这与 TeX 盒子模型差别太大了?我最接近的是以下环境
\newlength{\astheight}
\newsavebox{\astbox}
\newenvironment{AST}[1]{%
\emph{#1}(\settowidth{\astheight}{\hskip 0pt plus 1 fill}\begin{lrbox}{\astbox}%
\begin{minipage}[t]{\astheight}%
}{)\end{minipage}\end{lrbox}%
\settoheight{\astheight}{\astbox}%
\fboxsep=0pt\fbox{\usebox{\astbox}}%
\addtolength{\astheight}{-\baselineskip}\vspace*{\astheight}%
}
但它产生的输出如下
A(|B(|C,
| |D,
| |E
|) |)
(其中管道是零宽度、4 行高的 fbox)这不对:)我显然误解了 \hfill 在(受限?)水平模式下的工作方式,而且我不确定我的基本前提是否可行……
答案1
我认为在这里使用方框有点过分;我认为使用段落和/或间距参数来实现你想要的效果会更容易。这是一个粗略的例子(有点作弊,因为它假设不会换行)
\documentclass{article}
\usepackage{calc}
\begin{document}
\newlength\astindent
\newcommand\AST[2]{%
\begingroup
\addtolength\astindent{\widthof{#1(}}%
#1(#2)%
\endgroup
}
\newcommand\comma{,\\\hspace*{\astindent}}
\noindent
\AST{A}{\AST{B}{C\comma D}\comma E\comma \AST{F}{G}}
\end{document}
如你所见,每次输入时\AST
,缩进空间都会在局部增加。