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