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
.
The explanation will need a bit of TeX theory.
A group is a part of the document that confines most changes made inside it only to this group itself. That is, most settings changed inside a group will be reverted to their old values once the group ends. A group is delimited by { … }
or \begingroup … \endgroup
. For example, a command \itshape
switches the font shape to italic. If it is used in the document, all text after that point will be set in italic shape (unless another command switches the font again). But when used inside a group — {\itshape test}
— its effect will only last to the end of the group; when the group ends, the font will be restored to whatever it was before the group was started. If an assignment or a macro definition should transcend any groups it might be in and remain in effect after the groups end, it must be prefixed with \global
(this only works for primitive TeX operations).
Replacing a macro with its replacement text is called expanding the macro. TeX expands macros as it reads the input, but it does not necessarily expand arguments to commands — they are passed as they are. Therefore, in
\def\a{a}
\def\b{b \a}
(\def
is the TeX primitive for defining new macros), the replacement text for \b
is b \a
, not b a
. Only when \b
is used, \a
will be expanded recursively. If it is needed that \a
is expanded at the time of \b
definition, there exists a similar primitive to \def
— \edef
, which fully (that is, recursively) expands the to-be replacement text and only then associates the text with the macro name.
Now let's look at the code.
It cannot be seen directly, but the iteration code in \foreach
is processed inside a group. Therefore, the result of \renewcommand
is immediately forgotten after each iteration, and in the end \myresult
is still empty. We can remedy this by using \global\def
instead of \renewcommand
(\renewcommand
is a complex macro and won't be affected by \global
):
\global\def\myresult{blah \myresult}
But now we get a different problem. After at least one iteration, \myresult
now has the replacement text blah \myresult
. If TeX encounters \myresult
in input, it will replace the macro with blah \myresult
, which it will replace then with blah blah \myresult
, … until there is no more memory left. The problem is that we caused an infinite recursion by defining a macro that expands to itself. We wanted to use the old value of \myresult
when we redefined it, but ended up using the macro itself. We already know that we can use \edef
instead of \def
to do the former instead of the latter. Now the relevant line becomes
\global\edef\myresult{blah \myresult}
Plain TeX defines \xdef
to be \global\edef
. So we can shorten the code:
\xdef\myresult{blah \myresult}
Now it will work as planned.
With all this explained, package etoolbox
provides the commands \xpreto<hook>{<code>}
and \xappto<hook>{<code>}
, which will globally prepend or append the expansion of code
to the definition of <hook>
. I should also note that spaces and new lines are significant to TeX and the code needs some comment characters.
Best Answer
What you want to achieve can be done in several ways. First of all let me start with a small hint: The commands
\bf
andit
are obsolete and they don't have an argument. Please see this answer: Despite using backslash dollar sign, error persistsFirst of all you have to decide whether to save the contents in a token or a command. The differences and some explanation to your question are well explained by the great answer of Joseph Wright. Is \toks necessary to define \g@addto@macro? Can token registers be avoided in generel?
Using a command:
Approach 1: using
\g@addto@macro
:\g@addto@macro
is defined in the LaTeX Kernel. Based on the protected sign@
you have to use\makeatletter
...\makeatother
, see: What do \makeatletter and \makeatother do?Approach 2: using package
etoolbox
:The package
etoolbox
defines some helper macros to add new information to a given command. The material can be added before and after the command. Egreg provides a more robust package with the same functionality. The package is calledxpatch
. He also provides a more powerful package with is declared as experimental version, the packageregexpatch
.Here an example with
etoolbox
:The package
etoolbox
provides more useful functionality and can be loaded withxpatch
too.A special and new modern way is the usage of macros of the project LaTeX3 and the language
expl3
. Here you can work with token register as well as sequences. The range is really big. The usage of the new syntax needs some special handling which is explained in the short manualexpl3
. Of course you will find a lot of related questions here at tex.stackexchange.