# Incompatibility of calc and some styles for forest

I got a cool solution for integrating a tabular-like object into a forest figure (Relating tree nodes in forest to content in a table) but this is incompatible with another cool solution for fixing the triangles in trees and inserting a translation (Smaller roofs for forest).

This is what I have. LaTeX complains with a GenericError ...

\documentclass{article}

\usepackage{forest}

% to be able to do funny calculations for coordinates.
% used for the table explaining the topological model below the CP/IP/VP tree
\usetikzlibrary{calc}

% specification for all trees
\forestset{.style={for tree={parent anchor=south, child anchor=north,align=center,base=top}}}

% The following code fixes the size of triangles for examples with translations. The specification
% ",delay=with translation" at the leaves is important to make this work.
% https://tex.stackexchange.com/questions/167978/smaller-roofs-for-forest/205311#205311
\forestset{
with translation/.style={
l sep=0,inner xsep=0,
append translation/.expanded/.wrap pgfmath arg={\gettranslation{##1}}{content},
content/.expanded/.wrap pgfmath arg={\gettext{##1}}{content},
},
append translation/.style={append={[#1,no edge,l=0,inner xsep=0,inner ysep=0,outer ysep=0,before computing xy={l-=2pt}]}}
}

\def\gettext#1{\gettextA#1;;\endget}
\def\gettextA#1;#2;{\removesep#1;}
\def\gettranslation#1{\gettranslationA#1;;\endget}
\def\gettranslationA#1;#2;{\removesep#2;}
\def\removesep#1;#2\endget{#1}

% a specific style that specifies the word tier: all nodes that do not have any children
% to do: make this style default and change all other figures explicitely as is described here:
% https://tex.stackexchange.com/questions/167983/getting-rid-of-a-default-where-specification
\forestset{
sn edges/.style={for tree={parent anchor=south, child anchor=north,align=center,base=top},
where n children=0{tier=word,delay=with translation}{}
},
% auxiliary nodes without node label
empty nodes/.style={
delay={where content={}{shape=coordinate,for parent={for children={anchor=north}}}{}}}
}

\forestset{
terminus/.style={tier=word, for tree={fit=band}, for descendants={no path, align=left, l sep=0pt}},
no path/.style={edge path={}},
set me left/.style={calign with current edge, child anchor=north west, for parent={parent anchor=south west}},
}

%\usepackage{pstricks,pst-node}

\begin{document}

\begin{figure}[htbp]
\centering
\begin{forest}
sn edges,empty nodes
[CP
[{}
[XP,terminus
[SpecCP\\prefield, name=p1
]
]
]
[C$'$
[{}
[C$^0$, terminus
[C0\\left SB, name=c0
]
]
]
[IP
[{}
[XP, terminus
[{IP (without I0, V0)\\middlefield}
[SpecIP\\subject position, set me left, name=specip
]
[phrases inside\\the VP, name=p3
]
]
]
]
[I$'$
[VP, name=vp
[V$^0$, name=v0, terminus, no path, anchor=east
[{V0, I0\\right SB}, name=p2, set me left
]
]
]
[{}
[I$^0$, terminus, name=io
]
]
]
]
]
]
\draw [thick]
(p1.north west) rectangle (io.east |- p3.south);
\draw
($(c0.north east)!1/2!(specip.west |- c0.north east)$) coordinate (p6) -- (p6 |- p3.south)
($(p1.north east)!1/2!(c0.north west)$) coordinate (p4) -- (p3.south -| p4)
($(specip.north east)!1/2!(p3.north west)$) coordinate (p5) -- (p3.south -| p5)
($(p2.north west)!1/2!(p2.north west -| p3.east)$) coordinate (p7) -- (p3.south -| p7)
(p6 |- p2.south) -- (p2.south -| p7)
(vp.south) -- (v0.center -| p3.west) -- (v0.west)
(v0.east) -- +(4.5pt,0) -- (vp.south)
;
\end{forest}
\caption{\label{Abb-GB-Topo}CP, IP and VP and the topological model of German}
\end{figure}

\end{document}

• Have you tried changing the order of forest and calc? – John Kormylo Nov 23 '14 at 14:37
• I tried it now. Did not work. – Stefan Müller Nov 23 '14 at 17:13
• @JohnKormylo You can't just do that because \usetikzlibrary is not defined until forest is loaded. You could add an explicit call to tikz, then load the library and then load forest but I doubt that would help. You could, actually, remove the call to calc altogether. I just realised that it is redundant since forest loads it anyway. – cfr Nov 23 '14 at 17:18
• Note that your definition of terminus won't work as noted on your other question. – cfr Nov 23 '14 at 22:14

The problem, I think, is that you do not really want with translation to apply to the nodes which constitute the tabular. So the code you have for the translation stuff assumes that the nodes with 0 children are the right ones to apply with translation to but that won't work. You need instead to apply this to the nodes marked terminus which are the final nodes before the tabular.

You need to be just a tad careful if you wish to combine trees with all of the following sets of features in the same document:

• trees with translations but not tabulars - here we want the translation stuff applied when the number of children is 0 to avoid having to mark the terminal nodes ourselves;
• trees with tabulars but not translations;
• trees with translations and tabulars - here we want the translation stuff applied to the nodes marked terminus since the nodes with 0 children are actually likely to be part of the tabular;
• use of \trace.

The following code demonstrates how these can be combined into a single document. It is necessary to tell forest a little about each tree when initiating it. This is done by use of styles.

• Trees with no tabular: use sn edges, no tabular when initiating tree.
• Use of \trace: add the trace style to the relevant node.
• Trees with tabular: use sn edges alone when initiating tree, and mark the terminal nodes of the tree part with terminus except if trace is used as above. (You cannot have a tabular cell beneath the trace node as everything is currently defined.)

You must not use \trace in a node where with translation will be applied and you must not allow with translation to be applied to a node which should be part of the tabular.

If this seems overly complex, then the easiest solution would be to compile your trees individually and to then include images in your document.

\documentclass{article}
\usepackage{forest}
\forestset{
sn edges/.style={for tree={parent anchor=south, child anchor=north,align=center,base=top}},
no tabular/.style={sn edges, for tree={where n children=0{tier=word, delay=with translation}{}}},
trace/.style={
replace by={[\trace, delay={}, tier=word]}
},
terminus/.style={
tier=word,
delay=with translation,
for children={
tier=tabular,
},
for tree={
fit=band,
},
for descendants={
no path,
align=left,
l sep=0pt,
},
},
empty nodes/.style={
delay={where content={}{shape=coordinate,for parent={for children={anchor=north}}}{}}},
no path/.style={edge path={}},
set me left/.style={calign with current edge, child anchor=north west, for parent={parent anchor=south west}},
with translation/.style={
l sep=0,
inner xsep=0,
append translation/.expanded/.wrap pgfmath arg={\gettranslation{##1}}{content},
content/.expanded/.wrap pgfmath arg={\gettext{##1}}{content},
},
append translation/.style={
append={
[
#1,
no edge,
l=0,
inner xsep=0,
inner ysep=0,
outer ysep=0,
before computing xy={
l-=2pt
}
]
},
},
}

\def\gettext#1{\gettextA#1;;\endget}
\def\gettextA#1;#2;{\removesep#1;}
\def\gettranslation#1{\gettranslationA#1;;\endget}
\def\gettranslationA#1;#2;{\removesep#2;}
\def\removesep#1;#2\endget{#1}

\newcommand{\trace}{\raisebox{0.2ex}{\_}\rule{0cm}{0.7em}}

\begin{document}

\hfill
\begin{forest}
sn edges, no tabular
[NP
[Det [eine;a] ]
[N$'$
[A [kluge;smart] ]
[N$'$
[N [, trace ] ] ] ] ]
\end{forest}
\hfill
\begin{forest}
sn edges
[NP
[Det
[eine;a, terminus
[tab1, name=p1]
]
]
[N$'$
[A
[kluge;smart, terminus
[tab2, name=p2
]
]
]
[N$'$
[N
[, trace
]
]
]
]
]
\draw
(p1.north west) rectangle (p2.south east)
($(p1.north east)!1/2!(p2.north west)$) coordinate (p3) -- (p3 |- p2.south);
\end{forest}
\hfill
\bigskip

\begin{forest}
sn edges, empty nodes
[CP
[{}
[XP,terminus
[SpecCP\\prefield, name=p1
]
]
]
[C$'$
[{}
[C$^0$, terminus
[C0\\left SB, name=c0
]
]
]
[IP
[{}
[XP, terminus
[{IP (without I0, V0)\\middlefield}
[SpecIP\\subject position, set me left, name=specip
]
[phrases inside\\the VP, name=p3
]
]
]
]
[I$'$
[VP, name=vp
[V$^0$, name=v0, terminus, no path, anchor=east
[{V0, I0\\right SB}, name=p2, set me left
]
]
]
[{}
[I$^0$, terminus, name=io
]
]
]
]
]
]
\draw [thick]
(p1.north west) rectangle (io.east |- p3.south);
\draw
($(c0.north east)!1/2!(specip.west |- c0.north east)$) coordinate (p6) -- (p6 |- p3.south)
($(p1.north east)!1/2!(c0.north west)$) coordinate (p4) -- (p3.south -| p4)
($(specip.north east)!1/2!(p3.north west)$) coordinate (p5) -- (p3.south -| p5)
($(p2.north west)!1/2!(p2.north west -| p3.east)$) coordinate (p7) -- (p3.south -| p7)
(p6 |- p2.south) -- (p2.south -| p7)
(vp.south) -- (v0.center -| p3.west) -- (v0.west)
(v0.east) -- +(4.5pt,0) -- (vp.south)
;
\end{forest}

\end{document}


• Ah, OK. Yes. Thank you very much! So the solution is to keep my style for usual trees with a translation and use the version that you used for examples like the one at hand in which there is no translation anyway. One probably could go more complicated and try to come up with something that allows translations in cases like the one at hand, but may be this is overkill ... Thanks! – Stefan Müller Nov 23 '14 at 19:05
• @StefanMüller This should probably work with the translations but I didn't test that because I didn't know quite how you were using it here. Notice that I'm adding with translation to the final nodes of the tree part. I'm just removing them from the nodes in the tabular part. If you want the translation triggered by zero children, however, then, yes, you'd need to keep the styles separate. – cfr Nov 23 '14 at 19:36
• @StefanMüller Please see edit. Note this also includes the correction to the definition of terminus. – cfr Nov 23 '14 at 23:28
• @StefanMüller Did this solve the problem or is there an outstanding issue here? – cfr Dec 17 '14 at 22:38