doc-src/rail.sty
author wenzelm
Thu, 20 Feb 1997 15:15:17 +0100
changeset 2658 13ba951a4572
child 3097 ae362c99a635
permissions -rw-r--r--
added this file;
     1 % rail.sty - style file to support railroad diagrams
     2 %
     3 % 09-Jul-90 L. Rooijakkers
     4 % 08-Oct-90 L. Rooijakkers	fixed centering bug when \rail@tmpc<0.
     5 % 07-Feb-91 L. Rooijakkers	added \railoptions command, indexing
     6 % 08-Feb-91 L. Rooijakkers	minor fixes
     7 %
     8 % This style file needs to be used in conjunction with the 'rail'
     9 % program. Running LaTeX as 'latex file' produces file.rai, which should be
    10 % processed by Rail with 'rail file'. This produces file.rao, which will
    11 % be picked up by LaTeX on the next 'latex file' run.
    12 %
    13 % LaTeX will warn if there is no file.rao or it's out of date.
    14 %
    15 % The macros in this file thus consist of two parts: those that read and
    16 % write the .rai and .rao files, and those that do the actual formatting
    17 % of the railroad diagrams.
    18 
    19 % railroad read/write macros
    20 %
    21 % \begin{rail} TEXT \end{rail} : TEXT is written out to the .rai file,
    22 %                                as \rail@i{NR}{TEXT}. Then the matching
    23 %                                \rail@o{NR}{FMT} from the .rao file is
    24 %                                executed (if defined).
    25 %
    26 % \railoptions{OPTIONS} : OPTIONS are written out to the .rai file,
    27 %                         as \rail@p{OPTIONS}.
    28 %
    29 % \railterm{IDENT,IDENT,...} : format IDENT as terminals. writes out
    30 %                              \rail@t{IDENT} to the .rai file and
    31 %                              defines \rail@t@IDENT as \rail@termfont IDENT.
    32 %
    33 % \railtoken{IDENT}{TEXT} : format IDENT as terminal TEXT. writes out
    34 %                           \rail@t{IDENT} to the .rai file and defines
    35 %                           \rail@t@IDENT as TEXT.
    36 %
    37 % \rail@nr : railroad diagram counter, starts at 1
    38 %
    39 % \ifrail@match : current \rail@i{NR}{TEXT} matches
    40 %
    41 % \rail@first :	actions to be done first. read in .rao file,
    42 %               open .rai file if \@filesw true, undefine \rail@first.
    43 %               executed from \begin{rail} and \railtoken.
    44 %
    45 % \rail@i{NR}{TEXT} : defines \rail@i@NR as TEXT. written to the .rai
    46 %                     file by \rail, read from the .rao file by
    47 %                     \rail@first
    48 %
    49 % \rail@t{IDENT} : tells Rail that IDENT is to be custom formatted,
    50 %                  written to the .rai file by \railterm and \railtoken.
    51 %
    52 % \rail@o{NR}{TEXT} : defines \rail@o@NR as TEXT, read from the .rao
    53 %                     file by \rail@first.
    54 %
    55 % \rail@p{OPTIONS} : pass options to rail, written to the .rai file by
    56 %                    \railoptions
    57 %
    58 % \rail@warn : warn user for mismatching diagrams
    59 %
    60 % \rail@endwarn : either \relax or \rail@warn
    61 %
    62 % \rail@enddocument : original \enddocument
    63 %
    64 % \enddocument : checks \ifrail@all
    65 
    66 \newcount\rail@nr
    67 \rail@nr=1
    68 
    69 \newif\ifrail@all
    70 \rail@alltrue
    71 
    72 \newif\ifrail@match
    73 
    74 \def\rail@first{
    75 \makeatletter
    76 \@input{\jobname.rao}
    77 \makeatother
    78 \if@filesw
    79 \newwrite\tf@rai
    80 \immediate\openout\tf@rai\jobname.rai\relax
    81 \fi
    82 \global\let\rail@first=\relax
    83 }
    84 
    85 \long\def\rail#1\end#2{
    86 \end{#2}
    87 \rail@first
    88 \begingroup
    89 \let\\=\relax
    90 \global\edef\rail@i@{#1}
    91 \endgroup
    92 \@ifundefined{tf@rai}{}{
    93 \begingroup
    94 \let\\=\relax
    95 \immediate\write\tf@rai{\noexpand\rail@i{\number\rail@nr}{\rail@i@}}
    96 \endgroup
    97 }
    98 \rail@matchtrue
    99 \@ifundefined{rail@o@\number\rail@nr}{\rail@matchfalse}{}
   100 \expandafter\ifx\csname rail@i@\number\rail@nr\endcsname\rail@i@
   101 \else
   102 \rail@matchfalse
   103 \fi
   104 \ifrail@match
   105 \expandafter\relax\csname rail@o@\number\rail@nr\endcsname
   106 \else
   107 \@warning{Railroad diagram {\number\rail@nr} doesn't match}
   108 \global\let\rail@endwarn=\rail@warn
   109 \rail@begin{1}{}
   110 \rail@setbox{\bf ???}
   111 \rail@oval
   112 \rail@end
   113 \fi
   114 \global\advance\rail@nr by 1
   115 }
   116 
   117 \def\railoptions#1{
   118 \rail@first
   119 \@writefile{rai}{\noexpand\rail@p{#1}}
   120 }
   121 
   122 \def\railterm#1{
   123 \rail@first
   124 \@for\rail@i@:=#1\do{
   125 \@writefile{rai}{\noexpand\rail@t{\rail@i@}}
   126 }
   127 }
   128 
   129 \def\railtoken#1#2{
   130 \rail@first
   131 \@writefile{rai}{\noexpand\rail@t{#1}}
   132 \expandafter\def\csname rail@t@#1\endcsname{#2}
   133 }
   134 
   135 \long\def\rail@i#1#2{
   136 \expandafter\gdef\csname rail@i@#1\endcsname{#2}
   137 }
   138 
   139 \def\rail@o#1#2{
   140 \expandafter\gdef\csname rail@o@#1\endcsname{#2}
   141 }
   142 
   143 \def\rail@t#1{}
   144 
   145 \def\rail@p#1{}
   146 
   147 \def\rail@warn{
   148 \@warning{Railroad diagram(s) may have changed. Use 'rail' and rerun}
   149 }
   150 
   151 \let\rail@endwarn=\relax
   152 
   153 \let\rail@enddocument=\enddocument
   154 
   155 \def\enddocument{
   156 \rail@endwarn
   157 \rail@enddocument
   158 }
   159 
   160 % index entry macro
   161 %
   162 % \rail@index{IDENT} : add index entry for IDENT
   163 
   164 \def\rail@index#1{
   165 \index{\rail@indexfont#1}
   166 }
   167 
   168 % railroad diagram formatting parameters (user level)
   169 % all of these are copied into their internal versions by \railinit
   170 %
   171 % \railunit : \unitlength within railroad diagrams
   172 % \railextra : extra length at outside of diagram
   173 % \railboxheight : height of ovals and frames
   174 % \railboxskip : vertical space between lines
   175 % \railboxleft : space to the left of a box
   176 % \railboxright : space to the right of a box
   177 % \railovalspace : extra space around contents of oval
   178 % \railframespace : extra space around contents of frame
   179 % \railtextleft : space to the left of text
   180 % \railtextright : space to the right of text
   181 % \railtextup : space to lift text up
   182 % \railjoinsize : circle size of join/split arcs
   183 % \railjoinadjust : space to adjust join
   184 %
   185 % \railnamesep : separator between name and rule body
   186 
   187 \newdimen\railunit
   188 \newdimen\railextra
   189 \newdimen\railboxheight
   190 \newdimen\railboxskip
   191 \newdimen\railboxleft
   192 \newdimen\railboxright
   193 \newdimen\railovalspace
   194 \newdimen\railframespace
   195 \newdimen\railtextleft
   196 \newdimen\railtextright
   197 \newdimen\railtextup
   198 \newdimen\railjoinsize
   199 \newdimen\railjoinadjust
   200 \newdimen\railnamesep
   201 
   202 % internal versions of the formatting parameters
   203 %
   204 % \rail@extra   : \railextra
   205 % \rail@boxht   : \railboxheight
   206 % \rail@boxsp   : \railboxskip
   207 % \rail@boxlf   : \railboxleft
   208 % \rail@boxrt   : \railboxright
   209 % \rail@boxhht  : \railboxheight / 2
   210 % \rail@ovalsp  : \railovalspace
   211 % \rail@framesp : \railframespace
   212 % \rail@textlf	: \railtextleft
   213 % \rail@textrt	: \railtextright
   214 % \rail@textup	: \railtextup
   215 % \rail@joinsz  : \railjoinsize
   216 % \rail@joinhsz : \railjoinsize / 2
   217 % \rail@joinadj : \railjoinadjust
   218 %
   219 % \railinit : internalize all of the parameters.
   220 
   221 \newcount\rail@extra
   222 \newcount\rail@boxht
   223 \newcount\rail@boxsp
   224 \newcount\rail@boxlf
   225 \newcount\rail@boxrt
   226 \newcount\rail@boxhht
   227 \newcount\rail@ovalsp
   228 \newcount\rail@framesp
   229 \newcount\rail@textlf
   230 \newcount\rail@textrt
   231 \newcount\rail@textup
   232 \newcount\rail@joinsz
   233 \newcount\rail@joinhsz
   234 \newcount\rail@joinadj
   235 
   236 \def\railinit{
   237 \rail@extra=\railextra
   238 \divide\rail@extra by \railunit
   239 \rail@boxht=\railboxheight
   240 \divide\rail@boxht by \railunit
   241 \rail@boxsp=\railboxskip
   242 \divide\rail@boxsp by \railunit
   243 \rail@boxlf=\railboxleft
   244 \divide\rail@boxlf by \railunit
   245 \rail@boxrt=\railboxright
   246 \divide\rail@boxrt by \railunit
   247 \rail@boxhht=\railboxheight
   248 \divide\rail@boxhht by \railunit
   249 \divide\rail@boxhht by 2
   250 \rail@ovalsp=\railovalspace
   251 \divide\rail@ovalsp by \railunit
   252 \rail@framesp=\railframespace
   253 \divide\rail@framesp by \railunit
   254 \rail@textlf=\railtextleft
   255 \divide\rail@textlf by \railunit
   256 \rail@textrt=\railtextright
   257 \divide\rail@textrt by \railunit
   258 \rail@textup=\railtextup
   259 \divide\rail@textup by \railunit
   260 \rail@joinsz=\railjoinsize
   261 \divide\rail@joinsz by \railunit
   262 \rail@joinhsz=\railjoinsize
   263 \divide\rail@joinhsz by \railunit
   264 \divide\rail@joinhsz by 2
   265 \rail@joinadj=\railjoinadjust
   266 \divide\rail@joinadj by \railunit
   267 }
   268 
   269 % initialize the parameters
   270 
   271 \railunit=1sp
   272 \railextra=4ex
   273 \railboxleft=1ex
   274 \railboxright=1ex
   275 \railovalspace=2ex
   276 \railframespace=2ex
   277 \railtextleft=1ex
   278 \railtextright=1ex
   279 \railjoinadjust=0pt
   280 \railnamesep=1ex
   281 
   282 \ifcase\@ptsize
   283 % 10 pt
   284 \railboxheight=16pt
   285 \railboxskip=24pt
   286 \railtextup=5pt
   287 \railjoinsize=16pt
   288 \or
   289 % 11 pt
   290 \railboxheight=16pt
   291 \railboxskip=24pt
   292 \railtextup=5pt
   293 \railjoinsize=16pt
   294 \or
   295 % 12 pt
   296 \railboxheight=20pt
   297 \railboxskip=28pt
   298 \railtextup=6pt
   299 \railjoinsize=20pt
   300 \fi
   301 
   302 \railinit
   303 
   304 % railroad formatting primitives
   305 %
   306 % \rail@x : current x
   307 % \rail@y : current y
   308 % \rail@ex : current end x
   309 % \rail@sx : starting x for \rail@cr
   310 % \rail@rx : rightmost previous x for \rail@cr
   311 %
   312 % \rail@tmpa : temporary count
   313 % \rail@tmpb : temporary count
   314 % \rail@tmpc : temporary count
   315 %
   316 % \rail@put : put at (\rail@x,\rail@y)
   317 %
   318 % \rail@eline : end line by drawing from \rail@ex to \rail@x
   319 %
   320 % \rail@sety{LEVEL} : set \rail@y to level LEVEL
   321 
   322 \newcount\rail@x
   323 \newcount\rail@y
   324 \newcount\rail@ex
   325 \newcount\rail@sx
   326 \newcount\rail@rx
   327 
   328 \newcount\rail@tmpa
   329 \newcount\rail@tmpb
   330 \newcount\rail@tmpc
   331 
   332 \def\rail@put{\put(\number\rail@x,\number\rail@y)}
   333 
   334 \def\rail@eline{
   335 \rail@tmpb=\rail@x
   336 \advance\rail@tmpb by -\rail@ex
   337 \rail@put{\line(-1,0){\number\rail@tmpb}}
   338 }
   339 
   340 \def\rail@sety#1{
   341 \rail@y=#1
   342 \multiply\rail@y by -\rail@boxsp
   343 \advance\rail@y by -\rail@boxht
   344 }
   345 
   346 % \rail@list : declarations for list environment
   347 %
   348 % \railparam{TEXT} : sets \rail@list to TEXT
   349 %
   350 % \rail@begin{HEIGHT}{NAME} : begin a railroad diagram of height HEIGHT
   351 %
   352 % \rail@end : end a railroad diagram
   353 
   354 \def\rail@list{}
   355 
   356 \def\railparam#1{
   357 \def\rail@list{#1}
   358 }
   359 
   360 \newbox\tempbox
   361 
   362 \def\rail@begin#1#2{
   363 \medskip
   364 \begin{list}{}{\rail@list}
   365 \item[]
   366 \vbox\bgroup
   367 \ifx\@empty#2\else
   368 {\rail@namefont #2}
   369 \\*[\railnamesep]\nopagebreak
   370 \fi
   371 \unitlength=\railunit
   372 \rail@tmpa=#1
   373 \multiply\rail@tmpa by \rail@boxsp
   374 \begin{picture}(0,\number\rail@tmpa)(0,-\number\rail@tmpa)
   375 \rail@ex=0
   376 \rail@rx=0
   377 \rail@x=\rail@extra
   378 \rail@sx=\rail@x
   379 \rail@sety{0}
   380 }
   381 
   382 \def\rail@end{
   383 \advance\rail@x by \rail@extra
   384 \rail@eline
   385 \end{picture}
   386 \egroup
   387 \end{list}
   388 }
   389 
   390 % \rail@tokenfont : format setup for \railtoken identifiers
   391 %
   392 % \rail@termfont : format setup for terminals
   393 %
   394 % \rail@nontfont : format setup for nonterminals
   395 %
   396 % \rail@annofont : format setup for annotations
   397 %
   398 % \rail@rulefont : format setup for rule names
   399 %
   400 % \rail@indexfont : format setup for index entry
   401 %
   402 % \railtokenfont{TEXT} : set \railtoken format setup to TEXT
   403 %
   404 % \railtermfont{TEXT} : set terminal format setup to TEXT
   405 %
   406 % \railnontermfont{TEXT} : set nonterminal format setup to TEXT
   407 %
   408 % \railannotatefont{TEXT} : set annotation format setup to TEXT
   409 %
   410 % \railnamefont{TEXT} : set rule name format setup to TEXT
   411 %
   412 % \railindexfont{TEXT} : set index entry format setup to TEXT
   413 
   414 \let\rail@tokenfont=\tt
   415 \let\rail@termfont=\tt
   416 \let\rail@nontfont=\rm
   417 \let\rail@annofont=\it
   418 \let\rail@namefont=\it
   419 \let\rail@indexfont=\it
   420 
   421 \def\railtokenfont#1{
   422 \def\rail@tokenfont{#1}
   423 }
   424 
   425 \def\railtermfont#1{
   426 \def\rail@termfont{#1}
   427 }
   428 
   429 \def\railnontermfont#1{
   430 \def\rail@nontfont{#1}
   431 }
   432 
   433 \def\railannotatefont#1{
   434 \def\rail@annofont{#1}
   435 }
   436 
   437 \def\railnamefont#1{
   438 \def\rail@namefont{#1}
   439 }
   440 
   441 \def\railindexfont#1{
   442 \def\rail@indexfont{#1}
   443 }
   444 
   445 % \rail@token{TEXT} : format token TEXT
   446 %
   447 % \rail@ctoken{TEXT} : format token TEXT centered
   448 %
   449 % \rail@nont{TEXT} : format nonterminal TEXT
   450 %
   451 % \rail@cnont{TEXT} : format nonterminal TEXT centered
   452 %
   453 % \rail@cterm{TEXT} : format terminal TEXT
   454 %
   455 % \rail@cterm{TEXT} : format terminal TEXT centered
   456 %
   457 % \rail@annote[TEXT] : format TEXT as annotation
   458 %
   459 % \rail@annotebox[TEXT] : annotate box with TEXT
   460 
   461 \def\rail@token#1{
   462 \expandafter\@ifundefined{rail@t@#1}{
   463 \rail@setbox{\rail@termfont #1}
   464 }{
   465 \rail@setbox{\rail@tokenfont \csname rail@t@#1\endcsname}
   466 }
   467 \rail@oval
   468 }
   469 
   470 \def\rail@ctoken#1{
   471 \rail@setbox{\rail@tokenfont \csname rail@t@#1\endcsname}
   472 \rail@coval
   473 }
   474 
   475 \def\rail@nont#1{
   476 \rail@setbox{\rail@nontfont #1}
   477 \rail@frame
   478 }
   479 
   480 \def\rail@cnont#1{
   481 \rail@setbox{\rail@nontfont #1}
   482 \rail@cframe
   483 }
   484 
   485 \def\rail@term#1{
   486 \rail@setbox{\rail@termfont #1}
   487 \rail@oval
   488 }
   489 
   490 \def\rail@cterm#1{
   491 \rail@setbox{\rail@termfont #1}
   492 \rail@coval
   493 }
   494 
   495 \def\rail@annote[#1]{
   496 \rail@setbox{\rail@annofont #1}
   497 \rail@text
   498 }
   499 
   500 \def\rail@annotebox[#1]{
   501 \ \rail@annofont #1
   502 }
   503 
   504 % \rail@box : temporary box for \rail@oval and \rail@frame
   505 %
   506 % \rail@setbox{TEXT} : set \rail@box to TEXT, set \rail@tmpa to width
   507 %
   508 % \rail@oval : format \rail@box of width \rail@tmpa inside an oval
   509 %
   510 % \rail@coval : same as \rail@oval, but centered between \rail@x and
   511 %               \rail@mx
   512 %
   513 % \rail@frame : format \rail@box of width \rail@tmpa inside a frame
   514 %
   515 % \rail@cframe : same as \rail@frame, but centered between \rail@x and
   516 %                \rail@mx
   517 %
   518 % \rail@text : format \rail@box of width \rail@tmpa above the line
   519 
   520 \newbox\rail@box
   521 
   522 \def\rail@setbox#1{
   523 \setbox\rail@box\hbox{\strut#1}
   524 \rail@tmpa=\wd\rail@box
   525 \divide\rail@tmpa by \railunit
   526 }
   527 
   528 \def\rail@oval{
   529 \advance\rail@x by \rail@boxlf
   530 \rail@eline
   531 \advance\rail@tmpa by \rail@ovalsp
   532 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
   533 \rail@tmpb=\rail@tmpa
   534 \divide\rail@tmpb by 2
   535 \advance\rail@y by -\rail@boxhht
   536 \rail@put{\makebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
   537 \advance\rail@y by \rail@boxhht
   538 \advance\rail@x by \rail@tmpb
   539 \rail@put{\oval(\number\rail@tmpa,\number\rail@boxht)}
   540 \advance\rail@x by \rail@tmpb
   541 \rail@ex=\rail@x
   542 \advance\rail@x by \rail@boxrt
   543 }
   544 
   545 \def\rail@coval{
   546 \rail@tmpb=\rail@tmpa
   547 \advance\rail@tmpb by \rail@ovalsp
   548 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
   549 \advance\rail@tmpb by \rail@boxlf
   550 \advance\rail@tmpb by \rail@boxrt
   551 \rail@tmpc=\rail@mx
   552 \advance\rail@tmpc by -\rail@x
   553 \advance\rail@tmpc by -\rail@tmpb
   554 \divide\rail@tmpc by 2
   555 \ifnum\rail@tmpc>0
   556 \advance\rail@x by \rail@tmpc
   557 \fi
   558 \rail@oval
   559 }
   560 
   561 \def\rail@frame{
   562 \advance\rail@x by \rail@boxlf
   563 \rail@eline
   564 \advance\rail@tmpa by \rail@framesp
   565 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
   566 \advance\rail@y by -\rail@boxhht
   567 \rail@put{\framebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
   568 \advance\rail@y by \rail@boxhht
   569 \advance\rail@x by \rail@tmpa
   570 \rail@ex=\rail@x
   571 \advance\rail@x by \rail@boxrt
   572 }
   573 
   574 \def\rail@cframe{
   575 \rail@tmpb=\rail@tmpa
   576 \advance\rail@tmpb by \rail@framesp
   577 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
   578 \advance\rail@tmpb by \rail@boxlf
   579 \advance\rail@tmpb by \rail@boxrt
   580 \rail@tmpc=\rail@mx
   581 \advance\rail@tmpc by -\rail@x
   582 \advance\rail@tmpc by -\rail@tmpb
   583 \divide\rail@tmpc by 2
   584 \ifnum\rail@tmpc>0
   585 \advance\rail@x by \rail@tmpc
   586 \fi
   587 \rail@frame
   588 }
   589 
   590 \def\rail@text{
   591 \advance\rail@x by \rail@textlf
   592 \advance\rail@y by \rail@textup
   593 \rail@put{\box\rail@box}
   594 \advance\rail@y by -\rail@textup
   595 \advance\rail@x by \rail@tmpa
   596 \advance\rail@x by \rail@textrt
   597 }
   598 
   599 % alternatives
   600 %
   601 % \rail@jx \rail@jy : current join point
   602 %
   603 % \rail@gx \rail@gy \rail@gex \rail@grx : global versions of \rail@x etc,
   604 %                                         to pass values over group closings
   605 %
   606 % \rail@mx : maximum x so far
   607 %
   608 % \rail@sy : starting \rail@y for alternatives
   609 %
   610 % \rail@jput : put at (\rail@jx,\rail@jy)
   611 %
   612 % \rail@joval[PART] : put \oval[PART] with adjust
   613 
   614 \newcount\rail@jx
   615 \newcount\rail@jy
   616 
   617 \newcount\rail@gx
   618 \newcount\rail@gy
   619 \newcount\rail@gex
   620 \newcount\rail@grx
   621 
   622 \newcount\rail@sy
   623 \newcount\rail@mx
   624 
   625 \def\rail@jput{
   626 \put(\number\rail@jx,\number\rail@jy)
   627 }
   628 
   629 \def\rail@joval[#1]{
   630 \advance\rail@jx by \rail@joinadj
   631 \rail@jput{\oval(\number\rail@joinsz,\number\rail@joinsz)[#1]}
   632 \advance\rail@jx by -\rail@joinadj
   633 }
   634 
   635 % \rail@barsplit : incoming split for '|'
   636 %
   637 % \rail@plussplit : incoming split for '+'
   638 %
   639 
   640 \def\rail@barsplit{
   641 \advance\rail@jy by -\rail@joinhsz
   642 \rail@joval[tr]
   643 \advance\rail@jx by \rail@joinhsz
   644 }
   645 
   646 \def\rail@plussplit{
   647 \advance\rail@jy by -\rail@joinhsz
   648 \advance\rail@jx by \rail@joinsz
   649 \rail@joval[tl]
   650 \advance\rail@jx by -\rail@joinhsz
   651 }
   652 
   653 % \rail@alt{SPLIT} : start alternatives with incoming split SPLIT
   654 %
   655 
   656 \def\rail@alt#1{
   657 \rail@sy=\rail@y
   658 \rail@jx=\rail@x
   659 \rail@jy=\rail@y
   660 \advance\rail@x by \rail@joinsz
   661 \rail@mx=0
   662 \let\rail@list=\@empty
   663 \let\rail@comma=\@empty
   664 \let\rail@split=#1
   665 \begingroup
   666 \rail@sx=\rail@x
   667 \rail@rx=0
   668 }
   669 
   670 % \rail@nextalt{FIX}{Y} : start next alternative at vertical position Y
   671 %                         and fix-up FIX
   672 %
   673 
   674 \def\rail@nextalt#1#2{
   675 \global\rail@gx=\rail@x
   676 \global\rail@gy=\rail@y
   677 \global\rail@gex=\rail@ex
   678 \global\rail@grx=\rail@rx
   679 \endgroup
   680 #1
   681 \ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
   682 \ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
   683 \edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
   684 \def\rail@comma{,}
   685 \rail@split
   686 \let\rail@split=\@empty
   687 \rail@sety{#2}
   688 \rail@tmpa=\rail@jy
   689 \advance\rail@tmpa by -\rail@y
   690 \advance\rail@tmpa by -\rail@joinhsz
   691 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   692 \rail@jy=\rail@y
   693 \advance\rail@jy by \rail@joinhsz
   694 \advance\rail@jx by \rail@joinhsz
   695 \rail@joval[bl]
   696 \advance\rail@jx by -\rail@joinhsz
   697 \rail@ex=\rail@x
   698 \begingroup
   699 \rail@sx=\rail@x
   700 \rail@rx=0
   701 }
   702 
   703 % \rail@barjoin : outgoing join for first '|' alternative
   704 %
   705 % \rail@plusjoin : outgoing join for first '+' alternative
   706 %
   707 % \rail@altjoin : join for subsequent alternative
   708 %
   709 
   710 \def\rail@barjoin{
   711 \ifnum\rail@y<\rail@sy
   712 \global\rail@gex=\rail@jx
   713 \else
   714 \global\rail@gex=\rail@ex
   715 \fi
   716 \advance\rail@jy by -\rail@joinhsz
   717 \rail@joval[tl]
   718 \advance\rail@jx by -\rail@joinhsz
   719 \ifnum\rail@y<\rail@sy
   720 \rail@altjoin
   721 \fi
   722 }
   723 
   724 \def\rail@plusjoin{
   725 \global\rail@gex=\rail@ex
   726 \advance\rail@jy by -\rail@joinhsz
   727 \advance\rail@jx by -\rail@joinsz
   728 \rail@joval[tr]
   729 \advance\rail@jx by \rail@joinhsz
   730 }
   731 
   732 \def\rail@altjoin{
   733 \rail@eline
   734 \rail@tmpa=\rail@jy
   735 \advance\rail@tmpa by -\rail@y
   736 \advance\rail@tmpa by -\rail@joinhsz
   737 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   738 \rail@jy=\rail@y
   739 \advance\rail@jy by \rail@joinhsz
   740 \advance\rail@jx by -\rail@joinhsz
   741 \rail@joval[br]
   742 \advance\rail@jx by \rail@joinhsz
   743 }
   744 
   745 % \rail@eltsplit EX:Y; : split EX:Y into \rail@ex \rail@y
   746 %
   747 % \rail@endalt{JOIN} : end alternatives with outgoing join JOIN
   748 
   749 \def\rail@eltsplit#1:#2;{\rail@ex=#1\rail@y=#2}
   750 
   751 \def\rail@endalt#1{
   752 \global\rail@gx=\rail@x
   753 \global\rail@gy=\rail@y
   754 \global\rail@gex=\rail@ex
   755 \global\rail@grx=\rail@rx
   756 \endgroup
   757 \ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
   758 \ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
   759 \edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
   760 \rail@x=\rail@mx
   761 \rail@jx=\rail@x
   762 \rail@jy=\rail@sy
   763 \advance\rail@jx by \rail@joinsz
   764 \let\rail@join=#1
   765 \@for\rail@elt:=\rail@list\do{
   766 \expandafter\rail@eltsplit\rail@elt;
   767 \rail@join
   768 \let\rail@join=\rail@altjoin
   769 }
   770 \rail@x=\rail@mx
   771 \rail@y=\rail@sy
   772 \rail@ex=\rail@gex
   773 \advance\rail@x by \rail@joinsz
   774 }
   775 
   776 % \rail@bar : start '|' alternatives
   777 %
   778 % \rail@nextbar : next '|' alternative
   779 %
   780 % \rail@endbar : end '|' alternatives
   781 %
   782 
   783 \def\rail@bar{
   784 \rail@alt\rail@barsplit
   785 }
   786 
   787 \def\rail@nextbar{
   788 \rail@nextalt\relax
   789 }
   790 
   791 \def\rail@endbar{
   792 \rail@endalt\rail@barjoin
   793 }
   794 
   795 % \rail@plus : start '+' alternatives
   796 %
   797 % \rail@nextplus: next '+' alternative
   798 %
   799 % \rail@endplus : end '+' alternatives
   800 %
   801 
   802 \def\rail@plus{
   803 \rail@alt\rail@plussplit
   804 }
   805 
   806 \def\rail@nextplus{
   807 \rail@nextalt\rail@fixplus
   808 }
   809 
   810 \def\rail@fixplus{
   811 \ifnum\rail@gy<\rail@sy
   812 \begingroup
   813 \rail@x=\rail@gx
   814 \rail@y=\rail@gy
   815 \rail@ex=\rail@gex
   816 \rail@rx=\rail@grx
   817 \ifnum\rail@x<\rail@rx
   818 \rail@x=\rail@rx
   819 \fi
   820 \rail@eline
   821 \rail@jx=\rail@x
   822 \rail@jy=\rail@y
   823 \advance\rail@jy by \rail@joinhsz
   824 \rail@joval[br]
   825 \advance\rail@jx by \rail@joinhsz
   826 \rail@tmpa=\rail@sy
   827 \advance\rail@tmpa by -\rail@joinhsz
   828 \advance\rail@tmpa by -\rail@jy
   829 \rail@jput{\line(0,1){\number\rail@tmpa}}
   830 \rail@jy=\rail@sy
   831 \advance\rail@jy by -\rail@joinhsz
   832 \advance\rail@jx by \rail@joinhsz
   833 \rail@joval[tl]
   834 \advance\rail@jy by \rail@joinhsz
   835 \global\rail@gx=\rail@jx
   836 \global\rail@gy=\rail@jy
   837 \global\rail@gex=\rail@gx
   838 \global\rail@grx=\rail@rx
   839 \endgroup
   840 \fi
   841 }
   842 
   843 \def\rail@endplus{
   844 \rail@endalt\rail@plusjoin
   845 }
   846 
   847 % \rail@cr{Y} : carriage return to vertical position Y
   848 
   849 \def\rail@cr#1{
   850 \rail@tmpa=\rail@sx
   851 \advance\rail@tmpa by \rail@joinsz
   852 \ifnum\rail@x<\rail@tmpa\rail@x=\rail@tmpa\fi
   853 \rail@eline
   854 \rail@jx=\rail@x
   855 \rail@jy=\rail@y
   856 \advance\rail@x by \rail@joinsz
   857 \ifnum\rail@x>\rail@rx\rail@rx=\rail@x\fi
   858 \advance\rail@jy by -\rail@joinhsz
   859 \rail@joval[tr]
   860 \advance\rail@jx by \rail@joinhsz
   861 \rail@sety{#1}
   862 \rail@tmpa=\rail@jy
   863 \advance\rail@tmpa by -\rail@y
   864 \advance\rail@tmpa by -\rail@boxsp
   865 \advance\rail@tmpa by -\rail@joinhsz
   866 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   867 \rail@jy=\rail@y
   868 \advance\rail@jy by \rail@boxsp
   869 \advance\rail@jy by \rail@joinhsz
   870 \advance\rail@jx by -\rail@joinhsz
   871 \rail@joval[br]
   872 \advance\rail@jy by -\rail@joinhsz
   873 \rail@tmpa=\rail@jx
   874 \advance\rail@tmpa by -\rail@sx
   875 \advance\rail@tmpa by -\rail@joinhsz
   876 \rail@jput{\line(-1,0){\number\rail@tmpa}}
   877 \rail@jx=\rail@sx
   878 \advance\rail@jx by \rail@joinhsz
   879 \advance\rail@jy by -\rail@joinhsz
   880 \rail@joval[tl]
   881 \advance\rail@jx by -\rail@joinhsz
   882 \rail@tmpa=\rail@boxsp
   883 \advance\rail@tmpa by -\rail@joinsz
   884 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   885 \advance\rail@jy by -\rail@tmpa
   886 \advance\rail@jx by \rail@joinhsz
   887 \rail@joval[bl]
   888 \rail@x=\rail@jx
   889 \rail@ex=\rail@x
   890 }