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