1 % \begin{meta-comment} <general public licence>
3 %% syntax package -- typesetting syntax descriptions
4 %% Copyright (c) 1996, 2002, 2015, 2020 Mark Wooding
6 %% This file is part of the `mdwtools' LaTeX package collection.
8 %% `mdwtools' is free software: you can redistribute it and/or modify it
9 %% under the terms of the GNU General Public License as published by the
10 %% Free Software Foundation; either version 2 of the License, or (at your
11 %% option) any later version.
13 %% `mdwtools' is distributed in the hope that it will be useful, but
14 %% WITHOUT ANY WARRANTY; without even the implied warranty of
15 %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 %% General Public License for more details.
18 %% You should have received a copy of the GNU General Public License
19 %% along with `mdwtools'. If not, write to the Free Software Foundation,
20 %% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 % \begin{meta-comment} <Package preamble>
25 %<+package>\NeedsTeXFormat{LaTeX2e}
26 %<+package>\ProvidesPackage{syntax}
27 %<+package> [2020/09/06 1.14.0 Syntax typesetting]
32 %% {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
33 %% 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
34 %% Digits \0\1\2\3\4\5\6\7\8\9
35 %% Exclamation \! Double quote \" Hash (number) \#
36 %% Dollar \$ Percent \% Ampersand \&
37 %% Acute accent \' Left paren \( Right paren \)
38 %% Asterisk \* Plus \+ Comma \,
39 %% Minus \- Point \. Solidus \/
40 %% Colon \: Semicolon \; Less than \<
41 %% Equals \= Greater than \> Question mark \?
42 %% Commercial at \@ Left bracket \[ Backslash \\
43 %% Right bracket \] Circumflex \^ Underscore \_
44 %% Grave accent \` Left brace \{ Vertical bar \|
45 %% Right brace \} Tilde \~}
48 % \begin{meta-comment} <driver>
52 % This hacking will remember the old default underscore character. Even if
53 % T1 fonts are being used, it will get the grotty version. Why is it that
54 % all of the encoding handling ends up looking like this?
56 \expandafter\let\expandafter\oldus\csname?\string\textunderscore\endcsname
59 \describespackage{syntax}
60 \DeclareRobustCommand\syn{\package{syntax}}
66 % \section{User guide}
68 % \subsection{Introduction}
70 % The \syn\ package provides a number of commands and environments which
71 % extend \LaTeX\ and allow you to typeset good expositions of syntax.
73 % The package provides several different types of features: probably not all
74 % of these will be required by every document which needs the package:
76 % \item A system of abbreviated forms for typesetting syntactic items.
77 % \item An environment for typesetting BNF-type grammars
78 % \item A collection of environments for building syntax diagrams.
81 % The package also includes some other features which, while not necessarily
82 % syntax-related, will probably come in handy for similar types of document:
84 % \item An abbreviated notation for verbatim text, similar to the
85 % \package{shortvrb} package.
86 % \item A slightly different underscore character, which works as expected
87 % in text and maths modes.
90 % \subsection{The abbreviated verbatim notation}
92 % In documents describing programming languages and libraries, it can become
93 % tedious to type "\verb|...|" every time. Like Frank Mittelbach's
94 % \package{shortvrb} package, \syn\ provides a way of setting up single-^^A
95 % character abbreviations. The only real difference between the two is that
96 % the declarations provided by \syn\ obey \LaTeX's normal scoping rules.
98 % \DescribeMacro\shortverb
99 % You can set up a character as a `verbatim shorthand' character using the
100 % |\shortverb| command. This takes a single argument, which should be a
101 % single-character control sequence containing the character you want to use.
102 % So, for example, the command
106 % would set up the `"|"' character to act as a verbatim delimiter. While a
107 % |\shortverb| declaration is in force, any text surrounded by (in this case)
108 % vertical bar characters will be typeset as if using the normal |\verb|
111 % \DescribeEnv{shortverb}
112 % Since \LaTeX\ allows any declaration to be used as an environment, you can
113 % use a \env{shortverb} environment to delimit the text over which your
114 % character is active:
117 %\begin{shortverb}{\|}
122 % \DescribeMacro\unverb
123 % If you want to disable a |\shortverb| character without ending the scope
124 % of other declarations, you can use the |\unverb| command, passing it
125 % a character as a control sequence, in the same way as above.
127 % The default \TeX/\LaTeX\ underscore character is rather too short for
128 % use in identifiers. For example:
130 % \begingroup \let\_=\oldus
131 % \begin{demo}{Old-style underscores}
132 %Typing long underscore-filled
133 %names, like big\_function\_name,
134 %is normally tedious. The normal
135 %positioning of the underscore
140 % The \syn\ package redefines the |\_| command to draw a more attractive
141 % underscore character. It also allows you to use the |_|~character
142 % directly to produce an underscore outside of maths mode: |_|~behaves
143 % as a subscript character as usual inside maths mode.
145 % \begin{demo}{New \syn\ underscores}
146 %You can use underscore-filled
147 %names, like big_function_name,
148 %simply and naturally. Of
149 %course, subscripts still work
150 %normally in maths mode, e.g.,
154 % \subsection{Typesetting syntactic items}
157 % The \syn\ package provides some simple commands for typesetting syntactic
160 % \DescribeMacro\synt
161 % Typing "\\synt{"<text>"}" typesets <text> as a \lq non-terminal',
162 % in italics and surrounded by angle brackets. If you use "\\synt" a lot,
163 % you can use the incantation
165 %\def\<#1>{\synt{#1}}
167 % to allow you to type "\\<"<text>">" as an alternative to
168 % "\\synt{"<text>"}".
171 % You can also display literal text, which the reader should type directly,
172 % using the "\\lit" command.
174 % \begin{demo}{Use of \cmd\lit}
175 %Type \lit{ls} to display a
179 % Note that the literal text appears in quotes. To suppress the quotes,
180 % use the `*' variant.
182 % The "\\lit" command produces slightly better output than "\\verb" for
183 % running text, since the spaces are somewhat narrower. However, "\\verb"
184 % allows you to type arbitrary characters, which are treated literally,
185 % whereas you must use commands such as "\\{" to use special characters
186 % within the argument to "\\lit". Of course, you can use "\\lit" anywhere
187 % in the document: "\\verb" mustn't be used inside a command argument.
190 % \subsection{Abbreviated forms for syntactic items}
192 % It would be very tedious to require the use of commands like |\synt|
193 % when building syntax descriptions like BNF grammars. It would also make
194 % your \LaTeX\ source hard to read. Therefore, \syn\ provides some
195 % abbreviated forms which make typesetting syntax quicker and easier.
197 % Since the abbreviated forms use several characters which you may want to
198 % use in normal text, they aren't enabled by default. They only work
199 % with special commands and environments provided by the \syn\ package.
201 % The abbreviated forms are shown in the table below:
203 % \begin{tab}[\synshorts]{ll} \hline
204 % \bf Input & \bf Output \\ \hline
205 % "<some text>" & <some text> \\
206 % "`some text'" & `some text' \\
207 % "\"some text\"" & "some text" \\ \hline
210 % Within one of these abbreviated forms, text is treated more-or-less
214 % \item Any |$|, |%|, |^|, |&|, |{|, |}|, |~| or |#| characters are treated
215 % literally: their normal special meanings are ignored.
217 % \item Other special characters, with the exception of |\|, are also treated
218 % literally: this includes any characters made special by |\shortverb|.
222 % However, the |\| character retains its meaning. Since the brace
223 % characters are not recognised, most commands can't be used within
224 % abbreviated forms. However, you can use special commands to type some
225 % of the remaining special characters:
227 % \begin{tab}[\synshorts]{ll} \hline
228 % \bf Command & \bf Result \\ \hline
229 % "\\\\" & A `\\' character \\
230 % "\\>" & A `>' character \\
231 % "\\'" & A `\'' character \\
232 % "\\\"" & A `"' character \\
233 % "\\\ " & A `\ ' character (not a space) \\ \hline
236 % Note that |\\|, |\>|, |\"| and \verb*|\ | are only useful in a |\tt| font,
237 % i.e., inside |`...'| and |"..."| forms, since the characters don't exist
238 % in normal fonts. The |\>|, |\"| and |\'| commands are only provided so
239 % you can use these characters within |<...>|, |"..."| and |`...'| forms
240 % respectively: in the other forms, there is no need to use the special
243 % In addition, when the above abbreviations are enabled, the character "|"
244 % is set to typeset a \syntax{|} symbol, which is conventionally used to
245 % separate alternatives in syntax descriptions.
247 % \DescribeMacro\syntax
248 % Normally, these abbreviated forms are enabled only within special
249 % environments, such as \env{grammar} and \env{syntdiag}. To use them
250 % in running text, use the |\syntax| command. The abbreviations are made
251 % active within the argument of the |\syntax| command.\footnote{^^A
252 % The argument of the \cmd\syntax\ command may contain commands such
253 % as \cmd\verb, which are normally not allowed within arguments.
254 % } Note that you cannot use the |\syntax| command within the argument
255 % of another command.
257 % \DescribeMacro\synshorts
258 % \DescribeEnv{synshorts}
259 % You can also enable the syntax shortcuts using the |\synshorts| declaration
260 % or the \env{synshorts} environment. This enables the syntax shortcuts
261 % until the scope of the declaration ends.
263 % \DescribeMacro\synshortsoff
264 % If syntax shortcuts are enabled, you can disable them using the
265 % |\synshortsoff| declaration.
267 % \subsection{The \env{grammar} environment}
269 % \DescribeEnv{grammar}
270 % For typesetting formal grammars, for example, of programming languages,
271 % the \syn\ package provides a \env{grammar} environment. Within this
272 % environment, the abbreviated forms described above are enabled.
274 % Within the environment, separate production rules should be separated by
275 % blank lines. You can use the normal |\\| command to perform line-breaking
276 % of a production rule. Note that a production rule must begin with a
277 % nonterminal name enclosed in angle brackets (|<| \dots |>|), followed by
278 % any decorative material, whitespace, some kind of production operator
279 % (usually `::=') and then some more whitespace. You can control how this
280 % text is actually typeset, however.
282 % \DescribeMacro{\[[}
283 % \DescribeMacro{\]]}
284 % You can use syntax diagrams (see below) instead of a straight piece of BNF
285 % by enclosing it in a |\[[| \dots |\]]| pair. Note that you can't mix
286 % syntax diagrams and BNF in a production rule, and you will get something
287 % which looks very strange if you try.
290 % In addition, a command |\alt| is provided for splitting long production
291 % rules over several lines: the |\alt| command starts a new line and places
292 % a \syntax{|} character slightly in the left margin. This is useful when
293 % a symbol has many alternative productions.
295 % \begin{demo}[w]{The \env{grammar} environment}
297 %<statement> ::= <ident> `=' <expr>
298 % \alt `for' <ident> `=' <expr> `to' <expr> `do' <statement>
299 % \alt `{' <stat-list> `}'
302 %<stat-list> ::= <statement> `;' <stat-list> | <statement>
306 % You can modify the appearance of grammars using three length parameters:
308 % \begin{description} \setdescriptionlabel{\cmd{#1}}
310 % \item [\grammarparsep] is the amount of space inserted between production
311 % rules. It is a rubber length whose default value is 8\,pt, with
312 % 1\,pt of stretch and shrink.
314 % \item [\grammarindent] is the amount by which the right hand side of a
315 % production rule is indented from the left margin. It is a rigid
316 % length. Its default value is 2\,em.
320 % \DescribeMacro\grammarlabelx
321 % You can also control how the `label' is typeset by redefining the
322 % |\grammarlabelx| command. The command is given three arguments: the name
323 % of the nonterminal (which was enclosed in angle brackets), the following
324 % decorative material, and the `production operator'. The command is
325 % expected to produce the label. By default, it typesets the nonterminal
326 % name using |\synt| followed by the decoration, and the operator, at
327 % opposite ends of the label, separated by an |\hfill|.
329 % \DescribeMacro\grammarlabel
330 % For compatibility, if there is no decorative material, the macro
331 % |\grammarlabel| is called instead, with just two arguments: the nonterminal
332 % name and the operator. The default implementation of |\grammarlabel| just
333 % calls |\grammarlabelx| with empty decoration.
335 % \subsection{Syntax diagrams}
337 % A full formal BNF grammar can be somewhat overwhelming for less technical
338 % readers. Documents aimed at such readers tend to display grammatical
339 % structures as \emph{syntax diagrams}.
341 % \DescribeEnv{syntdiag}
342 % A syntax diagram is always enclosed in a \env{syntdiag} environment. You
343 % should think of the environment as enclosing a new sort of \LaTeX\ mode:
344 % trying to type normal text into a syntax diagram will result in very ugly
345 % output. \LaTeX\ ignores spaces and return characters while in syntax
348 % The syntax of the environment is very simple:
351 % <synt-diag-env> ::= \[[
352 % "\\begin{syntdiag}"
353 % \begin{stack} \\ "[" <decls> "]" \end{stack}
359 % The \<decls> contain any declarations you want to insert, to control
360 % the environment. The parameters to tweak are described below.
362 % Within a syntax diagram, you can include syntactic items using the
363 % abbreviated forms described elsewhere. The output from these forms is
364 % modified slightly in syntax diagram mode so that the diagram looks
367 % I probably ought to point out now that the syntax diagram typesetting
368 % commands produce beautiful-looking diagrams with all the rules and curves
369 % accurately positioned. Some device drivers don't position these objects
370 % correctly in their output. I've had particular trouble with |dvips|. I'll
371 % say it again: it's not my fault!
373 % \DescribeEnv{syntdiag*}
374 % The \env{syntdiag} environment only works in paragraph mode, and it acts
375 % rather like a paragraph, splitting over several lines when appropriate.
376 % If you just want to typeset a snippet of a syntax diagram, you can
377 % use the starred environment \env{syntdiag$*$}.
380 % <synt-diag-star-env> ::= \[[
381 % "\\begin{syntdiag*}"
382 % \begin{stack} \\ "[" <decls> "]" \end{stack}
383 % \begin{stack} \\ "[" <width> "]" \end{stack}
389 % When typesetting little demos like this, it's not normal to fully adorn
390 % the syntax diagram with the full double arrows
391 % (`\begin{syntdiag*}[\left{>>-}\right{-><}]\tok{$\cdots$}\end{syntdiag*}').
392 % The two declarations \syntax{"\\left{"<arrow>"}" and "\\right{"<arrow>"}"}
393 % allow you to choose the arrows on each side of the syntax diagram snippet.
394 % The possible values of \<arrow> are shown in the table-ette below:
396 % ^^A Time to remember what I learned about tables while writing mdwtab.
397 % ^^A Just for the embarassment factor, here's the number of attempts I
398 % ^^A took to get the table below to look right: __6. Hmm... not as bad
399 % ^^A as I expected. Most of them were fine-tuning things.
401 % \medskip ^^A Leave a vertical gap
402 % \hbox to\columnwidth{\hfil\vbox{\tabskip=0pt ^^A Centre it horizontally
403 % \sdsize \csname sd@setsize\endcsname ^^A Position syntdiag arrows
404 % \halign to .5\columnwidth{ ^^A Set the table width
405 % &\ttfamily\ignorespaces#\unskip\hfil\tabskip=0pt ^^A Typeset the name
406 % &\quad\csname sd@arr@#\endcsname\hfil ^^A Typeset the arrow
407 % &\setbox0=\hbox{#}\tabskip=0pt plus 1fil\cr ^^A Stretch between columns
408 % >>-&>>-& &>-&>-& &->&->\cr
409 % -><&-><& &...&...& &-&-\cr
410 % }}\hfil} ^^A Close the boxing
411 % \medskip ^^A And leave another gap
413 % These declarations should be used only in the optional argument to the
414 % \env{syntdiag$*$} command. The second optional argument to the
415 % environment, if specified, fixes the width of the syntax diagram snippet;
416 % if you omit this argument, the diagram is made just wide enough to
420 % \begin{demo}[w]{Example of \env{syntdiag$*$}}
421 %\newcommand{\bs}[2]{%
422 % \begin{minipage}{1.6in}%
423 % \begin{syntdiag*}[\left{#1}\right{#2}][1.6in]%
425 %\newcommand{\es}{\end{syntdiag*}\end{minipage}}
428 %\begin{tabular}{cl} \\ \hline
429 %\bf Construction & \bf Meaning \\ \hline
430 %\bs {>>-} {...} \es & Start of syntax diagram \\
431 %\bs {...} {-><} \es & End of syntax diagram \\
432 %\bs {>-} {...} \es & Continued on next line \\
433 %\bs {...} {->} \es & Continued from previous line \\ \hline
435 % \begin{stack} <option-a> \\ <option-b> \\ <option-c> \end{stack}
436 %\es & Alternatives: choose any one \\
438 % \begin{rep} <repeat-me> \\ <separator> \end{rep}
439 %\es & One or more items, with separators \\ \hline
446 % You can also include text using the |\tok| command. The argument of this
447 % command is typeset in \LaTeX's LR~mode and inserted into the diagram.
448 % Syntax abbreviations are allowed within the argument, so you can, for
449 % example, include textual descriptions like
451 %\tok{any <char> except `"'}
454 % \DescribeEnv{stack}
455 % Within a syntax diagram, a choice between several different items is
456 % shown by stacking the alternatives vertically. In \LaTeX, this is done
457 % by enclosing the items in a \env{stack} environment. Each individual item
458 % is separated by |\\| commands, as in the \env{array} and \env{tabular}
459 % environments. Each row may contain any syntax diagram material, including
460 % |\tok| commands and other \env{stack} environments.
462 % Note if you end a \env{stack} environment with a |\\| command, a blank
463 % row is added to the bottom of the stack, indicating that none of the items
467 % Text which can be repeated is enclosed in a \env{rep} environment: the
468 % text is displayed with a backwards pointing arrow drawn over it, showing
469 % that it may be repeated. Optionally, you can specify text to be
470 % displayed in the arrow, separating it from the main text with a |\\|
473 % Note that items on the backwards arrow of a \env{rep} construction should
474 % be displayed \emph{backwards}. You must put the individual items in
475 % reverse order when building this part of your diagrams. \syn\ will
476 % correctly reverse the arrows on \env{rep} structures, but apart from
477 % this, you must cope on your own. You are recommended to keep these parts
478 % of your diagrams as simple as possible to avoid confusing readers.
480 % \begin{demo}[w]{A syntax diagram}
483 % \begin{rep} \begin{stack} \\
484 % <type> \begin{stack} \\ <ident> \end{stack}
485 % \end{stack} \\ `,' \end{rep}
486 %\begin{stack} \\ `...' \end{stack} `)'
496 % The environments \env{stack} and \env{rep} are rather cumbersome to use.
497 % As an alternative, the commands |\(| and |\)| are equivalent to
498 % |\begin{stack}| and |\end{stack}| respectively, and |\<| and |\>| are
499 % equivalent to |\begin{rep}| and |\end{rep}|. Also, |\[| and |\]| are
500 % like |\begin{stack}| and |\end{stack}| except that an empty initial row is
503 % \subsubsection{Line breaking in syntax diagrams}
505 % Syntax diagrams are automatically broken over lines and across pages.
506 % Lines are only broken between items on the outermost level of the diagram:
507 % i.e., not within \env{stack} or \env{rep} environments.
509 % You can force a line break at a particular place by using the |\\| command
510 % as usual. This supports all the usual \LaTeX\ features: a `|*|' variant
511 % which prohibits page breaking, and an optional argument specifying the
512 % extra vertical space between lines.
514 % \subsubsection{Customising syntax diagrams}
516 % There are two basic styles of syntax diagrams supported:
518 % \begin{description}
520 % \item [square] Lines in the syntax diagram join at squared-off corners.
521 % This appears to be the standard way of displaying syntax diagrams
522 % in IBM manuals, and most other documents I've seen.
524 % \item [rounded] Lines curve around corners. Also, no arrows are drawn
525 % around repeating loops: the curving of the lines provides this
526 % information instead. This style is used in various texts on
527 % Pascal, and appears to be more popular in academic circles.
531 % You can specify the style you want to use for syntax diagrams by giving
532 % the style name as an option on the |\usepackage| command. For example,
533 % to force rounded edges to be used, you could say
536 %\usepackage[rounded]{syntax}
539 % \DescribeMacro\sdsize
540 % \DescribeMacro\sdlengths
541 % The \env{syntdiag} environment takes an option argument, which should
542 % contain declarations which are obeyed while the environment is set up.
543 % The default value of this argument is `|\sdsize\sdlengths|'. The
544 % |\sdsize| command sets the default type size for the environment: this is
545 % normally |\small|. |\sdlengths| sets the values of the length parameters
546 % used by the environment based on the current text size. These parameters
547 % are described below.
549 % For example, if you wanted to reduce the type size of the diagrams still
550 % further, you could use the command
552 %\begin{syntdiag}[\tiny\sdlengths]
555 % The following length parameters may be altered:
557 % \begin{description} \setdescriptionlabel{\cmd{#1}}
559 % \item [\sdstartspace] The length of the rule between the arrows which
560 % begin each line of the syntax diagram and the first item on the line.
561 % Note that most objects have some space on either side of them as
562 % well. This is a rubber length. Its default value is 1\,em, although
563 % it can shrink by up to 10\,pt.
565 % \item [\sdendspace] The length of the rule between the last item on a
566 % line and the arrow at the very end. Note that the final line also
567 % has extra rubber space on the end. This is a rubber length. Its
568 % default value is 1\,em, although it will shrink by up to 10\,pt.
570 % \item [\sdmidskip] The length of the rule on either side of a large
571 % construction (either a \env{stack} or a \env{rep}). It is a rubber
572 % length. Its default value is \smallf 1/2\,em, with a very small
573 % amount of infinite stretch.
575 % \item [\sdtokskip] The length of the rule on either side of a |\tok|
576 % item or syntax abbreviation. It is a rubber length. Its default
577 % value is \smallf 1/4\,em, with a very small amount of inifnite
580 % \item [\sdfinalskip] The length of the rule which finishes the last line
581 % of a syntax diagram. It is a rubber length. Its default value is
582 % \smallf 1/2\,em, with 10000\,fil of stretch, which will left-align
583 % the items on the line.\footnote{^^A
584 % This is a little \TeX nical. The idea is that if a stray 1\,fil
585 % of stretch is added to the end of the line, it won't be noticed.
586 % However, the alignment of the text on the line can still be
587 % modified using \cmd{\sd@rule}\cmd{\hfill}, if you're feeling
591 % \item [\sdrulewidth] Half the width of the rules used in the diagram.
592 % It is a rigid length. Its default value is 0.2\,pt.
594 % \item [\sdcirclediam] The diameter of the circle from which the quadrants
595 % used in rounded-style diagrams are taken. This must be a multiple
596 % of 4\,pt, or else the lines on the diagram won't match up.
600 % In addition, you should call |\sdsetstrut| passing it the total height
601 % (\({\rm height}+{\rm depth}\)) of a normal line of text at the current
602 % size. Normally, the value of |\baselineskip| will be appropriate.
604 % You can also alter the appearance of \env{stack}s and \env{rep}s by using
605 % their optional positioning arguments. By default, \env{stack}s descend
606 % below the main line of the diagram, and \env{rep}s extend above it.
607 % Specifying an optional argument of |[b]| for either environment reverses
608 % this, putting \env{stack}s above and \env{rep}s below the line.
610 % \subsection{Changing the presentation styles}
612 % You can change the way in which the syntax items are typeset by altering
613 % some simple commands (using |\renewcommand|). Each item (nonterminals,
614 % as typeset by |\synt|, and quoted and unquoted terminals, as typeset by
615 % |\lit| and |\lit*|) has two style commands associated with it, as shown
616 % in the table below.
618 % \begin{tab}{lll} \hline
619 % \bf Syntax item & \bf Left command & \bf Right command \\ \hline
620 % Nonterminals & |\syntleft| & |\syntright| \\
621 % Quoted terminals & |\litleft| & |\litright| \\
622 % Unquoted terminals & |\ulitleft| & |\ulitright| \\ \hline
625 % It's not too hard to see how this works. For example, if you look at
626 % the implementation for |\syntleft| and |\syntright| in the implementation
627 % section, you'll notice that they're defined like this:
629 %\newcommand{\syntleft}{$\langle$\normalfont\itshape}
630 %\newcommand{\syntright}{$\rangle$}
632 % I think this is fairly simple, if you understand things like font changing.
634 % Note that changing these style commands alters the appearance of all syntax
635 % objects of the appropriate types, as created by the |\synt| and |\lit|
636 % commands, in \env{grammar} environments, and in syntax diagrams.
641 % \section{Implementation of \syn}
647 % \subsection{Options handling}
649 % We define all the options we know about, and then see what's been put
650 % on the usepackage line.
652 % The options we provide currently are as follows:
654 % \begin{description}
655 % \item [rounded] draws neatly rounded edges on the diagram.
656 % \item [square] draws squared-off edges on the diagram. This is the
658 % \item [nounderscore] disables the undescore active character, The |\_|
659 % command still produces the nice version created here.
663 \DeclareOption{rounded}{\sd@roundtrue}
664 \DeclareOption{square}{\sd@roundfalse}
665 \DeclareOption{nounderscore}{\@uscorefalse}
668 % Now process the options:
672 \newif\if@uscore\@uscoretrue
673 \newif\ifsd@left\newif\ifsd@right
674 \ExecuteOptions{square}
678 % \subsection{Special character handling}
680 % A lot of the \syn\ package requires the use special active characters.
681 % These must be added to two lists: |\dospecials|, which is used by |\verb|
682 % and friends, and |\@sanitize|, which is used by |\index|. The two macros
683 % here, |\addspecial| and |\remspecial|, provide these registration
686 % Two similar macros are found in Frank Mittelbach's \package{doc} package:
687 % these have the disadvantage of global operation. My macros here are based
688 % on Frank's, which in turn appear to be based on Donald Knuth's list
689 % handling code presented in Appendix~D of \textit{The \TeX book}.
691 % Both these macros take a single argument: a single-character control
692 % sequence containing the special character to be added to or removed from
695 % \begin{macro}{\addspecial}
697 % This is reasonably straightforward. We remove the sequence from the lists,
698 % in case it's already there, and add it in in the obvious way. This
699 % requires a little bit of fun with |\expandafter|.
704 \expandafter\def\expandafter\dospecials\expandafter{\dospecials\do#1}%
705 \expandafter\def\expandafter\@santize\expandafter{%
706 \@sanitize\@makeother#1}%
712 % \begin{macro}{\remspecial}
714 % This is the difficult bit. Since |\dospecials| and |\@sanitize| have the
715 % form of list macros, we can redefine |\do| and |\@makeother| to do the
716 % job for us. We must be careful to put the old meaning of |\@makeother|
717 % back. The current implementation assumes it knows what |\@makeother| does.
721 \def\do##1{\ifnum`#1=`##1 \else\noexpand\do\noexpand##1\fi}%
722 \edef\dospecials{\dospecials}%
723 \def\@makeother##1{\ifnum`#1=`##1 \else%
724 \noexpand\@makeother\noexpand##1\fi}%
725 \edef\@sanitize{\@sanitize}%
726 \def\@makeother##1{\catcode`##112}%
732 % \subsection{Underscore handling}
734 % When typing a lot of identifiers, it can be irksome to have to escape
735 % all `|_|' characters in the manuscript. We make the underscore character
736 % active, so that it typesets an underscore in horizontal mode, and does
737 % its usual job as a subscript operator in maths mode. Underscore must
738 % already be in the special character lists, because of its use as a
739 % subscript character, so this doesn't cause us a problem.
741 % \begin{macro}{\underscore}
743 % The |\underscore| macro typesets an underline character, using a horizontal
744 % rule. This is positioned slightly below the baseline, and is also slightly
745 % wider than the default \TeX\ underscore. This code is based on a similar
746 % implementation found in the \package{lgrind} package.
753 \hrule\@width.6em\@depth.4ex\@height-.34ex%
755 \ifdim\fontdimen\@ne\font=\z@%
763 % \begin{macro}{\@foundunderscore}
765 % This macro is called by the `|_|' active character to sort out what to do.
767 % If this is maths mode, we use the |\sb| macro, which is already defined
768 % to do subscripting. Otherwise, we call |\textunderscore|, which picks the
769 % nicest underscore it can find.
771 % There's some extra cunningness here, because I'd like to be able to
772 % hyphenate after underscores usually, but not when there's another one
773 % following. And then, because \env{tabbing} redefines |\-|, there's some
774 % more yukkiness to handle that: the usual |\@tabacckludge| mechanism doesn't
775 % cope with this particular case.
778 \let\usc@builtindischyphen\-
781 \expandafter\@firstoftwo%
783 \expandafter\@secondoftwo%
786 {\textunderscore\@ifnextchar_{}{\usc@builtindischyphen}}%
792 % Now we set up the active character. Note the |\protect|, which makes
793 % underscores work reasonably well in moving arguments. Note also the way
794 % we end with a some funny stuff to prevent spaces being lost if this is
803 \lowercase{\endgroup\def~{\protect\@uscore.}}%
808 % Finally, we redefine the |\_| macro to use our own |\underscore|, because
809 % it's prettier. Actually, we don't: we just redefine the
810 % |\?\textunderscore| command (funny name, isn't it?).
813 \expandafter\let\csname?\string\textunderscore\endcsname\underscore
816 % \subsection{Abbreviated verbatim notation}
818 % In similar style to the \package{doc} package, we allow the user to set up
819 % characters which delimit verbatim text. Unlike \package{doc}, we make
820 % such changes local to the current group. This is performed through the
821 % |\shortverb| and |\unverb| commands.
823 % The implementations of these commands are based upon the |\MakeShortVerb|
824 % and |\DeleteShortVerb| commands of the \package{doc} package, although
825 % these versions have effect local to the current grouping level. This
826 % prevents their redefinition of |\dospecials| from interfering with the
827 % grammar shortcuts, which require local changes only.
829 % The command |\shortverb| takes a single argument: a single-character
830 % control sequence defining which character to make into the verbatim text
831 % delimiter. We store the old meaning of the active character in a control
832 % sequence called |\mn@\|\<char>. Note that this control sequence
833 % contains a backslash character, which is a little odd. We also define a
834 % command |\cc@\|\<char> which will return everything to normal. This
835 % is used by the |\unverb| command.
837 % \begin{macro}{\shortverb}
839 % Here we build the control sequences we need to make everything work nicely.
840 % The active character is defined via |\lowercase|, using the |~| character:
841 % this is already made active by \TeX\@.
843 % The actual code requires lots of fiddling with |\expandafter| and friends.
849 % First, we check to see if the command |\cc@\|\<char> has been defined.
852 \@ifundefined{cc@\string#1}{%
855 % If it hasn't been defined, we add the character to the specials list.
861 % Now we set our character to be the lowercase version of |~|, which allows
862 % us to use it, even though we don't know what it is.
869 % Finally, we reach the tricky bit. All of this is lowercased, so any
870 % occurrences of |~| are replaced by the user's special character.
877 % We remember the current meaning of the character, in case it has one. We
878 % have to use |\csname| to build the rather strange name we use for this.
881 \expandafter\let\csname mn@\string#1\endcsname~%
884 % Now we build |\cc@\|\<char>. This is done with |\edef|, since more
885 % of this needs to be expanded now than not. In this way, the actual macros
886 % we create end up being very short.
889 \expandafter\edef\csname cc@\string#1\endcsname{%
892 % First, add a command to restore the character's old catcode.
895 \catcode`\noexpand#1\the\catcode`#1%
898 % Now we restore the character's old meaning, using the version we saved
902 \let\noexpand~\expandafter\noexpand%
903 \csname mn@\string#1\endcsname%
906 % Now we remove the character from the specials lists.
909 \noexpand\remspecial\noexpand#1%
912 % Finally, we delete this macro, so that |\unverb| will generate a warning
913 % if the character is |\unverb|ed again.
916 \let\csname cc@\string#1\endcsname\relax%
920 % All of that's over now. We set up the new definition of the character,
921 % in terms of |\verb|, and make the character active. The nasty |\syn@ttspace|
922 % is there to make the spacing come out right. It's all right really. Honest.
925 \def~{\verb~\syn@ttspace}%
930 % If our magic control sequence already existed, we can assume that the
931 % character is already a verbatim delimiter, and raise a warning.
935 \PackageWarning{syntax}{Character `\expandafter\@gobble\string#1'
936 is already a verbatim\MessageBreak
944 % \begin{macro}{\unverb}
946 % This is actually terribly easy: we just use the |\cc@\|\<char> command
947 % we definied earlier, after making sure that it's been defined.
951 \@ifundefined{cc@\string#1}{%
952 \PackageWarning{syntax}{Character `\expandafter\@gobble\string#1'
953 is not a verbatim\MessageBreak
956 \csname cc@\string#1\endcsname%
963 % \subsection{Style hooks for syntax forms}
965 % To allow the appearance of syntax things to be configured, we provide some
968 % The three types of objects (nonterminal symbols, and quoted and unquoted
969 % terminals) each have two macros associated with them: one which does the
970 % `left' bit of the typesetting, and one which does the `right' bit. The
971 % items are typeset as LR~boxes. I'll be extra good while defining these
972 % hooks, so that it's obvious what's going on; macho \TeX\ hacker things
973 % resume after this section.
975 % \begin{macro}{\syntleft}
976 % \begin{macro}{\syntright}
978 % I can't see why anyone would want to change the typesetting of
979 % nonterminals, although I'll provide the hooks for symmetry's sake.
982 \newcommand{\syntleft}{$\langle$\normalfont\itshape}
983 \newcommand{\syntright}{$\rangle$}
989 % \begin{macro}{\ulitleft}
990 % \begin{macro}{\ulitright}
991 % \begin{macro}{\litleft}
992 % \begin{macro}{\litright}
994 % Now we can define the left and right parts of quoted and unquoted
995 % terminals. US~readers may want to put double quotes around the quoted
996 % terminals, for example.
999 \newcommand{\ulitleft}{\normalfont\ttfamily\syn@ttspace\frenchspacing}
1000 \newcommand{\ulitright}{}
1001 \newcommand{\litleft}{`\bgroup\ulitleft}
1002 \newcommand{\litright}{\ulitright\egroup'}
1010 % \subsection{Simple syntax typesetting}
1012 % In general text, we allow access to our typesetting conventions through
1013 % standard \LaTeX\ commands.
1015 % \begin{macro}{\synt}
1017 % The |\synt| macro typesets its argument as a syntactic quantity. It puts
1018 % the text of the argument in italics, and sets angle brackets around it.
1019 % Breaking of a |\synt| object across lines is forbidden.
1022 \def\synt#1{\mbox{\syntleft{#1\/}\syntright}}
1027 % \begin{macro}{\lit}
1029 % The |\lit| macro typesets its argument as literal text, to be typed in.
1030 % Normally, this means setting the text in |\tt| font, and putting quotes
1031 % around it, although the quotes can be suppressed by using the $*$-variant.
1033 % The |\syn@ttspace| macro sets up the spacing for the text nicely: |\tt|
1034 % spaces tend to be a little wide.
1037 \def\lit{\@ifstar{\lit@i\ulitleft\ulitright}{\lit@i\litleft\litright}}
1038 \def\lit@i#1#2#3{\mbox{#1{#3\/}#2}}
1043 % \begin{macro}{\syn@ttspace}
1045 % This sets up the |\spaceskip| value for |\tt| text.
1048 \def\syn@ttspace@{\spaceskip.35em\@plus.2em\@minus.15em\relax}
1051 % However, this isn't always the right thing to do.
1054 \def\ttthinspace{\let\syn@ttspace\syn@ttspace@}
1055 \def\ttthickspace{\let\syn@ttspace\@empty}
1058 % I know what I like thoough.
1066 % \subsubsection{The shortcuts}
1068 % The easy part is over now. The next job is to set up the `grammar
1069 % shortcuts' which allow easy changing of styles.
1071 % We support four shortcuts:
1073 % \item |`literal text'| typesets \syntax{`literal text'}
1074 % \item |<non-terminal>| typesets \syntax{<non-terminal>}
1075 % \item |"unquoted text"| typesets \syntax{"unquoted text"}
1076 % \item \verb"|" typesets a \syntax{|} character
1078 % These are all implemented through active characters, which are enabled
1079 % using the |\syntaxShortcuts| macro, described below.
1081 % \begin{macro}{\readupto}
1083 % \syntax{"\\readupto{"<char>"}{"<decls>"}{"<command>"}"} will read all
1084 % characters up until the next occurrence of \<char>. Normally, all
1085 % special characters will be deactivated. However, you can reactivate some
1086 % characters, using the \<decls> argument, which is processed before the
1089 % The code is borrowed fairly obviously from the \LaTeXe\ source for the
1093 \def\readupto#1#2#3{%
1096 \let\do\@makeother\dospecials%
1101 \gdef\verb@balance@group{\verb@egroup%
1102 \@latex@error{\noexpand\verb illegal in command argument}\@ehc}%
1103 \def\@vhook{\verb@egroup#3}%
1104 \aftergroup\verb@balance@group%
1105 \lowercase{\let~\@vhook}%
1111 % \begin{macro}{\syn@assist}
1113 % The |\syn@assist| macro is used for defining three of the shortcuts. It
1117 % \syntax{"\\syn@assist{"<left-decls>"}{"<actives>"}{"<delimeter>"}" \\
1118 % \null \quad "{"<right-decls>"}{"<end-cmd>"}"}
1121 % It creates an hbox, sets up the escape sequences for quoting our magic
1122 % characters, and then typesets a box containing
1125 % \syntax{<left-decls>"{"<delimited-text>"\\/}"<right-decls>}
1128 % The \<left-decls> and \<right-decls> can be |\relax| if they're not
1131 % The \<actives> argument is passed to |\readupto|, to allow some special
1132 % characters through. By default, we re-enable |\|, and make `\verb*" "'
1133 % typeset some space glue, rather than a space character. A macro
1134 % `\verb*"\ "' is defined to actually print a space character, which yield
1135 % `\verb*" "' in the `|\tt|' font.
1137 % Finally, it defines a |\ch| command, which, given a single-character
1138 % control sequence as its argument, typesets the character. This is useful,
1139 % since |`| has been made active when we set up these calls, so the
1140 % direct |\char`\|\<char> doesn't work.
1143 \def\syn@assist#1#2#3#4#5{%
1146 % First, we start the box, and open a group. We use |\mbox| because it
1147 % does all the messing with |\leavevmode| which is needed.
1150 \leavevmode\hbox\bgroup%
1153 % Next job is to set up the escape sequences.
1163 % Now to define |\ch|. This is done the obvious way.
1166 \def\ch##1{\char`##1}%
1169 % For active characters, we do some fiddling with |\lccode|s.
1173 \catcode`##1\active%
1176 \lowercase{\endgroup\def~}%
1180 % Finally, we do the real work of setting the text. We use |\readupto| to
1181 % actually find the text we want.
1191 \/\endgroup#4\egroup#5%
1198 % \begin{macro}{\syn@shorts}
1200 % This macro actually defines the expansions for the active characters.
1201 % We have to do this separately because |`| must be active when we use it
1202 % in the |\def|, but we can't do that and use |\catcode| at the same time.
1203 % The arguments are commands to do before and after the actual command.
1204 % These are passed up from |\syntaxShortcuts|.
1206 % All of the characters use |\syn@assist| in the obvious way except for
1207 % \verb"|", which drops into maths mode instead.
1209 % Note that when changing the catcodes, we must save |`| until last.
1218 \gdef\syn@shorts#1#2{%
1221 % The `|<|' character must typeset its argument in italics. We make `|_|'
1222 % do the same as the `|\_|' command.
1236 % The `|`|' and `|"|' characters should print its argument in |\tt| font.
1237 % We change the `|\tt|' space glue to provide nicer spacing on the line.
1260 % Finally, the `\verb"|"' character is typeset by using the mysterious
1261 % |\textbar| command.
1267 % We're finished here now.
1277 % \begin{macro}{\syntaxShortcuts}
1279 % This is a user-level command which enables the use of our shortcuts in the
1280 % current group. It uses |\addspecial|, defined below, to register the
1281 % active characters, sets up their definitions and activates them.
1283 % The two arguments are commands to be performed before and after the
1284 % handling of the abbreviation. In this way, you can further process the
1287 % This command is not intended to be used directly by users: it should be
1288 % used by other macros and packages which wish to take advantage of the
1289 % facilities offered by this package. We provide a |\synshorts| declaration
1290 % (which may be used as an environment, of course) which is more `user
1294 \def\syntaxShortcuts#1#2{%
1295 \syn@shorts{#1}{#2}%
1306 \def\synshorts{\syntaxShortcuts\relax\relax}
1311 % \begin{macro}{\synshortsoff}
1313 % This macro can be useful occasionally: it disables the syntax shortcuts,
1314 % so you can type normal text for a while.
1327 % \begin{macro}{\syntax}
1329 % The |\syntax| macro typesets its argument, allowing the use of our
1330 % shortcuts within the argument.
1332 % Actually, we go to some trouble to ensure that the argument to |\syntax|
1333 % \emph{isn't} a real argument so we can change catcodes as we go. We
1334 % use the |\let\@let@token=| trick from \PlainTeX\ to do this.
1337 \def\syntax#{\bgroup\syntaxShortcuts\relax\relax\let\@let@token}
1342 % \begin{environment}{grammar}
1344 % The \env{grammar} environment is the final object we have to define. It
1345 % allows typesetting of beautiful BNF grammars.
1347 % First, we define the length parameters we need:
1350 \newskip\grammarparsep
1351 \grammarparsep8\p@\@plus\p@\@minus\p@
1352 \newdimen\grammarindent
1356 % Now define the default label typesetting. This macro is designed to be
1357 % replaced by a user, so we'll be extra-well-behaved and use genuine \LaTeX\
1358 % commands. Well, almost \dots
1361 \newcommand{\grammarlabel}[2]{\grammarlabelx{#1}{}{#2}}
1362 \newcommand{\grammarlabelx}[3]{\synt{#1}#2 \hfill#3}
1365 % Now for a bit of hacking to make the item stuff work properly. This gets
1366 % done for every new paragraph that's started without an |\item| command.
1368 % First, store the left hand side of the production in a box. Then I'll
1369 % end the paragraph, and insert some nasty glue to take up all the space,
1370 % so no-one will ever notice that there was a paragraph break there. The
1371 % strut just makes sure that I know exactly how high the line is.
1374 \def\gr@implitem<#1>#2 #3 {%
1378 \ifx\@tempa\@empty\grammarlabel{#1}{#3}%
1379 \else\grammarlabelx{#1}{#2}{#3}\fi%
1383 \vskip-\baselineskip%
1386 % The |\item| command will notice that I've inserted these funny glues and
1387 % try to remove them: I'll stymie its efforts by inserting an invisible
1388 % rule. Then I'll insert the label using |\item| in the normal way.
1391 \hrule\@height\z@\@depth\z@\relax%
1395 % Just before I go, I'll make \lit{<} back into an active character.
1402 % Now for the environment proper. Deep down, it's a list environment, with
1403 % some nasty tricks to stop anyone from noticing.
1405 % The first job is to set up the list from the parameters I'm given.
1408 \newenvironment{grammar}{%
1410 \labelwidth\grammarindent%
1411 \leftmargin\grammarindent%
1412 \advance\grammarindent\labelsep
1415 \parsep\grammarparsep%
1419 % We have major problems in |\raggedright| layouts, which try to use |\par|
1420 % to start new lines. We go back to normal |\\| newlines to try and bodge
1421 % our way around these problems.
1427 % Now to enable the shortcuts.
1430 \syntaxShortcuts\relax\relax%
1433 % Now a little bit of magic. The |\alt| macro moves us to a new line, and
1434 % typesets a vertical bar in the margin. This allows typesetting of
1435 % multiline alternative productions in a pretty way.
1438 \def\alt{\\\llap{\textbar\quad}}%
1441 % Now for another bit of magic. We set up some |\par| cleverness to spot
1442 % the start of each production rule and format it in some cunning and
1448 \parshape\@ne\@totalleftmargin\linewidth%
1462 % Now set up the |\[[| and |\]]| commands to do the right thing. We have
1463 % to check the next character to see if it's correct, otherwise we'll
1464 % open a maths display as usual.
1469 \def\gr@endsyntdiag]{\end{syntdiag}\gr@setpar\par}%
1470 \def\[{\@ifnextchar[{\begin{syntdiag}\@gobble}\gr@leftsq}%
1471 \def\]{\@ifnextchar]\gr@endsyntdiag\gr@rightsq}%
1474 % Well, that's it for this side of the environment.
1480 % Closing the environment is a simple matter of tidying away the list.
1491 % \subsection{Syntax diagrams}
1493 % Now we come to the final and most complicated part of the package.
1495 % Syntax diagrams are drawn using arrow characters from \LaTeX's line font,
1496 % used in the \env{picture} environment, and rules. The horizontal rules
1497 % of the diagram are drawn along the baselines of the lines in which they
1498 % are placed. The text items in the diagram are placed in boxes and lowered
1499 % below the main baseline. Struts are added throughout to keep the vertical
1500 % spacing consistent.
1502 % The vertical structures (stacks and loops) are all implemented with \TeX's
1503 % primitive |\halign| command.
1505 % \subsubsection{User-configurable parameters}
1507 % First, we allocate the \<dimen> and \<skip> arguments needed. Fixed
1508 % lengths, as the \LaTeX book calls them, are allocated as \<dimen>s, to
1509 % take some of the load off of all the \<skip> registers.
1512 \newskip\sdstartspace
1516 \newskip\sdfinalskip
1517 \newdimen\sdrulewidth
1518 \newdimen\sdcirclediam
1522 % We need some \TeX\ \<dimen>s for our own purposes, to get everything in
1523 % the right places. We use labels for the `temporary' \TeX\ parameters
1524 % which we use, to avoid wasting registers.
1527 \dimendef\sd@lower\z@
1528 \dimendef\sd@upper\tw@
1530 \dimendef\sd@topcirc6
1531 \dimendef\sd@botcirc8
1535 % \begin{macro}{\sd@setsize}
1536 % When the text size for syntax diagrams changes, it's necessary to work out
1537 % the height for various rules in the diagram.
1541 \sd@mid\ht\strutbox%
1542 \advance\sd@mid-\dp\strutbox%
1544 \sd@upper\sdrulewidth%
1545 \advance\sd@upper\sd@mid%
1546 \sd@lower\sdrulewidth%
1547 \advance\sd@lower-\sd@mid%
1548 \sd@topcirc-.5\sdcirclediam%
1549 \advance\sd@topcirc\sd@mid%
1550 \sd@botcirc-.5\sdcirclediam%
1551 \advance\sd@botcirc-\sd@mid%
1557 % \begin{macro}{\sdsize}
1559 % You can set the default type size used by syntax diagrams by redefining
1560 % the |\sdsize| command, using the |\renewcommand| command.
1562 % By default, syntax diagrams are set slightly smaller than the main body
1563 % text.\footnote{^^A
1564 % I've used pure \LaTeX\ commands for this and the \cmd\sdlengths\ macro,
1565 % to try and illustrate how these values might be changed by a user. The
1566 % rest of the code is almost obfuscted in its use of raw \TeX\ features,
1567 % in an attempt to dissuade more na\"\i ve users from fiddling with it.
1568 % I suppose this is what you get when you let assembler hackers loose with
1569 % something like \LaTeX.
1573 \newcommand{\sdsize}{%
1580 % \begin{macro}{\sdlengths}
1582 % Finally, the default length parameters are set in the |\sdlengths| command.
1583 % You can redefine the command using |\renewcommand|.
1585 % We set up the length parameters here.
1588 \newcommand{\sdlengths}{%
1589 \setlength{\sdstartspace}{1em minus 10pt}%
1590 \setlength{\sdendspace}{1em minus 10pt}%
1591 \setlength{\sdmidskip}{0.5em plus 1em}%
1592 \setlength{\sdtokskip}{0.25em plus 1em}%
1593 \setlength{\sdfinalskip}{0.5em plus 10000fil}%
1594 \setlength{\sdrulewidth}{0.2pt}%
1595 \setlength{\sdcirclediam}{8pt}%
1596 \setlength{\sdindent}{0pt}%
1602 % \subsubsection{Other declarations}
1604 % We define four switches. The table shows what they're used for.
1607 % \begin{tab}{lp{3in}} \hline
1609 % \bf Switch & \bf Meaning \\ \hline
1611 % |\ifsd@base| & We are at `base level' in the diagram:
1612 % i.e., not in any other sorts of
1613 % constructions. This is used to decide
1614 % whether to allow line breaking. \\[2pt]
1616 % |\ifsd@top| & The current loop construct is being
1617 % typeset with the loop arrow above the
1620 % |\ifsd@toplayer| & We are typesetting the top layer of
1621 % a stack. This is used to ensure that
1622 % the vertical rules on either side are
1623 % typeset at the right height. \\[2pt]
1625 % |\ifsd@backwards| & We're typesetting backwards, because
1626 % we're in the middle of a loop arrow.
1627 % the only difference this makes is that
1628 % any subloops have the arrow on the
1632 % \caption{Syntax diagram switches}
1638 \newif\ifsd@toplayer
1639 \newif\ifsd@backwards
1642 % \begin{macro}{\sd@err}
1644 % We output our errors through this macro, which saves a little typing.
1647 \def\sd@err{\PackageError{syntax}}
1652 % \subsubsection{Arrow-drawing}
1654 % We need to draw some arrows. \LaTeX\ tries to make this as awkward as
1655 % possible, so we have to start moving the arrows around in boxes quite a
1658 % The left and right pointing arrows are fairly simple: we just add some
1659 % horizontal spacing to prevent the width of the arrow looking odd.
1665 \raise\sd@mid\box\tw@%
1670 \setbox\tw@\hbox{\kern-6\p@\@linefnt\char'55}%
1675 \setbox\tw@\hbox{\@linefnt\char'33\kern-6\p@}%
1680 % The up arrow is very strange. We need to bring the arrow down to base
1681 % level, and smash its height.
1686 \setbox\tw@\hb@xt@\z@{\kern-\sdrulewidth\@linefnt\char'66\hss}%
1687 \setbox\tw@\hbox{\lower10\p@\box\tw@}%
1692 % The down arrow is similar, although it's already at the right height.
1693 % Thus, we can just smash the box.
1698 \setbox\tw@\hb@xt@\z@{\kern-\sdrulewidth\@linefnt\char'77\hss}%
1703 % \subsubsection{Drawing curves}
1705 % If the user has selected curved edges, we use the \LaTeX\ features provided
1706 % to obtain the curves. These are drawn slightly oddly to make it easier
1707 % to fit them into the diagram.
1709 % Some explanation about the \LaTeX\ circle font is probably called for
1710 % before we go any further. The font consists of sets of four quadrants
1711 % of a particular size (and some other characters, which aren't important
1712 % at the moment). Each collection of quadrants fit together to form a
1713 % perfect circle of a given diameter. The individual quadrant characters
1714 % have strange bounding boxes, as described in the files \textit{lcircle.mf}
1715 % and \textit{ltpict.dtx}, and also in Appendix~D of \textit{The \TeX book}.
1716 % Our job here is to make these quadrants useful in the context of
1717 % drawing syntax diagrams.
1719 % \begin{macro}{\sd@circ}
1720 % First, we define |\sd@circ|, which performs the common parts of the four
1721 % routines. Since the characters in the circle font are grouped together,
1722 % we can pick out a particular corner piece by specifying its index into
1723 % the group for the required size. The |\sd@circ| routine will pick out
1724 % the required character, given this index as an argument, and put it in
1725 % box~2, after fiddling with the sizes a little:
1728 % \item We clear the width to zero. The individual routines then add a kern
1729 % of the correct amount, so that the quadrant appears in the right
1732 % \item The piece is lowered by half the rule width. This positions the
1733 % top and bottom pieces of the circle to be half way over the baseline,
1734 % which is the correct position for the rest of the diagram.
1738 % Finally, we make sure we're in horizontal mode: horrific results occur
1739 % if this is not the case. I'm sure I don't need to explain this any more
1744 \@getcirc\sdcirclediam%
1745 \advance\@tempcnta#1%
1746 \setbox\tw@\hbox{\lower\sdrulewidth%
1747 \hbox{\@circlefnt\char\@tempcnta}}%
1755 % \begin{macro}{\sd@tlcirc}
1756 % \begin{macro}{\sd@trcirc}
1757 % \begin{macro}{\sd@blcirc}
1758 % \begin{macro}{\sd@brcirc}
1760 % These are the macros which actually draw quadrants of circles. They all
1761 % call |\sd@circ|, passing an appropriate index, and then fiddle with the
1762 % box sizes and apply kerning specific to the quadrant positioning.
1764 % The exact requirements for positioning are as follows:
1768 % \item The horizontal parts of the arcs must lie along the baseline (i.e.,
1769 % half the line must be above the baseline, and half must be below).
1770 % This is consistent with the horizontal rules used in the diagram.
1772 % \item The vertical parts must overlap vertical rules on either side, so
1773 % that a |\vrule\sd@|\textit{xx}|circ| makes the arc appear to be
1774 % a real curve in the line. The requirements are actually somewhat
1775 % inconsistent; for example, the \env{stack} environment uses curves
1776 % \emph{before} the |\vrule|s. Special requirements like this are
1777 % handled as special cases later.
1779 % \item The height and width of the arc are at least roughly correct.
1786 \ht\tw@\sdrulewidth%
1787 \dp\tw@.5\sdcirclediam%
1788 \kern-\tw@\sdrulewidth%
1789 \raise\sd@mid\box\tw@%
1790 \kern.5\sdcirclediam%
1797 \ht\tw@\sdrulewidth%
1798 \dp\tw@.5\sdcirclediam%
1799 \kern.5\sdcirclediam%
1800 \raise\sd@mid\box\tw@%
1807 \ht\tw@.5\sdcirclediam%
1808 \dp\tw@\sdrulewidth%
1809 \kern-\tw@\sdrulewidth%
1810 \raise\sd@mid\box\tw@%
1811 \kern.5\sdcirclediam%
1818 \ht\tw@.5\sdcirclediam%
1819 \dp\tw@\sdrulewidth%
1820 \kern.5\sdcirclediam%
1821 \raise\sd@mid\box\tw@%
1826 \def\sd@nocirc{\sd@rule\hskip.5\sdcirclediam\relax}
1834 % \begin{macro}{\sd@llc}
1835 % \begin{macro}{\sd@rlc}
1837 % In the \env{rep} environment, we need to be able to draw arcs with
1838 % horizontal lines running through them. The two macros here do the job
1839 % nicely. |\sd@llc| (which is short for left overlapping circle) is
1840 % analogous to |\llap|: it puts its argument in a box of zero width, sticking
1841 % out to the left. However, it also draws a rule along the baseline. This
1842 % is important, as it prevents text from overprinting the arc. |\sd@rlc|
1843 % is very similar, just the other way around.
1847 \hb@xt@.5\sdcirclediam{%
1848 \sd@rule\hskip.5\sdcirclediam%
1857 \hb@xt@.5\sdcirclediam{%
1860 \sd@rule\hskip.5\sdcirclediam%
1868 % \subsubsection{Drawing rules}
1870 % It's important to draw the rules \emph{along} the baseline, rather than
1871 % above it: hence, the depth of the rule must be equal to the height.
1873 % \begin{macro}{\sd@rule}
1875 % We use rule leaders instead of glue through most of the syntax diagrams.
1876 % The command \syntax{"\\sd@rule"<skip>} draws a rule of the correct
1877 % dimensions, which has the behaviour of an \syntax{"\\hskip"<skip>}.
1880 \def\sd@rule{\leaders\hrule\@height\sd@upper\@depth\sd@lower}
1885 % \begin{macro}{\sd@gap}
1887 % The gap between elements is added using this macro. It will allow a
1888 % line break if we're at the top level of the diagram, using a rather
1889 % strange discretionary.
1891 % This is called as \syntax{"\\sd@gap{"<skip-register>"}"}.
1897 % First, we see if we're at the top level. Within constructs, we avoid the
1898 % overhead of a |\discretionary|. We put half of the width of the skip on
1899 % each side of the discretionary break.
1905 \divide\skip\z@\tw@%
1906 \nobreak\sd@rule\hskip\skip@%
1912 \sd@rule\hskip\sdstartspace%
1913 \sd@rule\hskip3.5\p@%
1917 \nobreak\sd@rule\hskip\skip@%
1920 % If we're not at the base level, we just put in a rule of the correct
1933 % \begin{macro}{\sd@qgap}
1934 % \begin{macro}{\sd@dequeue}
1936 % This is the high-level interface to spacing in syntax diagrams. Stuff only
1937 % gets printed if the diagram's actually started yet, and hasn't finished.
1942 \ifsd@right\advance\sd@qskip#1\relax%
1946 \def\sd@dequeue{\ifsd@left\sd@gap\sd@qskip\sd@qskip\z@\fi}
1952 % \begin{macro}{\sd@abbrev}
1954 % Sets up syntax diagram abbreviations.
1958 \def\({\begin{stack}}%
1959 \def\){\end{stack}}%
1960 \def\<{\begin{rep}}%
1963 \csname\ifx\gr@leftsq\@@undefined[\else gr@leftsq\fi\endcsname%
1966 \csname\ifx\gr@rightsq\@@undefined]\else gr@rightsq\fi\endcsname%
1973 % \subsubsection{The \protect\env{syntdiag} environment}
1975 % All syntax diagrams are contained within a \env{syntdiag} environment.
1977 % \begin{environment}{syntdiag}
1979 % The only argument is a collection of declarations, which by
1986 % However, if the optional argument is not specified, \TeX\ reads the first
1987 % character of the environment, which may not be catcoded correctly. We set
1988 % up the catcodes first, using the |\syntaxShortcuts| command, and then read
1989 % the argument. We don't use |\newcommand|, because that would involve
1990 % creating yet \emph{another} macro. Time to fiddle with |\@ifnextchar|
1995 \syntaxShortcuts\sd@tok@i\sd@tok@ii%
1997 \@ifnextchar[\syntdiag@i{\syntdiag@i[]}%
1999 \def\syntdiag@i[#1]{\@ifnextchar[{\syntdiag@ii{#1}}{\syntdiag@ii{#1}[b]}}
2002 % Now we actually do the job we're meant to.
2005 \def\syntdiag@ii#1[#2]{%
2008 % The first thing to do is execute the user's declarations. We then set
2009 % up things for the font size.
2017 % Sort out the omission of left or right sides.
2020 \sd@lefttrue\sd@righttrue%
2021 \if#2l\sd@rightfalse\fi%
2022 \if#2r\sd@leftfalse\fi%
2025 % Next, we start a list, to change the text layout.
2029 \leftmargin\sdindent%
2030 \rightmargin\leftmargin%
2037 % We reconfigure the paragraph format quite a lot now. We clear
2038 % |\parfillskip| to avoid any justification at the end of the paragraph.
2039 % We also turn off paragraph indentation.
2046 % Next, we add in the arrows on the beginning of the line, and a bit of
2052 \nobreak\sd@rule\hskip\sdstartspace%
2056 % This is the base level of the diagram, so we enable line breaking.
2062 % Since the objects being broken are rather large, we enable sloppy line
2063 % breaking. We also try to avoid page breaks in mid-diagram, by upping the
2064 % |\interlinepenalty|.
2068 \interlinepenalty100%
2072 % We handle all the spacing within the environment, so we make \TeX\ ignore
2073 % spaces and newlines.
2080 % We now have to change the behaviour of |\\| to line-break syntax diagrams.
2088 % When we end the diagram, we just have to add in the final fillskip, and
2095 \nobreak\sd@rule\hskip\sdmidskip%
2096 \sd@rule\hskip\sdfinalskip%
2108 % \begin{environment}{syntdiag*}
2110 % The starred form of \env{syntdiag} typesets a syntax diagram in LR-mode;
2111 % this is useful if you're describing parts of syntax diagrams, for example.
2113 % This is in fact really easy. The first bit which checks for an optional
2114 % argument is almost identical to the non-$*$ version.
2117 \@namedef{syntdiag*}{%
2118 \syntaxShortcuts\sd@tok@i\sd@tok@ii%
2121 \@ifnextchar[\syntdiag@s@i{\syntdiag@s@i[]}%
2125 % Handle another optional argument giving the width of the box to fill.
2128 \def\syntdiag@s@i[#1]{%
2129 \@ifnextchar[{\syntdiag@s@ii{#1}}{\syntdiag@s@iii{#1}{\hbox}}%
2131 \def\syntdiag@s@ii#1[#2]{%
2132 \def\@tempa{#2}\def\@tempb{*}%
2135 \syntdiag@s@iii{#1}{}%
2137 \syntdiag@s@iii{#1}{\hb@xt@#2}%
2142 % Now to actually start the display. This is mostly simple. Just to make
2143 % sure about the LR-ness of the typesetting, I'll put everything in an hbox.
2146 \def\syntdiag@s@iii#1#2{%
2151 % Now configure the typesetting according to the user's wishes.
2156 \def\left##1{\def\sd@startarr{##1}}%
2157 \def\right##1{\def\sd@endarr{##1}}%
2158 \left{>-}\right{->}%
2164 \sd@lefttrue\sd@righttrue%
2165 \ifx\sd@startarr\@empty\sd@leftfalse\fi%
2166 \ifx\sd@endarr\@empty\sd@rightfalse\fi%
2169 % Put in the initial double-arrow.
2173 \sd@qarrow\sd@startarr%
2174 \sd@rule\hskip\sdmidskip%
2178 % We're in horizontal mode, so don't bother with linebreaking.
2181 \if@tempswa\sd@basefalse\else\sd@basetrue\fi%
2184 % Finally, disable spaces and things.
2193 % Ending the environment is very similar.
2196 \@namedef{endsyntdiag*}{%
2199 \sd@rule\hskip\sdmidskip%
2200 \ifsd@base\else\sd@rule\hskip\sdfinalskip\fi%
2201 \sd@qarrow\sd@endarr%
2204 \ifsd@base\else\hskip\sdfinalskip\fi%
2212 % \begin{macro}{\sd@qarrow}
2214 % This typesets the various left and right arrows required in syntax
2215 % diagrams. The argument is one of \syntax{`>>-', `->', `>-' or `-><'}.
2220 \lccode`\~=`\<\lowercase{\def~{<}}%
2221 \hbox{\csname sd@arr@#1\endcsname}%
2224 \@namedef{sd@arr@>>-}{\sd@rightarr\kern-.5\p@\sd@rightarr\kern-\p@}
2225 \@namedef{sd@arr@>-}{\sd@rightarr\kern-\p@}
2226 \@namedef{sd@arr@->}{\sd@rightarr}
2227 \@namedef{sd@arr@-><}{\sd@rightarr\kern-\p@\sd@leftarr}
2228 \@namedef{sd@arr@...}{$\cdots$}
2229 \@namedef{sd@arr@-}{}
2230 \@namedef{sd@arr@}{}
2235 % \begin{macro}{\sd@newline}
2237 % The line breaking within a syntax diagram is controlled by the
2238 % |\sd@newline| command, to which |\\| is assigned.
2240 % We support all the standard \LaTeX\ features here. The line breaking
2241 % involves adding a fill skip and arrow, moving to the next line, adding
2242 % an arrow and a rule, and continuing.
2245 \def\sd@newline{\@ifstar{\vadjust{\penalty\@M}\sd@nl@i}\sd@nl@i}
2246 \def\sd@nl@i{\@ifnextchar[\sd@nl@ii\sd@nl@iii}
2247 \def\sd@nl@ii[#1]{\vspace{#1}\sd@nl@iii}
2249 \nobreak\sd@rule\hskip\sdmidskip%
2250 \sd@rule\hskip\sdfinalskip%
2255 \nobreak\sd@rule\hskip\sdstartspace%
2256 \sd@rule\hskip3.5\p@%
2262 % \subsubsection{Putting things in the right place}
2264 % Syntax diagrams have fairly stiff requirements on the positioning of text
2265 % relative to the diagram's rules. To help people (and me) to write
2266 % extensions to the syntax diagram typesetting which automatically put things
2267 % in the right place, I provide some simple macros.
2269 % \begin{environment}{sdbox}
2271 % By placing some text in the \env{sdbox} environment, it will be read into a
2272 % box and then output at the correct height for the syntax diagram. Note
2273 % that stuff in the box is set in horizontal (LR) mode, so you'll have to use
2274 % a \env{minipage} if you want formatted text. The macro also supplies rules
2275 % on either side of the box, with a length given in the environment's
2278 % Macro writers are given explicit permission to use this environment through
2279 % the |\sdbox| and |\endsdbox| commands if this makes life easier.
2281 % The calculation in the |\endsdbox| macro works out how to centre the box
2282 % vertically over the baseline. If the box's height is~$h$, and its depth
2283 % is~$d$, then its centre-line is $(h+d)/2$ from the bottom of the box.
2284 % Since the baseline is already $d$ from the bottom, we need to lower the box
2285 % by $(h+d)/2 - d$, or $h/2-d/2$.
2289 \@tempskipa#1\relax%
2291 \setbox\z@\hbox\bgroup%
2301 \advance\@tempdima-\dp\z@%
2302 \advance\@tempdima-\tw@\sd@mid%
2303 \lower.5\@tempdima\box\z@%
2311 % \subsubsection{Typesetting syntactic items}
2313 % Using the hooks built into the syntax abbreviations above, we typeset
2314 % the text into a box, and write it out, centred over the baseline. A strut
2315 % helps to keep the actual text baselines level for short pieces of text.
2317 % \begin{macro}{\sd@tok@i}
2319 % The preamble for a syntax abbreviation. We start a box, and set the
2320 % space and return characters to work again. A strut is added to the box to
2321 % ensure correct vertical spacing for normal text.
2333 % \begin{macro}{\sd@tok@ii}
2344 % \subsubsection{Inserting other pieces of text}
2346 % Arbitrary text may be put into a syntax diagram through the use of the
2347 % |\tok| macro. Its `argument' is typeset in the same way as a syntactic
2348 % item (centred over the baseline). The implementation goes to some effort
2349 % to ensure that the text is not actually an argument, to allow category
2350 % codes to change while the text is being typeset.
2352 % \begin{macro}{\tok}
2354 % We start a box, and make space and return do their normal jobs. We use
2355 % |\aftergroup| to regain control once the box is finished. |\doafter| is
2356 % used to get control after the group finishes.
2363 \syntaxShortcuts\relax\relax%
2368 % The |\sd@tok| macro is similar to |\sd@tok@ii| above.
2379 % \subsubsection{The \protect\env{stack} environment}
2381 % The \env{stack} environment is used to present alternatives in a syntax
2382 % diagram. The alternatives are separated by |\\| commands.
2384 % \begin{macro}{\stack}
2386 % Handle the optional arguments.
2389 \def\stack{\@ifnextchar[\stack@i{\stack@i[t]}}
2390 \def\stack@i[#1]{\@ifnextchar[{\stack@ii{#1}}{\stack@ii{#1}[b]}}
2391 \def\stack@ii#1[#2]{%
2394 % First, we add some horizontal space.
2400 % We're within a complex construction, so we need to clear the |\ifsd@base|
2404 \begingroup\sd@basefalse%
2407 % The top and bottom rows of the stack are different to the others, since
2408 % the vertical rules mustn't extend all the way up the side of the item.
2409 % The bottom row is handled separately by |\endstack| below. The top row
2410 % must be handled via a flag, |\ifsd@toplayer|.
2412 % Initially, the flag must be set true.
2418 % We set the |\\| command to separate the items in the |\halign|.
2424 % Sort out which sides of the construction are actually emitted.
2427 \sd@righttrue\if#2l\sd@rightfalse\fi%
2430 % The actual structure must be set in vertical mode, so we must place it
2431 % in a box. The position argument determines whether this must be a
2432 % |\vbox| or a |\vtop|. We also insert a bit of rounding if the options say
2439 \ifsd@left\ifsd@round\llap{\sd@trcirc\kern\tw@\sdrulewidth}\fi\fi%
2443 \ifsd@left\ifsd@round\llap{\sd@brcirc\kern\tw@\sdrulewidth}\fi\fi%
2445 \sd@err{Bad position argument passed to stack}%
2446 {The positioning argument must be one of `t' or `b'. I%
2447 have^^Jassumed you meant to type `t'.}%
2452 % Now we start the box, which we will complete at the end of the environment.
2458 % We must remove any extra space between rows of the table, since the rules
2459 % will not join up correctly. We can use |\offinterlineskip| safely, since
2460 % each individual row contains a strut.
2466 % Now we can start the alignment. We actually use \PlainTeX's |\ialign|
2467 % macro, which also clears |\tabskip| for us.
2473 % The preamble is trivial, since we must do all of the work ourselves
2479 % We can now start putting the text into a box ready for typesetting later.
2480 % The strut makes the vertical spacing correct.
2483 \setbox\z@\hbox\bgroup%
2490 % \begin{macro}{\endstack}
2492 % The first part of this is similar to the |\sd@stackcr| macro below, except
2493 % that the vertical rules are different. We don't support rounded edges
2494 % on single-row stacks, although this isn't a great loss to humanity.
2498 \ifsd@right\else\unskip\fi%
2501 \sd@dostack\sd@upper\sd@lower\sd@nocirc\sd@nocirc%
2505 \sd@dostack{\ht\z@}\sd@botcirc\sd@blcirc\sd@brcirc%
2507 \sd@dostack{\ht\z@}\sd@botcirc\sd@nocirc\sd@nocirc%
2510 \sd@dostack{\ht\z@}\sd@lower\relax\relax%
2515 % We now close the |\halign| and the vbox we created.
2522 % Deal with any rounding we started off.
2525 \ifsd@right\ifsd@round%
2527 \rlap{\kern\tw@\sdrulewidth\sd@tlcirc}%
2529 \rlap{\kern\tw@\sdrulewidth\sd@blcirc}%
2534 % Finally, we add some horizontal glue to space the diagram out.
2537 \endgroup\sd@lefttrue\ifsd@right\sd@gap\sdmidskip\fi%
2543 % \begin{macro}{\sd@stackcr}
2545 % The |\\| command is set to this macro during a \env{stack} environment.
2551 % The first job is to close the box containing the previous item.
2554 \ifsd@right\else\unskip\fi%
2558 % Now we typeset the vertical rules differently depending on whether this is
2559 % the first item in the stack. This looks quite terrifying initially, but
2560 % it's just an enumeration of the possible cases for the different values
2561 % of |\ifsd@toplayer|, |\ifsd@top| and |\ifsd@round|, putting in appropriate
2562 % rules and arcs in the right places.
2568 \sd@dostack\sd@topcirc{\dp\z@}\sd@nocirc\sd@nocirc%
2570 \sd@dostack\sd@topcirc{\dp\z@}\sd@tlcirc\sd@trcirc%
2573 \sd@dostack\sd@upper{\dp\z@}\relax\relax%
2578 \sd@dostack{\ht\z@}{\dp\z@}\sd@blcirc\sd@brcirc%
2580 \sd@dostack{\ht\z@}{\dp\z@}\sd@tlcirc\sd@trcirc%
2583 \sd@dostack{\ht\z@}{\dp\z@}\relax\relax%
2588 % The next item won't be the first, so we clear the flag.
2594 % Now we have to set up the next cell. We put the text into a box again.
2597 \setbox\z@\hbox\bgroup%
2604 % \begin{macro}{\sd@dostack}
2606 % Actually typesetting the text in a cell is performed here. The macro is
2608 % \begin{quote}\synshorts
2609 % "\\sd@dostack{"<height>"}{"<depth>"}{"<left-arc>"}{"<right-arc>"}"
2611 % where \<height> and \<depth> are the height and depth of the vertical
2612 % rules to put around the item, and \<left-arc> and \<right-arc> are
2613 % commands to draw rounded edges on the left and right hand sides of the
2616 % The values for the height and depth are quite often going to be the height
2617 % and depth of box~0. Since we empty box~0 in the course of typesetting the
2618 % row, we need to cache the sizes on entry.
2621 \def\sd@dostack#1#2#3#4{%
2625 \kern-\tw@\sdrulewidth%
2626 \vrule\@height\@tempdima\@depth\@tempdimb\@width\tw@\sdrulewidth%
2638 \vrule\@height\@tempdima\@depth\@tempdimb\@width\tw@\sdrulewidth%
2639 \kern-\tw@\sdrulewidth%
2649 % \subsubsection{The \protect\env{rep} environment}
2651 % The \env{rep} environment is used for typesetting loops in the diagram.
2652 % Again, we use |\halign| for the typesetting. Loops are simpler than
2653 % stacks, however, since there are always two rows. We store both rows in
2654 % box registers, and build the loop at the end.
2656 % \begin{macro}{\rep}
2658 % Again, we use |\newcommand| to process the optional argument.
2661 \newcommand\rep[1][t]{%
2664 % First, leave a gap on the left side.
2670 % We're not at base level any more, so disable linebreaking.
2673 \begingroup\sd@basefalse%
2676 % Remember we're going backwards now.
2679 \ifsd@backwards\sd@backwardsfalse\else\sd@backwardstrue\fi%
2682 % Define |\\| to separate the two parts of the loop.
2688 % Now check the argument, and use the appropriate type of box. In addition
2689 % to changing the typesetting, we must remember which way up to typeset the
2690 % loop, since the end code must always put the first argument on the
2691 % baseline, with the loop either above or below.
2701 \sd@err{Bad position argument passed to loop}%
2702 {The positioning argument must be `t' or `b'. I have^^J%
2703 assumed you meant to type `t'.}%
2709 % Now we start the box.
2715 % The loop is by default empty, apart from a strut. This is put into box~1.
2718 \setbox\tw@\copy\strutbox%
2721 % Now start typesetting the main text in box~0.
2724 \setbox\z@\hbox\bgroup\strut%
2730 % \begin{macro}{\endrep}
2732 % The final code must first close whatever box was open.
2739 % Now we typeset the loop, depending on which way up it was meant to be.
2740 % Again, this terrifying piece of code is a simple list of possibile values
2741 % of our various flags.
2746 \sd@doloop\tw@\z@\relax\relax%
2747 \sd@tlcirc\sd@trcirc{\sd@rlc\sd@blcirc}{\sd@llc\sd@brcirc}%
2749 \sd@doloop\tw@\z@\relax\sd@downarr\relax\relax\relax\relax%
2753 \sd@doloop\z@\tw@\relax\relax%
2754 {\sd@rlc\sd@tlcirc}{\sd@llc\sd@trcirc}\sd@blcirc\sd@brcirc%
2756 \sd@doloop\z@\tw@\sd@uparr\relax\relax\relax\relax\relax%
2761 % Close the vbox we opened.
2767 % Finally, we leave a gap before the next structure.
2770 \endgroup\sd@gap\sdmidskip%
2776 % \begin{macro}{\sd@loop}
2778 % This macro handles the |\\| command within a loop environment. We close
2779 % the current box, and start filling in box~1. We also redefine |\\| to
2780 % raise an error when the |\\| command is used again.
2785 \def\\{\sd@err{Too many \string\\\space commands in loop}\@ehc}%
2786 \setbox\tw@\hbox\bgroup\strut%
2792 % \begin{macro}{\sd@doloop}
2794 % This is the macro which actually creates the |\halign| for the loop. It
2795 % is called with four arguments, as:
2796 % \begin{quote}\synshorts
2797 % "\\sd@doloop{"<top-box>"}{"<bottom-box>"}"^^A
2798 % "{"<top-arrow>"}{"<btm-arrow>"}" \\
2799 % \hbox{}\quad "{"<top-left-arc>"}{"<top-right-arc>"}"^^A
2800 % "{"<bottom-left-arc>"}{"<btm-right-arc>"}"^^A
2801 % \kern-1in ^^A It may be overfull, but it looks OK to me ;-)
2804 % The two \<box> arguments give the numbers of boxes to extract in the top
2805 % and bottom rows of the alignment. The \<arrow> arguments specify
2806 % characters to typeset at the end of the top and bottom rows for arrows.
2807 % The various \<arc> arguments are commands which typeset arcs around the
2808 % various parts of the items.
2810 % We calculate the height and depth of the two boxes, and store them in
2811 % \<dimen> registers, because the boxes are emptied before the right-hand
2812 % rules are typeset.
2814 % Actually, the two rows of the alignment are typeset in a different macro:
2815 % we just pass the correct information on.
2818 \def\sd@doloop#1#2#3#4#5#6#7#8{%
2819 \@tempdima\dp#1\relax%
2820 \@tempdimb\ht#2\relax%
2825 \sd@doloop@i#1#3\sd@topcirc\@tempdima{#5}{#6}%
2826 \sd@doloop@i#2#4\@tempdimb\sd@botcirc{#7}{#8}%
2828 \sd@doloop@i#1#3\sd@upper\@tempdima{#5}{#6}%
2829 \sd@doloop@i#2#4\@tempdimb\sd@lower{#7}{#8}%
2837 % \begin{macro}{\sd@doloop@i}
2839 % Here we do the actual job of typesetting the rows of a loop alignment.
2840 % The four arguments are:
2841 % \begin{quote}\synshorts
2842 % "\\sd@doloop@i{"<box>"}{"<arrow>"}"^^A
2843 % "{"<rule-height>"}{"<rule-depth>"}" \\
2844 % \hbox{}\quad "{"<left-arc>"}{"<right-arc>"}"^^A
2847 % The arrow position is determined by the |\ifsd@backwards| flag. The rest
2851 \def\sd@doloop@i#1#2#3#4#5#6{%
2852 \ifsd@backwards#2\fi%
2853 \kern-\tw@\sdrulewidth%
2854 \vrule\@height#3\@depth#4\@width\tw@\sdrulewidth%
2862 \vrule\@height#3\@depth#4\@width\tw@\sdrulewidth%
2863 \ifsd@backwards\else#2\fi%
2864 \kern-\tw@\sdrulewidth%
2871 % \subsection{The end}
2873 % Phew! That's all of it completed. I hope this collection of commands
2874 % and environments is of some help to someone.
2880 % \hfill Mark Wooding, \today