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