StellSi-Fahrplancompiler		Version 0.19
----------------------------------------------------

1) Einführung

Der StellSi-Fahrplancompiler dient zur Erzeugung von StellSi-Fahrplänen (.stwf-Dateien) aus menschenlesbaren und mit einem normalen Texteditor erzeugten Fahrplanquelldateien (.stwfq und .stwfd). Dabei kann ein Fahrplan für ein ganzes Streckennetz aus nur einer Datei erzeugt werden.

Hierfür wurde eine sehr schlichte, imperative Programmiersprache entwickelt, deren Handhabung und Funktion im folgenden erläutert wird.


2) Aufbau einer Fahrplanquelldatei

Fahrplanquelldateien sind UTF-8-enkodierte Textdateien, die aus einem Header und einer Sequenz von Kommandos bestehen. Der Header definiert die zugrundeliegende Version der Programmiersprache und sieht wie folgt aus:

	StellSi	FplDef 1

Jedes Kommando beginnt mit einer neuen Zeile und besteht aus einem Befehl, gefolgt von Argumenten:

	CMD	[Arg1]	[Arg...]

Optional können auch noch Datenblöcke angehängt sein. Diese sind in geschweifte Klammern { } eingeschlossene, mehrzeilige Datenabschnitte. Diese Datenblöcke beginnen mit dem ersten Token hinter dem letzten Argument.

Kommentare, d.h. vom Compiler ignorierte Anmerkungen, können mit // eingeleitet werden und erstrecken sich über den Rest der Codezeile. Alternativ sind mit /* und */ eingeschlossene Abschnitte (auch über Zeilen hinweg) Kommentare.


3) Tokens

Der Programmcode wird aus sog. Tokens gebildet, d.h. Blöcken aus zusammenhängenden Zeichen und Ziffern. Ein neues Token beginnt nach einem Leerzeichen, Tabulator-Zeichen, Zeilenumbruch, Klammer oder Operator. Folgende Operatoren/Sonderzeichen sind derzeit definiert:

	->	<-	+	-	.	,	~	*

Eine Sonderrolle kommt Anführungszeichen zu: In Anführungszeichen eingeschlossener Text wird als ein Token interpretiert. Derartige Abschnitte dürfen sich nicht über mehrere Zeilen erstrecken.


4) Kommandos

Die folgend beschriebenen Kommandos sind derzeit definiert:

4.1) AUT [Autor] [Kommentar]

Fügt einen Autor in den erzeugten Fahrplänen hinzu. [Autor] ist der Name des Autors, [Kommentar]das Kommentarfeld.

4.2) BIB [ID] [Pfad]

Lädt eine StellSi-Bibliothek (.stwb) in den Fahrplan; üblicherweise nötig für Fahrzeugbibliotheken. [ID] ist dabei eine eindeutige Zahl, die die Biblitohek später identifiziert. Als [Pfad] muss ein StellSi-lesbarer Pfad angegeben werden, dieser wird i.d.R. mit "/lib" beginnen.

4.3) FZG [Name] [Bib-ID] [Fzg-ID]

Dieser Befehl ist hilfsweise notwendig, um später einfach Reihungen definieren zu können. Hierbei werden Aliasnamen [Name] für Fahrzeuge angelegt, die über die ID der Bibliothek [Bib-ID] und die innerhalb dieser .stwb-Datei von StellSi vergebenen [Fzg-ID] definiert werden.

4.4) BTR [Kurz] [Lang]

Dieser Befehl legt in der Betriebsstellenliste Aliasnamen [Kurz] für eine Betriebsstelle mit dem angegebenen Langnamen [Lang] an.

4.5) AA [Name] [Pfad] ([Suffix]) {Daten}

Mit diesem Befehl wird eine weitere Außenanlage unter der ID [Name] in die Liste der Außenanlagen eingefügt. [Pfad] beschreibt den Dateipfad zu dieser Außenanlage. Aus der Datei werden auch Betriebsstellen gelesen, die DS100-Abkürzungen aus der .stwa-Datei werden wie ein BTR-Kommando behandelt. Bei einem leeren Pfad wird die Außenanlage als Platzhalter betrachetet. Mit dem [Suffix] können mehreren Außenanlagen im gleichen Verzeichnis in den Ausgabedateien voneinander getrennt werden.

