%    
%   SYNTAX.STY
%
%
%   LATEX-Documentstyle-Option zum einfachen Setzen von Syntax-Diagrammen
%   Version 0.1a   vom   21.7.1989
%
%   Author : Jens Franzen
%            Laboratorium fuer Informationstechnologie
%            Universitaet Hannover
%            Schneiderberg 32
%            D-3000 Hannover 1
%            Tel. 0511 / 762 - 5039
%            FAX  0511 / 762 - 5051 
%
%
\typeout{Syntax-Diagramme Version 0.1a}
\typeout{Vorlaeufige Version zum Test }
%
%
%   Mit dieser Style-Option koennen Syntax-Diagramme mit Hilfe von 
%   Makros gesetzt werden, deren Struktur an die erweiterte 
%   Backus-Naur-Form angelehnt ist.
%
%   Die wesentlichen Elemente des Diagramms sind Terminale und Nonterminale
%   Symbole. Terminale werden einfach mit '\t{xxx}', Nonterminale mit 
%   '\nt{xxx}' gesetzt. 'xxx' ist dabei der Inhalt des Ovals bzw. des 
%   Rechtecks und kann bis auf die Hoehe beliebig 
%   sein ( inc. Makros .... ). Die Laenge wird automatisch richtig gesetzt, die 
%   Hoehe haengt von dem 'Zeilenabstand' im Diagramm ab und muss im Environment 
%   spezifiziert werden.
%  
%   Der gesamte Inhalt des Diagramms wird in ein Environment 'syntax'
%   gesetzt :
%
%   \begin{syntax}{Name}{Zeilenabstand}
%        ... Inhalt ...
%   \end{syntax}
%
%   Das Ergebnis ist eine horizontale Box, die das Diagramm enthaelt.
%   ( analog zu einem 'picture' ) und ein neues Makro '\Name', das als
%   Abkuerzung fuer das Setzen des Nonterminals '\nt{Name}' verwendet werden 
%   kann.
%   das Argument 'Name' darf keine Makros, Sonderzeichen etc. enthalten.
%   Sollen Makros vwerwendet werden, muss der Name des zu definierenden
%   neuen Makros als optionales Argument angegeben werden :
%   
%   \begin{syntax}[Name]{ \wilde \makrosequenz }{Zeilenabstand}
%        ... Inhalt ...
%   \end{syntax}
%
%   Der Zeilenabstand ist eine bei TeX uebliche Laenge.
%
%
%   Als Konstrukte stehen zur Verfuegung :
%
%   1. Symbole
%           Terminale :      \t{ ... } 
%           Nonterminale :   \nt{ ... }
%           Leersymbol :     \empty
% 
%
%   2. Alternative :
%    
%       \alt   'Alternative 1'  
%            \o  'Alternative 2' 
%            \o .....
%                   ....
%            \o 'Alternative n' 
%       \endalt
%
%
%   3. Alternative mit leerem Pfad
%    
%       \emptyalt   'Alternative 1'  
%            \o  'Alternative 2' 
%            \o .....
%                  ....
%            \o 'Alternative n' 
%       \endemptyalt
%
%
%   4. Schleife
%
%         \loopa   ... Inhalt ...  \endloopa
%
%   5. optionale Schleife 
%
%         \optloop   ... Inhalt ...  \endoptloop
%
%   6. ueber mehrere Zeilen verteilte Ketten von Elementen
%
%       \multiline   'Zeile 1'  
%            \oml  'Zeile 2' 
%            \oml .....
%                  ....
%            \oml 'Zeile n' 
%       \endmultiline
%
%
%   Alle diese Schleifen, Alternativen etc. koennen nahezu beliebig 
%   ineinander verschachtelt werden  ( Nur begrenzt vom maximalen 
%   Nesting-Level in TeX ) !
%
%
%
%##########################################################################
%
%
%  Hier geht's ins Eingemachte !
%
%
%  Definierte 'versteckte' Makros :
%
%      \syn@adh#1              \syn@adw#1              \syn@adx#1
%      \syn@ady#1              \syn@downline#1         \syn@horline#1
%      \syn@max(#1,#2)         \syn@put#1              \syn@putat(#1,#2)#3
%      \syn@rightline#1        \syn@saveh              \syn@savew
%      \syn@savex              \syn@savey              \syn@taxn#1
%      \syn@taxm[#1]#2#3       \syn@unithalfvec        \syn@unithalfline
%      \syn@unitline           \syn@unitvector         \syn@upvector#1
%      \syn@upline#1
%
%  Definierte 'sichtbare' Makros :
%
%      \alt                    \emptyalt               \endalt
%      \endemptyalt            \endloopa               \endmultiline
%      \endoptloop             \empty                  \loopa
%      \multiline              \nt#1                   \o 
%      \oml                    \optloop                \t#1
%
%  Das Environment definierende  Makros :
%
%      \syntax
%      \endsyntax
%
%  Zaehler fuer 
%
\newcount\x        % Koordinaten
\newcount\y
\newcount\bw       % Blockgroessen
\newcount\bh
\newcount\cw       % Blockgroessen ( Speicher zum Transfer ueber 
\newcount\ch       %                 Grouplevel )
\newcount\cx       % Koordinatenspeicher z. Transfer ueber Grouplevel
\newcount\cy
\newcount\altnum     % Anzahl der Alternativen
\newcount\altx       % Groesster x-Wert der Alternativen
\newcount\alty       % f. Alternativen
\newcount\altw       % f. Alternativen
\newcount\alth       % f. Alternativen
\newcount\ntwidth  % Zur Berechnung der Breite eines ( Non-)Terminals  
\newcount\ntwidtha  % Zur Berechnung der Breite eines ( Non-)Terminals  
\newcount\ntwidthb  % Zur Berechnung der Breite eines ( Non-)Terminals  
\newcount\ntdimen  % Zur Berechnung der Breite eines ( Non-)Terminals  
\newdimen\ntwidthdim %
%
%   Boxen 
% 
\newbox\syn@ntstorage   % zum Berechnen der Groesse des Textes in einem
%                       ( Non)Terminal      
\newbox\syn@storage     % Enthaelt das gesamte Diagramm !
%
%  Hilfsmakros aus Faulheit
%
\def\syn@adx#1{\advance\x by #1}
\def\syn@ady#1{\advance\y by #1}
\def\syn@adw#1{\advance\bw by #1}
\def\syn@adh#1{\advance\bh by #1}
%
\def\syn@savex{\global\cx=\number\x}
\def\syn@savey{\global\cy=\number\y}
\def\syn@savew{\global\cw=\number\bw}
\def\syn@saveh{\global\ch=\number\bh}
%
%  Plazierung der Elemente 
%
\long\def\syn@put#1{\@killglue\raise-\y\unitlength\hbox to \z@{\hskip
\x\unitlength #1\hss}\ignorespaces}
%
\long\def\syn@putat(#1,#2)#3{\@killglue\raise-#2\unitlength\hbox to \z@{\hskip
#1\unitlength #3\hss}\ignorespaces}

%
%  Graphische Hilfselemente
%      Bequemlichkeit siegt !    ( in Version 0.2 nicht mehr ! )
%
\def\syn@horline#1{\@linelen = #1\unitlength\@hline}%
\def\syn@unithalfvec{\@picture(1,1)(0,0)\put(0,0.5){\vector(1,0){0.5}}%
\put(0.5,0.5){\syn@horline{0.5}}\endpicture}
%
\def\syn@unithalfline{\@picture(1,1)(0,0)\put(0.5,0.5){\syn@horline{0.5}}%
\put(0.5,0.5){\syn@horline{0.5}}\endpicture}
%
\def\syn@unitvector{\@picture(1,1)(0,0)\put(0,0.5){\vector(1,0){1}}\endpicture}
%
\def\syn@unitline{\@picture(1,1)(0,0)%
\put(0,0.5){\syn@horline{1}}\endpicture}
%
\def\syn@downline#1{\@picture(1,1)(0,0)%
\put(0.5,0.5){\line(0,-1){#1}}\endpicture}
%
\def\syn@rightline#1{\@picture(1,1)(0,0)%
\put(0.5,0.5){\syn@horline{#1}}\endpicture}
%
\def\syn@upvector#1{\@picture(1,1)(0,0)%
\put(0.5,0.5){\vector(0,1){#1}}\endpicture}
%
\def\syn@upline#1{\@picture(1,1)(0,0)%
\put(0.5,0.5){\line(0,1){#1}}\endpicture}
%
%---------------------------------------------------------------------------
%
%  Das Environment :
%
%  syntax := BEGIN
%              IF nextchar = [ THEN
%                    \syn@taxm
%              ELSE
%                    \syn@taxn
%              ENDIF                   
%            END
%
%  syn@taxn #1 := BEGIN
%                  \syn@taxm[#1]#1
%                 END      
%
%    Weitere Documentation folgt spaeter ! 
%                  ( da z.T. wuesteste Programmierung ! )
%
\def\syntax{\@ifnextchar [{\syn@taxm}{\syn@taxn}}
%
\def\syn@taxn#1{\syn@taxm[#1]{#1}}
%
\def\syn@taxm[#1]#2#3{\typeout{Syntaxdiagramm #1}\setlength{\unitlength}{#3}%
\expandafter\gdef\csname#1\endcsname{\nt{#2}}%
\setbox\syn@storage=\hbox\bgroup%
\x=0 \y=0 \bh=0 \bw=0 \ntdimen = \unitlength%
\@picture(0,0)(0,1)\syn@put{\syn@unitline}\syn@adx 1 \syn@adw 1}%
%
\def\endsyntax{\syn@put{\syn@unitvector}\syn@adw 1\syn@savew\syn@saveh\endpicture\egroup%
\begin{picture}(\number\cw,\number\ch)(0,0)
\put(0,\number\ch){\box\syn@storage}\end{picture}}%
%
%  Mathematik :
%      Bequemlichkeit siegt !    ( in Version 0.2 nicht mehr ! )
%  
\def\syn@max(#1,#2){\ifnum #2 > #1 #1 = #2 \fi}
%
%  Terminals und Nonterminals
%
\def\t#1{\setbox\syn@ntstorage = \hbox{#1}\ntwidthdim = \wd\syn@ntstorage%
\advance\ntwidthdim by 0.5em \ntwidth = \ntwidthdim%
\divide\ntwidth by \ntdimen%
\ntwidtha = \ntwidth \advance\ntwidtha by 1%
\ntwidthb = \ntwidtha \divide\ntwidthb by 2%
\syn@put{\@picture(\number\ntwidtha,1)(0,0)%
\ifodd\ntwidtha %
\put(\number\ntwidthb .5,0.5){\oval(\number\ntwidth .75,0.75){}}%
\else %
\put(\number\ntwidthb,0.5){\oval(\number\ntwidth .75,0.75){}}%
\fi%
\put(0.125,0.125){\makebox(\number\ntwidth .75,0.75){\box\syn@ntstorage}}%
\put(0,0.5){\vector(1,0){0.125}}%
\put(\number\ntwidth .875,0.5){\syn@horline{0.125}}\endpicture}%
\syn@adx \ntwidtha \syn@adw \ntwidtha \syn@max(\bh,1)}%
%
\def\nt#1{\setbox\syn@ntstorage = \hbox{#1}\ntwidthdim = \wd\syn@ntstorage%
\advance\ntwidthdim by 0.5em \ntwidth = \ntwidthdim%
\divide\ntwidth by \ntdimen %
\ntwidtha = \ntwidth \advance\ntwidtha by 1%
\syn@put{\@picture(\number\ntwidtha,1)(0,0)%
\put(0.125,0.125){\framebox(\number\ntwidth .75,0.75){\box\syn@ntstorage}}%
\put(0,0.5){\vector(1,0){0.125}}%
\put(\number\ntwidth .875,0.5){\syn@horline{0.125}}\endpicture}%
\syn@adx \ntwidtha \syn@adw \ntwidtha \syn@max(\bh,1)}%
%
%    Leere Menge
%
\def\empty{\syn@put{\@picture(1,1)(0,0)\put(0,0.5){\syn@horline{1}}\endpicture}%
\syn@adx 1 \syn@adw 1 \syn@max(\bh,1)}
%
%
%    Schleifen
%
%         Der Trick bei den Schleifen und Alternativen ist die exzessive
%         Nutzung des Block-Nesting von TeX ( '\bgroup .... \egroup', 
%         '\bgroup' in einem Struktur oeffnenden Kommando ('\alt' ),
%         '\egroup' in einem Struktur schliessenden Kommando ('\endalt' ) ).
%         Damit sind alle neu zugewiesenen Zaehler nur lokal im Block 
%         geaendert, der Transfer ueber die Blockgrenze erfolgt mit 
%         '\syn@savex',... und den Zaehlern '\cx',... .
%
%
\def\loopa{\bgroup\syn@put{\syn@unithalfvec}%
\syn@adx 1 \bw=0 \bh = 0}
%
\def\endloopa{\syn@put{\syn@unitline}\syn@adx 1 \syn@savex \syn@adx -1%
\syn@put{\syn@downline{\number\bh}}  \syn@ady \number\bh \syn@adx -\number\bw \syn@adx -1 \syn@adw 1%
\syn@put{\syn@rightline{\number\bw}} \syn@adw 1 \syn@savew%
\syn@put{\syn@upvector{\number\bh}}  \syn@adh 1 \syn@saveh%
\egroup%
\x = \cx \syn@max(\bh,\number\ch) \syn@adw \number\cw}%
%
%  
%      Alternativen
%
%
\def\alt{\bgroup\alth=0\altw=0\altnum=0\altx=0%
\bw=0\bh=0\global\ch=0\global\cw=0%
\syn@put{\syn@unitline}\syn@adx 1\bgroup\bw=0\bh=0%
\global\ch=0\global\cw=0}%
%
\def\o{\syn@savex\syn@savey\syn@saveh\syn@savew\egroup%                           
\advance\altnum by 1%                                                
\edef\otto{\number\cx}%
\expandafter\edef\csname altex\romannumeral\altnum\endcsname{\number\cx}%
\expandafter\edef\csname altey\romannumeral\altnum\endcsname{\number\cy}%
\syn@ady\ch\syn@max(\altw,\number\cw)\advance\alth by\ch\syn@max(\altx,\number\cx)%       
\bgroup%\syn@ady\ch
\syn@adx -1\syn@put{\syn@unithalfline}\syn@put{\syn@upline{\number\ch}}
\syn@adx 1}  
%
\def\endalt{\syn@savex\syn@savey\syn@saveh\syn@savew\egroup%
\advance\altnum by 1%
\edef\otto{\number\cx}%
\expandafter\edef\csname altex\romannumeral\altnum\endcsname{\number\cx}%
\expandafter\edef\csname altey\romannumeral\altnum\endcsname{\number\cy}%
\syn@max(\altw,\number\cw)\advance\alth by\ch\syn@max(\altx,\number\cx)%
%\advance\alth by -1%
\cx=\cy\advance\cx by -\alteyi%
\syn@putat(\number\altx,\number\cy){\syn@upvector{\number\cx}}%
%\advance\alth by 1%
\loop\ifnum\altnum > 0 \cx=\altx%
  \advance\cx by -\csname altex\romannumeral\altnum\endcsname%
  \syn@putat(\csname altex\romannumeral\altnum\endcsname,%
  \csname altey\romannumeral\altnum\endcsname){%
  \@picture(1,1)(0,0)\put(0,0.5){\syn@horline{\number\cx}}\endpicture}%
  \syn@putat(\number\altx,%               
  \csname altey\romannumeral\altnum\endcsname){%                        
  \@picture(1,1)(0,0)\put(0,0.5){\vector(1,0){0.5}}\endpicture}%
  \advance\altnum by -1%
\repeat%
\bw=\altw\syn@adw 2\bh=\alth\syn@savew\syn@saveh\egroup%
\syn@adx\cw\syn@max(\bh,\ch)\syn@adw\cw%             
\syn@put{\@picture(1,1)(0,0)\put(0,0.5){\line(-1,0){0.5}}\endpicture}}%
%
%---------------------------------------------------------------------------
%
% Alternativen mit Nichts
%
\def\emptyalt{\alt\empty\o}%
\def\endemptyalt{\endalt}%
%
%---------------------------------------------------------------------------
%
% Optionale Schleife
%
\def\optloop{\alt\empty\o\loopa}%
\def\endoptloop{\endloopa\endalt}%
%
%
%---------------------------------------------------------------------------
%
% Ueber mehrere Zeilen Verteilte Ketten
%
%  
\def\multiline{\bgroup\alth=0\altw=0\altnum=0\altx=0%
\bw=0\bh=0\global\ch=0\global\cw=0%
\syn@put{\syn@unitline}\syn@adx 1\bgroup\bw=0\bh=0%
\global\ch=0\global\cw=0}%
%
\def\oml{\syn@savex\syn@savey\syn@saveh\syn@savew%
\syn@put{\begin{picture}(1,1)\put(0,0.5){\line(1,0){0.5}}%
\put(0.5,0.5){{\advance\ch by -1\line(0,-1){\number\ch .5}}}\end{picture}}%
\syn@ady\ch\syn@adx -\cw\syn@adx -1
\syn@put{\begin{picture}(1,1)%
\put(1.5,1){\line(1,0){\number\cw}}%
\put(0.5,1){\line(1,0){1}}%
\put(0.5,1){\line(0,-1){0.5}}%
\put(0.5,0.5){\line(1,0){0.5}}%
\end{picture}}%
\egroup%
\syn@ady\ch\syn@max(\altw,\number\cw)%
\advance\alth by\ch\syn@max(\altx,\number\cx)%       
\bgroup}
%
\def\endmultiline{\syn@savex\syn@savey\syn@saveh\syn@savew\egroup%
\syn@max(\altw,\number\cw)\advance\altw by 1%
\advance\alth by\ch\syn@max(\altx,\number\cx)%
\advance\cy by -1%
\syn@putat(\number\cx,\number\cy .5){\advance\altx by 1% 
%                                            \altx hier nur lokal geaendert !
\advance\altx by -\cx\line(1,0){\number\altx}}%
{\advance\altx by 1\syn@putat(\number\altx,\number\cy .5){\advance\alth by -\ch%
\line(0,1){\number\alth}}}%
\bw=\altw\syn@adw 1\bh=\alth\syn@savew\syn@saveh\egroup%
\syn@adx\cw\syn@max(\bh,\ch)\syn@adw\cw%             
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
