[comp.text.tex] BNF style: followup request

hugh@phoibos.cs.kun.nl (Hugh Osborne) (11/06/90)

Sorry - when I posted my BNF macros I forgot to ask:

      Could you let me know if they are of any use and, especially
      if you discover (and possibly repair) any bugs?

Thank you,
              Hugh.

jk@cs.man.ac.uk (John Kewley ICL) (11/07/90)

In article <2413@wn1.sci.kun.nl> hugh@phoibos.cs.kun.nl (Hugh Osborne) writes:
>Sorry - when I posted my BNF macros I forgot to ask:
>
>      Could you let me know if they are of any use and, especially
>      if you discover (and possibly repair) any bugs?
>
>Thank you,
>              Hugh.

I found them useful, but not quite perfect since we use a different style
of grammar syntax. We use [ ], { } and { ...} in the syntax as well as the
usual |.

I also got style files from Nick North <ndn@seg.npl.co> and rjc@uk.ac.ed.cstr.
the rjc ones were fairly easy to use, the ndn ones used a tabbing environment
to layout the productions, but Hugh's ones had the advantage of
user-configurable output and a very readable grammar.
--
        J.K.
 
John M. Kewley, ICL, Wenlock Way, West Gorton, Manchester. M12 5DR
Tel:   (+44) 61 223 1301 X2138  Email: jk@r6.cs.man.ac.uk / jk@nw.stl.stc.co.uk

jk@cs.man.ac.uk (John Kewley ICL) (11/09/90)

Due to popular request,
I thought I'd post the style files I received as a response to my request.

Thank you very much to all those who replied.

Here are the files, each with matching example.

        J.K.
 
John M. Kewley, ICL, Wenlock Way, West Gorton, Manchester. M12 5DR
Tel:   (+44) 61 223 1301 X2138  Email: jk@r6.cs.man.ac.uk / jk@nw.stl.stc.co.uk
--------------------------- Cut Here ------------------------------------
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 11/09/1990 07:38 UTC by jk@sc53
# Source directory /ss11/usr/jk/bnf
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1369 -rw-rw-rw- bnf.sty
#   1536 -rw-r--r-- bnf.tex
#    299 -rw-r--r-- bnf2.sty
#    260 -rw-r--r-- bnf2.tex
#   2539 -rw-rw-rw- bnf3.sty
#   7148 -rw-rw-rw- bnf3.tex
#   2002 -rw-r--r-- gram.tex
#    715 -rw-r--r-- gramtest.tex
#
# ============= bnf.sty ==============
if test -f 'bnf.sty' -a X"$1" != X"-c"; then
	echo 'x - skipping bnf.sty (File already exists)'
