Many on this site know (and perhaps find slightly annoying) that I will try to solve any LaTeX problem with the use of my stackengine package. My motto is like one of the overnight delivery services: "if it stacks, we ship it".
I found an odd problem in one of my parsing routines from that package, and I know it very much relates to the topic or robustness (which I kind of understand in theory, but certainly don't know enough to overcome). What I found surprising is that this particular problem only arises after an invocation of \centering which I found quite odd and unexpected.
I've boiled the problem down to this MWE. Here, \@readMANYrows will take an argument consisting of multi-row data, each row separated by a "end-of-line" (EOL) character, and parse it into individual row data. The stackengine package, for historical reasons, defaults this EOL character to a space, but has a package option to make the EOL a \\ to be more in line with what LaTeX users might expect (I realize \\ is a macro, not a character, and that perhaps is the root of this problem).
When the EOL is set to \\, everything works fine. If \centering is invoked, however, the routine will only work if the EOL is something other than \\. Finally, if I make \protect\\ the EOL, everything works again even when centering, but that last syntax is really a nuisance and for academic interest only.
So my question is two-fold: I am curious how it is that \centering undermines the parsing routine (it is not as if \centering is an argument to my routine... it is not)?; AND, is there an easy way to make the parsing routine robust without, for example, rewriting it in LaTeX3, as egreg did at Parsing rows (`\\`) and tab characters (`&`)?
I would only add, as a postscript, that \usepackage{fixltx2e} does not resolve this problem.
\documentclass{article}
\usepackage{ifthen}
\newcounter{ROWcellindex@}
\makeatletter
\newcommand\setstackEOL[1]{%
\ifthenelse{\equal{#1}{}}{\def\SEP@char{ }}{\def\SEP@char{#1}}%
\expandafter\define@processROW\expandafter{\SEP@char}%
}
\newcommand\define@processROW[1]{%
\def\@processROW##1#1##2||{%
\protected@edef\@preSEP{##1}%
\protected@edef\@postSEP{##2}%
}%
}
% FOR PROCESSING A GROUP OF STACK ROWS SEPARATED BY \SEP@char
\newcommand\@readMANYrows[1]{%
\def\@doneROWreads{F}%
\def\@postSEP{#1\SEP@char}%
\setcounter{ROWcellindex@}{0}%
\whiledo{\equal{\@doneROWreads}{F}}{%
\stepcounter{ROWcellindex@}%
\expandafter\@processROW\@postSEP||%
\ifthenelse{\equal{\@postSEP}{}}{%
\def\@doneROWreads{T}%
}{}%
\ifthenelse{\equal{\SEP@char}{ }}%
{\def\@preSEPtemp{\@preSEP}}%
{\def\@preSEPtemp{\ignorespaces\@preSEP\unskip}}%
\expandafter\protected@edef\csname arg\roman{ROWcellindex@}\endcsname{%
\@preSEPtemp}%
}%
% \narg GIVES HOW MANY ROWS WERE PROCESSED
\xdef\narg{\arabic{ROWcellindex@}}%
}
\begin{document}
% OK IF NO CENTERING
\setstackEOL{\\}
\@readMANYrows{a \\ b \\ c}
\argi, \argii, \argiii\\
% OK IF DIFFERENT EOL CHARACTER
\centering
\setstackEOL{$}
\@readMANYrows{d $ e $ f}
\argi, \argii, \argiii\\
% BREAKS! \\ NOT ROBUST
%\centering
%\setstackEOL{\\}
%\@readMANYrows{g \\ h \\ i}
%\argi, \argii, \argiii\\
% PROTECTING \\ WORKS, BUT IS A NUISANCE TO USE
\centering
\setstackEOL{\protect\\}
\@readMANYrows{j \protect\\ k \protect\\ l}
\argi, \argii, \argiii\\
\end{document}

\\is a robust command, but it isn't in the scope of\centering. My impression is that you're passing it in a\protected@edefand this would explain the problem. Why you're passing the row delimiter to\protected@edefin the first place is not clear. And the use of\protected@edefwhen splitting is questionable too, I believe. – egreg Oct 10 '13 at 17:58\\is redefined all over the place:centerraggedrighttabbingtabularanyway you are only using the sepchar as a separator so you may as well locally\letit to\relaxso it is always robust. – David Carlisle Oct 10 '13 at 18:12\protected@edefwas only adulterating the row data, and not the EOL, but I see now from the recursive nature of\@readMANYrowsthat downstream\SEP@chars become part of\@postSEP, and thus get expanded. And since you point out (I didn't know) that\\\is not robust with\centering`, I think I understand now why it breaks. – Steven B. Segletes Oct 10 '13 at 18:14\def\SEP@char{#1}}it does\def\SEP@char{\protect#1}}but as egreg commented you probably shouldn't be using edef anyway, then it wouldn't be an issue. – David Carlisle Oct 10 '13 at 18:24\\doesn't survive\ifthenelse{\equal{\\}{}}when it has the definition in\centering, which is the first problem. You really should use more robust tests, for instance those inetoolbox– egreg Oct 10 '13 at 19:20