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