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