On 9/2/20, John Gardner <gardnerjo...@gmail.com> wrote: > Here's a dummy program to > illustrate how \{ … \} get interpreted the same as everything else: once > they're reached:
But that precept doesn't hold in general. Consider the much simpler example: .if 0 .if 1 \{\ .tm foo .\} .tm bar Following your explanation, the interpreter would evaluate ".if 0", decide it was false, and ignore the rest of the line, thus missing that the line ends in a \{. Therefore it would go to the next line, and -- unaware that it's inside an opening brace, since it never "saw" it -- execute the ".tm foo" request. Proceeding to the next line, it encounters an unbalanced closing brace, which it silently ignores (you can verify that it doesn't care about mismatched closing braces by duplicating that line as many times as you please in the input file). Finally, it hits the last line and emits "bar" on stderr. But that's not what happens. Groff does not print "foo" to stderr, which can only happen if it does in fact process the opening brace -- which is associated with a request (the second .if) that it never looks at. This implies that, at least in some circumstances, the interpreter recognizes opening braces as flow-control structures, and scans for them even in code it would otherwise never examine. The .ie request is just as much a language flow-control element as an opening brace, yet (per my original question) the interpreter does not treat them the same, ignoring the .ie request in a position (after a false conditional) where it does not ignore an opening brace. And the opening brace is associated with the ".if 1", not the ".if 0", so it's not as simple as a special case of looking for such a brace immediately following a false conditional. It is, in fact, looking BEYOND where it would have needed to look just to find the .ie request of my first example. Again, if this is considered "working as designed," it should be documented as such, but it's not clear to me just how to document it. Tadziu's suggestion does not account for the opening-brace exception. And are there other exceptions? And why are there exceptions at all? It seems like a more consistent (and, not incidentally, easier to document) language design to handle all flow-control constructs the same way: it either unilaterally ignores them after an .if that evaluates to false, or unilaterally scans ahead to see whether any occur later on the line. Instead, the behavior seems arbitrary and capricious -- which *can* be documented, but still isn't a good language design.