Im Datenblock werden zeilenweise die Fahrtrichtungen definiert. Jede Fahrtrichtung definiert sich wie folgt:

	[Kurzname] ([Beschriftung]) ([Streckenanschluss-IDs...]) (LZ [Lenkziffern...])

Der [Kurzname] ist ein Aliasname für die Fahrtrichtung, die [Beschriftung] wird später in der Zugliste als Fahrtrichtung angezeigt. Dem folgt eine Liste beliebig vieler [Streckenanschluss-IDs]. Dabei handelt es sich um die von StellSi in der .stwa-Datei vergebenen IDs. Die Reihenfolge bestimmt, über welchen Anschluss die Züge bevorzugt angeboten werden. Diese können weggelassen werden, sofern in der Außenanlage eine Fahrtrichtung definiert ist, deren Name der [Beschriftung] entspricht. Auch die [Beschriftung] kann weggelassen werden, sofern in der Außenanlage ein passender [Kurzname] für die Fahrtrichtung vergeben wurde.

Folgt auf die [Streckenanschluss-IDs] das Schlüsselwort "LZ", so folgt anschließend noch eine Auflistung aller Lenkziffern, die in dieser Fahrtrichtung verwendet werden. Hieraus ermittelt der Compiler für die Züge automatisch eine passende Lenkziffer.

4.6) RHG [Name] [Fzg-IDs...]

Definiert eine Reihung mit dem angegebenen [Name]n, bestehend aus den angegebenen Fahrzeugen (siehe FZG-Kommando). Durch den vorangestellten Operator ~ kann ein Fahrzeug gedreht eingefügt werden.

4.7a) VT * [Von] [Bis]

Schränkt die Gültigkeit aller impliziten Verkehrstage ein auf die angegebene Spanne. Die Argumente sind in folgendem Format anzugeben: "YYYY-MM-DD"

4.7b) VT [Name] [Tage] [ARG3] [ARG4] [ARG5] [ARG6]

Definiert einen Verkehrstag mit dem angegebenen [Name]n. Die Züge verkehren an den angegebenen [Tage]n. Dabei handelt es sich um eine Folge von Ziffern zwischen 1 und 7, die den jeweiligen Wochentag (Montag bis Sonntag) beschreiben. [ARG3] bis [ARG6] sind nicht näher spezifiziert und mit - zu füllen.

4.8) ZL [Name] {Daten}

Erzeugt einen Zuglauf mit dem angegebenen [Name]n. Im Datenblock wird der Fahrplan definiert. Jeder Fahrplaneintrag (Einfahrten, Ausfahrten und Halte) nimmt dabei eine Zeile ein, die wie folgt aussieht:
Einfahrt: <- [AA-Name] . [Anschluss-Name] ([Zeit])
Ausfahrt: -> [AA-Name] . [Anschluss-Name] ([Zeit])
Halt: [BTR-Name] . [Signaltyp] [Gleis] [Ankunftzeit] [Abfahrtzeit] [Mindesthaltezeit] ([Aufträge...])
Durchfahrt/Abfahrt: [BTR-Name] . [Signaltyp] [Gleis] - [Abfahrtzeit] ([Aufträge...])
Ankunft: [BTR-Name] . [Signaltyp] [Gleis] [Ankunftzeit] - ([Aufträge...])
Hinweise: $ [Hinweisname] [Argument]

[AA-Name] bezieht sich auf das Kommando AA, [Anschluss-Name] auf dessen Datenblock. [BTR-Name] bezieht sich auf das Kommando BTR. Der [Signaltyp] kann H (H-Tafel), E (Einfahrsignal), A (Ausfahrsignal), Z (Zwischensignal), B (Blocksignal) oder AB (Blocksignal an Abzweigstelle) sein.

Wird bei einer Ein- oder Ausfahrt der Parameter [Zeit] weggelassen, wird eine geeignete Zeit automatisch ermittelt. Voraussetzung ist, dass ein Halt oder eine Durchfahrt vor bzw. nach dem Eintrag angegeben wurde.

