
wenzelm@2658: % rail.sty - style file to support railroad diagrams
wenzelm@2658: %
wenzelm@2658: % 09-Jul-90 L. Rooijakkers
wenzelm@8591: % 08-Oct-90 L. Rooijakkers      fixed centering bug when \rail@tmpc<0.
wenzelm@8591: % 07-Feb-91 L. Rooijakkers      added \railoptions command, indexing
wenzelm@8591: % 08-Feb-91 L. Rooijakkers      minor fixes
wenzelm@8591: % 28-Jun-94 K. Barthelmann      turned into LaTeX2e package
wenzelm@8591: % 08-Dec-96 K. Barthelmann      replaced \@writefile
wenzelm@8591: % 13-Dec-96 K. Barthelmann      cleanup
wenzelm@2658: %
wenzelm@2658: % This style file needs to be used in conjunction with the 'rail'
wenzelm@2658: % program. Running LaTeX as 'latex file' produces file.rai, which should be
wenzelm@2658: % processed by Rail with 'rail file'. This produces file.rao, which will
wenzelm@2658: % be picked up by LaTeX on the next 'latex file' run.
wenzelm@2658: %
wenzelm@2658: % LaTeX will warn if there is no file.rao or it's out of date.
wenzelm@2658: %
wenzelm@2658: % The macros in this file thus consist of two parts: those that read and
wenzelm@2658: % write the .rai and .rao files, and those that do the actual formatting
wenzelm@2658: % of the railroad diagrams.
wenzelm@2658: 
berghofe@3097: \NeedsTeXFormat{LaTeX2e}
berghofe@3097: \ProvidesPackage{rail}[1996/12/13]
wenzelm@2658: 
wenzelm@2658: % railroad diagram formatting parameters (user level)
wenzelm@2658: % all of these are copied into their internal versions by \railinit
wenzelm@2658: %
wenzelm@2658: % \railunit : \unitlength within railroad diagrams
wenzelm@2658: % \railextra : extra length at outside of diagram
wenzelm@2658: % \railboxheight : height of ovals and frames
wenzelm@2658: % \railboxskip : vertical space between lines
wenzelm@2658: % \railboxleft : space to the left of a box
wenzelm@2658: % \railboxright : space to the right of a box
wenzelm@2658: % \railovalspace : extra space around contents of oval
wenzelm@2658: % \railframespace : extra space around contents of frame
wenzelm@2658: % \railtextleft : space to the left of text
wenzelm@2658: % \railtextright : space to the right of text
wenzelm@2658: % \railtextup : space to lift text up
wenzelm@2658: % \railjoinsize : circle size of join/split arcs
wenzelm@2658: % \railjoinadjust : space to adjust join
wenzelm@2658: %
wenzelm@2658: % \railnamesep : separator between name and rule body
wenzelm@2658: 
berghofe@3097: \newlength\railunit
berghofe@3097: \newlength\railextra
berghofe@3097: \newlength\railboxheight
berghofe@3097: \newlength\railboxskip
berghofe@3097: \newlength\railboxleft
berghofe@3097: \newlength\railboxright
berghofe@3097: \newlength\railovalspace
berghofe@3097: \newlength\railframespace
berghofe@3097: \newlength\railtextleft
berghofe@3097: \newlength\railtextright
berghofe@3097: \newlength\railtextup
berghofe@3097: \newlength\railjoinsize
berghofe@3097: \newlength\railjoinadjust
berghofe@3097: \newlength\railnamesep
berghofe@3097: 
berghofe@3097: % initialize the parameters
berghofe@3097: 
berghofe@3097: \setlength\railunit{1sp}
berghofe@3097: \setlength\railextra{4ex}
berghofe@3097: \setlength\railboxleft{1ex}
berghofe@3097: \setlength\railboxright{1ex}
berghofe@3097: \setlength\railovalspace{2ex}
berghofe@3097: \setlength\railframespace{2ex}
berghofe@3097: \setlength\railtextleft{1ex}
berghofe@3097: \setlength\railtextright{1ex}
berghofe@3097: \setlength\railjoinadjust{0pt}
berghofe@3097: \setlength\railnamesep{1ex}
berghofe@3097: 
berghofe@3097: \DeclareOption{10pt}{
berghofe@3097:   \setlength\railboxheight{16pt}
berghofe@3097:   \setlength\railboxskip{24pt}
berghofe@3097:   \setlength\railtextup{5pt}
berghofe@3097:   \setlength\railjoinsize{16pt}
berghofe@3097: }
berghofe@3097: \DeclareOption{11pt}{
berghofe@3097:   \setlength\railboxheight{16pt}
berghofe@3097:   \setlength\railboxskip{24pt}
berghofe@3097:   \setlength\railtextup{5pt}
berghofe@3097:   \setlength\railjoinsize{16pt}
berghofe@3097: }
berghofe@3097: \DeclareOption{12pt}{
berghofe@3097:   \setlength\railboxheight{20pt}
berghofe@3097:   \setlength\railboxskip{28pt}
berghofe@3097:   \setlength\railtextup{6pt}
berghofe@3097:   \setlength\railjoinsize{20pt}
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \ExecuteOptions{10pt}
berghofe@3097: \ProcessOptions
wenzelm@2658: 
wenzelm@2658: % internal versions of the formatting parameters
wenzelm@2658: %
wenzelm@2658: % \rail@extra   : \railextra
wenzelm@2658: % \rail@boxht   : \railboxheight
wenzelm@2658: % \rail@boxsp   : \railboxskip
wenzelm@2658: % \rail@boxlf   : \railboxleft
wenzelm@2658: % \rail@boxrt   : \railboxright
wenzelm@2658: % \rail@boxhht  : \railboxheight / 2
wenzelm@2658: % \rail@ovalsp  : \railovalspace
wenzelm@2658: % \rail@framesp : \railframespace
wenzelm@8591: % \rail@textlf  : \railtextleft
wenzelm@8591: % \rail@textrt  : \railtextright
wenzelm@8591: % \rail@textup  : \railtextup
wenzelm@2658: % \rail@joinsz  : \railjoinsize
wenzelm@2658: % \rail@joinhsz : \railjoinsize / 2
wenzelm@2658: % \rail@joinadj : \railjoinadjust
wenzelm@2658: %
wenzelm@2658: % \railinit : internalize all of the parameters.
wenzelm@2658: 
wenzelm@2658: \newcount\rail@extra
wenzelm@2658: \newcount\rail@boxht
wenzelm@2658: \newcount\rail@boxsp
wenzelm@2658: \newcount\rail@boxlf
wenzelm@2658: \newcount\rail@boxrt
wenzelm@2658: \newcount\rail@boxhht
wenzelm@2658: \newcount\rail@ovalsp
wenzelm@2658: \newcount\rail@framesp
wenzelm@2658: \newcount\rail@textlf
wenzelm@2658: \newcount\rail@textrt
wenzelm@2658: \newcount\rail@textup
wenzelm@2658: \newcount\rail@joinsz
wenzelm@2658: \newcount\rail@joinhsz
wenzelm@2658: \newcount\rail@joinadj
wenzelm@2658: 
berghofe@3097: \newcommand\railinit{
wenzelm@2658: \rail@extra=\railextra
wenzelm@2658: \divide\rail@extra by \railunit
wenzelm@2658: \rail@boxht=\railboxheight
wenzelm@2658: \divide\rail@boxht by \railunit
wenzelm@2658: \rail@boxsp=\railboxskip
wenzelm@2658: \divide\rail@boxsp by \railunit
wenzelm@2658: \rail@boxlf=\railboxleft
wenzelm@2658: \divide\rail@boxlf by \railunit
wenzelm@2658: \rail@boxrt=\railboxright
wenzelm@2658: \divide\rail@boxrt by \railunit
wenzelm@2658: \rail@boxhht=\railboxheight
wenzelm@2658: \divide\rail@boxhht by \railunit
wenzelm@2658: \divide\rail@boxhht by 2
wenzelm@2658: \rail@ovalsp=\railovalspace
wenzelm@2658: \divide\rail@ovalsp by \railunit
wenzelm@2658: \rail@framesp=\railframespace
wenzelm@2658: \divide\rail@framesp by \railunit
wenzelm@2658: \rail@textlf=\railtextleft
wenzelm@2658: \divide\rail@textlf by \railunit
wenzelm@2658: \rail@textrt=\railtextright
wenzelm@2658: \divide\rail@textrt by \railunit
wenzelm@2658: \rail@textup=\railtextup
wenzelm@2658: \divide\rail@textup by \railunit
wenzelm@2658: \rail@joinsz=\railjoinsize
wenzelm@2658: \divide\rail@joinsz by \railunit
wenzelm@2658: \rail@joinhsz=\railjoinsize
wenzelm@2658: \divide\rail@joinhsz by \railunit
wenzelm@2658: \divide\rail@joinhsz by 2
wenzelm@2658: \rail@joinadj=\railjoinadjust
wenzelm@2658: \divide\rail@joinadj by \railunit
wenzelm@2658: }
wenzelm@2658: 
berghofe@3097: \AtBeginDocument{\railinit}
wenzelm@2658: 
berghofe@3097: % \rail@param : declarations for list environment
berghofe@3097: %
berghofe@3097: % \railparam{TEXT} : sets \rail@param to TEXT
wenzelm@2658: 
berghofe@3097: \def\rail@param{}
berghofe@3097: 
berghofe@3097: \newcommand\railparam[1]{
berghofe@3097: \def\rail@param{#1}
berghofe@3097: }
berghofe@3097: 
berghofe@3097: % \rail@tokenfont : format setup for \railtoken identifiers
berghofe@3097: %
berghofe@3097: % \rail@termfont : format setup for terminals
berghofe@3097: %
berghofe@3097: % \rail@nontfont : format setup for nonterminals
berghofe@3097: %
berghofe@3097: % \rail@annofont : format setup for annotations
berghofe@3097: %
berghofe@3097: % \rail@rulefont : format setup for rule names
berghofe@3097: %
berghofe@3097: % \rail@indexfont : format setup for index entry
berghofe@3097: %
berghofe@3097: % \railtermfont{TEXT} : set terminal format setup to TEXT
berghofe@3097: %
berghofe@3097: % \railnontermfont{TEXT} : set nonterminal format setup to TEXT
berghofe@3097: %
berghofe@3097: % \railannotatefont{TEXT} : set annotation format setup to TEXT
berghofe@3097: %
berghofe@3097: % \railnamefont{TEXT} : set rule name format setup to TEXT
berghofe@3097: %
berghofe@3097: % \railindexfont{TEXT} : set index entry format setup to TEXT
berghofe@3097: 
wenzelm@8591: \def\rail@tokenfont{\ttfamily\upshape}
berghofe@3097: \def\rail@termfont{\ttfamily\upshape}
berghofe@3097: \def\rail@nontfont{\rmfamily\upshape}
berghofe@3097: \def\rail@annofont{\rmfamily\itshape}
berghofe@3097: \def\rail@namefont{\rmfamily\itshape}
berghofe@3097: \def\rail@indexfont{\rmfamily\itshape}
berghofe@3097: 
berghofe@3097: \newcommand\railtermfont[1]{
berghofe@3097: \def\rail@termfont{#1}
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \newcommand\railnontermfont[1]{
berghofe@3097: \def\rail@nontfont{#1}
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \newcommand\railannotatefont[1]{
berghofe@3097: \def\rail@annofont{#1}
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \newcommand\railnamefont[1]{
berghofe@3097: \def\rail@namefont{#1}
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \newcommand\railindexfont[1]{
berghofe@3097: \def\rail@indexfont{#1}
berghofe@3097: }
berghofe@3097: 
berghofe@3097: % railroad read/write macros
berghofe@3097: %
berghofe@3097: % \begin{rail} TEXT \end{rail} : TEXT is written out to the .rai file,
berghofe@3097: %                                as \rail@i{NR}{TEXT}. Then the matching
berghofe@3097: %                                \rail@o{NR}{FMT} from the .rao file is
berghofe@3097: %                                executed (if defined).
berghofe@3097: %
berghofe@3097: % \railoptions{OPTIONS} : OPTIONS are written out to the .rai file,
berghofe@3097: %                         as \rail@p{OPTIONS}.
berghofe@3097: %
berghofe@3097: % \railterm{IDENT,IDENT,...} : format IDENT as terminals. writes out
berghofe@3097: %                              \rail@t{IDENT} to the .rai file
berghofe@3097: %
berghofe@3097: % \railalias{IDENT}{TEXT} : format IDENT as TEXT. defines \rail@t@IDENT as
berghofe@3097: %                           TEXT.
berghofe@3097: %
berghofe@3097: % \rail@nr : railroad diagram counter
berghofe@3097: %
berghofe@3097: % \ifrail@match : current \rail@i{NR}{TEXT} matches
berghofe@3097: %
wenzelm@8591: % \rail@first : actions to be done first. read in .rao file,
berghofe@3097: %               open .rai file if \@filesw true, undefine \rail@first.
berghofe@3097: %               executed from \begin{rail} and \railtoken.
berghofe@3097: %
berghofe@3097: % \rail@i{NR}{TEXT} : defines \rail@i@NR as TEXT. written to the .rai
berghofe@3097: %                     file by \rail, read from the .rao file by
berghofe@3097: %                     \rail@first
berghofe@3097: %
berghofe@3097: % \rail@t{IDENT} : tells Rail that IDENT is to be custom formatted,
berghofe@3097: %                  written to the .rai file by \railterm.
berghofe@3097: %
berghofe@3097: % \rail@o{NR}{TEXT} : defines \rail@o@NR as TEXT, read from the .rao
berghofe@3097: %                     file by \rail@first.
berghofe@3097: %
berghofe@3097: % \rail@p{OPTIONS} : pass options to rail, written to the .rai file by
berghofe@3097: %                    \railoptions
berghofe@3097: %
berghofe@3097: % \rail@write{TEXT} : write TEXT to the .rai file
berghofe@3097: %
berghofe@3097: % \rail@warn : warn user for mismatching diagrams
berghofe@3097: %
berghofe@3097: % \rail@endwarn : either \relax or \rail@warn
berghofe@3097: %
berghofe@3097: % \ifrail@all : checked at the end of the document
berghofe@3097: 
berghofe@3097: \newcount\rail@nr
berghofe@3097: 
berghofe@3097: \newif\ifrail@all
berghofe@3097: \rail@alltrue
berghofe@3097: 
berghofe@3097: \newif\ifrail@match
berghofe@3097: 
berghofe@3097: \def\rail@first{
berghofe@3097: \makeatletter
berghofe@3097: \InputIfFileExists{\jobname.rao}{}{\PackageInfo{rail}{No file \jobname.rao}}
berghofe@3097: \makeatother
berghofe@3097: \if@filesw
berghofe@3097: \newwrite\tf@rai
berghofe@3097: \immediate\openout\tf@rai=\jobname.rai
wenzelm@2658: \fi
berghofe@3097: \global\let\rail@first=\relax
berghofe@3097: }
wenzelm@2658: 
berghofe@3097: \long\def\rail@body#1\end{
berghofe@3097: \begingroup
berghofe@3097: \let\\=\relax
berghofe@3097: \xdef\rail@i@{#1}
berghofe@3097: \rail@write{\string\rail@i{\number\rail@nr}{\rail@i@}}
berghofe@3097: \endgroup
berghofe@3097: \end
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \newenvironment{rail}{
berghofe@3097: \global\advance\rail@nr by 1
berghofe@3097: \rail@first
berghofe@3097: \rail@body
berghofe@3097: }{
berghofe@3097: \rail@matchtrue
berghofe@3097: \@ifundefined{rail@o@\number\rail@nr}{\rail@matchfalse}{}
berghofe@3097: \expandafter\ifx\csname rail@i@\number\rail@nr\endcsname\rail@i@
berghofe@3097: \else
berghofe@3097: \rail@matchfalse
berghofe@3097: \fi
berghofe@3097: \ifrail@match
berghofe@3097: \csname rail@o@\number\rail@nr\endcsname
berghofe@3097: \else
berghofe@3097: \PackageWarning{rail}{Railroad diagram {\number\rail@nr} doesn't match}
berghofe@3097: \global\let\rail@endwarn=\rail@warn
berghofe@3097: \begin{list}{}{\rail@param}
berghofe@3097: \rail@begin{1}{}
berghofe@3097: \rail@setbox{\bfseries ???}
berghofe@3097: \rail@oval
berghofe@3097: \rail@end
berghofe@3097: \end{list}
berghofe@3097: \fi
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \newcommand\railoptions[1]{
berghofe@3097: \rail@first
berghofe@3097: \rail@write{\string\rail@p{#1}}
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \newcommand\railterm[1]{
berghofe@3097: \rail@first
berghofe@3097: \@for\rail@@:=#1\do{
berghofe@3097: \rail@write{\string\rail@t{\rail@@}}
berghofe@3097: }
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \newcommand\railalias[2]{
berghofe@3097: \expandafter\def\csname rail@t@#1\endcsname{#2}
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \long\def\rail@i#1#2{
berghofe@3097: \expandafter\gdef\csname rail@i@#1\endcsname{#2}
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \def\rail@o#1#2{
berghofe@3097: \expandafter\gdef\csname rail@o@#1\endcsname{
berghofe@3097: \begin{list}{}{\rail@param}#2\end{list}
berghofe@3097: }
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \def\rail@t#1{}
berghofe@3097: 
berghofe@3097: \def\rail@p#1{}
berghofe@3097: 
berghofe@3097: \def\rail@write#1{\@ifundefined{tf@rai}{}{\immediate\write\tf@rai{#1}}}
berghofe@3097: 
berghofe@3097: \def\rail@warn{
berghofe@3097: \PackageWarningNoLine{rail}{Railroad diagram(s) may have changed.
berghofe@3097:                             Use 'rail' and rerun}
berghofe@3097: }
berghofe@3097: 
berghofe@3097: \let\rail@endwarn=\relax
berghofe@3097: 
berghofe@3097: \AtEndDocument{\rail@endwarn}
berghofe@3097: 
berghofe@3097: % index entry macro
berghofe@3097: %
berghofe@3097: % \rail@index{IDENT} : add index entry for IDENT
berghofe@3097: 
berghofe@3097: \def\rail@index#1{
berghofe@3097: \index{\rail@indexfont#1}
berghofe@3097: }
wenzelm@2658: 
wenzelm@2658: % railroad formatting primitives
wenzelm@2658: %
wenzelm@2658: % \rail@x : current x
wenzelm@2658: % \rail@y : current y
wenzelm@2658: % \rail@ex : current end x
wenzelm@2658: % \rail@sx : starting x for \rail@cr
wenzelm@2658: % \rail@rx : rightmost previous x for \rail@cr
wenzelm@2658: %
wenzelm@2658: % \rail@tmpa : temporary count
wenzelm@2658: % \rail@tmpb : temporary count
wenzelm@2658: % \rail@tmpc : temporary count
wenzelm@2658: %
wenzelm@2658: % \rail@put : put at (\rail@x,\rail@y)
wenzelm@2658: %
wenzelm@2658: % \rail@eline : end line by drawing from \rail@ex to \rail@x
wenzelm@2658: %
wenzelm@2658: % \rail@sety{LEVEL} : set \rail@y to level LEVEL
wenzelm@2658: 
wenzelm@2658: \newcount\rail@x
wenzelm@2658: \newcount\rail@y
wenzelm@2658: \newcount\rail@ex
wenzelm@2658: \newcount\rail@sx
wenzelm@2658: \newcount\rail@rx
wenzelm@2658: 
wenzelm@2658: \newcount\rail@tmpa
wenzelm@2658: \newcount\rail@tmpb
wenzelm@2658: \newcount\rail@tmpc
wenzelm@2658: 
wenzelm@2658: \def\rail@put{\put(\number\rail@x,\number\rail@y)}
wenzelm@2658: 
wenzelm@2658: \def\rail@eline{
wenzelm@2658: \rail@tmpb=\rail@x
wenzelm@2658: \advance\rail@tmpb by -\rail@ex
wenzelm@2658: \rail@put{\line(-1,0){\number\rail@tmpb}}
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@sety#1{
wenzelm@2658: \rail@y=#1
wenzelm@2658: \multiply\rail@y by -\rail@boxsp
wenzelm@2658: \advance\rail@y by -\rail@boxht
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: % \rail@begin{HEIGHT}{NAME} : begin a railroad diagram of height HEIGHT
wenzelm@2658: %
wenzelm@2658: % \rail@end : end a railroad diagram
berghofe@3097: %
berghofe@3097: % \rail@expand{IDENT} : expand IDENT
wenzelm@2658: 
wenzelm@2658: \def\rail@begin#1#2{
wenzelm@2658: \item[]
berghofe@3097: \begin{minipage}[t]{\linewidth}
wenzelm@2658: \ifx\@empty#2\else
berghofe@3097: {\rail@namefont \rail@expand{#2}}\\*[\railnamesep]
wenzelm@2658: \fi
wenzelm@2658: \unitlength=\railunit
wenzelm@2658: \rail@tmpa=#1
wenzelm@2658: \multiply\rail@tmpa by \rail@boxsp
wenzelm@2658: \begin{picture}(0,\number\rail@tmpa)(0,-\number\rail@tmpa)
wenzelm@2658: \rail@ex=0
wenzelm@2658: \rail@rx=0
wenzelm@2658: \rail@x=\rail@extra
wenzelm@2658: \rail@sx=\rail@x
wenzelm@2658: \rail@sety{0}
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@end{
wenzelm@2658: \advance\rail@x by \rail@extra
wenzelm@2658: \rail@eline
wenzelm@2658: \end{picture}
berghofe@3097: \end{minipage}
wenzelm@2658: }
wenzelm@2658: 
berghofe@3097: \def\rail@expand#1{\@ifundefined{rail@t@#1}{#1}{\csname rail@t@#1\endcsname}}
berghofe@3097: 
berghofe@3097: % \rail@token{TEXT}[ANNOT] : format token TEXT with annotation
wenzelm@2658: %
berghofe@3097: % \rail@ctoken{TEXT}[ANNOT] : format token TEXT centered with annotation
wenzelm@2658: %
berghofe@3097: % \rail@nont{TEXT}[ANNOT] : format nonterminal TEXT with annotation
wenzelm@2658: %
berghofe@3097: % \rail@cnont{TEXT}[ANNOT] : format nonterminal TEXT centered with annotation
wenzelm@2658: %
berghofe@3097: % \rail@term{TEXT}[ANNOT] : format terminal TEXT with annotation
wenzelm@2658: %
berghofe@3097: % \rail@cterm{TEXT}[ANNOT] : format terminal TEXT centered with annotation
wenzelm@2658: %
wenzelm@2658: % \rail@annote[TEXT] : format TEXT as annotation
wenzelm@2658: 
berghofe@3097: \def\rail@token#1[#2]{
berghofe@3097: \rail@setbox{%
wenzelm@8591: {\rail@tokenfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
wenzelm@2658: }
wenzelm@2658: \rail@oval
wenzelm@2658: }
wenzelm@2658: 
berghofe@3097: \def\rail@ctoken#1[#2]{
berghofe@3097: \rail@setbox{%
wenzelm@8591: {\rail@tokenfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
berghofe@3097: }
wenzelm@2658: \rail@coval
wenzelm@2658: }
wenzelm@2658: 
berghofe@3097: \def\rail@nont#1[#2]{
berghofe@3097: \rail@setbox{%
berghofe@3097: {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
berghofe@3097: }
wenzelm@2658: \rail@frame
wenzelm@2658: }
wenzelm@2658: 
berghofe@3097: \def\rail@cnont#1[#2]{
berghofe@3097: \rail@setbox{%
berghofe@3097: {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
berghofe@3097: }
wenzelm@2658: \rail@cframe
wenzelm@2658: }
wenzelm@2658: 
berghofe@3097: \def\rail@term#1[#2]{
berghofe@3097: \rail@setbox{%
berghofe@3097: {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
berghofe@3097: }
wenzelm@2658: \rail@oval
wenzelm@2658: }
wenzelm@2658: 
berghofe@3097: \def\rail@cterm#1[#2]{
berghofe@3097: \rail@setbox{%
berghofe@3097: {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
berghofe@3097: }
wenzelm@2658: \rail@coval
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@annote[#1]{
wenzelm@2658: \rail@setbox{\rail@annofont #1}
wenzelm@2658: \rail@text
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: % \rail@box : temporary box for \rail@oval and \rail@frame
wenzelm@2658: %
wenzelm@2658: % \rail@setbox{TEXT} : set \rail@box to TEXT, set \rail@tmpa to width
wenzelm@2658: %
wenzelm@2658: % \rail@oval : format \rail@box of width \rail@tmpa inside an oval
wenzelm@2658: %
wenzelm@2658: % \rail@coval : same as \rail@oval, but centered between \rail@x and
wenzelm@2658: %               \rail@mx
wenzelm@2658: %
wenzelm@2658: % \rail@frame : format \rail@box of width \rail@tmpa inside a frame
wenzelm@2658: %
wenzelm@2658: % \rail@cframe : same as \rail@frame, but centered between \rail@x and
wenzelm@2658: %                \rail@mx
wenzelm@2658: %
wenzelm@2658: % \rail@text : format \rail@box of width \rail@tmpa above the line
wenzelm@2658: 
wenzelm@2658: \newbox\rail@box
wenzelm@2658: 
wenzelm@2658: \def\rail@setbox#1{
wenzelm@2658: \setbox\rail@box\hbox{\strut#1}
wenzelm@2658: \rail@tmpa=\wd\rail@box
wenzelm@2658: \divide\rail@tmpa by \railunit
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@oval{
wenzelm@2658: \advance\rail@x by \rail@boxlf
wenzelm@2658: \rail@eline
wenzelm@2658: \advance\rail@tmpa by \rail@ovalsp
wenzelm@2658: \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
wenzelm@2658: \rail@tmpb=\rail@tmpa
wenzelm@2658: \divide\rail@tmpb by 2
wenzelm@2658: \advance\rail@y by -\rail@boxhht
wenzelm@2658: \rail@put{\makebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
wenzelm@2658: \advance\rail@y by \rail@boxhht
wenzelm@2658: \advance\rail@x by \rail@tmpb
wenzelm@2658: \rail@put{\oval(\number\rail@tmpa,\number\rail@boxht)}
wenzelm@2658: \advance\rail@x by \rail@tmpb
wenzelm@2658: \rail@ex=\rail@x
wenzelm@2658: \advance\rail@x by \rail@boxrt
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@coval{
wenzelm@2658: \rail@tmpb=\rail@tmpa
wenzelm@2658: \advance\rail@tmpb by \rail@ovalsp
wenzelm@2658: \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
wenzelm@2658: \advance\rail@tmpb by \rail@boxlf
wenzelm@2658: \advance\rail@tmpb by \rail@boxrt
wenzelm@2658: \rail@tmpc=\rail@mx
wenzelm@2658: \advance\rail@tmpc by -\rail@x
wenzelm@2658: \advance\rail@tmpc by -\rail@tmpb
wenzelm@2658: \divide\rail@tmpc by 2
wenzelm@2658: \ifnum\rail@tmpc>0
wenzelm@2658: \advance\rail@x by \rail@tmpc
wenzelm@2658: \fi
wenzelm@2658: \rail@oval
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@frame{
wenzelm@2658: \advance\rail@x by \rail@boxlf
wenzelm@2658: \rail@eline
wenzelm@2658: \advance\rail@tmpa by \rail@framesp
wenzelm@2658: \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
wenzelm@2658: \advance\rail@y by -\rail@boxhht
wenzelm@2658: \rail@put{\framebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
wenzelm@2658: \advance\rail@y by \rail@boxhht
wenzelm@2658: \advance\rail@x by \rail@tmpa
wenzelm@2658: \rail@ex=\rail@x
wenzelm@2658: \advance\rail@x by \rail@boxrt
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@cframe{
wenzelm@2658: \rail@tmpb=\rail@tmpa
wenzelm@2658: \advance\rail@tmpb by \rail@framesp
wenzelm@2658: \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
wenzelm@2658: \advance\rail@tmpb by \rail@boxlf
wenzelm@2658: \advance\rail@tmpb by \rail@boxrt
wenzelm@2658: \rail@tmpc=\rail@mx
wenzelm@2658: \advance\rail@tmpc by -\rail@x
wenzelm@2658: \advance\rail@tmpc by -\rail@tmpb
wenzelm@2658: \divide\rail@tmpc by 2
wenzelm@2658: \ifnum\rail@tmpc>0
wenzelm@2658: \advance\rail@x by \rail@tmpc
wenzelm@2658: \fi
wenzelm@2658: \rail@frame
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@text{
wenzelm@2658: \advance\rail@x by \rail@textlf
wenzelm@2658: \advance\rail@y by \rail@textup
wenzelm@2658: \rail@put{\box\rail@box}
wenzelm@2658: \advance\rail@y by -\rail@textup
wenzelm@2658: \advance\rail@x by \rail@tmpa
wenzelm@2658: \advance\rail@x by \rail@textrt
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: % alternatives
wenzelm@2658: %
wenzelm@2658: % \rail@jx \rail@jy : current join point
wenzelm@2658: %
wenzelm@2658: % \rail@gx \rail@gy \rail@gex \rail@grx : global versions of \rail@x etc,
wenzelm@2658: %                                         to pass values over group closings
wenzelm@2658: %
wenzelm@2658: % \rail@mx : maximum x so far
wenzelm@2658: %
wenzelm@2658: % \rail@sy : starting \rail@y for alternatives
wenzelm@2658: %
wenzelm@2658: % \rail@jput : put at (\rail@jx,\rail@jy)
wenzelm@2658: %
wenzelm@2658: % \rail@joval[PART] : put \oval[PART] with adjust
wenzelm@2658: 
wenzelm@2658: \newcount\rail@jx
wenzelm@2658: \newcount\rail@jy
wenzelm@2658: 
wenzelm@2658: \newcount\rail@gx
wenzelm@2658: \newcount\rail@gy
wenzelm@2658: \newcount\rail@gex
wenzelm@2658: \newcount\rail@grx
wenzelm@2658: 
wenzelm@2658: \newcount\rail@sy
wenzelm@2658: \newcount\rail@mx
wenzelm@2658: 
wenzelm@2658: \def\rail@jput{
wenzelm@2658: \put(\number\rail@jx,\number\rail@jy)
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@joval[#1]{
wenzelm@2658: \advance\rail@jx by \rail@joinadj
wenzelm@2658: \rail@jput{\oval(\number\rail@joinsz,\number\rail@joinsz)[#1]}
wenzelm@2658: \advance\rail@jx by -\rail@joinadj
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: % \rail@barsplit : incoming split for '|'
wenzelm@2658: %
wenzelm@2658: % \rail@plussplit : incoming split for '+'
wenzelm@2658: %
wenzelm@2658: 
wenzelm@2658: \def\rail@barsplit{
wenzelm@2658: \advance\rail@jy by -\rail@joinhsz
wenzelm@2658: \rail@joval[tr]
wenzelm@2658: \advance\rail@jx by \rail@joinhsz
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@plussplit{
wenzelm@2658: \advance\rail@jy by -\rail@joinhsz
wenzelm@2658: \advance\rail@jx by \rail@joinsz
wenzelm@2658: \rail@joval[tl]
wenzelm@2658: \advance\rail@jx by -\rail@joinhsz
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: % \rail@alt{SPLIT} : start alternatives with incoming split SPLIT
wenzelm@2658: %
wenzelm@2658: 
wenzelm@2658: \def\rail@alt#1{
wenzelm@2658: \rail@sy=\rail@y
wenzelm@2658: \rail@jx=\rail@x
wenzelm@2658: \rail@jy=\rail@y
wenzelm@2658: \advance\rail@x by \rail@joinsz
wenzelm@2658: \rail@mx=0
wenzelm@2658: \let\rail@list=\@empty
wenzelm@2658: \let\rail@comma=\@empty
wenzelm@2658: \let\rail@split=#1
wenzelm@2658: \begingroup
wenzelm@2658: \rail@sx=\rail@x
wenzelm@2658: \rail@rx=0
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: % \rail@nextalt{FIX}{Y} : start next alternative at vertical position Y
wenzelm@2658: %                         and fix-up FIX
wenzelm@2658: %
wenzelm@2658: 
wenzelm@2658: \def\rail@nextalt#1#2{
wenzelm@2658: \global\rail@gx=\rail@x
wenzelm@2658: \global\rail@gy=\rail@y
wenzelm@2658: \global\rail@gex=\rail@ex
wenzelm@2658: \global\rail@grx=\rail@rx
wenzelm@2658: \endgroup
wenzelm@2658: #1
wenzelm@2658: \ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
wenzelm@2658: \ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
wenzelm@2658: \edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
wenzelm@2658: \def\rail@comma{,}
wenzelm@2658: \rail@split
wenzelm@2658: \let\rail@split=\@empty
wenzelm@2658: \rail@sety{#2}
wenzelm@2658: \rail@tmpa=\rail@jy
wenzelm@2658: \advance\rail@tmpa by -\rail@y
wenzelm@2658: \advance\rail@tmpa by -\rail@joinhsz
wenzelm@2658: \rail@jput{\line(0,-1){\number\rail@tmpa}}
wenzelm@2658: \rail@jy=\rail@y
wenzelm@2658: \advance\rail@jy by \rail@joinhsz
wenzelm@2658: \advance\rail@jx by \rail@joinhsz
wenzelm@2658: \rail@joval[bl]
wenzelm@2658: \advance\rail@jx by -\rail@joinhsz
wenzelm@2658: \rail@ex=\rail@x
wenzelm@2658: \begingroup
wenzelm@2658: \rail@sx=\rail@x
wenzelm@2658: \rail@rx=0
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: % \rail@barjoin : outgoing join for first '|' alternative
wenzelm@2658: %
wenzelm@2658: % \rail@plusjoin : outgoing join for first '+' alternative
wenzelm@2658: %
wenzelm@2658: % \rail@altjoin : join for subsequent alternative
wenzelm@2658: %
wenzelm@2658: 
wenzelm@2658: \def\rail@barjoin{
wenzelm@2658: \ifnum\rail@y<\rail@sy
wenzelm@2658: \global\rail@gex=\rail@jx
wenzelm@2658: \else
wenzelm@2658: \global\rail@gex=\rail@ex
wenzelm@2658: \fi
wenzelm@2658: \advance\rail@jy by -\rail@joinhsz
wenzelm@2658: \rail@joval[tl]
wenzelm@2658: \advance\rail@jx by -\rail@joinhsz
wenzelm@2658: \ifnum\rail@y<\rail@sy
wenzelm@2658: \rail@altjoin
wenzelm@2658: \fi
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@plusjoin{
wenzelm@2658: \global\rail@gex=\rail@ex
wenzelm@2658: \advance\rail@jy by -\rail@joinhsz
wenzelm@2658: \advance\rail@jx by -\rail@joinsz
wenzelm@2658: \rail@joval[tr]
wenzelm@2658: \advance\rail@jx by \rail@joinhsz
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@altjoin{
wenzelm@2658: \rail@eline
wenzelm@2658: \rail@tmpa=\rail@jy
wenzelm@2658: \advance\rail@tmpa by -\rail@y
wenzelm@2658: \advance\rail@tmpa by -\rail@joinhsz
wenzelm@2658: \rail@jput{\line(0,-1){\number\rail@tmpa}}
wenzelm@2658: \rail@jy=\rail@y
wenzelm@2658: \advance\rail@jy by \rail@joinhsz
wenzelm@2658: \advance\rail@jx by -\rail@joinhsz
wenzelm@2658: \rail@joval[br]
wenzelm@2658: \advance\rail@jx by \rail@joinhsz
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: % \rail@eltsplit EX:Y; : split EX:Y into \rail@ex \rail@y
wenzelm@2658: %
wenzelm@2658: % \rail@endalt{JOIN} : end alternatives with outgoing join JOIN
wenzelm@2658: 
wenzelm@2658: \def\rail@eltsplit#1:#2;{\rail@ex=#1\rail@y=#2}
wenzelm@2658: 
wenzelm@2658: \def\rail@endalt#1{
wenzelm@2658: \global\rail@gx=\rail@x
wenzelm@2658: \global\rail@gy=\rail@y
wenzelm@2658: \global\rail@gex=\rail@ex
wenzelm@2658: \global\rail@grx=\rail@rx
wenzelm@2658: \endgroup
wenzelm@2658: \ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
wenzelm@2658: \ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
wenzelm@2658: \edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
wenzelm@2658: \rail@x=\rail@mx
wenzelm@2658: \rail@jx=\rail@x
wenzelm@2658: \rail@jy=\rail@sy
wenzelm@2658: \advance\rail@jx by \rail@joinsz
wenzelm@2658: \let\rail@join=#1
wenzelm@2658: \@for\rail@elt:=\rail@list\do{
wenzelm@2658: \expandafter\rail@eltsplit\rail@elt;
wenzelm@2658: \rail@join
wenzelm@2658: \let\rail@join=\rail@altjoin
wenzelm@2658: }
wenzelm@2658: \rail@x=\rail@mx
wenzelm@2658: \rail@y=\rail@sy
wenzelm@2658: \rail@ex=\rail@gex
wenzelm@2658: \advance\rail@x by \rail@joinsz
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: % \rail@bar : start '|' alternatives
wenzelm@2658: %
wenzelm@2658: % \rail@nextbar : next '|' alternative
wenzelm@2658: %
wenzelm@2658: % \rail@endbar : end '|' alternatives
wenzelm@2658: %
wenzelm@2658: 
wenzelm@2658: \def\rail@bar{
wenzelm@2658: \rail@alt\rail@barsplit
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@nextbar{
wenzelm@2658: \rail@nextalt\relax
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@endbar{
wenzelm@2658: \rail@endalt\rail@barjoin
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: % \rail@plus : start '+' alternatives
wenzelm@2658: %
wenzelm@2658: % \rail@nextplus: next '+' alternative
wenzelm@2658: %
wenzelm@2658: % \rail@endplus : end '+' alternatives
wenzelm@2658: %
wenzelm@2658: 
wenzelm@2658: \def\rail@plus{
wenzelm@2658: \rail@alt\rail@plussplit
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@nextplus{
wenzelm@2658: \rail@nextalt\rail@fixplus
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@fixplus{
wenzelm@2658: \ifnum\rail@gy<\rail@sy
wenzelm@2658: \begingroup
wenzelm@2658: \rail@x=\rail@gx
wenzelm@2658: \rail@y=\rail@gy
wenzelm@2658: \rail@ex=\rail@gex
wenzelm@2658: \rail@rx=\rail@grx
wenzelm@2658: \ifnum\rail@x<\rail@rx
wenzelm@2658: \rail@x=\rail@rx
wenzelm@2658: \fi
wenzelm@2658: \rail@eline
wenzelm@2658: \rail@jx=\rail@x
wenzelm@2658: \rail@jy=\rail@y
wenzelm@2658: \advance\rail@jy by \rail@joinhsz
wenzelm@2658: \rail@joval[br]
wenzelm@2658: \advance\rail@jx by \rail@joinhsz
wenzelm@2658: \rail@tmpa=\rail@sy
wenzelm@2658: \advance\rail@tmpa by -\rail@joinhsz
wenzelm@2658: \advance\rail@tmpa by -\rail@jy
wenzelm@2658: \rail@jput{\line(0,1){\number\rail@tmpa}}
wenzelm@2658: \rail@jy=\rail@sy
wenzelm@2658: \advance\rail@jy by -\rail@joinhsz
wenzelm@2658: \advance\rail@jx by \rail@joinhsz
wenzelm@2658: \rail@joval[tl]
wenzelm@2658: \advance\rail@jy by \rail@joinhsz
wenzelm@2658: \global\rail@gx=\rail@jx
wenzelm@2658: \global\rail@gy=\rail@jy
wenzelm@2658: \global\rail@gex=\rail@gx
wenzelm@2658: \global\rail@grx=\rail@rx
wenzelm@2658: \endgroup
wenzelm@2658: \fi
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: \def\rail@endplus{
wenzelm@2658: \rail@endalt\rail@plusjoin
wenzelm@2658: }
wenzelm@2658: 
wenzelm@2658: % \rail@cr{Y} : carriage return to vertical position Y
wenzelm@2658: 
wenzelm@2658: \def\rail@cr#1{
wenzelm@2658: \rail@tmpa=\rail@sx
wenzelm@2658: \advance\rail@tmpa by \rail@joinsz
wenzelm@2658: \ifnum\rail@x<\rail@tmpa\rail@x=\rail@tmpa\fi
wenzelm@2658: \rail@eline
wenzelm@2658: \rail@jx=\rail@x
wenzelm@2658: \rail@jy=\rail@y
wenzelm@2658: \advance\rail@x by \rail@joinsz
wenzelm@2658: \ifnum\rail@x>\rail@rx\rail@rx=\rail@x\fi
wenzelm@2658: \advance\rail@jy by -\rail@joinhsz
wenzelm@2658: \rail@joval[tr]
wenzelm@2658: \advance\rail@jx by \rail@joinhsz
wenzelm@2658: \rail@sety{#1}
wenzelm@2658: \rail@tmpa=\rail@jy
wenzelm@2658: \advance\rail@tmpa by -\rail@y
wenzelm@2658: \advance\rail@tmpa by -\rail@boxsp
wenzelm@2658: \advance\rail@tmpa by -\rail@joinhsz
wenzelm@2658: \rail@jput{\line(0,-1){\number\rail@tmpa}}
wenzelm@2658: \rail@jy=\rail@y
wenzelm@2658: \advance\rail@jy by \rail@boxsp
wenzelm@2658: \advance\rail@jy by \rail@joinhsz
wenzelm@2658: \advance\rail@jx by -\rail@joinhsz
wenzelm@2658: \rail@joval[br]
wenzelm@2658: \advance\rail@jy by -\rail@joinhsz
wenzelm@2658: \rail@tmpa=\rail@jx
wenzelm@2658: \advance\rail@tmpa by -\rail@sx
wenzelm@2658: \advance\rail@tmpa by -\rail@joinhsz
wenzelm@2658: \rail@jput{\line(-1,0){\number\rail@tmpa}}
wenzelm@2658: \rail@jx=\rail@sx
wenzelm@2658: \advance\rail@jx by \rail@joinhsz
wenzelm@2658: \advance\rail@jy by -\rail@joinhsz
wenzelm@2658: \rail@joval[tl]
wenzelm@2658: \advance\rail@jx by -\rail@joinhsz
wenzelm@2658: \rail@tmpa=\rail@boxsp
wenzelm@2658: \advance\rail@tmpa by -\rail@joinsz
wenzelm@2658: \rail@jput{\line(0,-1){\number\rail@tmpa}}
wenzelm@2658: \advance\rail@jy by -\rail@tmpa
wenzelm@2658: \advance\rail@jx by \rail@joinhsz
wenzelm@2658: \rail@joval[bl]
wenzelm@2658: \rail@x=\rail@jx
wenzelm@2658: \rail@ex=\rail@x
wenzelm@2658: }




