1 % rail.sty - style file to support railroad diagrams
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 % 28-Jun-94 K. Barthelmann turned into LaTeX2e package
8 % 08-Dec-96 K. Barthelmann replaced \@writefile
9 % 13-Dec-96 K. Barthelmann cleanup
10 % 22-Feb-98 K. Barthelmann fixed catcodes of special characters
11 % 18-Apr-98 K. Barthelmann fixed \par handling
12 % 19-May-98 J. Olsson Added new macros to support arrow heads.
13 % 26-Jul-98 K. Barthelmann changed \par to output newlines
15 % This style file needs to be used in conjunction with the 'rail'
16 % program. Running LaTeX as 'latex file' produces file.rai, which should be
17 % processed by Rail with 'rail file'. This produces file.rao, which will
18 % be picked up by LaTeX on the next 'latex file' run.
20 % LaTeX will warn if there is no file.rao or it's out of date.
22 % The macros in this file thus consist of two parts: those that read and
23 % write the .rai and .rao files, and those that do the actual formatting
24 % of the railroad diagrams.
26 \NeedsTeXFormat{LaTeX2e}
27 \ProvidesPackage{rail}[1998/05/19]
29 % railroad diagram formatting parameters (user level)
30 % all of these are copied into their internal versions by \railinit
32 % \railunit : \unitlength within railroad diagrams
33 % \railextra : extra length at outside of diagram
34 % \railboxheight : height of ovals and frames
35 % \railboxskip : vertical space between lines
36 % \railboxleft : space to the left of a box
37 % \railboxright : space to the right of a box
38 % \railovalspace : extra space around contents of oval
39 % \railframespace : extra space around contents of frame
40 % \railtextleft : space to the left of text
41 % \railtextright : space to the right of text
42 % \railtextup : space to lift text up
43 % \railjoinsize : circle size of join/split arcs
44 % \railjoinadjust : space to adjust join
46 % \railnamesep : separator between name and rule body
50 \newlength\railboxheight
51 \newlength\railboxskip
52 \newlength\railboxleft
53 \newlength\railboxright
54 \newlength\railovalspace
55 \newlength\railframespace
56 \newlength\railtextleft
57 \newlength\railtextright
59 \newlength\railjoinsize
60 \newlength\railjoinadjust
61 \newlength\railnamesep
63 % initialize the parameters
65 \setlength\railunit{1sp}
66 \setlength\railextra{4ex}
67 \setlength\railboxleft{1ex}
68 \setlength\railboxright{1ex}
69 \setlength\railovalspace{2ex}
70 \setlength\railframespace{2ex}
71 \setlength\railtextleft{1ex}
72 \setlength\railtextright{1ex}
73 \setlength\railjoinadjust{0pt}
74 \setlength\railnamesep{1ex}
77 \setlength\railboxheight{16pt}
78 \setlength\railboxskip{24pt}
79 \setlength\railtextup{5pt}
80 \setlength\railjoinsize{16pt}
83 \setlength\railboxheight{16pt}
84 \setlength\railboxskip{24pt}
85 \setlength\railtextup{5pt}
86 \setlength\railjoinsize{16pt}
89 \setlength\railboxheight{20pt}
90 \setlength\railboxskip{28pt}
91 \setlength\railtextup{6pt}
92 \setlength\railjoinsize{20pt}
98 % internal versions of the formatting parameters
100 % \rail@extra : \railextra
101 % \rail@boxht : \railboxheight
102 % \rail@boxsp : \railboxskip
103 % \rail@boxlf : \railboxleft
104 % \rail@boxrt : \railboxright
105 % \rail@boxhht : \railboxheight / 2
106 % \rail@ovalsp : \railovalspace
107 % \rail@framesp : \railframespace
108 % \rail@textlf : \railtextleft
109 % \rail@textrt : \railtextright
110 % \rail@textup : \railtextup
111 % \rail@joinsz : \railjoinsize
112 % \rail@joinhsz : \railjoinsize / 2
113 % \rail@joinadj : \railjoinadjust
115 % \railinit : internalize all of the parameters.
122 \newcount\rail@boxhht
123 \newcount\rail@ovalsp
124 \newcount\rail@framesp
125 \newcount\rail@textlf
126 \newcount\rail@textrt
127 \newcount\rail@textup
128 \newcount\rail@joinsz
129 \newcount\rail@joinhsz
130 \newcount\rail@joinadj
132 \newcommand\railinit{
133 \rail@extra=\railextra
134 \divide\rail@extra by \railunit
135 \rail@boxht=\railboxheight
136 \divide\rail@boxht by \railunit
137 \rail@boxsp=\railboxskip
138 \divide\rail@boxsp by \railunit
139 \rail@boxlf=\railboxleft
140 \divide\rail@boxlf by \railunit
141 \rail@boxrt=\railboxright
142 \divide\rail@boxrt by \railunit
143 \rail@boxhht=\railboxheight
144 \divide\rail@boxhht by \railunit
145 \divide\rail@boxhht by 2
146 \rail@ovalsp=\railovalspace
147 \divide\rail@ovalsp by \railunit
148 \rail@framesp=\railframespace
149 \divide\rail@framesp by \railunit
150 \rail@textlf=\railtextleft
151 \divide\rail@textlf by \railunit
152 \rail@textrt=\railtextright
153 \divide\rail@textrt by \railunit
154 \rail@textup=\railtextup
155 \divide\rail@textup by \railunit
156 \rail@joinsz=\railjoinsize
157 \divide\rail@joinsz by \railunit
158 \rail@joinhsz=\railjoinsize
159 \divide\rail@joinhsz by \railunit
160 \divide\rail@joinhsz by 2
161 \rail@joinadj=\railjoinadjust
162 \divide\rail@joinadj by \railunit
165 \AtBeginDocument{\railinit}
167 % \rail@param : declarations for list environment
169 % \railparam{TEXT} : sets \rail@param to TEXT
171 % \rail@reserved : characters reserved for grammar
173 \newcommand\railparam[1]{
175 \setlength\leftmargin{0pt}\setlength\rightmargin{0pt}
176 \setlength\labelwidth{0pt}\setlength\labelsep{0pt}
177 \setlength\itemindent{0pt}\setlength\listparindent{0pt}
183 \newtoks\rail@reserved
184 \rail@reserved={:;|*+?[]()'"}
186 % \rail@termfont : format setup for terminals
188 % \rail@nontfont : format setup for nonterminals
190 % \rail@annofont : format setup for annotations
192 % \rail@rulefont : format setup for rule names
194 % \rail@indexfont : format setup for index entry
196 % \railtermfont{TEXT} : set terminal format setup to TEXT
198 % \railnontermfont{TEXT} : set nonterminal format setup to TEXT
200 % \railannotatefont{TEXT} : set annotation format setup to TEXT
202 % \railnamefont{TEXT} : set rule name format setup to TEXT
204 % \railindexfont{TEXT} : set index entry format setup to TEXT
206 \def\rail@termfont{\ttfamily\upshape}
207 \def\rail@nontfont{\rmfamily\upshape}
208 \def\rail@annofont{\rmfamily\itshape}
209 \def\rail@namefont{\rmfamily\itshape}
210 \def\rail@indexfont{\rmfamily\itshape}
212 \newcommand\railtermfont[1]{
213 \def\rail@termfont{#1}
216 \newcommand\railnontermfont[1]{
217 \def\rail@nontfont{#1}
220 \newcommand\railannotatefont[1]{
221 \def\rail@annofont{#1}
224 \newcommand\railnamefont[1]{
225 \def\rail@namefont{#1}
228 \newcommand\railindexfont[1]{
229 \def\rail@indexfont{#1}
232 % railroad read/write macros
234 % \begin{rail} TEXT \end{rail} : TEXT is written out to the .rai file,
235 % as \rail@i{NR}{TEXT}. Then the matching
236 % \rail@o{NR}{FMT} from the .rao file is
237 % executed (if defined).
239 % \railoptions{OPTIONS} : OPTIONS are written out to the .rai file,
240 % as \rail@p{OPTIONS}.
242 % \railterm{IDENT,IDENT,...} : format IDENT as terminals. writes out
243 % \rail@t{IDENT} to the .rai file
245 % \railalias{IDENT}{TEXT} : format IDENT as TEXT. defines \rail@t@IDENT as
248 % \railtoken{IDENT}{TEXT} : abbreviates \railalias{IDENT}{TEXT}\railterm{IDENT}
249 % (for backward compatibility)
251 % \rail@setcodes : guards special characters
253 % \rail@makeother{CHARACTER} : sets \catcode of CHARACTER to "other"
254 % used inside a loop for \rail@setcodes
256 % \rail@nr : railroad diagram counter
258 % \ifrail@match : current \rail@i{NR}{TEXT} matches
260 % \rail@first : actions to be done first. read in .rao file,
261 % open .rai file if \@filesw true, undefine \rail@first.
262 % executed from \begin{rail}, \railoptions and \railterm.
264 % \rail@i{NR}{TEXT} : defines \rail@i@NR as TEXT. written to the .rai
265 % file by \rail, read from the .rao file by
268 % \rail@t{IDENT} : tells Rail that IDENT is to be custom formatted,
269 % written to the .rai file by \railterm.
271 % \rail@o{NR}{TEXT} : defines \rail@o@NR as TEXT, read from the .rao
272 % file by \rail@first.
274 % \rail@p{OPTIONS} : pass options to rail, written to the .rai file by
277 % \rail@write{TEXT} : write TEXT to the .rai file
279 % \rail@warn : warn user for mismatching diagrams
281 % \rail@endwarn : either \relax or \rail@warn
283 % \ifrail@all : checked at the end of the document
285 \def\rail@makeother#1{
286 \expandafter\catcode\expandafter`\csname\string #1\endcsname=12
292 \expandafter\@tfor\expandafter\rail@symbol\expandafter:\expandafter=%
294 \do{\expandafter\rail@makeother\rail@symbol}
308 \InputIfFileExists{\jobname.rao}{}{\PackageInfo{rail}{No file \jobname.rao}}
313 \immediate\openout\tf@rai=\jobname.rai
315 \global\let\rail@first=\relax
318 \long\def\rail@body#1\end{
321 \def\par{\string\par^^J}
322 \rail@write{\string\rail@i{\number\rail@nr}{#1}}
328 \newenvironment{rail}{
329 \global\advance\rail@nr by 1
337 \@ifundefined{rail@o@\number\rail@nr}{\rail@matchfalse}{}
338 \expandafter\ifx\csname rail@i@\number\rail@nr\endcsname\rail@i@
343 \csname rail@o@\number\rail@nr\endcsname
345 \PackageWarning{rail}{Railroad diagram {\number\rail@nr} doesn't match}
346 \global\let\rail@endwarn=\rail@warn
347 \begin{list}{}{\rail@param}
349 \rail@setbox{\bfseries ???}
356 \newcommand\railoptions[1]{
358 \rail@write{\string\rail@p{#1}}
361 \newcommand\railterm[1]{
364 \rail@write{\string\rail@t{\rail@@}}
368 \newcommand\railalias[2]{
369 \expandafter\def\csname rail@t@#1\endcsname{#2}
372 \newcommand\railtoken[2]{\railalias{#1}{#2}\railterm{#1}}
374 \long\def\rail@i#1#2{
375 \expandafter\gdef\csname rail@i@#1\endcsname{#2}
379 \expandafter\gdef\csname rail@o@#1\endcsname{
380 \begin{list}{}{\rail@param}
390 \long\def\rail@write#1{\@ifundefined{tf@rai}{}{\immediate\write\tf@rai{#1}}}
393 \PackageWarningNoLine{rail}{Railroad diagram(s) may have changed.
394 Use 'rail' and rerun}
397 \let\rail@endwarn=\relax
399 \AtEndDocument{\rail@endwarn}
403 % \rail@index{IDENT} : add index entry for IDENT
406 \index{\rail@indexfont#1}
409 % railroad formatting primitives
411 % \rail@x : current x
412 % \rail@y : current y
413 % \rail@ex : current end x
414 % \rail@sx : starting x for \rail@cr
415 % \rail@rx : rightmost previous x for \rail@cr
417 % \rail@tmpa : temporary count
418 % \rail@tmpb : temporary count
419 % \rail@tmpc : temporary count
421 % \rail@put : put at (\rail@x,\rail@y)
422 % \rail@vput : put vector at (\rail@x,\rail@y)
424 % \rail@eline : end line by drawing from \rail@ex to \rail@x
426 % \rail@vreline : end line by drawing a vector from \rail@x to \rail@ex
428 % \rail@vleline : end line by drawing a vector from \rail@ex to \rail@x
430 % \rail@sety{LEVEL} : set \rail@y to level LEVEL
442 \def\rail@put{\put(\number\rail@x,\number\rail@y)}
444 \def\rail@vput{\put(\number\rail@ex,\number\rail@y)}
448 \advance\rail@tmpb by -\rail@ex
449 \rail@put{\line(-1,0){\number\rail@tmpb}}
454 \advance\rail@tmpb by -\rail@ex
455 \rail@vput{\vector(1,0){\number\rail@tmpb}}
460 \advance\rail@tmpb by -\rail@ex
461 \rail@put{\vector(-1,0){\number\rail@tmpb}}
466 \multiply\rail@y by -\rail@boxsp
467 \advance\rail@y by -\rail@boxht
470 % \rail@begin{HEIGHT}{NAME} : begin a railroad diagram of height HEIGHT
472 % \rail@end : end a railroad diagram
474 % \rail@expand{IDENT} : expand IDENT
478 \begin{minipage}[t]{\linewidth}
480 {\rail@namefont \rail@expand{#2}}\\*[\railnamesep]
482 \unitlength=\railunit
484 \multiply\rail@tmpa by \rail@boxsp
485 \begin{picture}(0,\number\rail@tmpa)(0,-\number\rail@tmpa)
494 \advance\rail@x by \rail@extra
501 \advance\rail@x by \rail@extra
507 \def\rail@expand#1{\@ifundefined{rail@t@#1}{#1}{\csname rail@t@#1\endcsname}}
509 % \rail@token{TEXT}[ANNOT] : format token TEXT with annotation
510 % \rail@ltoken{TEXT}[ANNOT] : format token TEXT with annotation, arrow left
511 % \rail@rtoken{TEXT}[ANNOT] : format token TEXT with annotation, arrow right
513 % \rail@ctoken{TEXT}[ANNOT] : format token TEXT centered with annotation
514 % \rail@lctoken{TEXT}[ANNOT] : format token TEXT centered with annotation, arrow left
515 % \rail@rctoken{TEXT}[ANNOT] : format token TEXT centered with annotation, arrow right
517 % \rail@nont{TEXT}[ANNOT] : format nonterminal TEXT with annotation
518 % \rail@lnont{TEXT}[ANNOT] : format nonterminal TEXT with annotation, arrow left
519 % \rail@rnont{TEXT}[ANNOT] : format nonterminal TEXT with annotation. arrow right
521 % \rail@cnont{TEXT}[ANNOT] : format nonterminal TEXT centered with annotation
522 % \rail@lcnont{TEXT}[ANNOT] : format nonterminal TEXT centered with annotation,
524 % \rail@rcnont{TEXT}[ANNOT] : format nonterminal TEXT centered with annotation,
527 % \rail@term{TEXT}[ANNOT] : format terminal TEXT with annotation
528 % \rail@lterm{TEXT}[ANNOT] : format terminal TEXT with annotation, arrow left
529 % \rail@rterm{TEXT}[ANNOT] : format terminal TEXT with annotation, arrow right
531 % \rail@cterm{TEXT}[ANNOT] : format terminal TEXT centered with annotation
532 % \rail@lcterm{TEXT}[ANNOT] : format terminal TEXT centered with annotation, arrow left
533 % \rail@rcterm{TEXT}[ANNOT] : format terminal TEXT centered with annotation,
536 % \rail@annote[TEXT] : format TEXT as annotation
538 \def\rail@token#1[#2]{
540 {\rail@termfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
545 \def\rail@ltoken#1[#2]{
547 {\rail@termfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
552 \def\rail@rtoken#1[#2]{
554 {\rail@termfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
559 \def\rail@ctoken#1[#2]{
561 {\rail@termfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
566 \def\rail@lctoken#1[#2]{
568 {\rail@termfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
573 \def\rail@rctoken#1[#2]{
575 {\rail@termfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
580 \def\rail@nont#1[#2]{
582 {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
587 \def\rail@lnont#1[#2]{
589 {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
594 \def\rail@rnont#1[#2]{
596 {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
601 \def\rail@cnont#1[#2]{
603 {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
608 \def\rail@lcnont#1[#2]{
610 {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
615 \def\rail@rcnont#1[#2]{
617 {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
622 \def\rail@term#1[#2]{
624 {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
629 \def\rail@lterm#1[#2]{
631 {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
636 \def\rail@rterm#1[#2]{
638 {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
643 \def\rail@cterm#1[#2]{
645 {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
650 \def\rail@lcterm#1[#2]{
652 {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
657 \def\rail@rcterm#1[#2]{
659 {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
664 \def\rail@annote[#1]{
665 \rail@setbox{\rail@annofont #1}
669 % \rail@box : temporary box for \rail@oval and \rail@frame
671 % \rail@setbox{TEXT} : set \rail@box to TEXT, set \rail@tmpa to width
673 % \rail@oval : format \rail@box of width \rail@tmpa inside an oval
674 % \rail@vloval : format \rail@box of width \rail@tmpa inside an oval, vector left
675 % \rail@vroval : format \rail@box of width \rail@tmpa inside an oval, vector right
677 % \rail@coval : same as \rail@oval, but centered between \rail@x and
679 % \rail@vlcoval : same as \rail@oval, but centered between \rail@x and
680 % \rail@mx, vector left
681 % \rail@vrcoval : same as \rail@oval, but centered between \rail@x and
682 % \rail@mx, vector right
684 % \rail@frame : format \rail@box of width \rail@tmpa inside a frame
685 % \rail@vlframe : format \rail@box of width \rail@tmpa inside a frame, vector left
686 % \rail@vrframe : format \rail@box of width \rail@tmpa inside a frame, vector right
688 % \rail@cframe : same as \rail@frame, but centered between \rail@x and
690 % \rail@vlcframe : same as \rail@frame, but centered between \rail@x and
691 % \rail@mx, vector left
692 % \rail@vrcframe : same as \rail@frame, but centered between \rail@x and
693 % \rail@mx, vector right
695 % \rail@text : format \rail@box of width \rail@tmpa above the line
700 \setbox\rail@box\hbox{\strut#1}
701 \rail@tmpa=\wd\rail@box
702 \divide\rail@tmpa by \railunit
706 \advance\rail@x by \rail@boxlf
708 \advance\rail@tmpa by \rail@ovalsp
709 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
710 \rail@tmpb=\rail@tmpa
711 \divide\rail@tmpb by 2
712 \advance\rail@y by -\rail@boxhht
713 \rail@put{\makebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
714 \advance\rail@y by \rail@boxhht
715 \advance\rail@x by \rail@tmpb
716 \rail@put{\oval(\number\rail@tmpa,\number\rail@boxht)}
717 \advance\rail@x by \rail@tmpb
719 \advance\rail@x by \rail@boxrt
723 \advance\rail@x by \rail@boxlf
725 \advance\rail@tmpa by \rail@ovalsp
726 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
727 \rail@tmpb=\rail@tmpa
728 \divide\rail@tmpb by 2
729 \advance\rail@y by -\rail@boxhht
730 \rail@put{\makebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
731 \advance\rail@y by \rail@boxhht
732 \advance\rail@x by \rail@tmpb
733 \rail@put{\oval(\number\rail@tmpa,\number\rail@boxht)}
734 \advance\rail@x by \rail@tmpb
736 \advance\rail@x by \rail@boxrt
741 \advance\rail@x by \rail@boxlf
743 \advance\rail@tmpa by \rail@ovalsp
744 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
745 \rail@tmpb=\rail@tmpa
746 \divide\rail@tmpb by 2
747 \advance\rail@y by -\rail@boxhht
748 \rail@put{\makebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
749 \advance\rail@y by \rail@boxhht
750 \advance\rail@x by \rail@tmpb
751 \rail@put{\oval(\number\rail@tmpa,\number\rail@boxht)}
752 \advance\rail@x by \rail@tmpb
754 \advance\rail@x by \rail@boxrt
758 \rail@tmpb=\rail@tmpa
759 \advance\rail@tmpb by \rail@ovalsp
760 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
761 \advance\rail@tmpb by \rail@boxlf
762 \advance\rail@tmpb by \rail@boxrt
764 \advance\rail@tmpc by -\rail@x
765 \advance\rail@tmpc by -\rail@tmpb
766 \divide\rail@tmpc by 2
768 \advance\rail@x by \rail@tmpc
774 \rail@tmpb=\rail@tmpa
775 \advance\rail@tmpb by \rail@ovalsp
776 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
777 \advance\rail@tmpb by \rail@boxlf
778 \advance\rail@tmpb by \rail@boxrt
780 \advance\rail@tmpc by -\rail@x
781 \advance\rail@tmpc by -\rail@tmpb
782 \divide\rail@tmpc by 2
784 \advance\rail@x by \rail@tmpc
790 \rail@tmpb=\rail@tmpa
791 \advance\rail@tmpb by \rail@ovalsp
792 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
793 \advance\rail@tmpb by \rail@boxlf
794 \advance\rail@tmpb by \rail@boxrt
796 \advance\rail@tmpc by -\rail@x
797 \advance\rail@tmpc by -\rail@tmpb
798 \divide\rail@tmpc by 2
800 \advance\rail@x by \rail@tmpc
806 \advance\rail@x by \rail@boxlf
808 \advance\rail@tmpa by \rail@framesp
809 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
810 \advance\rail@y by -\rail@boxhht
811 \rail@put{\framebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
812 \advance\rail@y by \rail@boxhht
813 \advance\rail@x by \rail@tmpa
815 \advance\rail@x by \rail@boxrt
819 \advance\rail@x by \rail@boxlf
821 \advance\rail@tmpa by \rail@framesp
822 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
823 \advance\rail@y by -\rail@boxhht
824 \rail@put{\framebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
825 \advance\rail@y by \rail@boxhht
826 \advance\rail@x by \rail@tmpa
828 \advance\rail@x by \rail@boxrt
833 \advance\rail@x by \rail@boxlf
835 \advance\rail@tmpa by \rail@framesp
836 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
837 \advance\rail@y by -\rail@boxhht
838 \rail@put{\framebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
839 \advance\rail@y by \rail@boxhht
840 \advance\rail@x by \rail@tmpa
842 \advance\rail@x by \rail@boxrt
846 \rail@tmpb=\rail@tmpa
847 \advance\rail@tmpb by \rail@framesp
848 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
849 \advance\rail@tmpb by \rail@boxlf
850 \advance\rail@tmpb by \rail@boxrt
852 \advance\rail@tmpc by -\rail@x
853 \advance\rail@tmpc by -\rail@tmpb
854 \divide\rail@tmpc by 2
856 \advance\rail@x by \rail@tmpc
862 \rail@tmpb=\rail@tmpa
863 \advance\rail@tmpb by \rail@framesp
864 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
865 \advance\rail@tmpb by \rail@boxlf
866 \advance\rail@tmpb by \rail@boxrt
868 \advance\rail@tmpc by -\rail@x
869 \advance\rail@tmpc by -\rail@tmpb
870 \divide\rail@tmpc by 2
872 \advance\rail@x by \rail@tmpc
878 \rail@tmpb=\rail@tmpa
879 \advance\rail@tmpb by \rail@framesp
880 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
881 \advance\rail@tmpb by \rail@boxlf
882 \advance\rail@tmpb by \rail@boxrt
884 \advance\rail@tmpc by -\rail@x
885 \advance\rail@tmpc by -\rail@tmpb
886 \divide\rail@tmpc by 2
888 \advance\rail@x by \rail@tmpc
894 \advance\rail@x by \rail@textlf
895 \advance\rail@y by \rail@textup
896 \rail@put{\box\rail@box}
897 \advance\rail@y by -\rail@textup
898 \advance\rail@x by \rail@tmpa
899 \advance\rail@x by \rail@textrt
904 % \rail@jx \rail@jy : current join point
906 % \rail@gx \rail@gy \rail@gex \rail@grx : global versions of \rail@x etc,
907 % to pass values over group closings
909 % \rail@mx : maximum x so far
911 % \rail@sy : starting \rail@y for alternatives
913 % \rail@jput : put at (\rail@jx,\rail@jy)
915 % \rail@joval[PART] : put \oval[PART] with adjust
929 \put(\number\rail@jx,\number\rail@jy)
933 \advance\rail@jx by \rail@joinadj
934 \rail@jput{\oval(\number\rail@joinsz,\number\rail@joinsz)[#1]}
935 \advance\rail@jx by -\rail@joinadj
938 % \rail@barsplit : incoming split for '|'
940 % \rail@plussplit : incoming split for '+'
944 \advance\rail@jy by -\rail@joinhsz
946 \advance\rail@jx by \rail@joinhsz
950 \advance\rail@jy by -\rail@joinhsz
951 \advance\rail@jx by \rail@joinsz
953 \advance\rail@jx by -\rail@joinhsz
956 % \rail@alt{SPLIT} : start alternatives with incoming split SPLIT
963 \advance\rail@x by \rail@joinsz
965 \let\rail@list=\@empty
966 \let\rail@comma=\@empty
973 % \rail@nextalt{FIX}{Y} : start next alternative at vertical position Y
977 \def\rail@nextalt#1#2{
978 \global\rail@gx=\rail@x
979 \global\rail@gy=\rail@y
980 \global\rail@gex=\rail@ex
981 \global\rail@grx=\rail@rx
984 \ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
985 \ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
986 \edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
989 \let\rail@split=\@empty
992 \advance\rail@tmpa by -\rail@y
993 \advance\rail@tmpa by -\rail@joinhsz
994 \rail@jput{\line(0,-1){\number\rail@tmpa}}
996 \advance\rail@jy by \rail@joinhsz
997 \advance\rail@jx by \rail@joinhsz
999 \advance\rail@jx by -\rail@joinhsz
1006 % \rail@barjoin : outgoing join for first '|' alternative
1008 % \rail@plusjoin : outgoing join for first '+' alternative
1010 % \rail@altjoin : join for subsequent alternative
1014 \ifnum\rail@y<\rail@sy
1015 \global\rail@gex=\rail@jx
1017 \global\rail@gex=\rail@ex
1019 \advance\rail@jy by -\rail@joinhsz
1021 \advance\rail@jx by -\rail@joinhsz
1022 \ifnum\rail@y<\rail@sy
1028 \global\rail@gex=\rail@ex
1029 \advance\rail@jy by -\rail@joinhsz
1030 \advance\rail@jx by -\rail@joinsz
1032 \advance\rail@jx by \rail@joinhsz
1038 \advance\rail@tmpa by -\rail@y
1039 \advance\rail@tmpa by -\rail@joinhsz
1040 \rail@jput{\line(0,-1){\number\rail@tmpa}}
1042 \advance\rail@jy by \rail@joinhsz
1043 \advance\rail@jx by -\rail@joinhsz
1045 \advance\rail@jx by \rail@joinhsz
1048 % \rail@eltsplit EX:Y; : split EX:Y into \rail@ex \rail@y
1050 % \rail@endalt{JOIN} : end alternatives with outgoing join JOIN
1052 \def\rail@eltsplit#1:#2;{\rail@ex=#1\rail@y=#2}
1055 \global\rail@gx=\rail@x
1056 \global\rail@gy=\rail@y
1057 \global\rail@gex=\rail@ex
1058 \global\rail@grx=\rail@rx
1060 \ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
1061 \ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
1062 \edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
1066 \advance\rail@jx by \rail@joinsz
1068 \@for\rail@elt:=\rail@list\do{
1069 \expandafter\rail@eltsplit\rail@elt;
1071 \let\rail@join=\rail@altjoin
1076 \advance\rail@x by \rail@joinsz
1079 % \rail@bar : start '|' alternatives
1081 % \rail@nextbar : next '|' alternative
1083 % \rail@endbar : end '|' alternatives
1087 \rail@alt\rail@barsplit
1095 \rail@endalt\rail@barjoin
1098 % \rail@plus : start '+' alternatives
1100 % \rail@nextplus: next '+' alternative
1102 % \rail@endplus : end '+' alternatives
1106 \rail@alt\rail@plussplit
1110 \rail@nextalt\rail@fixplus
1114 \ifnum\rail@gy<\rail@sy
1120 \ifnum\rail@x<\rail@rx
1126 \advance\rail@jy by \rail@joinhsz
1128 \advance\rail@jx by \rail@joinhsz
1130 \advance\rail@tmpa by -\rail@joinhsz
1131 \advance\rail@tmpa by -\rail@jy
1132 \rail@jput{\line(0,1){\number\rail@tmpa}}
1134 \advance\rail@jy by -\rail@joinhsz
1135 \advance\rail@jx by \rail@joinhsz
1137 \advance\rail@jy by \rail@joinhsz
1138 \global\rail@gx=\rail@jx
1139 \global\rail@gy=\rail@jy
1140 \global\rail@gex=\rail@gx
1141 \global\rail@grx=\rail@rx
1147 \rail@endalt\rail@plusjoin
1150 % \rail@cr{Y} : carriage return to vertical position Y
1154 \advance\rail@tmpa by \rail@joinsz
1155 \ifnum\rail@x<\rail@tmpa\rail@x=\rail@tmpa\fi
1159 \advance\rail@x by \rail@joinsz
1160 \ifnum\rail@x>\rail@rx\rail@rx=\rail@x\fi
1161 \advance\rail@jy by -\rail@joinhsz
1163 \advance\rail@jx by \rail@joinhsz
1166 \advance\rail@tmpa by -\rail@y
1167 \advance\rail@tmpa by -\rail@boxsp
1168 \advance\rail@tmpa by -\rail@joinhsz
1169 \rail@jput{\line(0,-1){\number\rail@tmpa}}
1171 \advance\rail@jy by \rail@boxsp
1172 \advance\rail@jy by \rail@joinhsz
1173 \advance\rail@jx by -\rail@joinhsz
1175 \advance\rail@jy by -\rail@joinhsz
1177 \advance\rail@tmpa by -\rail@sx
1178 \advance\rail@tmpa by -\rail@joinhsz
1179 \rail@jput{\line(-1,0){\number\rail@tmpa}}
1181 \advance\rail@jx by \rail@joinhsz
1182 \advance\rail@jy by -\rail@joinhsz
1184 \advance\rail@jx by -\rail@joinhsz
1185 \rail@tmpa=\rail@boxsp
1186 \advance\rail@tmpa by -\rail@joinsz
1187 \rail@jput{\line(0,-1){\number\rail@tmpa}}
1188 \advance\rail@jy by -\rail@tmpa
1189 \advance\rail@jx by \rail@joinhsz