5

Could someone please tell me if my understanding of how a TeX engine, such as tex or pdftex, processes the following TeX manuscript is correct, and, if not, set me straight?

\iftrue\expandafter a\else b\fi c\bye

The difficulty arises in understanding how \else is expanded, and whether \fi remains on the input stream when the \else clause is consumed.

My interest in this form is due to my coming across a similar form in the TikZ source code (in the file <pgf installation dir>/frontendlayer/tikz/tikz.code.tex):

\def\tikz@endscope{%
    \iftikz@auto@end@path%
        \expandafter\tikz@finish\expandafter\egroup%
        \else\expandafter\tikz@@endscope%
    \fi%
}

Here's how a TeX engine processes the TeX manuscript

\iftrue\expandafter a\else b\fi c\bye
  1. The control sequence \iftrue is removed from the input stream, and an internal flag is pushed onto a stack, which I will call the if stack, to indicate we are inside the true-clause of a conditional expression.

  2. \expandafter expands as follows:

    1. The control sequence \expandafter is removed from the input stream.

    2. The token at the beginning of the input stream, namely a, is removed from the input stream and pushed on an internal stack that I will call the expand after stack.

    3. The token at the beginning of the input stream, namely \else, is expanded. Now, how does an \else expand? According to the TeX Book (20th printing, 1991, p. 213):

      when \else, \or, or \fi is expanded, TEX reads to the end of any text that ought to be skipped.

      So TeX skips, i.e. drops from the input stream, everything between the \else, including the \else, and the first \fi, not including the \fi. This leaves the input stream with the following contents:

      \fi c\bye
      
    4. The expand after stack is popped and its elements are prepended to the beginning of the input stream. So at the end of this step, the input stream consists of the following:

      a\fi c\bye
      
    5. Normal TeX processing resumes.

  3. The letter a is written to the dvi file.

  4. The \fi pops the if stack (recall step 1). The if stack is now empty, so TeX knows we're no longer inside a conditional.

  5. The letter c is written to the dvi file.

  6. The engine stops.

In the end, the dvi file contains the text

ac

  • 1
    Not sure what you are after as an answer here, but you've got the \fi business wrong: it's been removed by the expansion of \else. That's important where a consumes the next token ... – Joseph Wright Aug 10 '17 at 15:01
  • @JosephWright: Your comment is precisely the kind of answer I was hoping for, though I would appreciate it if you can elaborate on this, because, if the \fi is removed by the expansion of \else, then shouldn't the engine complain at the end of the manuscript about an unclosed \if? – Evan Aad Aug 10 '17 at 15:06
  • 1
    Well finding \else means that the conditional has ended and TeX is simply 'tidying up', so there is naturally not error. – Joseph Wright Aug 10 '17 at 15:08
  • @JosephWright: I see. And how can you be sure that this is how things work, rather than the way I described? Is there a way to tell the two interpretations apart? – Evan Aad Aug 10 '17 at 15:10
  • 1
    Try replacing a by for example \show ... – Joseph Wright Aug 10 '17 at 15:11
8

You have a series of expandable commands. Her, I'm going to largely focus on how things happen from a 'TeX macro point-of-view': there is of course detail in TeX-the-program but my understanding is that is not the focus.

First, TeX expands \iftrue which increases the conditional counter by one but does nothing else. TeX then finds \expandafter, which skips over the a (as you say putting on a stack) and expands \else. The result is that TeX looks for a matching \fi, so examines but does not expand tokens until it finds one, discarding the material it collects on the way. Once it finds \fi (or something \let to the primitive), the conditional counter is decreased and the \fi is also discarded. At this stage the a is reinserted and we (effectively) have

ac\bye

This is typeset in the usual way.

The fact that expansion of a conditional removes it is important. It means that in combination with \expandafter the conditional can be closed before the 'payload' is expanded. You can see that in a construct such as

\iftrue\expandafter\show\else b\fi c\bye

where you will get

> the letter c.
l.1 \iftrue\expandafter \show\else b\fi c
                                         \bye

That is vital if you are looking to insert anything taking an argument: you'd otherwise have to contend with stray conditional ends everywhere.

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.