Zu den Einträgen können Aufträge angegeben werden. Folgende Aufträge sind möglich:
- WENDE: Zug wendet an der Betriebsstelle.
- FOLGE: Zug wechselt auf die Folgeleistung. Es ist eine Zugnummernregel der Form "ZN (+- ) [Wert]", oder "ZN *" anzugeben. Letzteres nutzt die automatische Ermittlung von Folgeleistungen.
- GATTUNG: Zug wechselt auf die angegebene Gattung.
- LINIE: Zug wechselt auf die angegebene Gattung und Liniennummer.
- LZ: Zug wechselt seine Lenkziffer. Es ist die neue Lenkziffer anzugeben. Ist zwischen LZ und Lenkziffer ein *, handelt es sich nur um einen Lenkziffernhinweis für die automatische Lenkziffernbestimmung.

Mit Hinweisen können Zusatzangaben gesetzt werden, damit die richtigen Fahrwege genutzt werden. Er bezieht sich jeweils auf den vorherigen und alle nachfolgenden Einträge. Derzeit ist nur der Hinweis "VzG" unterstützt; als Argument wird eine Streckennummer erwartet.

4.9) ZLS [BTR-Name 1] ([VzG-Nummer]) [BTR-Name 2] {Daten}

Erzeugt ein Zuglaufsegment. Wann immer in einem Zuglauf die erste angegebene Betriebsstelle ([BTR-Name 1]) von der Zweiten gefolgt wird, werden die im Datenblock angegebenen Einträge eingefügt. Der Datenblock entspricht dem Kommando ZL, unterstützt derzeit aber nur Ein- und Ausfahrten.

Ist eine VzG-Nummer angegeben, wird das Zuglaufsegment nur auf Züge angewendet, die gemäß Hinweis über die angegebene Strecke verkehren sollen.

4.10) SET [Variable] [Wert]

Setzt die angegebene [Variable] auf den gegebenen [Wert]. Als Wert kommen - je nach Variable, auch komplexe Ausdrücke wie Listen oder Zuglaufspezifikationen in Frage.

Die Variable "Linie" ist dabei ein Alias für die Variable "Gattung" gefolgt von "Liniennummer".

4.11a) Z [Zugnummer] [Startzeit] [Verkehrstag] ([Gattung])

Erzeugt einen Zug mit der angegebenen [Zugnummer] mit dem gegebenen [Verkehrstag] zur gegebenen [Startzeit]. Letztere fungiert als Offset zum aktuellen Zuglauf. Die Angabe einer [Gattung] ist optional. Als weitere Parameter des Zugs werden die Variablen "Gattung" (wenn nicht angegeben), "Liniennummer" (wenn keine Gattung angegeben), "Reihung" und "Zuglauf" zugrundegelegt.

4.11b) Z [Zugnummer] [ZL-Spezifikation] [Verkehrstag] ([Gattung])

Verglichen mit dem vorigen Befehl wird anstelle der Variable "Zuglauf" eine Zuglauf-Spezifikation entgegengenommen.

4.11c) Z [Zugnummer] * [Verkehrstag] ([Gattung]) {Daten}

Verglichen mit dem vorigen Befehl wird anstelle der Variable "Zuglauf" ein eigener, im Datenblock definierter impliziter Zuglauf erzeugt. Das Format des Datenblocks entspricht dem Kommando ZL.

4.12a) TZ (Liste) [Startzeit erster Zug] [Schrittweite Zeit] [Verkehrstag]

Erzeugt mehrere Züge zugleich: Die aufgelisteten Züge werden angelegt. Die [Startzeit erster Zug], jeweils inkrementiert mit [Schrittweite Zeit] wird zugrundegelegt, und für alle Züge der angegebene [Verkehrstag] gesetzt. Wie beim Kommando Z werden dabei die Variablen "Gattung", "Liniennummer", "Reihung" und "Zuglauf" zugrundegelegt.

4.12b) TZ * [Verkehrstag] {Daten}

Erzeugt mehrere Züge zugleich: Der Datenblock enthält jeweils Pärchen aus Zugnummer und Startzeit. Wie beim Kommando Z werden dabei die Variablen "Gattung", "Liniennummer", "Reihung" und "Zuglauf" zugrundegelegt.

4.12c) TZ [Zugnummer Start] [Zugnummer Ende] [Schrittweite Zugnummer] [Startzeit erster Zug] [Schrittweite Zeit] [Verkehrstag] (Veraltet)

