Package environ to capture the contents of an environment. LaTeX3 code (package expl3) to split it into lines, cells, and more general programming tools. Rather than making an environment with 4 parameters as I did, you can hard-code some of them in the definition if it is more practical.
\documentclass{article}
\usepackage{environ}
\usepackage{expl3}
\ExplSyntaxOn
\seq_new:N \l_jb_lines_seq
\seq_new:N \l_jb_tmp_seq
\tl_new:N \l_jb_result_tl
\int_new:N \l_jb_cols_int
\int_new:N \l_jb_cell_int
\tl_new:N \l_jb_one_line_tl
\NewEnviron{mytable}[4][]
{
\seq_set_split:NnV \l_jb_lines_seq { \\ } \BODY
%
% If the user gives no indication of number of cells, find the max
% number by reading all rows. Otherwise, use the user-given value,
% all extras will be thrown out silently.
%
\tl_if_empty:nTF {#1}
{ \jb_get_max_cells:NN \l_jb_lines_seq \l_jb_cols_int }
{ \int_set:Nn \l_jb_cols_int {#1} }
%
% Build the result into a token list, initially the begin-code |#3|.
% For each line |##1|, add a call to the command |#2| with exactly
% |\l_jb_cols_int| arguments. Then append the end-code |#4|.
% Finally, use the token list.
%
\tl_set:Nn \l_jb_result_tl {#3}
\seq_map_inline:Nn \l_jb_lines_seq
{ \jb_append_one_line:NnNn \l_jb_result_tl {#2} \l_jb_cols_int {##1} }
\tl_put_right:Nn \l_jb_result_tl {#4}
\tl_use:N \l_jb_result_tl
}
\cs_new_protected:Npn \jb_get_max_cells:NN #1#2
{
% Find the max number of cells over all lines.
% Not terribly efficient way of counting |&|: split at each |&|
% and store in a tmp sequence, then count its items.
%
\int_zero:N #2
\seq_map_inline:Nn #1
{
\seq_set_split:Nnn \l_jb_tmp_seq { & } {##1}
\int_set:Nn #2
{ \int_max:nn #2 { \seq_count:N \l_jb_tmp_seq } }
}
}
\cs_new_protected:Npn \jb_append_one_line:NnNn #1#2#3#4
{
\tl_set:Nn \l_jb_one_line_tl {#2}
\seq_set_split:Nnn \l_jb_tmp_seq { & } {#4}
\int_set:Nn \l_jb_cell_int { \seq_count:N \l_jb_tmp_seq }
\int_compare:nNnTF \l_jb_cell_int > {#3}
{
\int_zero:N \l_jb_cell_int
\seq_map_inline:Nn \l_jb_tmp_seq
{
\int_compare:nNnF \l_jb_cell_int < {#3} { \seq_map_break: }
\int_incr:N \l_jb_cell_int
\tl_put_right:Nn \l_jb_one_line_tl { {##1} }
}
}
{
\seq_map_inline:Nn \l_jb_tmp_seq
{ \tl_put_right:Nn \l_jb_one_line_tl { {##1} } }
\tl_put_right:Nx \l_jb_one_line_tl
{ \prg_replicate:nn { #3 - \l_jb_cell_int } { { } } }
}
\tl_put_right:NV #1 \l_jb_one_line_tl
}
\ExplSyntaxOff
\begin{document}
\newcommand{\RowMacro}[5]{[1: #1] & [2: #2] & [3 and 4: #3, #4] & [5: #5]\\}
\begin{mytable}[5]{\RowMacro}{\begin{tabular}{cccc}}{\end{tabular}}
a & b & c \\
d & e & f & g & h & extra\notused \\
ijk & l
\end{mytable}
\end{document}
expl3something that is commonly around? Or would I have to worry using it in a submission to a CS journal? – Joachim Breitner May 22 '13 at 14:03expl3more recent than 2012-07-02, relatively more recent than what journals would have. – Bruno Le Floch May 22 '13 at 14:28