5

The qtree package permits drawing syntactic trees with a syntax like this:

\ex. \Tree [.S [.NP This ] [.VP [.V is ] [.NP an example ]]]

The linguex package typesets bracketed expressions with a similar syntax:

\exi. [S [NP This ] [VP [V is ] [NP an example. ]]]

As you see, the only difference is that the labels in \Tree command (S, NP, VP etc.) are preceded by a dot. Now, I want to write a macro which gets such an argument and first produces a bracketed expression with \exi. and then a tree with \Tree. In order to achieve this I tried to define the following macro, which would add dots after the [ bracket:

\newcommand{\dotify}[1]{\catcode`[=13 \def[{\[.} {#1} \catcode`[=12}

This doesn't work, however. Could anyone help me out with this? Or maybe there is a simpler way to achieve my goal?

5

New answer: You want to do an "input substitution", as compared with an "output substitution". That is, you want to replace [ with [. as material in the .tex file, rather than as printable material. More precisely, you don't want to have the braces replace themselves "as you go along", because the \Tree command will absorb them all at once and not allow them to be executed before it parses what's written, which will not have the dots yet inserted.

In short, what you want is to do a string substitution replacing [ with [., saving the result in a macro that can then be expanded after \Tree to give it the correct syntax. For this, the stringstrings package seems ideal. Here's a minimal document showing how you can define a macro to automate the whole process for you:

\documentclass{article}
\usepackage{stringstrings,qtree,linguex}
\newcommand*\dotify[1]{%
  \convertchar[q]{#1}{[}{[.}%
}
\newcommand*\doboth[1]{%
  \dotify{#1}%
  \ex. \expandafter\Tree\thestring

  \exi. #1

}
\begin{document}
\doboth{[S [NP This ] [VP [V is ] [NP an example ]]]}
\end{document}

Old answer: If you do want to do something like this with catcode methods, you still have a few problems. Most critically, you can't make catcode changes to a macro argument that has already been read, so you should not declare \dotify as having an argument. Instead, you should use the braces delimiting its "argument" to contain a group that "sets up" the correct parsing context; see this interesting answer for the source (for me) of this trick. The group will naturally restrict the scope of the catcode change as well; a bonus.

Your other problem is that \[ means \begin{equation} and not a left brace. I'm sure there's already a command for that, but you can define your own with \let\lb[.

With these changes, the correct code would be:

\documentclass{article}
\def\activebrace{\catcode`\[=\active}
\let\lb[
{\activebrace \global\def[{\lb.}}
\def\dotify#{%
  \bgroup
    \activebrace
    \let\next=%
}
\begin{document}
\dotify{[a[b[c]]]}
\end{document}

which outputs [.a[.b[.c]]].

  • But what Ariel wants is to be able to pass the output of dotify as the argument of the \Tree command, so that \Tree \dotify{[a [b [c ]]]} will be typeset exactly as \Tree [.a [.b [.c ]]] would be. – Alan Munn Apr 25 '13 at 16:57
  • @AlanMunn That's not possible no matter how \dotify is defined, unless \Tree expands its argument, and even then, it can't work unless \dotify is fully expandable (which it's not, if it makes a \catcode change. – Ryan Reich Apr 25 '13 at 17:02
  • Thanks for the new answer. I wasn't aware of the stringstrings package. That's a pretty neat trick. – Alan Munn Apr 25 '13 at 17:59
  • The author is on this site, too. I learn about all kinds of neat packages here (tikz being the big one). – Ryan Reich Apr 25 '13 at 19:15
  • Thanks. This looks reasonably simple, but how do I combine it then into a macro which will do both the \exi. and the \Tree on the same parameter? – Ariel Apr 26 '13 at 11:26
5

Here's a \doubletree macro with l3regex. I show both inputs for comparison.

\documentclass{article}
\usepackage{qtree,linguex,xparse,l3regex}

\ExplSyntaxOn
\NewDocumentCommand{\doubletree}{m}
 {
  \ariel_do_double_tree:n { #1 }
 }
\tl_new:N \l__ariel_tree_tl
\cs_new_protected:Npn \ariel_do_double_tree:n #1
 {
  %% print the first representation
  \exi.~#1\par

  %% change it for \Tree
  \tl_set:Nn \l__ariel_tree_tl { #1 }
  \regex_replace_all:nnN { \[ } { \[\. } \l__ariel_tree_tl
  \tl_put_left:Nn \l__ariel_tree_tl { \Tree }
  \tl_use:N \l__ariel_tree_tl
 }
\ExplSyntaxOff


\begin{document}
\exi. [S [NP This ] [VP [V is ] [NP an example. ]]]

\Tree [.S [.NP This ] [.VP [.V is ] [.NP an example ]]]

\bigskip

\doubletree{[S [NP This ] [VP [V is ] [NP an example. ]]] }

\end{document}

enter image description here


Here's a (less efficient) version without l3regex, with identical output.

\documentclass{article}
\usepackage{qtree,linguex,xstring}

\newcommand{\doubletree}[1]{%
  \exi. #1\par
  \saveexpandmode
  \noexpandarg
  \StrSubstitute{#1}{[}{[.}[\temp]
  \expandafter\Tree\temp
  \restoreexpandmode}

\begin{document}
\exi. [S [NP This ] [VP [V is ] [NP an example. ]]]

\Tree [.S [.NP This ] [.VP [.V is ] [.NP an example ]]]

\bigskip

\doubletree{[S [NP This ] [VP [V is ] [NP an example. ]]] }

\end{document}
  • 2
    I think I need to learn LaTeX3. – Alan Munn Apr 25 '13 at 23:49
  • Unfortunately I don't see the `l3regex' package in my package list. – Ariel Apr 26 '13 at 13:54
  • @Ariel Update your TeX distribution. – egreg Apr 26 '13 at 13:56
  • @Ariel I've added a "l3regex-free" version – egreg Apr 26 '13 at 15:39
  • @egreg Thanks, this works for me! It seems it is essentially the same idea as in the answer above, but with the xstring package, instead of stringstrings. So which package is better? – Ariel Apr 29 '13 at 9:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.