Erzeugt mehrere Züge zugleich: Die Züge von [Zugnummer Start] bis [Zugnummer Ende], mit der angegebenen [Schrittweite Zugnummer] werden angelegt. Die [Startzeit erster Zug], jeweils inkrementiert mit [Schrittweite Zeit] wird zugrundegelegt, und für alle Züge der angegebene [Verkehrstag] gesetzt. Wie beim Kommando Z werden dabei die Variablen "Gattung", "Liniennummer", "Reihung" und "Zuglauf" zugrundegelegt.

4.13a) M (Liste) [Modifikationsregel]

Dieser Befehl modifiziert die durch die Liste selektierten Züge anhand der angegebenen [Modifikationsregel]. Die Änderungen wirken nur auf die ausgewählten Züge; andere Züge, die den gleichen Zuglauf nutzen, sind nicht betroffen.

Folgende Modifikationsregeln sind derzeit definiert:

- Setzen des Verkehrstags: VT [Verkehrstag]
- Setzen der Zuggattung: GATTUNG [Gattung]
- Setzen der Reihung: RHG [Reihung]
- Setzen des Zuglaufs: ZL [ZL-Spezifikation]
- Setzen der Linie: LINIE [Gattung] [Linie]
- Subtraktion/Addition von Verkehrstagen: VT (+-) [Verkehrstag] (nicht implementiert)
- Ändern der Regel für die Folgeleistung: FOLGE (+- ) [Wert]
- Löschen eines Fahrplaneintrags: ENTF [BTR-Name] . [Signaltyp], oder LOE <- [AA-Name], oder LOE -> [AA-Name] (nicht implementiert)
- Einfügen eines Fahrplaneintrags: EINFG (nicht implementiert)
- Ändern eines Fahrplaneintrags: EDIT (nicht implementiert)
- Setzen der Aufträge an einem Fahrplaneintrag: AUFTRAG [BTR-Name] . [Signaltyp] [Aufträge...]

4.13b) M (Liste) (Einschränkung) [Modifikationsregel]

Dieser Befehl modifiziert die durch die Liste selektierten Züge unter Beachtung der gegebenen Einschränkung anhand der angegebenen [Modifikationsregel]. Die Änderungen wirken nur auf die ausgewählten Züge; andere Züge, die den gleichen Zuglauf nutzen, sind nicht betroffen.

4.14) OUT [Name] [Pfadregel]

Dieser Befehl dient abschließend der Erzeugung von .stwf-Dateien aus den zuvor angelegten Fahrplandaten. Als Fahrplanname wird der gegebene [Name] gesetzt. Es wird pro Außenanlage (siehe Kommando AA) eine .stwf-Datei generiert. Zur Erzeugung der Dateien wird die [Pfadregel] genutzt, ein String, der den Ausgabedateinamen angibt. Damit hier tatsächlich mehrere Dateien erzeugt werden können, sind zwei Sonder-Makros definiert:
$(ThisStwDir): Nutzt das Verzeichnis der jeweiligen Außenanlage.
$(ThisStwPath): Nutzt Verzeichnis und Dateiname der jeweiligen Außenanlage.
$(AASuffix): Fügt Außenanlagen-spezifischen Suffix ein.

4.15) DAT [Datei]

Mit diesem Befehl kann eine weitere Fahrplanquelldatei geladen und ausgeführt werden. Diese Dateien müssen in sich gültige Quelldateien sein und werden an der Stelle des DAT-Befehls rekursiv ausgeführt. Hierdurch können Fahrpläne auf mehrere Quelldateien verteilt oder streckenspezifische Daten von Fahrplandaten getrennt werden. Empfohlene Dateiendung ist .stwfd.

4.16) BIF [Name] {Daten}

Für das mitgelieferte Bildfahrplan-Programm definiert dieses Kommando eine Strecke, d.h. Ansicht. Der Datenblock enthält zeilenweise die Daten, die abwechselnd folgenden Formaten entsprechen:
Betriebsstelle: [Typ] [BTR-Name] [Streckenkilometer] (| [Streckenkilometer])
Strecke: [Anzahl Gleise] ($ (*) [VzG-Nummer])

Die zweite [Streckenkilometer]-Angabe kann für Kilometrierungswechsel genutzt werden.

