为了教人们如何使用它forest
来绘制树木,能够展示树木本身和括号之间的关系是很有帮助的。我已经编写了一些代码来做到这一点,但我怀疑还有一种更优雅的方法可以使用它本身来做到这一点forest
。有没有更简单/更好的方法来做到这一点?
\documentclass[12pt,border=.5in]{standalone}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[linguistics]{forest}
\forestset{nice nodes/.style={for tree={inner sep=0pt,s sep=.4in}},default preamble=nice nodes}
\usepackage{xstring}
\usepackage{amsmath}
\makeatletter
% This code based on a suggestion from Alenanno
\newcommand\nd[1]{%
\noexpandarg
\IfSubStr{#1}{\\}
{\def\nodetext{\StrBefore{#1}{\\}}}
{\def\nodetext{#1}}
\leavevmode\llap{\color{red}[$_{\text{\nodetext}}$}#1}
\makeatletter
% This code due to David Carlisle
\newcommand*\dnx{\textcolor{red}{]}}
\newcommand\dn{\hbox to \z@\bgroup\let\dn\dnxx\dnxx}
\newcommand\dnxx{\dnx\@ifnextchar\dn{}{\hss\egroup}}
\makeatother
\begin{document}
\begin{forest}
[\nd{TP}
[\nd{DP} [{\nd{D\\the\dn}} ] [\nd{NP} [\nd{N\\man\dn\dn\dn} ]]]
[\nd{T’}
[\nd{T\\will\dn} ]
[\nd{VP}
[\nd{V\\eat\dn} ]
[\nd{DP} [\nd{D\\a\dn\dn} ] [\nd{NP} [\nd{N\\burger\dn\dn\dn\dn\dn\dn} ]]]
]
]
]
\end{forest}
\end{document}
答案1
这是全森林版本,感谢Sašo 正在解释如何通过去标记化来测试多行内容中的字符串。否xstring
或amsmath
必填!
\documentclass[12pt,border=25pt]{standalone}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[linguistics]{forest}
\forestset{%
declare toks={dntoks}{},
declare toks={ndtoks}{},
nd/.style={%
delay={%
% detokenize to test for string in multi-line content: Sašo Živanović: https://tex.stackexchange.com/questions/330228/annotating-a-forest-tree-with-its-corresponding-bracketing/330237?noredirect=1#comment809615_330237
temptoksa/.expanded=\detokenize{\\},
temptoksb/.option=content,
temptoksb/.wrap value=\detokenize{##1},
temptoksb/.expanded/.register=temptoksb,
if={instr(temptoksa,temptoksb)}{%
split register/.wrap pgfmath arg={{temptoksb}{##1}{ndtoks,temptoksc}}{(temptoksa)},
}{%
ndtoks/.option=content,
},
},
before typesetting nodes={%
content/.wrap value={\llap{\textcolor{red}{[\textsubscript{\foresteoption{ndtoks}}}}##1},
},
},
dn/.style={%
repeat=#1{%
dntoks+={]},
},
before typesetting nodes={%
content/.wrap value={##1\rlap{\textcolor{red}{\foresteoption{dntoks}}}},
},
},
}
\begin{document}
\begin{forest}
[TP, nd
[DP, nd
[D, nd
]
[NP
[N\\man, dn=2
]
]
]
[T', nd
[T\\will, nd, dn=1
]
[VP, nd
[V\\eat, nd, dn=1
]
[DP, nd
[D\\a, nd, dn=1
]
[NP, nd
[N\\burger, nd, dn=6
]
]
]
]
]
]
\end{forest}
\end{document}
如果所有节点都应采用这种nd
风格(如问题中的例子),那么显然可以进一步简化。
\documentclass[12pt,border=25pt]{standalone}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[linguistics]{forest}
\forestset{%
declare toks={dntoks}{},
declare toks={ndtoks}{},
nd/.style={%
delay={%
% detokenize to test for string in multi-line content: Sašo Živanović: https://tex.stackexchange.com/questions/330228/annotating-a-forest-tree-with-its-corresponding-bracketing/330237?noredirect=1#comment809615_330237
temptoksa/.expanded=\detokenize{\\},
temptoksb/.option=content,
temptoksb/.wrap value=\detokenize{##1},
temptoksb/.expanded/.register=temptoksb,
if={instr(temptoksa,temptoksb)}{%
split register/.wrap pgfmath arg={{temptoksb}{##1}{ndtoks,temptoksc}}{(temptoksa)},
}{%
ndtoks/.option=content,
},
},
before typesetting nodes={%
content/.wrap value={\llap{\textcolor{red}{[\textsubscript{\foresteoption{ndtoks}}}}##1},
},
},
dn/.style={%
repeat=#1{%
dntoks+={]},
},
before typesetting nodes={%
content/.wrap value={##1\rlap{\textcolor{red}{\foresteoption{dntoks}}}},
},
},
default preamble={%
for tree={nd},
},
}
\begin{document}
\begin{forest}
[TP
[DP
[D
]
[NP
[N\\man, dn=2
]
]
]
[T'
[T\\will, dn=1
]
[VP
[V\\eat, dn=1
]
[DP
[D\\a, dn=1
]
[NP
[N\\burger, dn=6
]
]
]
]
]
]
\end{forest}
\end{document}