else
echo 'x - extracting bnf.sty (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'bnf.sty' &&
%From: Nick North <ndn@seg.npl.co>
%
%
%	BSI BNF MACROS
%
\newcommand{\Lit}[1]{`#1'}%             Literals enclosed in quotes
\newcommand{\AltSep}{$ | $}%            Separator for alternative expansions
%
%	A Rule is just a fairly unstructured tabbing environment;
%	first parameter is the left-hand non-terminal,
%	second is the production, in a fairly free style.
%	(The ending semicolon is provided here).
%	Note the use of the indexing command.  When we stick this into
%	document 40, this will have to change: possibly to
%	\index{#1!math syntax} or \index{#1|italic}
%
\newcommand{\Rule}[2]{%
X    \begin{quote}\begin{tabbing}
X        #1\index{#1}\ \ \= = \ \ \= #2 ;  %    Adds production rule to index
X
X    \end{tabbing}\end{quote}%
X    }
%
\newcommand{\dsep}{\\ \> $|$ \>}%       Just to make typing easier!
\newcommand{\dsepl}{\ $|$\ }%           Same-line separator
\newcommand{\OptPt}[1]{[\ #1\ ]}%       was \Opt but that's defined in bsivdm!
\newcommand{\SeqPt}[1]{\{\ #1\ \}}%	was \Seq but defined in vdmsl
\newcommand{\kewd}[1]{\kw{#1}}%         BSI/VDM keywords (maybe use {\bf #1}??)
\newcommand{\Lkewd}[1]{\Lit{\kewd{#1}}}
\newcommand{\Lop}[1]{\Lit{\kw{#1}}}
\newcommand{\Brack}[1]{(\ #1\ )}%       BSI bracketing
\newcommand{\commaList}[1]{#1, \SeqPt{\Lit{,}, #1}}%     Shorthand!!
\newcommand{\ttLit}[1]{\Lit{{\tt #1}}}
\newcommand{\Hex}[1]{\%#1\%}
SHAR_EOF
chmod 0666 bnf.sty ||
echo 'restore of bnf.sty failed'
Wc_c="`wc -c < 'bnf.sty'`"
test 1369 -eq "$Wc_c" ||
	echo 'bnf.sty: original size 1369, current size' "$Wc_c"
fi
# ============= bnf.tex ==============
if test -f 'bnf.tex' -a X"$1" != X"-c"; then
	echo 'x - skipping bnf.tex (File already exists)'
else
echo 'x - extracting bnf.tex (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'bnf.tex' &&
% bnf.sty in action - taken from the Modula-2 standard
\documentstyle[bnf]{article}
X
\begin{document}
\Rule{modula2 document }{
\SeqPt{separator},
\Brack{delimited word, \SeqPt{delimited word \dsepl symbol \dsepl separator} \dsep
X  symbol, \SeqPt{delimited word \dsepl symbol \dsepl separator} } }
X
\Rule{delimited word }{ word, \Brack{separator \dsepl symbol} }
X
\Rule{word }{ identifier \dsepl keyword \dsepl numeric literal \dsepl character number literal }
X
\Rule{identifier }{ full identifier \dsepl portable identifier }
X
\Rule{portable identifier }{ simple letter, \SeqPt{\OptPt{low line}, simple alphanumeric} }
X
\Rule{low line }{ \Lit{\_} }
X
\Rule{full identifier }{ letter, \SeqPt{\OptPt{low line}, national alphanumeric} }
X
%\clause{Keywords}
X
\Rule{keyword }{
\Lit{AND}	\dsepl	\Lit{ARRAY}	\dsepl	\Lit{BEGIN}	\dsepl	\Lit{BY}	\dsep
\Lit{CASE}	\dsepl	\Lit{CONST}	\dsepl	\Lit{DEFINITION}	\dsepl	\Lit{DIV}	\dsep
\Lit{DO}	\dsepl	\Lit{ELSE}	\dsepl	\Lit{ELSIF}	\dsepl	\Lit{END}	\dsep
\Lit{EXIT}	\dsepl	\Lit{EXPORT}	\dsepl	\Lit{FOR}	\dsepl	\Lit{FROM}	\dsep
\Lit{IF}	\dsepl \Lit{IMPLEMENTATION}	\dsepl	\Lit{IMPORT}	\dsepl	\Lit{IN}	\dsep
\Lit{LOOP}	\dsepl	\Lit{MOD}	\dsepl	\Lit{MODULE}	\dsepl	\Lit{NOT}	\dsep
\Lit{OF}	\dsepl	\Lit{OR}	\dsepl	\Lit{POINTER}	\dsepl	\Lit{PROCEDURE}	\dsep
\Lit{QUALIFIED}	\dsepl	\Lit{RECORD}	\dsepl	\Lit{REM}	\dsepl
X	\Lit{REPEAT}	\dsep
\Lit{RETURN}	\dsepl	\Lit{SET}	\dsepl	\Lit{THEN}	\dsepl	\Lit{TO}	\dsep
\Lit{TYPE}	\dsepl	\Lit{UNTIL}	\dsepl	\Lit{VAR}	\dsepl	\Lit{WHILE}	\dsep
\Lit{WITH} }
X
\end{document}
SHAR_EOF
chmod 0644 bnf.tex ||
echo 'restore of bnf.tex failed'
Wc_c="`wc -c < 'bnf.tex'`"
test 1536 -eq "$Wc_c" ||
	echo 'bnf.tex: original size 1536, current size' "$Wc_c"
fi
# ============= bnf2.sty ==============
if test -f 'bnf2.sty' -a X"$1" != X"-c"; then
	echo 'x - skipping bnf2.sty (File already exists)'
else
echo 'x - extracting bnf2.sty (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'bnf2.sty' &&
\def\grammarrule#1{\description \item[\nt{#1} \(\Rightarrow\)]\sf}
\def\endgrammarrule{\enddescription}
\def\nt#1{\ifmmode{\langle\hbox{\sf #1}\rangle}\else {\sf
\(\langle\)#1\(\rangle\)}\fi}
\def\tm#1{\mbox{`{\tt #1}'}}
\def\den#1{{\lscott \mbox{\sf #1} \rscott}}
\def\|{\(|\)}
\def\star{\(^*\)\ }
SHAR_EOF
chmod 0644 bnf2.sty ||
echo 'restore of bnf2.sty failed'
Wc_c="`wc -c < 'bnf2.sty'`"
test 299 -eq "$Wc_c" ||
	echo 'bnf2.sty: original size 299, current size' "$Wc_c"
fi
# ============= bnf2.tex ==============
if test -f 'bnf2.tex' -a X"$1" != X"-c"; then
	echo 'x - skipping bnf2.tex (File already exists)'
else
echo 'x - extracting bnf2.tex (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'bnf2.tex' &&
\documentstyle[bnf2]{article}
X
\begin{document}
X
\begin{grammarrule}{list}
X         \tm{[} ( \nt{atom} \| \nt{list} )\star  \{ \tm{\|} \nt{atom} \} \tm{]}
\end{grammarrule}
\begin{grammarrule}{atom}
X      { \tm{a} \| \tm{b} }
\end{grammarrule}
X
\end{document}
SHAR_EOF
chmod 0644 bnf2.tex ||
echo 'restore of bnf2.tex failed'
Wc_c="`wc -c < 'bnf2.tex'`"
test 260 -eq "$Wc_c" ||
	echo 'bnf2.tex: original size 260, current size' "$Wc_c"
fi
# ============= bnf3.sty ==============
if test -f 'bnf3.sty' -a X"$1" != X"-c"; then
	echo 'x - skipping bnf3.sty (File already exists)'
else
echo 'x - extracting bnf3.sty (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'bnf3.sty' &&
%Sender: root@sci.kun.nl
% These are the BNF style macros. In the documentation it is assumed
% that you will place these in a file called "bnf.sty"
X
\def\@actifygrammarchars{\catcode`\ \active\catcode`\:\active\catcode`\,\active\catcode`\;\active\catcode`\.\active\catcode`\<\active\catcode`\>\active}
\def\@deactifygrammarchars{\@makeother\ \@makeother\:\@makeother\,\@makeother\;\@makeother\.\@makeother\<\@makeother\>}
X
\begingroup
X  \@actifygrammarchars
X   \gdef\@defcolon#1{
X    \catcode`\:\active
X    \def:{\def\newline{\hfill\break\hspace*{2em}}{\@deactifygrammarchars #1}}}
X   \gdef\@defcomma#1{
X    \catcode`\,\active
X    \def,{\def\newline{\hfill\break\hspace*{4em}}{\@deactifygrammarchars #1}}}
X   \gdef\@defsemicolon#1{
X    \catcode`\;\active
X    \def;{\def\newline{\hfill\break\hspace*{2em}}{\@deactifygrammarchars #1}}}
X   \gdef\@defperiod#1{
X    \catcode`\.\active
X    \def.{\def\newline{\vskip10pt plus10pt minus5pt}{\@deactifygrammarchars #1}}}
X   \gdef\@defnonterminal#1{
X    \def\@first##1##2{##1}
X    \def\@second##1##2{##2}
X    \catcode`\<\active
X    \def<{{\@deactifygrammarchars \@first#1}}
X    \catcode`\>\active
X    \def>{{\@deactifygrammarchars \@second#1}}}
\endgroup
X
\def\quotesymbol{\begingroup\@makeother\""\endgroup}
\def\lessthan{\begingroup\@makeother\<<\endgroup}
\def\greaterthan{\begingroup\@makeother\>>\endgroup}
X
\newif\if@string
\@stringfalse
\begingroup
X  \catcode`\"\active
X  \gdef\@defquote#1{
X    \def\@openquote##1##2{##1}
X    \def\@closequote##1##2{##2}
X	\catcode`\"\active
X    \def"{\if@string\@closequote#1\endgroup\@stringfalse
X          \else\@openquote#1\begingroup\@deactifygrammarchars\@stringtrue\fi}}
\endgroup
X
\newif\if@colon
\newif\if@semicolon
\newif\if@period
\newif\if@comma
\newif\if@quote
\newif\if@nonterminal
X
\newenvironment{grammar}%
X  {\begin{quote}%
X   \@colonfalse%
X   \@semicolonfalse%
X   \@periodfalse%
X   \@commafalse%
X   \@quotefalse%
X   \@nonterminalfalse%
X   \@dogrammarchars}%
X  {\@deactifygrammarchars%
X   \end{quote}}
X
\def\@dogrammarchars{
X  \@ifnextchar [{\@getchardef}{\@defaultchardefs}}
X
\def\@getchardef[(#1)#2]{
X  \@dogrammarchar{#1}[#2]
X  \@dogrammarchars}
X
\def\@dogrammarchar#1[#2]{
X  \csname if@#1\endcsname\else
X  \csname @def#1\endcsname{#2}\csname @#1true\endcsname\fi}
X
\def\@defaultchardefs{
X   \if@quote\else\@defquote{{``}{''}}\fi%
X   \if@nonterminal\else\@defnonterminal{<>}\fi%
X   \if@colon\else\@defcolon{:\\}\fi%
X   \if@semicolon\else\@defsemicolon{;\\}\fi%
X   \if@period\else\@defperiod{.\\}\fi%
X   \if@comma\else\@defcomma{, }\fi}%
X
X
SHAR_EOF
chmod 0666 bnf3.sty ||
echo 'restore of bnf3.sty failed'
Wc_c="`wc -c < 'bnf3.sty'`"
test 2539 -eq "$Wc_c" ||
	echo 'bnf3.sty: original size 2539, current size' "$Wc_c"
fi
# ============= bnf3.tex ==============
if test -f 'bnf3.tex' -a X"$1" != X"-c"; then
	echo 'x - skipping bnf3.tex (File already exists)'
else
echo 'x - extracting bnf3.tex (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'bnf3.tex' &&
\documentstyle[bnf3]{article}
\title{Pretty Printing Context Free Grammars}
\author{Hugh Osborne\\
X        Department of Informatics,\\
X        Faculty of Mathematics and Informatics,\\
X        University of Nijmegen,\\
X        Toernooiveld,\\
X        6525 ED Nijmegen,\\
X        The Netherlands.\\
X        tel. +31.(0)80.652599\\
X        email {\tt hugh@cs.kun.nl}}
X
\begin{document}
\maketitle
\subsection{The grammar Environment}
The {\tt grammar}
environment will take a context free grammar, written using the notation
used in~LP81\footnote{Harry R.\ Lewis and Christos H.\ 
Papadimitriou, {\sl Elements of the Theory of Computation,}
Prentice-Hall, 1981} and pretty print the grammar. The {\tt grammar}
environment has up to five optional parameters, which specify the notation to
be used to print the grammar. Note that whichever notation is chosen for
the output, the {\tt grammar} environment only recognises the LP81~notation in the input.
X
A short summary of the notation used in~LP81 is presented here for
those readers not familiar with it. It is assumed that the reader is
familiar with context free grammars.
\begin{itemize}
X \item There is a ``:'' between the left hand side of a rule and the right hand of a rule
X \item Two alternatives within a rule are separated by a ``;''
X \item A ``,'' is placed between members of the same alternative
X \item Each rule ends with a ``.''
\end{itemize}
A context free grammar for this notation is presented in
figure~\ref{grammar}.
X
The optional parameters of the {\tt grammar} environment are all of the
form \verb![(!{\sc symbol name}\verb!)!{\sc replacement}\verb!]!, where
{\sc symbol name} is one of ``{\tt colon}'', ``{\tt semicolon}'', ``{\tt
period}'', ``{\tt comma}'' and ``{\tt quote}''. {\sc replacement} is then the text\footnote{In the case of ``{\tt quote}'', the texts --- the first text
is the replacement for an opening quote, the second for a closing quote.} that
will replace the symbol specified by {\sc symbol name}. Note that a new
line (\verb!\\!) can be included in the replacement text, in which case
the output will automatically start on a new line after each occurrence
of the symbol specified. The default values are
\begin{itemize}
X  \item \verb![(!colon\verb!){:\\}]!
X  \item \verb![(!semicolon\verb!){;\\}]!
X  \item \verb![(!period\verb!){.\\}]!
X  \item \verb![(!comma\verb!){,}]!
X  \item \verb![(!quote\verb!){``}{''}]!
\end{itemize}
X
Strings in the grammar environment are indicated by double-quote symbols
(\verb!"!). The colon, semicolon, period and comma have no special
significance within a string, but are the same simple characters they
are outside the grammar environment. A double-quote symbol can be
produced by using the \verb!\quotesymbol! command.
X
All of these features are demonstrated below. The text:
\begin{verbatim}
\begin{grammar}
X  [(colon){::$\Rightarrow$}]
X  [(semicolon){ $|$}]
X  [(period){ \rule{1ex}{1ex}\\}]
X  [(quote){$\langle$}{$\rangle$}]
grammar environment:\\
X  "\verb!\begin{grammar}!",\\
X	optional parameters,\\
X	 context free grammar,\\
X	  "\verb!\end{grammar}!".
optional parameters:\\
X  "[",optional parameter,"]",\\
X   optional parameters;.
optional parameter:\\
X  "(", specification, ")",\\
X   \LaTeX\ strings.
\LaTeX\ strings:\\
X   \LaTeX\ string;\\
X   "\{",\LaTeX\ string,"\}",\\
X   \LaTeX\ strings.
specification:\\
X  "{\tt colon}";\\
X  "{\tt semicolon}";\\
X  "{\tt period}";\\
X  "{\tt comma}";\\
X  "{\tt quote}".
context free grammar:\\
X  rule,\\
X  context free grammar;.
rule:\\
X  nonterminal,":",\\
X  alternatives,".".
alternatives:\\
X  alternative,";",\\
X   alternatives;.
alternative:
X  members;.
members:\\
X  member,",",members;\\
X  member.
member:\LaTeX\ string,string.
string:"{\tt \quotesymbol}",
X  \LaTeX\ string ,
X  "{\tt \quotesymbol}".
\end{grammar}
\end{verbatim}
produces the following output:
\begin{grammar}
X  [(colon){::$\Rightarrow$}]
X  [(semicolon){ $|$}]
X  [(period){ \rule{1ex}{1ex}\\}]
X  [(quote){$\langle$}{$\rangle$}]
grammar environment:\\
X  "\verb!\begin{grammar}!",\\
X	optional parameters,\\
X	 context free grammar,\\
X	  "\verb!\end{grammar}!".
optional parameters:\\
X  "[",optional parameter,"]",\\
X   optional parameters;.
optional parameter:\\
X  "(", specification, ")",\\
X   \LaTeX\ strings.
\LaTeX\ strings:\\
X   \LaTeX\ string;\\
X   "\{",\LaTeX\ string,"\}",\\
X   \LaTeX\ strings.
specification:\\
X  "{\tt colon}";\\
X  "{\tt semicolon}";\\
X  "{\tt period}";\\
X  "{\tt comma}";\\
X  "{\tt quote}".
context free grammar:\\
X  rule,\\
X  context free grammar;.
rule:\\
X  nonterminal,":",\\
X  alternatives,".".
alternatives:\\
X  alternative,";",\\
X   alternatives;.
alternative:
X  members;.
members:\\
X  member,",",members;\\
X  member.
member:\LaTeX\ string,string.
string:"{\tt \quotesymbol}",
X  \LaTeX\ string ,
X  "{\tt \quotesymbol}".
\end{grammar}
\subsection{The grammar environment: Update}
The {\tt grammar} environment has been extended to allow the use of the
`\verb!<!' and `\verb!>!' symbols to delimit nonterminals in the grammar
(in a manner reminiscent of Backus-Naur form). These symbols can then be
redefined in the same way as the `\verb!"!' symbol by means of an
optional paramter at the start of the environment. The {\sc symbol name}
part is then ``\verb!nonterminal!''. The default value is to use the
symbols themselves. If the symbols have been redefined, the `\verb!<!'
and `\verb!>!' symbols can be produced using \verb!\lessthan! and
\verb!\greaterthan! respectively.
\begin{verbatim}
\begin{grammar}
X      [(colon){$\rightarrow$}]
X      [(semicolon)$|$]
X      [(comma){}]
X      [(period){\\}]
X      [(quote){\begin{bf}}{\end{bf}}]
X      [(nonterminal){$\langle$}{$\rangle$}]
<expression>:<number>;\\
X             <number>, <relational operator>, <number>.
<number>:<digit>;<digit>,<number>.
<digit>:"0";"1";"2";"3";"4";"5";"6";"7";"8";"9".
<relational operator>:"$=$";"$\lessthan\greaterthan$";
X                      "$\lessthan$";"$\greaterthan$";
X                      "$\lessthan=$";"$\greaterthan=$";"in".
\end{grammar}
\end{verbatim}
gives
\begin{grammar}
X      [(colon){$\rightarrow$}]
X      [(semicolon)$|$]
X      [(comma){}]
X      [(period){\\}]
X      [(quote){\begin{bf}}{\end{bf}}]
X      [(nonterminal){$\langle$}{$\rangle$}]
<expression>:<number>;\\
X             <number>, <relational operator>, <number>.
<number>:<digit>;<digit>,<number>.
<digit>:"0";"1";"2";"3";"4";"5";"6";"7";"8";"9".
<relational operator>:"$=$";"$\lessthan\greaterthan$";
X                      "$\lessthan$";"$\greaterthan$";
X                      "$\lessthan=$";"$\greaterthan=$";"in".
\end{grammar}
There is one feature of the {\tt grammar} environment which could be
considered a bug. The normal line breaking routine is still in force
inside a {\tt grammar} environment but a new line produced by \LaTeX\
will {\em not} use the {\tt grammar} environment's layout. {\em Only
newlines given explicitly with a \verb!\\! or \verb!\newline! command,
or implicitly by means of one the redefined symbols (`\verb!:!',
`\verb!;!' etc.) will use the {\tt grammar} layout!}\/ It is therefore
recommended that you aviod this situation by providing the layout
explicitly.
\end{document}
X
X
SHAR_EOF
chmod 0666 bnf3.tex ||
echo 'restore of bnf3.tex failed'
Wc_c="`wc -c < 'bnf3.tex'`"
test 7148 -eq "$Wc_c" ||
	echo 'bnf3.tex: original size 7148, current size' "$Wc_c"
fi
# ============= gram.tex ==============
if test -f 'gram.tex' -a X"$1" != X"-c"; then
	echo 'x - skipping gram.tex (File already exists)'
else
echo 'x - extracting gram.tex (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gram.tex' &&
% -*- latex -*-
%
% an attempt at minimal grammar environment for LaTeX
%
% counter to automatically number the rules
%
\newcounter{grammarcounter}
\newcounter{grammartempcounter}
%
% grammer counter punctuation
%
\newcommand{\grammarcounterpunc}{\mbox{.}}
%
% the becomes (goes to) symbol
%
\newcommand{\grammarbecomes}{\mbox{$::=$}}
%
% the alternate becomes symbol
%
\newcommand{\grammaralternate}{\mbox{$\mid$}}
%
% the bracketting for non-terminals
%
\newcommand{\grammarntermleft}{\mbox{$<$}}
\newcommand{\grammarntermright}{\mbox{$>$}}
%
% a non-terminal
%
\newcommand{\gntm}[1]{\mbox{\grammarntermleft#1\grammarntermright}}
%
% the bracketting for terminals
%
\newcommand{\grammartermleft}{\mbox{`\,}}
\newcommand{\grammartermright}{\mbox{\,'}}
%
% a terminal
%
\newcommand{\gtm}[1]{\mbox{\grammartermleft#1\grammartermright}}
%
% start a new set of lhs productions
%
\newcommand{\glhsitem}[1]{%
\thegrammarcounter\grammarcounterpunc\hspace{1em}\gntm{#1}\hspace{1em}}
%
\newcommand{\glhs}[1]{\refstepcounter{grammarcounter}%
\item [\glhsitem{#1}\hfill\grammarbecomes] }
%
% start a new set of rhs productions
%
\newcommand{\grhs}{\item }
%
% non-terminal nominal length for list label length
%   uses are nonterminal of 10 M's
%
\newlength{\glhsitemlength}
\settowidth{\glhsitemlength}{\glhsitem{MMMMMMMMMMMM}}
%
% The environment definition to get things started
%
\newenvironment{grammar}{
X \singlespace
X \begin{list}%
{\thegrammarcounter\grammarcounterpunc\hfill\grammaralternate}%
{\usecounter{grammarcounter}%
\setlength{\labelwidth}{\glhsitemlength}%
\setlength{\leftmargin}{\labelwidth}\addtolength{\leftmargin}{\labelsep}%
}
X \raggedright
X }{
X \end{list}}
%
% interrupt a grammar
%
\newcommand{\grammarint}{%
\setcounter{grammartempcounter}{\value{grammarcounter}}%
\end{grammar}}
%
% continue the grammar just interrupted
%
\newcommand{\grammarcont}{%
\begin{grammar}%
\setcounter{grammarcounter}{\value{grammartempcounter}}}
%
% extra little items
%
\newcommand{\gempty}{{\em empty}}
SHAR_EOF
chmod 0644 gram.tex ||
echo 'restore of gram.tex failed'
Wc_c="`wc -c < 'gram.tex'`"
test 2002 -eq "$Wc_c" ||
	echo 'gram.tex: original size 2002, current size' "$Wc_c"
fi
# ============= gramtest.tex ==============
if test -f 'gramtest.tex' -a X"$1" != X"-c"; then
	echo 'x - skipping gramtest.tex (File already exists)'
else
echo 'x - extracting gramtest.tex (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gramtest.tex' &&
% -*- latex -*-
This is a grammar test.
X
\begin{grammar}
\glhs{start symbol} \gntm{foo} \gtm{and} \gntm{more} \gntm{foo} \label{RHA}
X  her I attempt a rather long right hand side to see how the spacing turns out
X  for long alternatives
\grhs bar and more bar \label{RHC}
\glhs{foo} lets check the fun stuff \label{RHE}
\grhs and check again \label{RHF}
\grammarint
X
RHA is \ref{RHA}.
RHC is \ref{RHC}.
RHE is \ref{RHE}.
RHF is \ref{RHF}.
X
\grammarcont
\glhs{start symbol} \gntm{foo} \gtm{and} \gntm{more} \gntm{foo}
X  here I attempt a rather long right hand side to see how the spacing turns out
X  for long alternatives
\grhs bar and more bar
\glhs{foo} lets check the fun stuff
\grhs and check again
\end{grammar}
SHAR_EOF
chmod 0644 gramtest.tex ||
echo 'restore of gramtest.tex failed'
Wc_c="`wc -c < 'gramtest.tex'`"
test 715 -eq "$Wc_c" ||
	echo 'gramtest.tex: original size 715, current size' "$Wc_c"
fi
exit 0
--
        J.K.
 
John M. Kewley, ICL, Wenlock Way, West Gorton, Manchester. M12 5DR
Tel:   (+44) 61 223 1301 X2138  Email: jk@r6.cs.man.ac.uk / jk@nw.stl.stc.co.uk