Use column-separator & (ampersand) inside \newenvironment
The problem is that the \begin{...}
and \end{...}
pair commands automatically create a "group" so that, in effect, the &
and \\
are "out of scope" for the tabular, while inside the "production" environment they just show up at a place where the compiler is not expecting them.
A second problem with your definitions is that, even if they would work, they would be adding an extra \\
at the end of the tabular, adding an unwanted space at the end. Perhaps some more appropriate definitions would be
\documentclass[a4paper,10pt]{article}
\newcommand{\production}[1]{#1 ::= &}
\newenvironment{grammar}{\tabular{p{3cm}l}}{\endtabular}
\begin{document}
\begin{grammar}
\production{XmlStartTag} ... \\
\production{XmlOtherTag} ... \\
\production{XmlEndTag} ...
\end{grammar}
\end{document}
Note no \\
at the end of the last production. Also in the definition of the grammar
you don't need to repeat the work of \begin
/\end
, and you can instead directly use \tabular
and \endtabular
.
EDIT: The answer was completely wrong; sorry to those who had upvoted.
I found a trick when trying to solve this question. You can use the environ
package and define the production
environment as follows:
\usepackage{environ}
\NewEnviron{production}[1]{%
\toks0={\noindent\ignorespaces#1 ::= &}%
\toks2=\expandafter{\BODY}%
\toks4={\\}%
\xdef\gtemp{\the\toks0 \the\toks2 \the\toks4 }%
\aftergroup\gtemp
}
\BODY
is the content of the environment. The code works as follows: store \noindent\ignorespaces#1 ::= &
into the token register \toks0
, then store \BODY
(expanded by \expandafter
) into \toks2
, and the trailing code \\
into \toks4
. Put everything together into the global token list \gtemp
. The \xdef
expands \the\toks0
, \the\toks2
, and \the\toks4
(spaces after the numbers are important). Finally, \aftergroup\gtemp
places the \gtemp
after the end of the group formed by \begin{production}...\end{production}
, so that this group does not interfere with groups produced by the tabular. See the answer to the question I mention above.
Two questions for more experienced TeXers: can I use \unexpanded
to do this better? Is there a good way of executing a lot of stuff \aftergroup
: I hate having to define \gtemp
globally.
It has nothing to do with macro expansion but with grouping: Cells in a tabular build a group. You are starting an environment in one group and close it in the next. Use better a command \production.