# Bug? LaTeX misparses nested optional arguments

LaTeX seems to be having problems handling nested optional arguments. I've included a minimal code example that generates the error:

\documentclass[12pt,oneside]{book}
\begin{document}

\newcommand{\termgood}[2][]{#2#1}

\newcommand{\up}[1]{#1}
\newcommand{\dd}[1][]{#1}

\termgood{\up{Tart}}{Pop}

\termgood{\dd[Tart]}{Pop}

\end{document}


If you run this code, it works. If you remove the % in the second to last line, it fails with:

Runaway argument?

Tart{Pop} \par \par \end {document}

!File ended while scanning use of \dd.


After further tinkering, I have discovered the problem: LaTeX is reading the ] for the inner optional argument as the end of the outer optional argument and then passing a malformed argument in. So it is passing in \dd[Tart as the optional argument to \termbad instead of \dd[Tart].

This still feels like a bug to me. Nesting braces in arguments works, brackets should as well. The following are workarounds:

• Enclose the inner optional argument in braces (as in the line before %).

• Redefine your inner function to require its argument instead of using optional arguments.

• Redefine your outer function to require its argument instead of using optional arguments.

Any one of the three works around the issue.

(Reposted here; question was originally posted to stackexchange and then closed instead of being migrated.)

-
As far as I can see, the main problem is that LaTeX doesn't define the notion of nested optional arguments. This is why different implementations have different semantics. –  Marc van Dongen Oct 20 '12 at 11:57

When TeX reads arguments, then TeX only checks for matching curly braces (characters with catcode 1 and 2). Square brackets are not special in this sense. The first ] that is not hidden inside curly braces is taken as the end of the optional argument. Therefore an additional set of braces is the usual solution:

\foo[{\bar[...]}]{...}


It is only a bug, if this does not work, e.g. if the definition passes optional arguments to other commands:

\def\foo#1#2{\bar[#1]{#2}}


This should be

\def\foo#1#2{\bar[{#1}]{#2}}


Then #1 may contain square brackets, especially ].

-
Worth noting that xparse-defined functions do not suffer from this –  Joseph Wright Oct 20 '12 at 11:41
Thanks for the answers. I'm looking at xparse now, since I'm using some complex code to create a highly linked and formatted document. This may solve a few of the problems I've been having. –  JKreft Oct 23 '12 at 12:33