[Tex/LaTex] How does TeX look for delimited arguments

macrostex-core

The following code

\def\foo#1#2\baz{\#1: -#1- \quad \#2: -#2-}

1) \foo hello world\baz

2) \foo supercalifragilistiexpialidocious\baz

3) \foo a \baz

4) \foo a\baz

%5) \foo \baz % error!

\bye

yields

enter image description here

The cases 1) to 3) are perfectly understandable to me. To a certain surprise, even 4) works: the second argument #2 becomes empty (and the two hyphens render as an en dash). But then case 5) breaks down with Runaway argument? ! Paragraph ended before \foo was complete instead of recognizing both arguments as empty.

I wouldn't have bothered if also case 4) had broken down: both cases 4) and 5) failing would seem "logical" to me. Or I'd expect both of them to work. Alas, my logic is seldom trustworthy :-)

Best Answer

From \def\foo#1#2\baz{..}, the #1#2 bit means that #1 is not delimited, so it's either a single token or a braced argument, so the commands grabs a single token or a braced group (the only way one of this arguments are empty is with {}); after that, the #2\baz part means that #2 is indeed delimited, so it grabs until \baz (removing possibly outer braces, this can be empty by just putting \baz next). In case 4 it grabs first argument, and then goes until \baz for the second one; in case 5 it grabs first argument (which is \baz) and then grabs until \baz but there is no \baz left (it's been grabbed as first argument) so it cannot grab the second argument, hence the error message.

Maybe it could help to think in terms of nested commands, each grabbing one argument. \def\foo#1#2\baz{(1:#1) and (2:#2)} could be done like

\def\foo#1{(1:#1) and \footwo}
\def\footwo#1\baz{(2:#1)}