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