Vor und nach Betriebsstellen kann folgendes eingefügt werden:
Streckenfilter: -> [AA-Name] . [Anschluss-Name]
                <- [AA-Name] . [Anschluss-Name]
Bahnhofsfilter: * [BTR-Name]

Der Betriebsstellen-[Typ] kann Bf, Abzw, Uest, Hp oder Bk sein. Der Streckenkilometer ist als Fließkommazahl anzugeben. Der Streckenfilter wirkt jeweils im Zulauf auf die zugehörige Betriebsstelle. Mehrere Filter können mit dem Operator | getrennt werden.

Zur Strecke kann eine VzG-Nummer angegeben werden. Ist diese mit einem * gekennzeichnet, werden nur Züge gezeichnet, die explizit diese Strecke befahren.

5) Namen

Wann immer IDs oder Namen vergeben werden, werden die in nach Objekttypen separierten Listen geführt. Das bedeutet, es kann z.B. Außenanlagen (Kommando AA) und Betriebsstellen (BTR) unter demselben Namen geben. Innerhalb der jeweilgen Liste müssen die Namen allerdings eindeutig sein, eine Neudefinition überschreibt die vorangehende.


6) Verkehrstage

Verkehrstage können explizit und implizit definiert werden. Die explizite Definition erfolgt über das Kommando VT. Es lassen sich jedoch überall, wo ein Verkehrstag anzugeben ist, auch implizite Definitionen nutzen. Hierzu sind die Operatoren '+', ',' und '-' implementiert, mit denen Verkehrstage zusammengeführt ('+' und ',') und Bereiche gebildet ('-') werden können. Diese Ausdrücke sind in runde Klammern zu setzen. Zusätzlich sind die Verkehrstage Mo, Di, Mi, Do, Fr, Sa und So definiert. Der implizite Verkehrstag (Mo-Mi,Fr) lässt einen Zug Montags, Dienstags, Mittwochs und Freitags fahren. Aus Komfortgründen ist zudem "tgl" für tägliche Züge vordefiniert.


7) Listen

Listen werden mit runden Klammern umschlossen. Im Inneren können entweder die Listenelemente direkt aufgelistet werden, oder eine Funktion zur Erzeugung der Elemente genutzt werden. Als Funktionen definiert sind:

LISTE [Elemente...]: Auflistung aller Elemente, mit Leerzeichen getrennt
SCHLEIFE [Start] [Ende] [Schrittweite]: Generiert die Zahlen von [Start] bis [Ende] mit der angegebenen [Schrittweite].


8) Einschränkungen

Einschränkungen werden mit runden Klammern umschlossen. Derzeit sind nur Einschränkungen folgenden Typs zulässig: (WENN VT [Verkehrstag])


9) Zuglauf-Spezifikationen

Zuglauf-Spezifikationen werden mit runden Klammern umschlossen. Im Inneren werden sie mit "ZL" eingeleitet, gefolgt von abwechselnd einer Zeitangabe und dem Namen eines Zuglaufs. Die Zeitangabe ist optional - fehlt sie, wird Null angenommen. Die erste Zeitangabe definiert die Basiszeit, die folgenden Zeiten definieren die Übergangszeit zwischen den Zugläufen. Beginnt der nachfolgende Zuglauf mit derselben Betriebsstellenspezifikation, mit der der vorherige endet, entspricht die Übergangszeit der planmäßigen Haltezeit. Etwaige Aufträge werden vom vorherigen Zuglauf übernommen. Sind die Betriebsstellen verschieden, so entspricht die Übergangszeit der Fahrtzeit. Das Gleis wird vom vorherigen Zuglauf übernommen, außer, es ist mit "-" angegeben. Die Mindesthaltezeit wird vom vorherigen Zuglauf übernommen, außer, es wurde keine angegeben.


10) Folgeleistungen

Die automatische Ermittlung von Folgeleistungen (Auftrag "FOLGE ZN *") sucht für jeden Zug mit dieser Regel an jedem Wochentag die zeitlich nächste Fahrplanleistung, die auf demselben Gleis derselben Betriebsstelle beginnt. Das Suchfenster erstreckt sich dabei auf den aktuellen und folgenden Wochentag. Wird keine Folgeleistung gefunden, wird eine Warnung generiert.
