chiark / gitweb /
Fix dates and version numbers in the package files.
[mdwtools] / syntax.dtx
1 % \begin{meta-comment} <general public licence>
2 %%
3 %% syntax package -- typesetting syntax descriptions
4 %% Copyright (c) 1996, 2002, 2015, 2020 Mark Wooding
5 %%
6 %% This program is free software; you can redistribute it and/or modify
7 %% it under the terms of the GNU General Public License as published by
8 %% the Free Software Foundation; either version 2 of the License, or
9 %% (at your option) any later version.
10 %%
11 %% This program is distributed in the hope that it will be useful,
12 %% but WITHOUT ANY WARRANTY; without even the implied warranty of
13 %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 %% GNU General Public License for more details.
15 %%
16 %% You should have received a copy of the GNU General Public License
17 %% along with this program; if not, write to the Free Software
18 %% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 %%
20 % \end{meta-comment}
21 %
22 % \begin{meta-comment} <Package preamble>
23 %<+package>\NeedsTeXFormat{LaTeX2e}
24 %<+package>\ProvidesPackage{syntax}
25 %<+package>                [2020/09/06 1.14.0 Syntax typesetting]
26 % \end{meta-comment}
27 %
28 % \CheckSum{1628}
29 %% \CharacterTable
30 %%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
31 %%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
32 %%   Digits        \0\1\2\3\4\5\6\7\8\9
33 %%   Exclamation   \!     Double quote  \"     Hash (number) \#
34 %%   Dollar        \$     Percent       \%     Ampersand     \&
35 %%   Acute accent  \'     Left paren    \(     Right paren   \)
36 %%   Asterisk      \*     Plus          \+     Comma         \,
37 %%   Minus         \-     Point         \.     Solidus       \/
38 %%   Colon         \:     Semicolon     \;     Less than     \<
39 %%   Equals        \=     Greater than  \>     Question mark \?
40 %%   Commercial at \@     Left bracket  \[     Backslash     \\
41 %%   Right bracket \]     Circumflex    \^     Underscore    \_
42 %%   Grave accent  \`     Left brace    \{     Vertical bar  \|
43 %%   Right brace   \}     Tilde         \~}
44 %%
45 %
46 % \begin{meta-comment} <driver>
47 %
48 %<*driver>
49 %
50 % This hacking will remember the old default underscore character.  Even if
51 % T1 fonts are being used, it will get the grotty version.  Why is it that
52 % all of the encoding handling ends up looking like this?
53 %
54 \expandafter\let\expandafter\oldus\csname?\string\textunderscore\endcsname
55 %
56 \input{mdwtools}
57 \describespackage{syntax}
58 \DeclareRobustCommand\syn{\package{syntax}}
59 \mdwdoc
60 %</driver>
61 %
62 % \end{meta-comment}
63 %
64 % \section{User guide}
65 %
66 % \subsection{Introduction}
67 %
68 % The \syn\ package provides a number of commands and environments which
69 % extend \LaTeX\ and allow you to typeset good expositions of syntax.
70 %
71 % The package provides several different types of features: probably not all
72 % of these will be required by every document which needs the package:
73 % \begin{itemize}
74 % \item A system of abbreviated forms for typesetting syntactic items.
75 % \item An environment for typesetting BNF-type grammars
76 % \item A collection of environments for building syntax diagrams.
77 % \end{itemize}
78 %
79 % The package also includes some other features which, while not necessarily
80 % syntax-related, will probably come in handy for similar types of document:
81 % \begin{itemize}
82 % \item An abbreviated notation for verbatim text, similar to the
83 %       \package{shortvrb} package.
84 % \item A slightly different underscore character, which works as expected
85 %       in text and maths modes.
86 % \end{itemize}
87 %
88 % \subsection{The abbreviated verbatim notation}
89 %
90 % In documents describing programming languages and libraries, it can become
91 % tedious to type "\verb|...|" every time.  Like Frank Mittelbach's
92 % \package{shortvrb} package, \syn\ provides a way of setting up single-^^A
93 % character abbreviations.  The only real difference between the two is that
94 % the declarations provided by \syn\ obey \LaTeX's normal scoping rules.
95 %
96 % \DescribeMacro\shortverb
97 % You can set up a character as a `verbatim shorthand' character using the
98 % |\shortverb| command.  This takes a single argument, which should be a
99 % single-character control sequence containing the character you want to use.
100 % So, for example, the command
101 % \begin{listing}
102 %\shortverb{\|}
103 % \end{listing}
104 % would set up the `"|"' character to act as a verbatim delimiter.  While a
105 % |\shortverb| declaration is in force, any text surrounded by (in this case)
106 % vertical bar characters will be typeset as if using the normal |\verb|
107 % command.
108 %
109 % \DescribeEnv{shortverb}
110 % Since \LaTeX\ allows any declaration to be used as an environment, you can
111 % use a \env{shortverb} environment to delimit the text over which your
112 % character is active:
113 % \begin{listing}
114 %Some text...
115 %\begin{shortverb}{\|}
116 %...
117 %\end{shortverb}
118 % \end{listing}
119 %
120 % \DescribeMacro\unverb
121 % If you want to disable a |\shortverb| character without ending the scope
122 % of other declarations, you can use the |\unverb| command, passing it
123 % a character as a control sequence, in the same way as above.
124 %
125 % The default \TeX/\LaTeX\ underscore character is rather too short for
126 % use in identifiers.  For example:
127 %
128 % \begingroup \let\_=\oldus
129 % \begin{demo}{Old-style underscores}
130 %Typing long underscore-filled
131 %names, like big\_function\_name,
132 %is normally tedious.  The normal
133 %positioning of the underscore
134 %is wrong, too.
135 % \end{demo}
136 % \endgroup
137 %
138 % The \syn\ package redefines the |\_| command to draw a more attractive
139 % underscore character.  It also allows you to use the |_|~character
140 % directly to produce an underscore outside of maths mode: |_|~behaves
141 % as a subscript character as usual inside maths mode.
142 %
143 % \begin{demo}{New \syn\ underscores}
144 %You can use underscore-filled
145 %names, like big_function_name,
146 %simply and naturally.  Of
147 %course, subscripts still work
148 %normally in maths mode, e.g.,
149 %$x_i$.
150 % \end{demo}
151 %
152 % \subsection{Typesetting syntactic items}
153 % \begin{synshorts}
154 %
155 % The \syn\ package provides some simple commands for typesetting syntactic
156 % items.
157 %
158 % \DescribeMacro\synt
159 % Typing "\\synt{"<text>"}" typesets <text> as a \lq non-terminal',
160 % in italics and surrounded by angle brackets.  If you use "\\synt" a lot,
161 % you can use the incantation
162 % \begin{listing}
163 %\def\<#1>{\synt{#1}}
164 % \end{listing}
165 % to allow you to type "\\<"<text>">" as an alternative to
166 % "\\synt{"<text>"}".
167 %
168 % \DescribeMacro\lit
169 % You can also display literal text, which the reader should type directly,
170 % using the "\\lit" command.
171 %
172 % \begin{demo}{Use of \cmd\lit}
173 %Type \lit{ls} to display a
174 %list of files.
175 % \end{demo}
176 %
177 % Note that the literal text appears in quotes.  To suppress the quotes,
178 % use the `*' variant.
179 %
180 % The "\\lit" command produces slightly better output than "\\verb" for
181 % running text, since the spaces are somewhat narrower.  However, "\\verb"
182 % allows you to type arbitrary characters, which are treated literally,
183 % whereas you must use commands such as "\\{" to use special characters
184 % within the argument to "\\lit".  Of course, you can use "\\lit" anywhere
185 % in the document: "\\verb" mustn't be used inside a command argument.
186 % \end{synshorts}
187 %
188 % \subsection{Abbreviated forms for syntactic items}
189 %
190 % It would be very tedious to require the use of commands like |\synt|
191 % when building syntax descriptions like BNF grammars.  It would also make
192 % your \LaTeX\ source hard to read.  Therefore, \syn\ provides some
193 % abbreviated forms which make typesetting syntax quicker and easier.
194 %
195 % Since the abbreviated forms use several characters which you may want to
196 % use in normal text, they aren't enabled by default.  They only work
197 % with special commands and environments provided by the \syn\ package.
198 %
199 % The abbreviated forms are shown in the table below:
200 %
201 % \begin{tab}[\synshorts]{ll}                                       \hline
202 % \bf Input        & \bf Output                                  \\ \hline
203 % "<some text>"    & <some text>                                 \\
204 % "`some text'"    & `some text'                                 \\
205 % "\"some text\""  & "some text"                                 \\ \hline
206 % \end{tab}
207 %
208 % Within one of these abbreviated forms, text is treated more-or-less
209 % verbatim:
210 % \begin{itemize}
211 %
212 % \item Any |$|, |%|, |^|, |&|, |{|, |}|, |~| or |#| characters are treated
213 %       literally: their normal special meanings are ignored.
214 %
215 % \item Other special characters, with the exception of |\|, are also treated
216 %       literally: this includes any characters made special by |\shortverb|.
217 %
218 % \end{itemize}
219 %
220 % However, the |\| character retains its meaning.  Since the brace
221 % characters are not recognised, most commands can't be used within
222 % abbreviated forms.  However, you can use special commands to type some
223 % of the remaining special characters:
224 %
225 % \begin{tab}[\synshorts]{ll}                                       \hline
226 % \bf Command   & \bf Result                                     \\ \hline
227 % "\\\\"        & A `\\' character                               \\
228 % "\\>"         & A `>' character                                \\
229 % "\\'"         & A `\'' character                               \\
230 % "\\\""        & A `"' character                                \\
231 % "\\\ "        & A `\ ' character (not a space)                 \\ \hline
232 % \end{tab}
233 %
234 % Note that |\\|, |\>|, |\"| and \verb*|\ | are only useful in a |\tt| font,
235 % i.e., inside |`...'| and |"..."| forms, since the characters don't exist
236 % in normal fonts.  The |\>|, |\"| and |\'| commands are only provided so
237 % you can use these characters within |<...>|, |"..."| and |`...'| forms
238 % respectively: in the other forms, there is no need to use the special
239 % command.
240 %
241 % In addition, when the above abbreviations are enabled, the character "|"
242 % is set to typeset a \syntax{|} symbol, which is conventionally used to
243 % separate alternatives in syntax descriptions.
244 %
245 % \DescribeMacro\syntax
246 % Normally, these abbreviated forms are enabled only within special
247 % environments, such as \env{grammar} and \env{syntdiag}.  To use them
248 % in running text, use the |\syntax| command.  The abbreviations are made
249 % active within the argument of the |\syntax| command.\footnote{^^A
250 %   The argument of the \cmd\syntax\ command may contain commands such
251 %   as \cmd\verb, which are normally not allowed within arguments.
252 % }  Note that you cannot use the |\syntax| command within the argument
253 % of another command.
254 %
255 % \DescribeMacro\synshorts
256 % \DescribeEnv{synshorts}
257 % You can also enable the syntax shortcuts using the |\synshorts| declaration
258 % or the \env{synshorts} environment.  This enables the syntax shortcuts
259 % until the scope of the declaration ends.
260 %
261 % \DescribeMacro\synshortsoff
262 % If syntax shortcuts are enabled, you can disable them using the
263 % |\synshortsoff| declaration.
264 %
265 % \subsection{The \env{grammar} environment}
266 %
267 % \DescribeEnv{grammar}
268 % For typesetting formal grammars, for example, of programming languages,
269 % the \syn\ package provides a \env{grammar} environment.  Within this
270 % environment, the abbreviated forms described above are enabled.
271 %
272 % Within the environment, separate production rules should be separated by
273 % blank lines.  You can use the normal |\\| command to perform line-breaking
274 % of a production rule.  Note that a production rule must begin with a
275 % nonterminal name enclosed in angle brackets (|<| \dots |>|), followed by
276 % any decorative material, whitespace, some kind of production operator
277 % (usually `::=') and then some more whitespace.  You can control how this
278 % text is actually typeset, however.
279 %
280 % \DescribeMacro{\[[}
281 % \DescribeMacro{\]]}
282 % You can use syntax diagrams (see below) instead of a straight piece of BNF
283 % by enclosing it in a |\[[| \dots |\]]| pair.  Note that you can't mix
284 % syntax diagrams and BNF in a production rule, and you will get something
285 % which looks very strange if you try.
286 %
287 % \DescribeMacro\alt
288 % In addition, a command |\alt| is provided for splitting long production
289 % rules over several lines: the |\alt| command starts a new line and places
290 % a \syntax{|} character slightly in the left margin.  This is useful when
291 % a symbol has many alternative productions.
292 %
293 % \begin{demo}[w]{The \env{grammar} environment}
294 %\begin{grammar}
295 %<statement> ::= <ident> `=' <expr>
296 %  \alt `for' <ident> `=' <expr> `to' <expr> `do' <statement>
297 %  \alt `{' <stat-list> `}'
298 %  \alt <empty>
299 %
300 %<stat-list> ::= <statement> `;' <stat-list> | <statement>
301 %\end{grammar}
302 % \end{demo}
303 %
304 % You can modify the appearance of grammars using three length parameters:
305 %
306 % \begin{description} \setdescriptionlabel{\cmd{#1}}
307 %
308 % \item [\grammarparsep] is the amount of space inserted between production
309 %       rules.  It is a rubber length whose default value is 8\,pt, with
310 %       1\,pt of stretch and shrink.
311 %
312 % \item [\grammarindent] is the amount by which the right hand side of a
313 %       production rule is indented from the left margin.  It is a rigid
314 %       length.  Its default value is 2\,em.
315 %
316 % \end{description}
317 %
318 % \DescribeMacro\grammarlabelx
319 % You can also control how the `label' is typeset by redefining the
320 % |\grammarlabelx| command.  The command is given three arguments: the name
321 % of the nonterminal (which was enclosed in angle brackets), the following
322 % decorative material, and the `production operator'.  The command is
323 % expected to produce the label.  By default, it typesets the nonterminal
324 % name using |\synt| followed by the decoration, and the operator, at
325 % opposite ends of the label, separated by an |\hfill|.
326 %
327 % \DescribeMacro\grammarlabel
328 % For compatibility, if there is no decorative material, the macro
329 % |\grammarlabel| is called instead, with just two arguments: the nonterminal
330 % name and the operator.  The default implementation of |\grammarlabel| just
331 % calls |\grammarlabelx| with empty decoration.
332 %
333 % \subsection{Syntax diagrams}
334 %
335 % A full formal BNF grammar can be somewhat overwhelming for less technical
336 % readers.  Documents aimed at such readers tend to display grammatical
337 % structures as \emph{syntax diagrams}.
338 %
339 % \DescribeEnv{syntdiag}
340 % A syntax diagram is always enclosed in a \env{syntdiag} environment.  You
341 % should think of the environment as enclosing a new sort of \LaTeX\ mode:
342 % trying to type normal text into a syntax diagram will result in very ugly
343 % output.  \LaTeX\ ignores spaces and return characters while in syntax
344 % diagram mode.
345 %
346 % The syntax of the environment is very simple:
347 %
348 % \begin{grammar}
349 % <synt-diag-env> ::= \[[
350 %   "\\begin{syntdiag}"
351 %   \begin{stack} \\ "[" <decls> "]" \end{stack}
352 %   <text>
353 %   "\\end{syntdiag}"
354 % \]]
355 % \end{grammar}
356 %
357 % The \<decls> contain any declarations you want to insert, to control
358 % the environment.  The parameters to tweak are described below.
359 %
360 % Within a syntax diagram, you can include syntactic items using the
361 % abbreviated forms described elsewhere.  The output from these forms is
362 % modified slightly in syntax diagram mode so that the diagram looks
363 % right.
364 %
365 % I probably ought to point out now that the syntax diagram typesetting
366 % commands produce beautiful-looking diagrams with all the rules and curves
367 % accurately positioned.  Some device drivers don't position these objects
368 % correctly in their output.  I've had particular trouble with |dvips|.  I'll
369 % say it again: it's not my fault!
370 %
371 % \DescribeEnv{syntdiag*}
372 % The \env{syntdiag} environment only works in paragraph mode, and it acts
373 % rather like a paragraph, splitting over several lines when appropriate.
374 % If you just want to typeset a snippet of a syntax diagram, you can
375 % use the starred environment \env{syntdiag$*$}.
376 %
377 % \begin{grammar}
378 % <synt-diag-star-env> ::= \[[
379 %   "\\begin{syntdiag*}"
380 %   \begin{stack} \\ "[" <decls> "]" \end{stack}
381 %   \begin{stack} \\ "[" <width> "]" \end{stack}
382 %   <text>
383 %   "\\end{syntdiag*}"
384 % \]]
385 % \end{grammar}
386 %
387 % When typesetting little demos like this, it's not normal to fully adorn
388 % the syntax diagram with the full double arrows
389 % (`\begin{syntdiag*}[\left{>>-}\right{-><}]\tok{$\cdots$}\end{syntdiag*}').
390 % The two declarations \syntax{"\\left{"<arrow>"}" and "\\right{"<arrow>"}"}
391 % allow you to choose the arrows on each side of the syntax diagram snippet.
392 % The possible values of \<arrow> are shown in the table-ette below:
393 %
394 % ^^A Time to remember what I learned about tables while writing mdwtab.
395 % ^^A Just for the embarassment factor, here's the number of attempts I
396 % ^^A took to get the table below to look right: __6.  Hmm... not as bad
397 % ^^A as I expected.  Most of them were fine-tuning things.
398 %
399 % \medskip                                      ^^A Leave a vertical gap
400 % \hbox to\columnwidth{\hfil\vbox{\tabskip=0pt  ^^A Centre it horizontally
401 % \sdsize \csname sd@setsize\endcsname          ^^A Position syntdiag arrows
402 % \halign to .5\columnwidth{                    ^^A Set the table width
403 %   &\ttfamily\ignorespaces#\unskip\hfil\tabskip=0pt ^^A Typeset the name
404 %   &\quad\csname sd@arr@#\endcsname\hfil       ^^A Typeset the arrow
405 %   &\setbox0=\hbox{#}\tabskip=0pt plus 1fil\cr ^^A Stretch between columns
406 %   >>-&>>-&   &>-&>-&   &->&->\cr
407 %   -><&-><&   &...&...& &-&-\cr
408 % }}\hfil}                                      ^^A Close the boxing
409 % \medskip                                      ^^A And leave another gap
410 %
411 % These declarations should be used only in the optional argument to the
412 % \env{syntdiag$*$} command.  The second optional argument to the
413 % environment, if specified, fixes the width of the syntax diagram snippet;
414 % if you omit this argument, the diagram is made just wide enough to
415 % fit everything in.
416 %
417 % \begin{figure}
418 % \begin{demo}[w]{Example of \env{syntdiag$*$}}
419 %\newcommand{\bs}[2]{%
420 %  \begin{minipage}{1.6in}%
421 %  \begin{syntdiag*}[\left{#1}\right{#2}][1.6in]%
422 %}
423 %\newcommand{\es}{\end{syntdiag*}\end{minipage}}
424 %
425 %\begin{center}
426 %\begin{tabular}{cl}                                      \\ \hline
427 %\bf Construction    & \bf Meaning                        \\ \hline
428 %\bs {>>-} {...} \es & Start of syntax diagram            \\
429 %\bs {...} {-><} \es & End of syntax diagram              \\
430 %\bs {>-}  {...} \es & Continued on next line             \\
431 %\bs {...} {->}  \es & Continued from previous line       \\ \hline
432 %\bs {...} {...}
433 %  \begin{stack} <option-a> \\ <option-b> \\ <option-c> \end{stack}
434 %\es                 & Alternatives: choose any one       \\
435 %\bs {...} {...}
436 %  \begin{rep} <repeat-me> \\ <separator> \end{rep}
437 %\es                 & One or more items, with separators \\ \hline
438 %\end{tabular}
439 %\end{center}
440 % \end{demo}
441 % \end{figure}
442 %
443 % \DescribeMacro\tok
444 % You can also include text using the |\tok| command.  The argument of this
445 % command is typeset in \LaTeX's LR~mode and inserted into the diagram.
446 % Syntax abbreviations are allowed within the argument, so you can, for
447 % example, include textual descriptions like
448 % \begin{listing}
449 %\tok{any <char> except `"'}
450 % \end{listing}
451 %
452 % \DescribeEnv{stack}
453 % Within a syntax diagram, a choice between several different items is
454 % shown by stacking the alternatives vertically.  In \LaTeX, this is done
455 % by enclosing the items in a \env{stack} environment.  Each individual item
456 % is separated by |\\| commands, as in the \env{array} and \env{tabular}
457 % environments.  Each row may contain any syntax diagram material, including
458 % |\tok| commands and other \env{stack} environments.
459 %
460 % Note if you end a \env{stack} environment with a |\\| command, a blank
461 % row is added to the bottom of the stack, indicating that none of the items
462 % need be specified.
463 %
464 % \DescribeEnv{rep}
465 % Text which can be repeated is enclosed in a \env{rep} environment: the
466 % text is displayed with a backwards pointing arrow drawn over it, showing
467 % that it may be repeated.  Optionally, you can specify text to be
468 % displayed in the arrow, separating it from the main text with a |\\|
469 % command.
470 %
471 % Note that items on the backwards arrow of a \env{rep} construction should
472 % be displayed \emph{backwards}.  You must put the individual items in
473 % reverse order when building this part of your diagrams.  \syn\ will
474 % correctly reverse the arrows on \env{rep} structures, but apart from
475 % this, you must cope on your own.  You are recommended to keep these parts
476 % of your diagrams as simple as possible to avoid confusing readers.
477 %
478 % \begin{demo}[w]{A syntax diagram}
479 %\begin{syntdiag}
480 %<ident> `('
481 %  \begin{rep} \begin{stack} \\
482 %    <type> \begin{stack} \\ <ident> \end{stack}
483 %  \end{stack} \\ `,' \end{rep}
484 %\begin{stack} \\ `...' \end{stack} `)'
485 %\end{syntdiag}
486 % \end{demo}
487 %
488 % \DescribeMacro\(
489 % \DescribeMacro\)
490 % \DescribeMacro\<
491 % \DescribeMacro\>
492 % \DescribeMacro\[
493 % \DescribeMacro\]
494 % The environments \env{stack} and \env{rep} are rather cumbersome to use.
495 % As an alternative, the commands |\(| and |\)| are equivalent to
496 % |\begin{stack}| and |\end{stack}| respectively, and |\<| and |\>| are
497 % equivalent to |\begin{rep}| and |\end{rep}|.  Also, |\[| and |\]| are
498 % like |\begin{stack}| and |\end{stack}| except that an empty initial row is
499 % implicitly added.
500 %
501 % \subsubsection{Line breaking in syntax diagrams}
502 %
503 % Syntax diagrams are automatically broken over lines and across pages.
504 % Lines are only broken between items on the outermost level of the diagram:
505 % i.e., not within \env{stack} or \env{rep} environments.
506 %
507 % You can force a line break at a particular place by using the |\\| command
508 % as usual.  This supports all the usual \LaTeX\ features: a `|*|' variant
509 % which prohibits page breaking, and an optional argument specifying the
510 % extra vertical space between lines.
511 %
512 % \subsubsection{Customising syntax diagrams}
513 %
514 % There are two basic styles of syntax diagrams supported:
515 %
516 % \begin{description}
517 %
518 % \item [square] Lines in the syntax diagram join at squared-off corners.
519 %       This appears to be the standard way of displaying syntax diagrams
520 %       in IBM manuals, and most other documents I've seen.
521 %
522 % \item [rounded] Lines curve around corners.  Also, no arrows are drawn
523 %       around repeating loops: the curving of the lines provides this
524 %       information instead.  This style is used in various texts on
525 %       Pascal, and appears to be more popular in academic circles.
526 %
527 % \end{description}
528 %
529 % You can specify the style you want to use for syntax diagrams by giving
530 % the style name as an option on the |\usepackage| command.  For example,
531 % to force rounded edges to be used, you could say
532 %
533 % \begin{listing}
534 %\usepackage[rounded]{syntax}
535 % \end{listing}
536 %
537 % \DescribeMacro\sdsize
538 % \DescribeMacro\sdlengths
539 % The \env{syntdiag} environment takes an option argument, which should
540 % contain declarations which are obeyed while the environment is set up.
541 % The default value of this argument is `|\sdsize\sdlengths|'.  The
542 % |\sdsize| command sets the default type size for the environment: this is
543 % normally |\small|.  |\sdlengths| sets the values of the length parameters
544 % used by the environment based on the current text size.  These parameters
545 % are described below.
546 %
547 % For example, if you wanted to reduce the type size of the diagrams still
548 % further, you could use the command
549 % \begin{listing}
550 %\begin{syntdiag}[\tiny\sdlengths]
551 % \end{listing}
552 %
553 % The following length parameters may be altered:
554 %
555 % \begin{description} \setdescriptionlabel{\cmd{#1}}
556 %
557 % \item [\sdstartspace] The length of the rule between the arrows which
558 %       begin each line of the syntax diagram and the first item on the line.
559 %       Note that most objects have some space on either side of them as
560 %       well.  This is a rubber length.  Its default value is 1\,em, although
561 %       it can shrink by up to 10\,pt.
562 %
563 % \item [\sdendspace] The length of the rule between the last item on a
564 %       line and the arrow at the very end.  Note that the final line also
565 %       has extra rubber space on the end.  This is a rubber length.  Its
566 %       default value is 1\,em, although it will shrink by up to 10\,pt.
567 %
568 % \item [\sdmidskip] The length of the rule on either side of a large
569 %       construction (either a \env{stack} or a \env{rep}).  It is a rubber
570 %       length.  Its default value is \smallf 1/2\,em, with a very small
571 %       amount of infinite stretch.
572 %
573 % \item [\sdtokskip] The length of the rule on either side of a |\tok|
574 %       item or syntax abbreviation.  It is a rubber length.  Its default
575 %       value is \smallf 1/4\,em, with a very small amount of inifnite
576 %       stretch.
577 %
578 % \item [\sdfinalskip] The length of the rule which finishes the last line
579 %       of a syntax diagram.  It is a rubber length.  Its default value is
580 %       \smallf 1/2\,em, with 10000\,fil of stretch, which will left-align
581 %       the items on the line.\footnote{^^A
582 %         This is a little \TeX nical.  The idea is that if a stray 1\,fil
583 %         of stretch is added to the end of the line, it won't be noticed.
584 %         However, the alignment of the text on the line can still be
585 %         modified using \cmd{\sd@rule}\cmd{\hfill}, if you're feeling
586 %         brave.
587 %       }
588 %
589 % \item [\sdrulewidth] Half the width of the rules used in the diagram.
590 %       It is a rigid length.  Its default value is 0.2\,pt.
591 %
592 % \item [\sdcirclediam] The diameter of the circle from which the quadrants
593 %       used in rounded-style diagrams are taken.  This must be a multiple
594 %       of 4\,pt, or else the lines on the diagram won't match up.
595 %
596 % \end{description}
597 %
598 % In addition, you should call |\sdsetstrut| passing it the total height
599 % (\({\rm height}+{\rm depth}\)) of a normal line of text at the current
600 % size.  Normally, the value of |\baselineskip| will be appropriate.
601 %
602 % You can also alter the appearance of \env{stack}s and \env{rep}s by using
603 % their optional positioning arguments.  By default, \env{stack}s descend
604 % below the main line of the diagram, and \env{rep}s extend above it.
605 % Specifying an optional argument of |[b]| for either environment reverses
606 % this, putting \env{stack}s above and \env{rep}s below the line.
607 %
608 % \subsection{Changing the presentation styles}
609 %
610 % You can change the way in which the syntax items are typeset by altering
611 % some simple commands (using |\renewcommand|).  Each item (nonterminals,
612 % as typeset by |\synt|, and quoted and unquoted terminals, as typeset by
613 % |\lit| and |\lit*|) has two style commands associated with it, as shown
614 % in the table below.
615 %
616 % \begin{tab}{lll}                                                 \hline
617 % \bf Syntax item       & \bf Left command & \bf Right command  \\ \hline
618 % Nonterminals          & |\syntleft|      & |\syntright|       \\
619 % Quoted terminals      & |\litleft|       & |\litright|        \\
620 % Unquoted terminals    & |\ulitleft|      & |\ulitright|       \\ \hline
621 % \end{tab}
622 %
623 % It's not too hard to see how this works.  For example, if you look at
624 % the implementation for |\syntleft| and |\syntright| in the implementation
625 % section, you'll notice that they're defined like this:
626 % \begin{listing}
627 %\newcommand{\syntleft}{$\langle$\normalfont\itshape}
628 %\newcommand{\syntright}{$\rangle$}
629 % \end{listing}
630 % I think this is fairly simple, if you understand things like font changing.
631 %
632 % Note that changing these style commands alters the appearance of all syntax
633 % objects of the appropriate types, as created by the |\synt| and |\lit|
634 % commands, in \env{grammar} environments, and in syntax diagrams.
635 %
636 %
637 % \implementation
638 %
639 % \section{Implementation of \syn}
640 %
641 %    \begin{macrocode}
642 %<*package>
643 %    \end{macrocode}
644 %
645 % \subsection{Options handling}
646 %
647 % We define all the options we know about, and then see what's been put
648 % on the usepackage line.
649 %
650 % The options we provide currently are as follows:
651 %
652 % \begin{description}
653 % \item [rounded] draws neatly rounded edges on the diagram.
654 % \item [square] draws squared-off edges on the diagram.  This is the
655 %       default.
656 % \item [nounderscore] disables the undescore active character,  The |\_|
657 %       command still produces the nice version created here.
658 % \end{description}
659 %
660 %    \begin{macrocode}
661 \DeclareOption{rounded}{\sd@roundtrue}
662 \DeclareOption{square}{\sd@roundfalse}
663 \DeclareOption{nounderscore}{\@uscorefalse}
664 %    \end{macrocode}
665 %
666 % Now process the options:
667 %
668 %    \begin{macrocode}
669 \newif\ifsd@round
670 \newif\if@uscore\@uscoretrue
671 \newif\ifsd@left\newif\ifsd@right
672 \ExecuteOptions{square}
673 \ProcessOptions
674 %    \end{macrocode}
675 %
676 % \subsection{Special character handling}
677 %
678 % A lot of the \syn\ package requires the use special active characters.
679 % These must be added to two lists: |\dospecials|, which is used by |\verb|
680 % and friends, and |\@sanitize|, which is used by |\index|.  The two macros
681 % here, |\addspecial| and |\remspecial|, provide these registration
682 % facilities.
683 %
684 % Two similar macros are found in Frank Mittelbach's \package{doc} package:
685 % these have the disadvantage of global operation.  My macros here are based
686 % on Frank's, which in turn appear to be based on Donald Knuth's list
687 % handling code presented in Appendix~D of \textit{The \TeX book}.
688 %
689 % Both these macros take a single argument: a single-character control
690 % sequence containing the special character to be added to or removed from
691 % the lists.
692 %
693 % \begin{macro}{\addspecial}
694 %
695 % This is reasonably straightforward.  We remove the sequence from the lists,
696 % in case it's already there, and add it in in the obvious way.  This
697 % requires a little bit of fun with |\expandafter|.
698 %
699 %    \begin{macrocode}
700 \def\addspecial#1{%
701   \remspecial{#1}%
702   \expandafter\def\expandafter\dospecials\expandafter{\dospecials\do#1}%
703   \expandafter\def\expandafter\@santize\expandafter{%
704     \@sanitize\@makeother#1}%
705 }
706 %    \end{macrocode}
707 %
708 % \end{macro}
709 %
710 % \begin{macro}{\remspecial}
711 %
712 % This is the difficult bit.  Since |\dospecials| and |\@sanitize| have the
713 % form of list macros, we can redefine |\do| and |\@makeother| to do the
714 % job for us.  We must be careful to put the old meaning of |\@makeother|
715 % back.  The current implementation assumes it knows what |\@makeother| does.
716 %
717 %    \begin{macrocode}
718 \def\remspecial#1{%
719   \def\do##1{\ifnum`#1=`##1 \else\noexpand\do\noexpand##1\fi}%
720   \edef\dospecials{\dospecials}%
721   \def\@makeother##1{\ifnum`#1=`##1 \else%
722     \noexpand\@makeother\noexpand##1\fi}%
723   \edef\@sanitize{\@sanitize}%
724   \def\@makeother##1{\catcode`##112}%
725 }
726 %    \end{macrocode}
727 %
728 % \end{macro}
729 %
730 % \subsection{Underscore handling}
731 %
732 % When typing a lot of identifiers, it can be irksome to have to escape
733 % all `|_|' characters in the manuscript.  We make the underscore character
734 % active, so that it typesets an underscore in horizontal mode, and does
735 % its usual job as a subscript operator in maths mode.  Underscore must
736 % already be in the special character lists, because of its use as a
737 % subscript character, so this doesn't cause us a problem.
738 %
739 % \begin{macro}{\underscore}
740 %
741 % The |\underscore| macro typesets an underline character, using a horizontal
742 % rule.  This is positioned slightly below the baseline, and is also slightly
743 % wider than the default \TeX\ underscore.  This code is based on a similar
744 % implementation found in the \package{lgrind} package.
745 %
746 %    \begin{macrocode}
747 \def\underscore{%
748   \leavevmode%
749   \kern.06em%
750   \vbox{%
751     \hrule\@width.6em\@depth.4ex\@height-.34ex%
752   }%
753   \ifdim\fontdimen\@ne\font=\z@%
754     \kern.06em%
755   \fi%
756 }
757 %    \end{macrocode}
758 %
759 % \end{macro}
760 %
761 % \begin{macro}{\@foundunderscore}
762 %
763 % This macro is called by the `|_|' active character to sort out what to do.
764 %
765 % If this is maths mode, we use the |\sb| macro, which is already defined
766 % to do subscripting.  Otherwise, we call |\textunderscore|, which picks the
767 % nicest underscore it can find.
768 %
769 % There's some extra cunningness here, because I'd like to be able to
770 % hyphenate after underscores usually, but not when there's another one
771 % following.  And then, because \env{tabbing} redefines |\-|, there's some
772 % more yukkiness to handle that: the usual |\@tabacckludge| mechanism doesn't
773 % cope with this particular case.
774 %
775 %    \begin{macrocode}
776 \let\usc@builtindischyphen\-
777 \def\@uscore.{%
778   \ifmmode%
779     \expandafter\@firstoftwo%
780   \else%
781     \expandafter\@secondoftwo%
782   \fi%
783   \sb%
784   {\textunderscore\@ifnextchar_{}{\usc@builtindischyphen}}%
785 }
786 %    \end{macrocode}
787 %
788 % \end{macro}
789 %
790 % Now we set up the active character.  Note the |\protect|, which makes
791 % underscores work reasonably well in moving arguments.  Note also the way
792 % we end with a some funny stuff to prevent spaces being lost if this is
793 % written to a file.
794 %
795 %    \begin{macrocode}
796 \if@uscore
797   \AtBeginDocument{%
798     \catcode`\_\active%
799     \begingroup%
800     \lccode`\~`\_%
801     \lowercase{\endgroup\def~{\protect\@uscore.}}%
802   }
803 \fi
804 %    \end{macrocode}
805 %
806 % Finally, we redefine the |\_| macro to use our own |\underscore|, because
807 % it's prettier.  Actually, we don't: we just redefine the
808 % |\?\textunderscore| command (funny name, isn't it?).
809 %
810 %    \begin{macrocode}
811 \expandafter\let\csname?\string\textunderscore\endcsname\underscore
812 %    \end{macrocode}
813 %
814 % \subsection{Abbreviated verbatim notation}
815 %
816 %  In similar style to the \package{doc} package, we allow the user to set up
817 % characters which delimit verbatim text.  Unlike \package{doc}, we make
818 % such changes local to the current group.  This is performed through the
819 % |\shortverb| and |\unverb| commands.
820 %
821 % The implementations of these commands are based upon the |\MakeShortVerb|
822 % and |\DeleteShortVerb| commands of the \package{doc} package, although
823 % these versions have effect local to the current grouping level.  This
824 % prevents their redefinition of |\dospecials| from interfering with the
825 % grammar shortcuts, which require local changes only.
826 %
827 % The command |\shortverb| takes a single argument: a single-character
828 % control sequence defining which character to make into the verbatim text
829 % delimiter.  We store the old meaning of the active character in a control
830 % sequence called |\mn@\|\<char>.  Note that this control sequence
831 % contains a backslash character, which is a little odd.  We also define a
832 % command |\cc@\|\<char> which will return everything to normal.  This
833 % is used by the |\unverb| command.
834 %
835 % \begin{macro}{\shortverb}
836 %
837 % Here we build the control sequences we need to make everything work nicely.
838 % The active character is defined via |\lowercase|, using the |~| character:
839 % this is already made active by \TeX\@.
840 %
841 % The actual code requires lots of fiddling with |\expandafter| and friends.
842 %
843 %    \begin{macrocode}
844 \def\shortverb#1{%
845 %    \end{macrocode}
846 %
847 % First, we check to see if the command |\cc@\|\<char> has been defined.
848 %
849 %    \begin{macrocode}
850   \@ifundefined{cc@\string#1}{%
851 %    \end{macrocode}
852 %
853 % If it hasn't been defined, we add the character to the specials list.
854 %
855 %    \begin{macrocode}
856     \addspecial#1%
857 %    \end{macrocode}
858 %
859 % Now we set our character to be the lowercase version of |~|, which allows
860 % us to use it, even though we don't know what it is.
861 %
862 %    \begin{macrocode}
863     \begingroup%
864     \lccode`\~`#1%
865 %    \end{macrocode}
866 %
867 % Finally, we reach the tricky bit.  All of this is lowercased, so any
868 % occurrences of |~| are replaced by the user's special character.
869 %
870 %    \begin{macrocode}
871     \lowercase{%
872       \endgroup%
873 %    \end{macrocode}
874 %
875 % We remember the current meaning of the character, in case it has one.  We
876 % have to use |\csname| to build the rather strange name we use for this.
877 %
878 %    \begin{macrocode}
879       \expandafter\let\csname mn@\string#1\endcsname~%
880 %    \end{macrocode}
881 %
882 % Now we build |\cc@\|\<char>.  This is done with |\edef|, since more
883 % of this needs to be expanded now than not.  In this way, the actual macros
884 % we create end up being very short.
885 %
886 %    \begin{macrocode}
887       \expandafter\edef\csname cc@\string#1\endcsname{%
888 %    \end{macrocode}
889 %
890 % First, add a command to restore the character's old catcode.
891 %
892 %    \begin{macrocode}
893         \catcode`\noexpand#1\the\catcode`#1%
894 %    \end{macrocode}
895 %
896 % Now we restore the character's old meaning, using the version we saved
897 % earlier.
898 %
899 %    \begin{macrocode}
900         \let\noexpand~\expandafter\noexpand%
901           \csname mn@\string#1\endcsname%
902 %    \end{macrocode}
903 %
904 % Now we remove the character from the specials lists.
905 %
906 %    \begin{macrocode}
907         \noexpand\remspecial\noexpand#1%
908 %    \end{macrocode}
909 %
910 % Finally, we delete this macro, so that |\unverb| will generate a warning
911 % if the character is |\unverb|ed again.
912 %
913 %    \begin{macrocode}
914         \let\csname cc@\string#1\endcsname\relax%
915       }%
916 %    \end{macrocode}
917 %
918 % All of that's over now.  We set up the new definition of the character,
919 % in terms of |\verb|, and make the character active.  The nasty |\syn@ttspace|
920 % is there to make the spacing come out right.  It's all right really.  Honest.
921 %
922 %    \begin{macrocode}
923       \def~{\verb~\syn@ttspace}%
924     }%
925     \catcode`#1\active%
926 %    \end{macrocode}
927 %
928 % If our magic control sequence already existed, we can assume that the
929 % character is already a verbatim delimiter, and raise a warning.
930 %
931 %    \begin{macrocode}
932   }{%
933     \PackageWarning{syntax}{Character `\expandafter\@gobble\string#1'
934                             is already a verbatim\MessageBreak
935                             delimiter}%
936   }%
937 }
938 %    \end{macrocode}
939 %
940 % \end{macro}
941 %
942 % \begin{macro}{\unverb}
943 %
944 % This is actually terribly easy: we just use the |\cc@\|\<char> command
945 % we definied earlier, after making sure that it's been defined.
946 %
947 %    \begin{macrocode}
948 \def\unverb#1{%
949   \@ifundefined{cc@\string#1}{%
950     \PackageWarning{syntax}{Character `\expandafter\@gobble\string#1'
951                             is not a verbatim\MessageBreak
952                             delimiter}%
953   }{%
954     \csname cc@\string#1\endcsname%
955   }%
956 }
957 %    \end{macrocode}
958 %
959 % \end{macro}
960 %
961 % \subsection{Style hooks for syntax forms}
962 %
963 % To allow the appearance of syntax things to be configured, we provide some
964 % redefinable bits.
965 %
966 % The three types of objects (nonterminal symbols, and quoted and unquoted
967 % terminals) each have two macros associated with them: one which does the
968 % `left' bit of the typesetting, and one which does the `right' bit.  The
969 % items are typeset as LR~boxes.  I'll be extra good while defining these
970 % hooks, so that it's obvious what's going on; macho \TeX\ hacker things
971 % resume after this section.
972 %
973 % \begin{macro}{\syntleft}
974 % \begin{macro}{\syntright}
975 %
976 % I can't see why anyone would want to change the typesetting of
977 % nonterminals, although I'll provide the hooks for symmetry's sake.
978 %
979 %     \begin{macrocode}
980 \newcommand{\syntleft}{$\langle$\normalfont\itshape}
981 \newcommand{\syntright}{$\rangle$}
982 %    \end{macrocode}
983 %
984 % \end{macro}
985 % \end{macro}
986 %
987 % \begin{macro}{\ulitleft}
988 % \begin{macro}{\ulitright}
989 % \begin{macro}{\litleft}
990 % \begin{macro}{\litright}
991 %
992 % Now we can define the left and right parts of quoted and unquoted
993 % terminals.  US~readers may want to put double quotes around the quoted
994 % terminals, for example.
995 %
996 %    \begin{macrocode}
997 \newcommand{\ulitleft}{\normalfont\ttfamily\syn@ttspace\frenchspacing}
998 \newcommand{\ulitright}{}
999 \newcommand{\litleft}{`\bgroup\ulitleft}
1000 \newcommand{\litright}{\ulitright\egroup'}
1001 %    \end{macrocode}
1002 %
1003 % \end{macro}
1004 % \end{macro}
1005 % \end{macro}
1006 % \end{macro}
1007 %
1008 % \subsection{Simple syntax typesetting}
1009 %
1010 % In general text, we allow access to our typesetting conventions through
1011 % standard \LaTeX\ commands.
1012 %
1013 % \begin{macro}{\synt}
1014 %
1015 % The |\synt| macro typesets its argument as a syntactic quantity.  It puts
1016 % the text of the argument in italics, and sets angle brackets around it.
1017 % Breaking of a |\synt| object across lines is forbidden.
1018 %
1019 %    \begin{macrocode}
1020 \def\synt#1{\mbox{\syntleft{#1\/}\syntright}}
1021 %    \end{macrocode}
1022 %
1023 % \end{macro}
1024 %
1025 % \begin{macro}{\lit}
1026 %
1027 % The |\lit| macro typesets its argument as literal text, to be typed in.
1028 % Normally, this means setting the text in |\tt| font, and putting quotes
1029 % around it, although the quotes can be suppressed by using the $*$-variant.
1030 %
1031 % The |\syn@ttspace| macro sets up the spacing for the text nicely: |\tt|
1032 % spaces tend to be a little wide.
1033 %
1034 %    \begin{macrocode}
1035 \def\lit{\@ifstar{\lit@i\ulitleft\ulitright}{\lit@i\litleft\litright}}
1036 \def\lit@i#1#2#3{\mbox{#1{#3\/}#2}}
1037 %    \end{macrocode}
1038 %
1039 % \end{macro}
1040 %
1041 % \begin{macro}{\syn@ttspace}
1042 %
1043 % This sets up the |\spaceskip| value for |\tt| text.
1044 %
1045 %    \begin{macrocode}
1046 \def\syn@ttspace@{\spaceskip.35em\@plus.2em\@minus.15em\relax}
1047 %    \end{macrocode}
1048 %
1049 % However, this isn't always the right thing to do.
1050 %
1051 %    \begin{macrocode}
1052 \def\ttthinspace{\let\syn@ttspace\syn@ttspace@}
1053 \def\ttthickspace{\let\syn@ttspace\@empty}
1054 %    \end{macrocode}
1055 %
1056 % I know what I like thoough.
1057 %
1058 %    \begin{macrocode}
1059 \ttthinspace
1060 %    \end{macrocode}
1061 %
1062 % \end{macro}
1063 %
1064 % \subsubsection{The shortcuts}
1065 %
1066 % The easy part is over now.  The next job is to set up the `grammar
1067 % shortcuts' which allow easy changing of styles.
1068 %
1069 % We support four shortcuts:
1070 % \begin{itemize}
1071 % \item |`literal text'| typesets \syntax{`literal text'}
1072 % \item |<non-terminal>| typesets \syntax{<non-terminal>}
1073 % \item |"unquoted text"| typesets \syntax{"unquoted text"}
1074 % \item \verb"|" typesets a \syntax{|} character
1075 % \end{itemize}
1076 % These are all implemented through active characters, which are enabled
1077 % using the |\syntaxShortcuts| macro, described below.
1078 %
1079 % \begin{macro}{\readupto}
1080 %
1081 % \syntax{"\\readupto{"<char>"}{"<decls>"}{"<command>"}"} will read all
1082 % characters up until the next occurrence of \<char>.  Normally, all
1083 % special characters will be deactivated.  However, you can reactivate some
1084 % characters, using the \<decls> argument, which is processed before the
1085 % text is read.
1086 %
1087 % The code is borrowed fairly obviously from the \LaTeXe\ source for the
1088 % |\verb| command.
1089 %
1090 %    \begin{macrocode}
1091 \def\readupto#1#2#3{%
1092   \bgroup%
1093   \verb@eol@error%
1094   \let\do\@makeother\dospecials%
1095   \@noligs%
1096   #2%
1097   \catcode`#1\active%
1098   \lccode`\~`#1%
1099   \gdef\verb@balance@group{\verb@egroup%
1100      \@latex@error{\noexpand\verb illegal in command argument}\@ehc}%
1101   \def\@vhook{\verb@egroup#3}%
1102   \aftergroup\verb@balance@group%
1103   \lowercase{\let~\@vhook}%
1104 }
1105 %    \end{macrocode}
1106 %
1107 % \end{macro}
1108 %
1109 % \begin{macro}{\syn@assist}
1110 %
1111 % The |\syn@assist| macro is used for defining three of the shortcuts.  It
1112 % is called as
1113 %
1114 % \begin{quote}
1115 % \syntax{"\\syn@assist{"<left-decls>"}{"<actives>"}{"<delimeter>"}" \\
1116 % \null \quad "{"<right-decls>"}{"<end-cmd>"}"}
1117 % \end{quote}
1118 %
1119 % It creates an hbox, sets up the escape sequences for quoting our magic
1120 % characters, and then typesets a box containing
1121 %
1122 % \begin{quote}
1123 % \syntax{<left-decls>"{"<delimited-text>"\\/}"<right-decls>}
1124 % \end{quote}
1125 %
1126 % The \<left-decls> and \<right-decls> can be |\relax| if they're not
1127 % required.
1128 %
1129 % The \<actives> argument is passed to |\readupto|, to allow some special
1130 % characters through.  By default, we re-enable |\|, and make `\verb*" "'
1131 % typeset some space glue, rather than a space character.  A macro
1132 % `\verb*"\ "' is defined to actually print a space character, which yield
1133 % `\verb*" "' in the `|\tt|' font.
1134 %
1135 % Finally, it defines a |\ch| command, which, given a single-character
1136 % control sequence as its argument, typesets the character.  This is useful,
1137 % since |`| has been made active when we set up these calls, so the
1138 % direct |\char`\|\<char> doesn't work.
1139 %
1140 %    \begin{macrocode}
1141 \def\syn@assist#1#2#3#4#5{%
1142 %    \end{macrocode}
1143 %
1144 % First, we start the box, and open a group.  We use |\mbox| because it
1145 % does all the messing with |\leavevmode| which is needed.
1146 %
1147 %    \begin{macrocode}
1148   \leavevmode\hbox\bgroup%
1149 %    \end{macrocode}
1150 %
1151 % Next job is to set up the escape sequences.
1152 %
1153 %    \begin{macrocode}
1154   \chardef\\`\\%
1155   \chardef\>`\>%
1156   \chardef\'`\'%
1157   \chardef\"`\"%
1158   \chardef\ `\ %
1159 %    \end{macrocode}
1160 %
1161 % Now to define |\ch|.  This is done the obvious way.
1162 %
1163 %    \begin{macrocode}
1164   \def\ch##1{\char`##1}%
1165 %    \end{macrocode}
1166 %
1167 % For active characters, we do some fiddling with |\lccode|s.
1168 %
1169 %    \begin{macrocode}
1170   \def\act##1{%
1171     \catcode`##1\active%
1172     \begingroup%
1173     \lccode`\~`##1%
1174     \lowercase{\endgroup\def~}%
1175   }%
1176 %    \end{macrocode}
1177 %
1178 % Finally, we do the real work of setting the text.  We use |\readupto| to
1179 % actually find the text we want.
1180 %
1181 %    \begin{macrocode}
1182   #1%
1183   \begingroup%
1184   \readupto#3{%
1185     \catcode`\\0%
1186     \catcode`\ 10%
1187     #2%
1188   }{%
1189     \/\endgroup#4\egroup#5%
1190   }%
1191 }
1192 %    \end{macrocode}
1193 %
1194 % \end{macro}
1195 %
1196 % \begin{macro}{\syn@shorts}
1197 %
1198 % This macro actually defines the expansions for the active characters.
1199 % We have to do this separately because |`| must be active when we use it
1200 % in the |\def|, but we can't do that and use |\catcode| at the same time.
1201 % The arguments are commands to do before and after the actual command.
1202 % These are passed up from |\syntaxShortcuts|.
1203 %
1204 % All of the characters use |\syn@assist| in the obvious way except for
1205 % \verb"|", which drops into maths mode instead.
1206 %
1207 % Note that when changing the catcodes, we must save |`| until last.
1208 %
1209 %    \begin{macrocode}
1210 \begingroup
1211 \catcode`\<\active
1212 \catcode`\|\active
1213 \catcode`\"\active
1214 \catcode`\`\active
1215 %
1216 \gdef\syn@shorts#1#2{%
1217 %    \end{macrocode}
1218 %
1219 % The `|<|' character must typeset its argument in italics.  We make `|_|'
1220 % do the same as the `|\_|' command.
1221 %
1222 %    \begin{macrocode}
1223   \def<{%
1224     #1%
1225     \syn@assist%
1226       \syntleft%
1227       {\act_{\@uscore.}}%
1228       >%
1229       \syntright%
1230       {#2}%
1231   }%
1232 %    \end{macrocode}
1233 %
1234 % The `|`|' and `|"|' characters should print its argument in |\tt| font.
1235 % We change the `|\tt|' space glue to provide nicer spacing on the line.
1236 %
1237 %    \begin{macrocode}
1238   \def`{%
1239     #1%
1240     \syn@assist%
1241       \litleft%
1242       \relax%
1243       '%
1244       \litright%
1245       {#2}%
1246   }%
1247   \def"{%
1248     #1%
1249     \syn@assist%
1250       \ulitleft%
1251       \relax%
1252       "%
1253       \ulitright%
1254       {#2}%
1255   }%
1256 %    \end{macrocode}
1257 %
1258 % Finally, the `\verb"|"' character is typeset by using the mysterious
1259 % |\textbar| command.
1260 %
1261 %    \begin{macrocode}
1262   \def|{\textbar}%
1263 %    \end{macrocode}
1264 %
1265 % We're finished here now.
1266 %
1267 %    \begin{macrocode}
1268 }
1269 %
1270 \endgroup
1271 %    \end{macrocode}
1272 %
1273 % \end{macro}
1274 %
1275 % \begin{macro}{\syntaxShortcuts}
1276 %
1277 % This is a user-level command which enables the use of our shortcuts in the
1278 % current group.  It uses |\addspecial|, defined below, to register the
1279 % active characters, sets up their definitions and activates them.
1280 %
1281 % The two arguments are commands to be performed before and after the
1282 % handling of the abbreviation.  In this way, you can further process the
1283 % output.
1284 %
1285 % This command is not intended to be used directly by users: it should be
1286 % used by other macros and packages which wish to take advantage of the
1287 % facilities offered by this package.  We provide a |\synshorts| declaration
1288 % (which may be used as an environment, of course) which is more `user
1289 % palatable'.
1290 %
1291 %    \begin{macrocode}
1292 \def\syntaxShortcuts#1#2{%
1293   \syn@shorts{#1}{#2}%
1294   \addspecial\`%
1295   \addspecial\<%
1296   \addspecial\|%
1297   \addspecial\"%
1298   \catcode`\|\active%
1299   \catcode`\<\active%
1300   \catcode`\"\active%
1301   \catcode`\`\active%
1302 }
1303 %
1304 \def\synshorts{\syntaxShortcuts\relax\relax}
1305 %    \end{macrocode}
1306 %
1307 % \end{macro}
1308 %
1309 % \begin{macro}{\synshortsoff}
1310 %
1311 % This macro can be useful occasionally: it disables the syntax shortcuts,
1312 % so you can type normal text for a while.
1313 %
1314 %    \begin{macrocode}
1315 \def\synshortsoff{%
1316   \catcode`\|12%
1317   \catcode`\<12%
1318   \catcode`\"12%
1319   \catcode`\`12%
1320 }
1321 %    \end{macrocode}
1322 %
1323 % \end{macro}
1324 %
1325 % \begin{macro}{\syntax}
1326 %
1327 % The |\syntax| macro typesets its argument, allowing the use of our
1328 % shortcuts within the argument.
1329 %
1330 % Actually, we go to some trouble to ensure that the argument to |\syntax|
1331 % \emph{isn't} a real argument so we can change catcodes as we go.  We
1332 % use the |\let\@let@token=| trick from \PlainTeX\ to do this.
1333 %
1334 %    \begin{macrocode}
1335 \def\syntax#{\bgroup\syntaxShortcuts\relax\relax\let\@let@token}
1336 %    \end{macrocode}
1337 %
1338 % \end{macro}
1339 %
1340 % \begin{environment}{grammar}
1341 %
1342 % The \env{grammar} environment is the final object we have to define.  It
1343 % allows typesetting of beautiful BNF grammars.
1344 %
1345 % First, we define the length parameters we need:
1346 %
1347 %    \begin{macrocode}
1348 \newskip\grammarparsep
1349   \grammarparsep8\p@\@plus\p@\@minus\p@
1350 \newdimen\grammarindent
1351   \grammarindent2em
1352 %    \end{macrocode}
1353 %
1354 % Now define the default label typesetting.  This macro is designed to be
1355 % replaced by a user, so we'll be extra-well-behaved and use genuine \LaTeX\
1356 % commands.  Well, almost \dots
1357 %
1358 %    \begin{macrocode}
1359 \newcommand{\grammarlabel}[2]{\grammarlabelx{#1}{}{#2}}
1360 \newcommand{\grammarlabelx}[3]{\synt{#1}#2 \hfill#3}
1361 %    \end{macrocode}
1362 %
1363 % Now for a bit of hacking to make the item stuff work properly.  This gets
1364 % done for every new paragraph that's started without an |\item| command.
1365 %
1366 % First, store the left hand side of the production in a box.  Then I'll
1367 % end the paragraph, and insert some nasty glue to take up all the space,
1368 % so no-one will ever notice that there was a paragraph break there.  The
1369 % strut just makes sure that I know exactly how high the line is.
1370 %
1371 %    \begin{macrocode}
1372 \def\gr@implitem<#1>#2 #3 {%
1373   \sbox\z@{%
1374     \hskip\labelsep%
1375     \def\@tempa{#2}%
1376     \ifx\@tempa\@empty\grammarlabel{#1}{#3}%
1377     \else\grammarlabelx{#1}{#2}{#3}\fi%
1378   }%
1379   \strut\@@par%
1380   \vskip-\parskip%
1381   \vskip-\baselineskip%
1382 %    \end{macrocode}
1383 %
1384 % The |\item| command will notice that I've inserted these funny glues and
1385 % try to remove them: I'll stymie its efforts by inserting an invisible
1386 % rule.  Then I'll insert the label using |\item| in the normal way.
1387 %
1388 %    \begin{macrocode}
1389   \hrule\@height\z@\@depth\z@\relax%
1390   \item[\unhbox\z@]%
1391 %    \end{macrocode}
1392 %
1393 % Just before I go, I'll make \lit{<} back into an active character.
1394 %
1395 %    \begin{macrocode}
1396   \catcode`\<\active%
1397 }
1398 %    \end{macrocode}
1399 %
1400 % Now for the environment proper.  Deep down, it's a list environment, with
1401 % some nasty tricks to stop anyone from noticing.
1402 %
1403 % The first job is to set up the list from the parameters I'm given.
1404 %
1405 %    \begin{macrocode}
1406 \newenvironment{grammar}{%
1407   \list{}{%
1408     \labelwidth\grammarindent%
1409     \leftmargin\grammarindent%
1410     \advance\grammarindent\labelsep
1411     \itemindent\z@%
1412     \listparindent\z@%
1413     \parsep\grammarparsep%
1414   }%
1415 %    \end{macrocode}
1416 %
1417 % We have major problems in |\raggedright| layouts, which try to use |\par|
1418 % to start new lines.  We go back to normal |\\| newlines to try and bodge
1419 % our way around these problems.
1420 %
1421 %    \begin{macrocode}
1422   \let\\\@normalcr
1423 %    \end{macrocode}
1424 %
1425 % Now to enable the shortcuts.
1426 %
1427 %    \begin{macrocode}
1428   \syntaxShortcuts\relax\relax%
1429 %    \end{macrocode}
1430 %
1431 % Now a little bit of magic.  The |\alt| macro moves us to a new line, and
1432 % typesets a vertical bar in the margin.  This allows typesetting of
1433 % multiline alternative productions in a pretty way.
1434 %
1435 %    \begin{macrocode}
1436   \def\alt{\\\llap{\textbar\quad}}%
1437 %    \end{macrocode}
1438 %
1439 % Now for another bit of magic.  We set up some |\par| cleverness to spot
1440 % the start of each production rule and format it in some cunning and
1441 % user-defined way.
1442 %
1443 %    \begin{macrocode}
1444   \def\gr@setpar{%
1445     \def\par{%
1446       \parshape\@ne\@totalleftmargin\linewidth%
1447       \@@par%
1448       \catcode`\<12%
1449       \everypar{%
1450         \everypar{}%
1451         \catcode`\<\active%
1452         \gr@implitem%
1453       }%
1454     }%
1455   }%
1456   \gr@setpar%
1457   \par%
1458 %    \end{macrocode}
1459 %
1460 % Now set up the |\[[| and |\]]| commands to do the right thing.  We have
1461 % to check the next character to see if it's correct, otherwise we'll
1462 % open a maths display as usual.
1463 %
1464 %    \begin{macrocode}
1465   \let\gr@leftsq\[%
1466   \let\gr@rightsq\]%
1467   \def\gr@endsyntdiag]{\end{syntdiag}\gr@setpar\par}%
1468   \def\[{\@ifnextchar[{\begin{syntdiag}\@gobble}\gr@leftsq}%
1469   \def\]{\@ifnextchar]\gr@endsyntdiag\gr@rightsq}%
1470 %    \end{macrocode}
1471 %
1472 % Well, that's it for this side of the environment.
1473 %
1474 %    \begin{macrocode}
1475 }{%
1476 %    \end{macrocode}
1477 %
1478 % Closing the environment is a simple matter of tidying away the list.
1479 %
1480 %    \begin{macrocode}
1481   \@newlistfalse%
1482   \everypar{}%
1483   \endlist%
1484 }
1485 %    \end{macrocode}
1486 %
1487 % \end{environment}
1488 %
1489 % \subsection{Syntax diagrams}
1490 %
1491 % Now we come to the final and most complicated part of the package.
1492 %
1493 % Syntax diagrams are drawn using arrow characters from \LaTeX's line font,
1494 % used in the \env{picture} environment, and rules.  The horizontal rules
1495 % of the diagram are drawn along the baselines of the lines in which they
1496 % are placed.  The text items in the diagram are placed in boxes and lowered
1497 % below the main baseline.  Struts are added throughout to keep the vertical
1498 % spacing consistent.
1499 %
1500 % The vertical structures (stacks and loops) are all implemented with \TeX's
1501 % primitive |\halign| command.
1502 %
1503 % \subsubsection{User-configurable parameters}
1504 %
1505 % First, we allocate the \<dimen> and \<skip> arguments needed.  Fixed
1506 % lengths, as the \LaTeX book calls them, are allocated as \<dimen>s, to
1507 % take some of the load off of all the \<skip> registers.
1508 %
1509 %    \begin{macrocode}
1510 \newskip\sdstartspace
1511 \newskip\sdendspace
1512 \newskip\sdmidskip
1513 \newskip\sdtokskip
1514 \newskip\sdfinalskip
1515 \newdimen\sdrulewidth
1516 \newdimen\sdcirclediam
1517 \newdimen\sdindent
1518 %    \end{macrocode}
1519 %
1520 % We need some \TeX\ \<dimen>s for our own purposes, to get everything in
1521 % the right places.  We use labels for the `temporary' \TeX\ parameters
1522 % which we use, to avoid wasting registers.
1523 %
1524 %    \begin{macrocode}
1525 \dimendef\sd@lower\z@
1526 \dimendef\sd@upper\tw@
1527 \dimendef\sd@mid4
1528 \dimendef\sd@topcirc6
1529 \dimendef\sd@botcirc8
1530 \skipdef\sd@qskip2
1531 %    \end{macrocode}
1532 %
1533 % \begin{macro}{\sd@setsize}
1534 % When the text size for syntax diagrams changes, it's necessary to work out
1535 % the height for various rules in the diagram.
1536 %
1537 %    \begin{macrocode}
1538 \def\sd@setsize{%
1539   \sd@mid\ht\strutbox%
1540   \advance\sd@mid-\dp\strutbox%
1541   \sd@mid.5\sd@mid%
1542   \sd@upper\sdrulewidth%
1543     \advance\sd@upper\sd@mid%
1544   \sd@lower\sdrulewidth%
1545     \advance\sd@lower-\sd@mid%
1546   \sd@topcirc-.5\sdcirclediam%
1547     \advance\sd@topcirc\sd@mid%
1548   \sd@botcirc-.5\sdcirclediam%
1549     \advance\sd@botcirc-\sd@mid%
1550 }
1551 %    \end{macrocode}
1552 %
1553 % \end{macro}
1554 %
1555 % \begin{macro}{\sdsize}
1556 %
1557 % You can set the default type size used by syntax diagrams by redefining
1558 % the |\sdsize| command, using the |\renewcommand| command.
1559 %
1560 % By default, syntax diagrams are set slightly smaller than the main body
1561 % text.\footnote{^^A
1562 %   I've used pure \LaTeX\ commands for this and the \cmd\sdlengths\ macro,
1563 %   to try and illustrate how these values might be changed by a user.  The
1564 %   rest of the code is almost obfuscted in its use of raw \TeX\ features,
1565 %   in an attempt to dissuade more na\"\i ve users from fiddling with it.
1566 %   I suppose this is what you get when you let assembler hackers loose with
1567 %   something like \LaTeX.
1568 % }
1569 %
1570 %    \begin{macrocode}
1571 \newcommand{\sdsize}{%
1572   \small%
1573 }
1574 %    \end{macrocode}
1575 %
1576 % \end{macro}
1577 %
1578 % \begin{macro}{\sdlengths}
1579 %
1580 % Finally, the default length parameters are set in the |\sdlengths| command.
1581 % You can redefine the command using |\renewcommand|.
1582 %
1583 % We set up the length parameters here.
1584 %
1585 %    \begin{macrocode}
1586 \newcommand{\sdlengths}{%
1587   \setlength{\sdstartspace}{1em minus 10pt}%
1588   \setlength{\sdendspace}{1em minus 10pt}%
1589   \setlength{\sdmidskip}{0.5em plus 1em}%
1590   \setlength{\sdtokskip}{0.25em plus 1em}%
1591   \setlength{\sdfinalskip}{0.5em plus 10000fil}%
1592   \setlength{\sdrulewidth}{0.2pt}%
1593   \setlength{\sdcirclediam}{8pt}%
1594   \setlength{\sdindent}{0pt}%
1595 }
1596 %    \end{macrocode}
1597 %
1598 % \end{macro}
1599 %
1600 % \subsubsection{Other declarations}
1601 %
1602 % We define four switches.  The table shows what they're used for.
1603 %
1604 % \begin{table}
1605 % \begin{tab}{lp{3in}}                                              \hline
1606 %
1607 % \bf Switch        & \bf Meaning                                \\ \hline
1608 %
1609 % |\ifsd@base|      & We are at `base level' in the diagram:
1610 %                     i.e., not in any other sorts of
1611 %                     constructions.  This is used to decide
1612 %                     whether to allow line breaking.            \\[2pt]
1613 %
1614 % |\ifsd@top|       & The current loop construct is being
1615 %                     typeset with the loop arrow above the
1616 %                     baseline.                                  \\[2pt]
1617 %
1618 % |\ifsd@toplayer|  & We are typesetting the top layer of
1619 %                     a stack.  This is used to ensure that
1620 %                     the vertical rules on either side are
1621 %                     typeset at the right height.               \\[2pt]
1622 %
1623 % |\ifsd@backwards| & We're typesetting backwards, because
1624 %                     we're in the middle of a loop arrow.
1625 %                     the only difference this makes is that
1626 %                     any subloops have the arrow on the
1627 %                     side.                                      \\ \hline
1628 %
1629 % \end{tab}
1630 % \caption{Syntax diagram switches}
1631 % \end{table}
1632 %
1633 %    \begin{macrocode}
1634 \newif\ifsd@base
1635 \newif\ifsd@top
1636 \newif\ifsd@toplayer
1637 \newif\ifsd@backwards
1638 %    \end{macrocode}
1639 %
1640 % \begin{macro}{\sd@err}
1641 %
1642 % We output our errors through this macro, which saves a little typing.
1643 %
1644 %    \begin{macrocode}
1645 \def\sd@err{\PackageError{syntax}}
1646 %    \end{macrocode}
1647 %
1648 % \end{macro}
1649 %
1650 % \subsubsection{Arrow-drawing}
1651 %
1652 % We need to draw some arrows.  \LaTeX\ tries to make this as awkward as
1653 % possible, so we have to start moving the arrows around in boxes quite a
1654 % lot.
1655 %
1656 % The left and right pointing arrows are fairly simple: we just add some
1657 % horizontal spacing to prevent the width of the arrow looking odd.
1658 %
1659 %    \begin{macrocode}
1660 \def\sd@arrow{%
1661   \ht\tw@\z@%
1662   \dp\tw@\z@%
1663   \raise\sd@mid\box\tw@%
1664   \egroup%
1665 }
1666 \def\sd@rightarr{%
1667   \bgroup%
1668   \setbox\tw@\hbox{\kern-6\p@\@linefnt\char'55}%
1669   \sd@arrow%
1670 }
1671 \def\sd@leftarr{%
1672   \bgroup%
1673   \setbox\tw@\hbox{\@linefnt\char'33\kern-6\p@}%
1674   \sd@arrow%
1675 }
1676 %    \end{macrocode}
1677 %
1678 % The up arrow is very strange.  We need to bring the arrow down to base
1679 % level, and smash its height.
1680 %
1681 %    \begin{macrocode}
1682 \def\sd@uparr{%
1683   \bgroup%
1684   \setbox\tw@\hb@xt@\z@{\kern-\sdrulewidth\@linefnt\char'66\hss}%
1685   \setbox\tw@\hbox{\lower10\p@\box\tw@}%
1686   \sd@arrow%
1687 }
1688 %    \end{macrocode}
1689 %
1690 % The down arrow is similar, although it's already at the right height.
1691 % Thus, we can just smash the box.
1692 %
1693 %    \begin{macrocode}
1694 \def\sd@downarr{%
1695   \bgroup%
1696   \setbox\tw@\hb@xt@\z@{\kern-\sdrulewidth\@linefnt\char'77\hss}%
1697   \sd@arrow%
1698 }
1699 %    \end{macrocode}
1700 %
1701 % \subsubsection{Drawing curves}
1702 %
1703 % If the user has selected curved edges, we use the \LaTeX\ features provided
1704 % to obtain the curves.  These are drawn slightly oddly to make it easier
1705 % to fit them into the diagram.
1706 %
1707 % Some explanation about the \LaTeX\ circle font is probably called for
1708 % before we go any further.  The font consists of sets of four quadrants
1709 % of a particular size (and some other characters, which aren't important
1710 % at the moment).  Each collection of quadrants fit together to form a
1711 % perfect circle of a given diameter.  The individual quadrant characters
1712 % have strange bounding boxes, as described in the files \textit{lcircle.mf}
1713 % and \textit{ltpict.dtx}, and also in Appendix~D of \textit{The \TeX book}.
1714 % Our job here is to make these quadrants useful in the context of
1715 % drawing syntax diagrams.
1716 %
1717 % \begin{macro}{\sd@circ}
1718 % First, we define |\sd@circ|, which performs the common parts of the four
1719 % routines.  Since the characters in the circle font are grouped together,
1720 % we can pick out a particular corner piece by specifying its index into
1721 % the group for the required size.  The |\sd@circ| routine will pick out
1722 % the required character, given this index as an argument, and put it in
1723 % box~2, after fiddling with the sizes a little:
1724 % \begin{itemize}
1725 %
1726 % \item We clear the width to zero.  The individual routines then add a kern
1727 %       of the correct amount, so that the quadrant appears in the right
1728 %       place.
1729 %
1730 % \item The piece is lowered by half the rule width.  This positions the
1731 %       top and bottom pieces of the circle to be half way over the baseline,
1732 %       which is the correct position for the rest of the diagram.
1733 %
1734 % \end{itemize}
1735 %
1736 % Finally, we make sure we're in horizontal mode: horrific results occur
1737 % if this is not the case.  I'm sure I don't need to explain this any more
1738 % graphically.
1739 %
1740 %    \begin{macrocode}
1741 \def\sd@circ#1{%
1742   \@getcirc\sdcirclediam%
1743   \advance\@tempcnta#1%
1744   \setbox\tw@\hbox{\lower\sdrulewidth%
1745     \hbox{\@circlefnt\char\@tempcnta}}%
1746   \wd\tw@\z@%
1747   \leavevmode%
1748 }
1749 %    \end{macrocode}
1750 %
1751 % \end{macro}
1752 %
1753 % \begin{macro}{\sd@tlcirc}
1754 % \begin{macro}{\sd@trcirc}
1755 % \begin{macro}{\sd@blcirc}
1756 % \begin{macro}{\sd@brcirc}
1757 %
1758 % These are the macros which actually draw quadrants of circles.  They all
1759 % call |\sd@circ|, passing an appropriate index, and then fiddle with the
1760 % box sizes and apply kerning specific to the quadrant positioning.
1761 %
1762 % The exact requirements for positioning are as follows:
1763 %
1764 % \begin{itemize}
1765 %
1766 % \item The horizontal parts of the arcs must lie along the baseline (i.e.,
1767 %       half the line must be above the baseline, and half must be below).
1768 %       This is consistent with the horizontal rules used in the diagram.
1769 %
1770 % \item The vertical parts must overlap vertical rules on either side, so
1771 %       that a |\vrule\sd@|\textit{xx}|circ| makes the arc appear to be
1772 %       a real curve in the line.  The requirements are actually somewhat
1773 %       inconsistent; for example, the \env{stack} environment uses curves
1774 %       \emph{before} the |\vrule|s.  Special requirements like this are
1775 %       handled as special cases later.
1776 %
1777 % \item The height and width of the arc are at least roughly correct.
1778 %
1779 % \end{itemize}
1780 %
1781 %    \begin{macrocode}
1782 \def\sd@tlcirc{{%
1783   \sd@circ3%
1784   \ht\tw@\sdrulewidth%
1785   \dp\tw@.5\sdcirclediam%
1786   \kern-\tw@\sdrulewidth%
1787   \raise\sd@mid\box\tw@%
1788   \kern.5\sdcirclediam%
1789 }}
1790 %    \end{macrocode}
1791 %
1792 %    \begin{macrocode}
1793 \def\sd@trcirc{{%
1794   \sd@circ0%
1795   \ht\tw@\sdrulewidth%
1796   \dp\tw@.5\sdcirclediam%
1797   \kern.5\sdcirclediam%
1798   \raise\sd@mid\box\tw@%
1799 }}
1800 %    \end{macrocode}
1801 %
1802 %    \begin{macrocode}
1803 \def\sd@blcirc{{%
1804   \sd@circ2%
1805   \ht\tw@.5\sdcirclediam%
1806   \dp\tw@\sdrulewidth%
1807   \kern-\tw@\sdrulewidth%
1808   \raise\sd@mid\box\tw@%
1809   \kern.5\sdcirclediam%
1810 }}
1811 %    \end{macrocode}
1812 %
1813 %    \begin{macrocode}
1814 \def\sd@brcirc{{%
1815   \sd@circ1%
1816   \ht\tw@.5\sdcirclediam%
1817   \dp\tw@\sdrulewidth%
1818   \kern.5\sdcirclediam%
1819   \raise\sd@mid\box\tw@%
1820 }}
1821 %    \end{macrocode}
1822 %
1823 %    \begin{macrocode}
1824 \def\sd@nocirc{\sd@rule\hskip.5\sdcirclediam\relax}
1825 %    \end{macrocode}
1826 %
1827 % \end{macro}
1828 % \end{macro}
1829 % \end{macro}
1830 % \end{macro}
1831 %
1832 % \begin{macro}{\sd@llc}
1833 % \begin{macro}{\sd@rlc}
1834 %
1835 % In the \env{rep} environment, we need to be able to draw arcs with
1836 % horizontal lines running through them.  The two macros here do the job
1837 % nicely.  |\sd@llc| (which is short for left overlapping circle) is
1838 % analogous to |\llap|: it puts its argument in a box of zero width, sticking
1839 % out to the left.  However, it also draws a rule along the baseline.  This
1840 % is important, as it prevents text from overprinting the arc.  |\sd@rlc|
1841 % is very similar, just the other way around.
1842 %
1843 %    \begin{macrocode}
1844 \def\sd@llc#1{%
1845   \hb@xt@.5\sdcirclediam{%
1846     \sd@rule\hskip.5\sdcirclediam%
1847     \hss%
1848     #1%
1849   }%
1850 }
1851 %    \end{macrocode}
1852 %
1853 %    \begin{macrocode}
1854 \def\sd@rlc#1{%
1855   \hb@xt@.5\sdcirclediam{%
1856     #1%
1857     \hss%
1858     \sd@rule\hskip.5\sdcirclediam%
1859   }%
1860 }
1861 %    \end{macrocode}
1862 %
1863 % \end{macro}
1864 % \end{macro}
1865 %
1866 % \subsubsection{Drawing rules}
1867 %
1868 % It's important to draw the rules \emph{along} the baseline, rather than
1869 % above it: hence, the depth of the rule must be equal to the height.
1870 %
1871 % \begin{macro}{\sd@rule}
1872 %
1873 % We use rule leaders instead of glue through most of the syntax diagrams.
1874 % The command \syntax{"\\sd@rule"<skip>} draws a rule of the correct
1875 % dimensions, which has the behaviour of an \syntax{"\\hskip"<skip>}.
1876 %
1877 %    \begin{macrocode}
1878 \def\sd@rule{\leaders\hrule\@height\sd@upper\@depth\sd@lower}
1879 %    \end{macrocode}
1880 %
1881 % \end{macro}
1882 %
1883 % \begin{macro}{\sd@gap}
1884 %
1885 % The gap between elements is added using this macro.  It will allow a
1886 % line break if we're at the top level of the diagram, using a rather
1887 % strange discretionary.
1888 %
1889 % This is called as \syntax{"\\sd@gap{"<skip-register>"}"}.
1890 %
1891 %    \begin{macrocode}
1892 \def\sd@gap#1{%
1893 %    \end{macrocode}
1894 %
1895 % First, we see if we're at the top level.  Within constructs, we avoid the
1896 % overhead of a |\discretionary|.  We put half of the width of the skip on
1897 % each side of the discretionary break.
1898 %
1899 %    \begin{macrocode}
1900   \ifsd@left%
1901     \ifsd@base%
1902       \skip@#1%
1903         \divide\skip\z@\tw@%
1904       \nobreak\sd@rule\hskip\skip@%
1905       \discretionary{%
1906         \sd@qarrow{->}%
1907       }{%
1908         \hbox{%
1909           \sd@qarrow{>-}%
1910           \sd@rule\hskip\sdstartspace%
1911           \sd@rule\hskip3.5\p@%
1912         }%
1913       }{%
1914       }%
1915       \nobreak\sd@rule\hskip\skip@%
1916 %    \end{macrocode}
1917 %
1918 % If we're not at the base level, we just put in a rule of the correct
1919 % width.
1920 %
1921 %    \begin{macrocode}
1922     \else%
1923       \sd@rule\hskip#1%
1924     \fi%
1925   \fi%
1926 }
1927 %    \end{macrocode}
1928 %
1929 % \end{macro}
1930 %
1931 % \begin{macro}{\sd@qgap}
1932 % \begin{macro}{\sd@dequeue}
1933 %
1934 % This is the high-level interface to spacing in syntax diagrams.  Stuff only
1935 % gets printed if the diagram's actually started yet, and hasn't finished.
1936 %
1937 %    \begin{macrocode}
1938 \def\sd@qgap#1{%
1939   \ifsd@left%
1940     \ifsd@right\advance\sd@qskip#1\relax%
1941     \else\sd@gap#1\fi%
1942   \fi%
1943 }
1944 \def\sd@dequeue{\ifsd@left\sd@gap\sd@qskip\sd@qskip\z@\fi}
1945 %    \end{macrocode}
1946 %
1947 % \end{macro}
1948 % \end{macro}
1949 %
1950 % \begin{macro}{\sd@abbrev}
1951 %
1952 % Sets up syntax diagram abbreviations.
1953 %
1954 %    \begin{macrocode}
1955 \def\sd@abbrev{%
1956   \def\({\begin{stack}}%
1957   \def\){\end{stack}}%
1958   \def\<{\begin{rep}}%
1959   \def\>{\end{rep}}%
1960   \expandafter\def%
1961     \csname\ifx\gr@leftsq\@@undefined[\else gr@leftsq\fi\endcsname%
1962     {\begin{stack}\\}%
1963   \expandafter\let%
1964     \csname\ifx\gr@rightsq\@@undefined]\else gr@rightsq\fi\endcsname%
1965     \)%
1966 }
1967 %    \end{macrocode}
1968 %
1969 % \end{macro}
1970 %
1971 % \subsubsection{The \protect\env{syntdiag} environment}
1972 %
1973 % All syntax diagrams are contained within a \env{syntdiag} environment.
1974 %
1975 % \begin{environment}{syntdiag}
1976 %
1977 % The only argument is a collection of declarations, which by
1978 % default is
1979 %
1980 % \begin{listing}
1981 %\sdsize\sdlengths
1982 % \end{listing}
1983 %
1984 % However, if the optional argument is not specified, \TeX\ reads the first
1985 % character of the environment, which may not be catcoded correctly.  We set
1986 % up the catcodes first, using the |\syntaxShortcuts| command, and then read
1987 % the argument.  We don't use |\newcommand|, because that would involve
1988 % creating yet \emph{another} macro.  Time to fiddle with |\@ifnextchar|
1989 % \dots
1990 %
1991 %    \begin{macrocode}
1992 \def\syntdiag{%
1993   \syntaxShortcuts\sd@tok@i\sd@tok@ii%
1994   \sd@abbrev%
1995   \@ifnextchar[\syntdiag@i{\syntdiag@i[]}%
1996 }
1997 \def\syntdiag@i[#1]{\@ifnextchar[{\syntdiag@ii{#1}}{\syntdiag@ii{#1}[b]}}
1998 %    \end{macrocode}
1999 %
2000 % Now we actually do the job we're meant to.
2001 %
2002 %    \begin{macrocode}
2003 \def\syntdiag@ii#1[#2]{%
2004 %    \end{macrocode}
2005 %
2006 % The first thing to do is execute the user's declarations.  We then set
2007 % up things for the font size.
2008 %
2009 %    \begin{macrocode}
2010   \sdsize\sdlengths%
2011   #1%
2012   \sd@setsize%
2013 %    \end{macrocode}
2014 %
2015 % Sort out the omission of left or right sides.
2016 %
2017 %    \begin{macrocode}
2018   \sd@lefttrue\sd@righttrue%
2019   \if#2l\sd@rightfalse\fi%
2020   \if#2r\sd@leftfalse\fi%
2021 %    \end{macrocode}
2022 %
2023 % Next, we start a list, to change the text layout.
2024 %
2025 %    \begin{macrocode}
2026   \list{}{%
2027     \leftmargin\sdindent%
2028     \rightmargin\leftmargin%
2029     \labelsep\z@%
2030     \labelwidth\z@%
2031   }%
2032   \item[]%
2033 %    \end{macrocode}
2034 %
2035 % We reconfigure the paragraph format quite a lot now.  We clear
2036 % |\parfillskip| to avoid any justification at the end of the paragraph.
2037 % We also turn off paragraph indentation.
2038 %
2039 %    \begin{macrocode}
2040   \parfillskip\z@%
2041   \noindent%
2042 %    \end{macrocode}
2043 %
2044 % Next, we add in the arrows on the beginning of the line, and a bit of
2045 % glue.
2046 %
2047 %    \begin{macrocode}
2048   \ifsd@left%
2049     \sd@qarrow{>>-}%
2050     \nobreak\sd@rule\hskip\sdstartspace%
2051    \fi%
2052 %    \end{macrocode}
2053 %
2054 % This is the base level of the diagram, so we enable line breaking.
2055 %
2056 %    \begin{macrocode}
2057   \sd@basetrue%
2058 %    \end{macrocode}
2059 %
2060 % Since the objects being broken are rather large, we enable sloppy line
2061 % breaking.  We also try to avoid page breaks in mid-diagram, by upping the
2062 % |\interlinepenalty|.
2063 %
2064 %    \begin{macrocode}
2065   \sloppy%
2066   \interlinepenalty100%
2067   \hyphenpenalty0%
2068 %    \end{macrocode}
2069 %
2070 % We handle all the spacing within the environment, so we make \TeX\ ignore
2071 % spaces and newlines.
2072 %
2073 %    \begin{macrocode}
2074   \catcode`\ 9%
2075   \catcode`\^^M9%
2076 %    \end{macrocode}
2077 %
2078 % We now have to change the behaviour of |\\| to line-break syntax diagrams.
2079 %
2080 %    \begin{macrocode}
2081   \let\\\sd@newline%
2082   \ignorespaces%
2083 }
2084 %    \end{macrocode}
2085 %
2086 % When we end the diagram, we just have to add in the final fillskip, and
2087 % double arrow.
2088 %
2089 %    \begin{macrocode}
2090 \def\endsyntdiag{%
2091   \unskip%
2092   \ifsd@right%
2093     \nobreak\sd@rule\hskip\sdmidskip%
2094     \sd@rule\hskip\sdfinalskip%
2095     \sd@qarrow{-><}%
2096   \else%
2097     \hskip\sdfinalskip%
2098     \vadjust{}%
2099   \fi%
2100   \endlist%
2101 }
2102 %    \end{macrocode}
2103 %
2104 % \end{environment}
2105 %
2106 % \begin{environment}{syntdiag*}
2107 %
2108 % The starred form of \env{syntdiag} typesets a syntax diagram in LR-mode;
2109 % this is useful if you're describing parts of syntax diagrams, for example.
2110 %
2111 % This is in fact really easy.  The first bit which checks for an optional
2112 % argument is almost identical to the non-$*$ version.
2113 %
2114 %    \begin{macrocode}
2115 \@namedef{syntdiag*}{%
2116   \syntaxShortcuts\sd@tok@i\sd@tok@ii%
2117   \sd@abbrev%
2118   \@tempswatrue%
2119   \@ifnextchar[\syntdiag@s@i{\syntdiag@s@i[]}%
2120 }
2121 %    \end{macrocode}
2122 %
2123 % Handle another optional argument giving the width of the box to fill.
2124 %
2125 %    \begin{macrocode}
2126 \def\syntdiag@s@i[#1]{%
2127   \@ifnextchar[{\syntdiag@s@ii{#1}}{\syntdiag@s@iii{#1}{\hbox}}%
2128 }
2129 \def\syntdiag@s@ii#1[#2]{%
2130   \def\@tempa{#2}\def\@tempb{*}%
2131   \ifx\@tempa\@tempb%
2132     \@tempswafalse%
2133     \syntdiag@s@iii{#1}{}%
2134   \else%
2135     \syntdiag@s@iii{#1}{\hb@xt@#2}%
2136   \fi%
2137 }
2138 %    \end{macrocode}
2139 %
2140 % Now to actually start the display.  This is mostly simple.  Just to make
2141 % sure about the LR-ness of the typesetting, I'll put everything in an hbox.
2142 %
2143 %    \begin{macrocode}
2144 \def\syntdiag@s@iii#1#2{%
2145   \leavevmode%
2146   #2\bgroup%
2147 %    \end{macrocode}
2148 %
2149 % Now configure the typesetting according to the user's wishes.
2150 %
2151 %    \begin{macrocode}
2152   \let\@@left\left%
2153   \let\@@right\right%
2154   \def\left##1{\def\sd@startarr{##1}}%
2155   \def\right##1{\def\sd@endarr{##1}}%
2156   \left{>-}\right{->}%
2157   \sdsize\sdlengths%
2158   #1%
2159   \sd@setsize%
2160   \let\left\@@left%
2161   \let\right\@@right%
2162   \sd@lefttrue\sd@righttrue%
2163   \ifx\sd@startarr\@empty\sd@leftfalse\fi%
2164   \ifx\sd@endarr\@empty\sd@rightfalse\fi%
2165 %    \end{macrocode}
2166 %
2167 % Put in the initial double-arrow.
2168 %
2169 %    \begin{macrocode}
2170   \ifsd@left%
2171     \sd@qarrow\sd@startarr%
2172     \sd@rule\hskip\sdmidskip%
2173   \fi%
2174 %    \end{macrocode}
2175 %
2176 % We're in horizontal mode, so don't bother with linebreaking.
2177 %
2178 %    \begin{macrocode}
2179   \if@tempswa\sd@basefalse\else\sd@basetrue\fi%
2180 %    \end{macrocode}
2181 %
2182 % Finally, disable spaces and things.
2183 %
2184 %    \begin{macrocode}
2185   \catcode`\ 9%
2186   \catcode`\^^M9%
2187   \ignorespaces%
2188 }
2189 %    \end{macrocode}
2190 %
2191 % Ending the environment is very similar.
2192 %
2193 %    \begin{macrocode}
2194 \@namedef{endsyntdiag*}{%
2195   \unskip%
2196   \ifsd@right%
2197     \sd@rule\hskip\sdmidskip%
2198     \ifsd@base\else\sd@rule\hskip\sdfinalskip\fi%
2199     \sd@qarrow\sd@endarr%
2200   \else%
2201     \hskip\sdmidskip%
2202     \ifsd@base\else\hskip\sdfinalskip\fi%
2203   \fi%
2204   \egroup%
2205 }
2206 %    \end{macrocode}
2207 %
2208 % \end{environment}
2209 %
2210 % \begin{macro}{\sd@qarrow}
2211 %
2212 % This typesets the various left and right arrows required in syntax
2213 % diagrams.  The argument is one of \syntax{`>>-', `->', `>-' or `-><'}.
2214 %
2215 %    \begin{macrocode}
2216 \def\sd@qarrow#1{%
2217   \begingroup%
2218   \lccode`\~=`\<\lowercase{\def~{<}}%
2219   \hbox{\csname sd@arr@#1\endcsname}%
2220   \endgroup%
2221 }
2222 \@namedef{sd@arr@>>-}{\sd@rightarr\kern-.5\p@\sd@rightarr\kern-\p@}
2223 \@namedef{sd@arr@>-}{\sd@rightarr\kern-\p@}
2224 \@namedef{sd@arr@->}{\sd@rightarr}
2225 \@namedef{sd@arr@-><}{\sd@rightarr\kern-\p@\sd@leftarr}
2226 \@namedef{sd@arr@...}{$\cdots$}
2227 \@namedef{sd@arr@-}{}
2228 \@namedef{sd@arr@}{}
2229 %    \end{macrocode}
2230 %
2231 % \end{macro}
2232 %
2233 % \begin{macro}{\sd@newline}
2234 %
2235 % The line breaking within a syntax diagram is controlled by the
2236 % |\sd@newline| command, to which |\\| is assigned.
2237 %
2238 % We support all the standard \LaTeX\ features here.  The line breaking
2239 % involves adding a fill skip and arrow, moving to the next line, adding
2240 % an arrow and a rule, and continuing.
2241 %
2242 %    \begin{macrocode}
2243 \def\sd@newline{\@ifstar{\vadjust{\penalty\@M}\sd@nl@i}\sd@nl@i}
2244 \def\sd@nl@i{\@ifnextchar[\sd@nl@ii\sd@nl@iii}
2245 \def\sd@nl@ii[#1]{\vspace{#1}\sd@nl@iii}
2246 \def\sd@nl@iii{%
2247   \nobreak\sd@rule\hskip\sdmidskip%
2248   \sd@rule\hskip\sdfinalskip%
2249   \kern-3\p@%
2250   \sd@rightarr%
2251   \newline%
2252   \sd@rightarr%
2253   \nobreak\sd@rule\hskip\sdstartspace%
2254   \sd@rule\hskip3.5\p@%
2255 }
2256 %    \end{macrocode}
2257 %
2258 % \end{macro}
2259 %
2260 % \subsubsection{Putting things in the right place}
2261 %
2262 % Syntax diagrams have fairly stiff requirements on the positioning of text
2263 % relative to the diagram's rules.  To help people (and me) to write
2264 % extensions to the syntax diagram typesetting which automatically put things
2265 % in the right place, I provide some simple macros.
2266 %
2267 % \begin{environment}{sdbox}
2268 %
2269 % By placing some text in the \env{sdbox} environment, it will be read into a
2270 % box and then output at the correct height for the syntax diagram.  Note
2271 % that stuff in the box is set in horizontal (LR) mode, so you'll have to use
2272 % a \env{minipage} if you want formatted text.  The macro also supplies rules
2273 % on either side of the box, with a length given in the environment's
2274 % argument.
2275 %
2276 % Macro writers are given explicit permission to use this environment through
2277 % the |\sdbox| and |\endsdbox| commands if this makes life easier.
2278 %
2279 % The calculation in the |\endsdbox| macro works out how to centre the box
2280 % vertically over the baseline.  If the box's height is~$h$, and its depth
2281 % is~$d$, then its centre-line is $(h+d)/2$ from the bottom of the box.
2282 % Since the baseline is already $d$ from the bottom, we need to lower the box
2283 % by $(h+d)/2 - d$, or $h/2-d/2$.
2284 %
2285 %    \begin{macrocode}
2286 \def\sdbox#1{%
2287   \@tempskipa#1\relax%
2288   \sd@gap\@tempskipa%
2289   \setbox\z@\hbox\bgroup%
2290     \begingroup%
2291     \catcode`\ 10%
2292     \catcode`\^^M5%
2293     \synshortsoff%
2294 }
2295 \def\endsdbox{%
2296     \endgroup%
2297   \egroup%
2298   \@tempdima\ht\z@%
2299   \advance\@tempdima-\dp\z@%
2300   \advance\@tempdima-\tw@\sd@mid%
2301   \lower.5\@tempdima\box\z@%
2302   \sd@lefttrue%
2303   \sd@gap\@tempskipa%
2304 }
2305 %    \end{macrocode}
2306 %
2307 % \end{environment}
2308 %
2309 % \subsubsection{Typesetting syntactic items}
2310 %
2311 % Using the hooks built into the syntax abbreviations above, we typeset
2312 % the text into a box, and write it out, centred over the baseline.  A strut
2313 % helps to keep the actual text baselines level for short pieces of text.
2314 %
2315 % \begin{macro}{\sd@tok@i}
2316 %
2317 % The preamble for a syntax abbreviation.  We start a box, and set the
2318 % space and return characters to work again.  A strut is added to the box to
2319 % ensure correct vertical spacing for normal text.
2320 %
2321 %    \begin{macrocode}
2322 \def\sd@tok@i{%
2323   \sdbox\sdtokskip%
2324   \strut%
2325   \space%
2326 }
2327 %    \end{macrocode}
2328 %
2329 % \end{macro}
2330 %
2331 % \begin{macro}{\sd@tok@ii}
2332 %
2333 %    \begin{macrocode}
2334 \def\sd@tok@ii{%
2335   \space%
2336   \endsdbox%
2337 }
2338 %    \end{macrocode}
2339 %
2340 % \end{macro}
2341 %
2342 % \subsubsection{Inserting other pieces of text}
2343 %
2344 % Arbitrary text may be put into a syntax diagram through the use of the
2345 % |\tok| macro.  Its `argument' is typeset in the same way as a syntactic
2346 % item (centred over the baseline).  The implementation goes to some effort
2347 % to ensure that the text is not actually an argument, to allow category
2348 % codes to change while the text is being typeset.
2349 %
2350 % \begin{macro}{\tok}
2351 %
2352 % We start a box, and make space and return do their normal jobs.  We use
2353 % |\aftergroup| to regain control once the box is finished.  |\doafter| is
2354 % used to get control after the group finishes.
2355 %
2356 %    \begin{macrocode}
2357 \def\tok#{%
2358   \sdbox\sdtokskip%
2359   \strut%
2360   \enspace%
2361   \syntaxShortcuts\relax\relax%
2362   \doafter\sd@tok%
2363 }
2364 %    \end{macrocode}
2365 %
2366 % The |\sd@tok| macro is similar to |\sd@tok@ii| above.
2367 %
2368 %    \begin{macrocode}
2369 \def\sd@tok{%
2370   \enspace%
2371   \endsdbox%
2372 }
2373 %    \end{macrocode}
2374 %
2375 % \end{macro}
2376 %
2377 % \subsubsection{The \protect\env{stack} environment}
2378 %
2379 % The \env{stack} environment is used to present alternatives in a syntax
2380 % diagram.  The alternatives are separated by |\\| commands.
2381 %
2382 % \begin{macro}{\stack}
2383 %
2384 % Handle the optional arguments.
2385 %
2386 %    \begin{macrocode}
2387 \def\stack{\@ifnextchar[\stack@i{\stack@i[t]}}
2388 \def\stack@i[#1]{\@ifnextchar[{\stack@ii{#1}}{\stack@ii{#1}[b]}}
2389 \def\stack@ii#1[#2]{%
2390 %    \end{macrocode}
2391 %
2392 % First, we add some horizontal space.
2393 %
2394 %    \begin{macrocode}
2395   \sd@gap\sdmidskip%
2396 %    \end{macrocode}
2397 %
2398 % We're within a complex construction, so we need to clear the |\ifsd@base|
2399 % flag.
2400 %
2401 %    \begin{macrocode}
2402   \begingroup\sd@basefalse%
2403 %    \end{macrocode}
2404 %
2405 % The top and bottom rows of the stack are different to the others, since
2406 % the vertical rules mustn't extend all the way up the side of the item.
2407 % The bottom row is handled separately by |\endstack| below.  The top row
2408 % must be handled via a flag, |\ifsd@toplayer|.
2409 %
2410 % Initially, the flag must be set true.
2411 %
2412 %    \begin{macrocode}
2413   \sd@toplayertrue%
2414 %    \end{macrocode}
2415 %
2416 % We set the |\\| command to separate the items in the |\halign|.
2417 %
2418 %    \begin{macrocode}
2419   \let\\\sd@stackcr%
2420 %    \end{macrocode}
2421 %
2422 % Sort out which sides of the construction are actually emitted.
2423 %
2424 %    \begin{macrocode}
2425   \sd@righttrue\if#2l\sd@rightfalse\fi%
2426 %    \end{macrocode}
2427 %
2428 % The actual structure must be set in vertical mode, so we must place it
2429 % in a box.  The position argument determines whether this must be a
2430 % |\vbox| or a |\vtop|.  We also insert a bit of rounding if the options say
2431 % we must.
2432 %
2433 %    \begin{macrocode}
2434   \if#1t%
2435     \let\@tempa\vtop%
2436     \sd@toptrue%
2437     \ifsd@left\ifsd@round\llap{\sd@trcirc\kern\tw@\sdrulewidth}\fi\fi%
2438   \else\if#1b%
2439     \let\@tempa\vbox%
2440     \sd@topfalse%
2441     \ifsd@left\ifsd@round\llap{\sd@brcirc\kern\tw@\sdrulewidth}\fi\fi%
2442   \else%
2443     \sd@err{Bad position argument passed to stack}%
2444            {The positioning argument must be one of `t' or `b'.  I%
2445             have^^Jassumed you meant to type `t'.}%
2446     \let\@tempa\vtop%
2447   \fi\fi%
2448 %    \end{macrocode}
2449 %
2450 % Now we start the box, which we will complete at the end of the environment.
2451 %
2452 %    \begin{macrocode}
2453   \@tempa\bgroup%
2454 %    \end{macrocode}
2455 %
2456 % We must remove any extra space between rows of the table, since the rules
2457 % will not join up correctly.  We can use |\offinterlineskip| safely, since
2458 % each individual row contains a strut.
2459 %
2460 %    \begin{macrocode}
2461   \offinterlineskip%
2462 %    \end{macrocode}
2463 %
2464 % Now we can start the alignment.  We actually use \PlainTeX's |\ialign|
2465 % macro, which also clears |\tabskip| for us.
2466 %
2467 %    \begin{macrocode}
2468   \ialign\bgroup%
2469 %    \end{macrocode}
2470 %
2471 % The preamble is trivial, since we must do all of the work ourselves
2472 %
2473 %    \begin{macrocode}
2474     ##\cr%
2475 %    \end{macrocode}
2476 %
2477 % We can now start putting the text into a box ready for typesetting later.
2478 % The strut makes the vertical spacing correct.
2479 %
2480 %    \begin{macrocode}
2481   \setbox\z@\hbox\bgroup%
2482     \strut%
2483 }
2484 %    \end{macrocode}
2485 %
2486 % \end{macro}
2487 %
2488 % \begin{macro}{\endstack}
2489 %
2490 % The first part of this is similar to the |\sd@stackcr| macro below, except
2491 % that the vertical rules are different.  We don't support rounded edges
2492 % on single-row stacks, although this isn't a great loss to humanity.
2493 %
2494 %    \begin{macrocode}
2495 \def\endstack{%
2496   \ifsd@right\else\unskip\fi%
2497   \egroup%
2498   \ifsd@toplayer%
2499     \sd@dostack\sd@upper\sd@lower\sd@nocirc\sd@nocirc%
2500   \else%
2501     \ifsd@round%
2502       \ifsd@top%
2503         \sd@dostack{\ht\z@}\sd@botcirc\sd@blcirc\sd@brcirc%
2504       \else%
2505         \sd@dostack{\ht\z@}\sd@botcirc\sd@nocirc\sd@nocirc%
2506       \fi%
2507     \else%
2508       \sd@dostack{\ht\z@}\sd@lower\relax\relax%
2509     \fi%
2510   \fi%
2511 %    \end{macrocode}
2512 %
2513 % We now close the |\halign| and the vbox we created.
2514 %
2515 %    \begin{macrocode}
2516   \egroup%
2517   \egroup%
2518 %    \end{macrocode}
2519 %
2520 % Deal with any rounding we started off.
2521 %
2522 %    \begin{macrocode}
2523   \ifsd@right\ifsd@round%
2524     \ifsd@top
2525       \rlap{\kern\tw@\sdrulewidth\sd@tlcirc}%
2526     \else%
2527       \rlap{\kern\tw@\sdrulewidth\sd@blcirc}%
2528     \fi%
2529   \fi\fi%
2530 %    \end{macrocode}
2531 %
2532 % Finally, we add some horizontal glue to space the diagram out.
2533 %
2534 %    \begin{macrocode}
2535   \endgroup\sd@lefttrue\ifsd@right\sd@gap\sdmidskip\fi%
2536 }
2537 %    \end{macrocode}
2538 %
2539 % \end{macro}
2540 %
2541 % \begin{macro}{\sd@stackcr}
2542 %
2543 % The |\\| command is set to this macro during a \env{stack} environment.
2544 %
2545 %    \begin{macrocode}
2546 \def\sd@stackcr{%
2547 %    \end{macrocode}
2548 %
2549 % The first job is to close the box containing the previous item.
2550 %
2551 %    \begin{macrocode}
2552   \ifsd@right\else\unskip\fi%
2553   \egroup%
2554 %    \end{macrocode}
2555 %
2556 % Now we typeset the vertical rules differently depending on whether this is
2557 % the first item in the stack.  This looks quite terrifying initially, but
2558 % it's just an enumeration of the possible cases for the different values
2559 % of |\ifsd@toplayer|, |\ifsd@top| and |\ifsd@round|, putting in appropriate
2560 % rules and arcs in the right places.
2561 %
2562 %    \begin{macrocode}
2563   \ifsd@toplayer%
2564     \ifsd@round%
2565       \ifsd@top%
2566         \sd@dostack\sd@topcirc{\dp\z@}\sd@nocirc\sd@nocirc%
2567       \else%
2568         \sd@dostack\sd@topcirc{\dp\z@}\sd@tlcirc\sd@trcirc%
2569       \fi%
2570     \else%
2571       \sd@dostack\sd@upper{\dp\z@}\relax\relax%
2572     \fi%
2573   \else%
2574     \ifsd@round%
2575       \ifsd@top%
2576         \sd@dostack{\ht\z@}{\dp\z@}\sd@blcirc\sd@brcirc%
2577       \else%
2578         \sd@dostack{\ht\z@}{\dp\z@}\sd@tlcirc\sd@trcirc%
2579       \fi%
2580     \else%
2581       \sd@dostack{\ht\z@}{\dp\z@}\relax\relax%
2582     \fi%
2583   \fi%
2584 %    \end{macrocode}
2585 %
2586 % The next item won't be the first, so we clear the flag.
2587 %
2588 %    \begin{macrocode}
2589   \sd@toplayerfalse%
2590 %    \end{macrocode}
2591 %
2592 % Now we have to set up the next cell.  We put the text into a box again.
2593 %
2594 %    \begin{macrocode}
2595   \setbox\z@\hbox\bgroup%
2596     \strut%
2597 }
2598 %    \end{macrocode}
2599 %
2600 % \end{macro}
2601 %
2602 % \begin{macro}{\sd@dostack}
2603 %
2604 % Actually typesetting the text in a cell is performed here.  The macro is
2605 % called as
2606 % \begin{quote}\synshorts
2607 % "\\sd@dostack{"<height>"}{"<depth>"}{"<left-arc>"}{"<right-arc>"}"
2608 % \end{quote}
2609 % where \<height> and \<depth> are the height and depth of the vertical
2610 % rules to put around the item, and \<left-arc> and \<right-arc> are
2611 % commands to draw rounded edges on the left and right hand sides of the
2612 % item.
2613 %
2614 % The values for the height and depth are quite often going to be the height
2615 % and depth of box~0.  Since we empty box~0 in the course of typesetting the
2616 % row, we need to cache the sizes on entry.
2617 %
2618 %    \begin{macrocode}
2619 \def\sd@dostack#1#2#3#4{%
2620   \@tempdima#1%
2621   \@tempdimb#2%
2622   \ifsd@left%
2623     \kern-\tw@\sdrulewidth%
2624     \vrule\@height\@tempdima\@depth\@tempdimb\@width\tw@\sdrulewidth%
2625     #3%
2626     \sd@rule\hfil%
2627     \sd@gap\sdtokskip%
2628   \else%
2629     \hfill%
2630   \fi%
2631   \unhbox\z@%
2632   \ifsd@right%
2633     \sd@gap\sdtokskip%
2634     \sd@rule\hfil%
2635     #4%
2636     \vrule\@height\@tempdima\@depth\@tempdimb\@width\tw@\sdrulewidth%
2637     \kern-\tw@\sdrulewidth%
2638   \else%
2639     \hfill%
2640   \fi%
2641   \cr%
2642 }
2643 %    \end{macrocode}
2644 %
2645 % \end{macro}
2646 %
2647 % \subsubsection{The \protect\env{rep} environment}
2648 %
2649 % The \env{rep} environment is used for typesetting loops in the diagram.
2650 % Again, we use |\halign| for the typesetting.  Loops are simpler than
2651 % stacks, however, since there are always two rows.  We store both rows in
2652 % box registers, and build the loop at the end.
2653 %
2654 % \begin{macro}{\rep}
2655 %
2656 % Again, we use |\newcommand| to process the optional argument.
2657 %
2658 %    \begin{macrocode}
2659 \newcommand\rep[1][t]{%
2660 %    \end{macrocode}
2661 %
2662 % First, leave a gap on the left side.
2663 %
2664 %    \begin{macrocode}
2665   \sd@gap\sdmidskip%
2666 %    \end{macrocode}
2667 %
2668 % We're not at base level any more, so disable linebreaking.
2669 %
2670 %    \begin{macrocode}
2671   \begingroup\sd@basefalse%
2672 %    \end{macrocode}
2673 %
2674 % Remember we're going backwards now.
2675 %
2676 %    \begin{macrocode}
2677   \ifsd@backwards\sd@backwardsfalse\else\sd@backwardstrue\fi%
2678 %    \end{macrocode}
2679 %
2680 % Define |\\| to separate the two parts of the loop.
2681 %
2682 %    \begin{macrocode}
2683    \let\\\sd@loop%
2684 %    \end{macrocode}
2685 %
2686 % Now check the argument, and use the appropriate type of box.  In addition
2687 % to changing the typesetting, we must remember which way up to typeset the
2688 % loop, since the end code must always put the first argument on the
2689 % baseline, with the loop either above or below.
2690 %
2691 %    \begin{macrocode}
2692   \if#1t%
2693     \let\@tempa\vbox%
2694     \sd@toptrue%
2695   \else\if#1b%
2696     \let\@tempa\vtop%
2697     \sd@topfalse%
2698   \else%
2699     \sd@err{Bad position argument passed to loop}%
2700            {The positioning argument must be `t' or `b'.  I have^^J%
2701             assumed you meant to type `t'.}%
2702     \let\@tempa\vbox%
2703     \sd@toptrue%
2704   \fi\fi%
2705 %    \end{macrocode}
2706 %
2707 % Now we start the box.
2708 %
2709 %    \begin{macrocode}
2710   \@tempa\bgroup%
2711 %    \end{macrocode}
2712 %
2713 % The loop is by default empty, apart from a strut.  This is put into box~1.
2714 %
2715 %    \begin{macrocode}
2716   \setbox\tw@\copy\strutbox%
2717 %    \end{macrocode}
2718 %
2719 % Now start typesetting the main text in box~0.
2720 %
2721 %    \begin{macrocode}
2722   \setbox\z@\hbox\bgroup\strut%
2723 }
2724 %    \end{macrocode}
2725 %
2726 % \end{macro}
2727 %
2728 % \begin{macro}{\endrep}
2729 %
2730 % The final code must first close whatever box was open.
2731 %
2732 %    \begin{macrocode}
2733 \def\endrep{%
2734   \egroup%
2735 %    \end{macrocode}
2736 %
2737 % Now we typeset the loop, depending on which way up it was meant to be.
2738 % Again, this terrifying piece of code is a simple list of possibile values
2739 % of our various flags.
2740 %
2741 %    \begin{macrocode}
2742   \ifsd@top%
2743     \ifsd@round%
2744       \sd@doloop\tw@\z@\relax\relax%
2745         \sd@tlcirc\sd@trcirc{\sd@rlc\sd@blcirc}{\sd@llc\sd@brcirc}%
2746     \else%
2747       \sd@doloop\tw@\z@\relax\sd@downarr\relax\relax\relax\relax%
2748     \fi%
2749   \else%
2750     \ifsd@round%
2751       \sd@doloop\z@\tw@\relax\relax%
2752         {\sd@rlc\sd@tlcirc}{\sd@llc\sd@trcirc}\sd@blcirc\sd@brcirc%
2753     \else%
2754       \sd@doloop\z@\tw@\sd@uparr\relax\relax\relax\relax\relax%
2755     \fi%
2756   \fi%
2757 %    \end{macrocode}
2758 %
2759 % Close the vbox we opened.
2760 %
2761 %    \begin{macrocode}
2762   \egroup%
2763 %    \end{macrocode}
2764 %
2765 % Finally, we leave a gap before the next structure.
2766 %
2767 %    \begin{macrocode}
2768   \endgroup\sd@gap\sdmidskip%
2769 }
2770 %    \end{macrocode}
2771 %
2772 % \end{macro}
2773 %
2774 % \begin{macro}{\sd@loop}
2775 %
2776 % This macro handles the |\\| command within a loop environment.  We close
2777 % the current box, and start filling in box~1.  We also redefine |\\| to
2778 % raise an error when the |\\| command is used again.
2779 %
2780 %    \begin{macrocode}
2781 \def\sd@loop{%
2782   \egroup%
2783   \def\\{\sd@err{Too many \string\\\space commands in loop}\@ehc}%
2784   \setbox\tw@\hbox\bgroup\strut%
2785 }
2786 %    \end{macrocode}
2787 %
2788 % \end{macro}
2789 %
2790 % \begin{macro}{\sd@doloop}
2791 %
2792 % This is the macro which actually creates the |\halign| for the loop.  It
2793 % is called with four arguments, as:
2794 % \begin{quote}\synshorts
2795 % "\\sd@doloop{"<top-box>"}{"<bottom-box>"}"^^A
2796 %                "{"<top-arrow>"}{"<btm-arrow>"}" \\
2797 % \hbox{}\quad "{"<top-left-arc>"}{"<top-right-arc>"}"^^A
2798 %                "{"<bottom-left-arc>"}{"<btm-right-arc>"}"^^A
2799 % \kern-1in ^^A It may be overfull, but it looks OK to me ;-)
2800 % \end{quote}
2801 %
2802 % The two \<box> arguments give the numbers of boxes to extract in the top
2803 % and bottom rows of the alignment.  The \<arrow> arguments specify
2804 % characters to typeset at the end of the top and bottom rows for arrows.
2805 % The various \<arc> arguments are commands which typeset arcs around the
2806 % various parts of the items.
2807 %
2808 % We calculate the height and depth of the two boxes, and store them in
2809 % \<dimen> registers, because the boxes are emptied before the right-hand
2810 % rules are typeset.
2811 %
2812 % Actually, the two rows of the alignment are typeset in a different macro:
2813 % we just pass the correct information on.
2814 %
2815 %    \begin{macrocode}
2816 \def\sd@doloop#1#2#3#4#5#6#7#8{%
2817   \@tempdima\dp#1\relax%
2818   \@tempdimb\ht#2\relax%
2819   \offinterlineskip%
2820   \ialign{%
2821     ##\cr%
2822     \ifsd@round%
2823       \sd@doloop@i#1#3\sd@topcirc\@tempdima{#5}{#6}%
2824       \sd@doloop@i#2#4\@tempdimb\sd@botcirc{#7}{#8}%
2825     \else%
2826       \sd@doloop@i#1#3\sd@upper\@tempdima{#5}{#6}%
2827       \sd@doloop@i#2#4\@tempdimb\sd@lower{#7}{#8}%
2828     \fi%
2829   }%
2830 }
2831 %    \end{macrocode}
2832 %
2833 % \end{macro}
2834 %
2835 % \begin{macro}{\sd@doloop@i}
2836 %
2837 % Here we do the actual job of typesetting the rows of a loop alignment.
2838 % The four arguments are:
2839 % \begin{quote}\synshorts
2840 % "\\sd@doloop@i{"<box>"}{"<arrow>"}"^^A
2841 %              "{"<rule-height>"}{"<rule-depth>"}" \\
2842 % \hbox{}\quad "{"<left-arc>"}{"<right-arc>"}"^^A
2843 % \end{quote}
2844 %
2845 % The arrow position is determined by the |\ifsd@backwards| flag.  The rest
2846 % is fairly simple.
2847 %
2848 %    \begin{macrocode}
2849 \def\sd@doloop@i#1#2#3#4#5#6{%
2850   \ifsd@backwards#2\fi%
2851   \kern-\tw@\sdrulewidth%
2852   \vrule\@height#3\@depth#4\@width\tw@\sdrulewidth%
2853   #5%
2854   \sd@rule\hfill%
2855   \sd@gap\sdtokskip%
2856   \unhbox#1%
2857   \sd@gap\sdtokskip%
2858   \sd@rule\hfill%
2859   #6%
2860   \vrule\@height#3\@depth#4\@width\tw@\sdrulewidth%
2861   \ifsd@backwards\else#2\fi%
2862   \kern-\tw@\sdrulewidth%
2863   \cr%
2864 }
2865 %    \end{macrocode}
2866 %
2867 % \end{macro}
2868 %
2869 % \subsection{The end}
2870 %
2871 % Phew!  That's all of it completed.  I hope this collection of commands
2872 % and environments is of some help to someone.
2873 %
2874 %    \begin{macrocode}
2875 %</package>
2876 %    \end{macrocode}
2877 %
2878 % \hfill Mark Wooding, \today
2879 %
2880 % \Finale
2881 %
2882 \endinput