2

I need to make several syntax trees using forest, and there are some structures that show up over and over again in multiple trees. How can I achieve this? So far attempts I've made with \newcommand haven't worked. As a basic example, I'd expect to be able to enter something like this:

\newcommand{\asdf}[1]{a [#1] [c]}

...

\begin{forest}
[x
    [y]
    [\asdf{b}]
]
\end{forest}

and produce this tree:

A tree with the root node x, the nodes y and a as children of x, and then the nodes b and c as children of a

What am I doing wrong?

Edit: here's a more complete example of what I'm trying to do:

\documentclass{article}
\usepackage{forest}
\usepackage{ulem}
\usepackage{textcomp}

\renewcommand{\ln}{\textit{n}}
\newcommand{\uX}[1]{\sout{u#1}}
\newcommand{\mvmt}[1]{\textlangle#1\textrangle}
\newcommand{\basen}[1]{
\ln
[\ln
    [#1{[N]}]
    [\ln {[\uX{N*}]}]
]
[\mvmt{#1[N]}]
}

\begin{document}

\begin{forest}
[D
    [the{[D,\uX{\ln}]}]
    [\basen{dog}]
]
\end{forest}
\end{document}

with this as the intended result:

enter image description here

sorry for not being clearer to begin with!

1 Answer 1

2

Inside a forest environment, Forest's parser is responsible for reading in the content and expanding things etc. This means that ordinary parsing is suspended and macros don't get expanded as you might expect.

Forest provides a mechanism (actually several mechanisms) for temporarily switching its specialist parser off and enabling ordinary expansion. In your example, the easiest way to manage it is to simply set an action character and precede the macro \asdf with that character. The character can be anything you like which won't interfere with other things. (For example, it obviously wouldn't work to use [ or ] or something.) I usually use @.

The only potential pitfall is to try defining the character after the forest environment has started. It's too late then, because Forest's parser is already running the show. Instead, use \bracketset{} outside the Forest environment.

If this sounds involved, it isn't. In practice, all you need is this:

\documentclass[border=9pt]{standalone}

\usepackage{forest}
\newcommand{\asdf}[1]{a [#1] [c]}

\begin{document}

\bracketset{action character=@}
\begin{forest}
  [x
    [y]
    [@\asdf{b}]
  ]
\end{forest}

\end{document}

tree with expanded macro

EDIT

For the more complex case in the edited question, exactly the same approach can be used.

\begin{forest}
  [D
    [the{[D,\uX{\lynx}]}]% avoid changing \ln
    [@\basen{dog}]
  ]
\end{forest}

gives

output for more complex case with expanded macro

Complete code:

\documentclass[border=9pt]{standalone}
\usepackage{forest}
\usepackage{ulem}
\usepackage{textcomp}

\newcommand{\asdf}[1]{a [#1] [c]}
\newcommand{\lynx}{\textit{n}}
\newcommand{\uX}[1]{\sout{u#1}}
\newcommand{\mvmt}[1]{\textlangle#1\textrangle}
\newcommand{\basen}[1]{
  \lynx
  [\lynx
    [#1{[N]}]
    [\ln {[\uX{N*}]}]
  ]
  [\mvmt{#1[N]}]
}

\begin{document}

\bracketset{action character=@}
\begin{forest}
  [x
    [y]
    [@\asdf{b}]
  ]
\end{forest}


\begin{forest}
  [D
    [the{[D,\uX{\lynx}]}]
    [@\basen{dog}]
  ]
\end{forest}

\end{document}
4
  • 1
    Didn't know that. +1
    – user194703
    Nov 18, 2019 at 2:52
  • 1
    @Schrödinger'scat prooftrees depends on it (AND the environ trick).
    – cfr
    Nov 18, 2019 at 2:54
  • 1
    @Schrödinger'scat Will \lynx do?
    – cfr
    Nov 18, 2019 at 2:59
  • 2
    ;-) how could a cat object that? (Of course, there is a chance that one day the TikZling family will have a lynx .... ;-)
    – user194703
    Nov 18, 2019 at 3:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .