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