doc-src/rail.sty
changeset 2658 13ba951a4572
child 3097 ae362c99a635
equal deleted inserted replaced
2657:448bb82c4003 2658:13ba951a4572
       
     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 }