# Tabular end-of-row \\ macro fails when trying to capture cell contents

I am trying to create a tabular environment that captures the contents of table cells for an associated Lua module. The Lua module will then reformat the tabular data and export as C/C++ and VHDL source files to minimize transcription errors from the pdf design specification.

This example preamble defines a couple of macros to capture the cell data:

\documentclass{article}

\usepackage{array}
\usepackage{luacode}

%
% Capture a tablular cell's contents.
% The \endCell token serves as an end-of-cell marker and is never defined.
%
\long\def\startCell#1\endCell{%
% This normally calls a function in a separate Lua module.
% Just print the cell contents to stdout for this example.
\luadirect{print("Cell ***" .. [==[#1]==] .. "***")}%
% Then put the original cell contents back into the TeX stream.
#1%
}

%
% This macro normally calls a Lua function in a separate module to process the
% cell data captured in the current row. Print to stdout for testing instead.
%


A tabular environment (using the array package) then captures columns 2 and 3:

\begin{document}

\begin{tabular}{
l % Don't capture data from the first column.
>{\startCell}l<{\endCell}
>{\startCell}l<{\endCell\processRow}
}
1 & 2 & 3 \cr
4 & 5 & 6 \cr
7 & 8 & 9 \cr
\end{tabular}

\end{document}


Processing with lualatex shows the expected cell captures for columns 2 and 3 in the terminal:

...
Cell ***\ignorespaces 2 \unskip ***
Cell ***\ignorespaces 3 \unskip ***
=== End of row ===
Cell ***\ignorespaces 5 \unskip ***
Cell ***\ignorespaces 6 \unskip ***
=== End of row ===
Cell ***\ignorespaces 8 \unskip ***
Cell ***\ignorespaces 9 \unskip ***
=== End of row ===
...


The table in the pdf output is also correct:

The problem: This doesn't work if the \\ macro is used in place of the \cr macro to end rows. Using a table body of

    1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\


captures one cell, but then fails:

...
Cell ***\ignorespaces 2 \unskip ***

! Use of \@@array doesn't match its definition.
\@ifnextchar ... \reserved@d =#1\def \reserved@a {
#2}\def \reserved@b {#3}\f...

l.32     4 &
5 & 6 \\
?


Commenting out \usepackage{luacode} and the \luadirect references results in a slightly different error, which is identical under both lualatex and pdflatex:

...
! Misplaced \cr.
\reserved@c ->\ifnum 0={}\fi \cr

l.32     4 &
5 & 6 \\
?


Using a similar but non-capturing tabular preamble does not generate the error:

    l
>{\relax}l<{\relax}
>{\relax}l<{\relax}


The lualatex version is as follows:

\$ lualatex --version
This is LuaTeX, Version 1.07.0 (TeX Live 2018)


Using \cr to end rows will probably work for this application, but why does this cell-capturing logic break the \\ macro? Is there a better way to capture tabular cell data for a Lua script?

• Welcome to TeX-SE! Are you aware of the collcell package? – user121799 Jun 21 at 6:05
• @marmot: No, I was not aware of collcell. It looks pretty close to what I am trying to do and will try it out! – Fred Schleifer Jun 21 at 6:13

I will be happy to delete this but using collcell seems to solve your problem.

\documentclass{article}
\usepackage{array}
\usepackage{collcell}
\usepackage{luacode}
\newcommand\mymacroE[1]{\luadirect{print("Cell ***" .. [==[#1]==] .. "***")}#1}
\newcommand\mymacroF[1]{\mymacroE{#1}\processRow}
\newcolumntype{E}{>{\collectcell\mymacroE}c<{\endcollectcell}}
\newcolumntype{F}{>{\collectcell\mymacroF}c<{\endcollectcell}}
\begin{document}
\begin{tabular}{
l % Don't capture data from the first column.
EF
}
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{tabular}
\end{document}
`
• Very nice! This approach also removes the superfluous tokens that showed up in the cell data with my attempt. – Fred Schleifer Jun 21 at 6:22