
genau - Umwandlung einer Automatenbeschreibung in eine C-Funktion
	ggf. mit Zustandsreduktion

Optionen:
=========

genau
genau <filename>

Wird keine Datei angegeben, wird die Standardeingabe verarbeitet.


Format der Eingabedatei
=======================

Die Eingabedatei gliedert sich in mehrere Abschnitte für
Optionen (options), Zustands-Definitionen (states),
Eingabe-Definitionen (inputs), Ausgabe-Definitionen (outputs)
und Übergangs-Regeln (rules).


Options-Abschnitt
-----------------

Der Options-Abschnitt wird durch eine Zeile eingeleitet, in der nur

[options]

enthalten ist.
Die einzelnen Optionen haben jeweils das Format

<name> = <wert>

wobei sich die Namen und Werte ggf. aus mehreren Teilstrings zusammensetzen
können.
Folgende Einträge sind möglich:

c file
  gibt an, in welche Datei die C-Funktion geschrieben werden soll.

h file
  gibt an, in welche Header-Datei die Konstanten-Definitionen
  für Ein- u. Ausgänge und Zusände geschrieben werden soll.

prototypes
  gibt an, ob Protoypen für den C-Compiler erzeugt werden sollen
  (yes, on, 1, true) oder die Prototypen mit dklibs-Konstanten
  geschrieben werden sollen (dk) oder K&R-Deklarationen erzeugt
  werden sollen (no, off, 0, false).

transition function
  legt den Namen für die Zustands-Übergangs-Funktion fest.

reset function
  legt den Namen für die Reset-Funktion fest.

reduced file
  legt den Namen für die Datei fest, in der eine reduzierte
  Automatenbeschreibung abgelegt wird.

reduce
  legt fest, daß eine Zustandsreduktion erfolgen soll.

include protect
  legt einen Namen für die Konstante fest, die in der Header-Datei
  genutzt wird, um mehrfacher Inclusion vorzubeugen.

c define
  legt einen Namen für die Präprozessor-Konstante fest,
  die für die intern/extern-Unterscheidung genutzt wird.

test file
  generiert ein C-Programm, daß alle Kombinationen von
  Zuständen und Eingaben testet.

doxygen comments
  legt fest, ob Kommentare für doxygen mit in die Ausgabe geschrieben werden.

suqeezed
  legt fest, ob "schmale" Ausgabe (weniger Leerzeichen und Leerzeilen)
  oder normale Ausgabe erzeugt wird.

Der States-Abschnitt
--------------------

Der Abschnitt wird durch

[states]

eingeleitet. Jede Zeile enthaält den Namen für einen
möglichen Zustand, optional gefolgt von einer int-Kennnummer.


Der Inputs-Abschnitt
--------------------

Der Abschnitt wird durch

[inputs]

eingeleitet. Jede Zeile enthält den Namen für eine
mögliche Eingabe, optional gefolgt von einer int-Kennnummer.


Der Outputs-Abschnitt
---------------------

Der Abschnitt wird durch

[outputs]

eingeleitet. Jede Zeile entählt den Namen für eine
mögliche Ausgabe, optional gefolgt von einer int-Kennnummer.


Der Rules-Abschnitt
-------------------

Der Abschnitt wird durch

[rules]

eingeleitet. Jede Zeile enthält eine Übergangsregel,
bestehend aus
- aktuellem Zustand
- Eingabe, die verarbeitet werden soll
- Folgezustand, in den der Automat bei der Bearbeitung übergeht
- Ausgabe.
Jede dieser Komponenten wird über ihren in den vorherigen
Abschnitten festgelegten Namen angesprochen.
Für den aktuellen Zustand und die Eingabe kann das
Wildcard-Symbol "*" verwendet werden, dieses sorgt darür, daß
die Regel für alle Zustände/Eingaben Anwendung findet.
Die Verwendung von Wildcard-Regeln kann dazu führen, daß für
bestimmte Zustand-Eingabe-Kombinationen mehrere Regeln vorhanden
sind. In diesem Fall werden die Prioritäten wie folgt gesetzt:
- Ist eine genau zutreffende Regel (ohne Wildcard-Symbole) vorhanden,
  wird diese Regel genutzt.
- Andernfalls wird nach Regeln mit einem Wildcard-Symbol gesucht, sind
  hiervon mehrere vorhanden, wird die _erste_ (in der Datei am weitesten
  oben stehende) Regel verwendet.
- Wurde keine zutreffende Regel ohne Wildcard-Symbol bzw. mit einem
  Wildcard-Symbol gefunden, wird nach einer allgemeinen Regel
  (Zustand und Eingabe jeweils durch Wildcard-Symbol ausgedrückt)
  gesucht.
- Wurde gar keine passende Regel gefunden, kommt die implizite Regel
  zum Tragen. Diese besagt, daß der Automat in seinem derzeitigen
  Zustand verbleibt und diejenige Ausgabe tätigt, die im
  Outputs-Abschnitt als erste definiert wurde.


Beispiel-Datei
==============

Beschrieben wird ein Automat, der für einen String ermittelt,
ob er einem Identifier entspricht, wie er in der Programmiersprache
C verwendet wird. D.h. der String setzt sich aus Buchstaben,
Zahlen und Unterstrichen zusammen, darf aber nur mit Buchstaben
oder Unterstrich beginnen.

Die Automatenfunktion wird aus einer Check-Funktion heraus aufgerufen:

  #include "testid.h"

  int check_string(char *str)
  {
    int state_machine;
    int input;
    int output;
    char *ptr;
    reset_decide(&state_machine);
    ptr = str;
    while(*ptr) {
      input = I_ANY;
      if(((*ptr) >= 'a') && ((*ptr) <= 'z')) input = I_CHARACTER;
      if(((*ptr) >= 'A') && ((*ptr) <= 'Z')) input = I_CHARACTER;
      if(((*ptr) >= '1') && ((*ptr) <= '9')) input = I_DIGIT;
      if((*ptr) == '0') input = I_DIGIT;
      if((*ptr) == '_') input = I_UNDERSCORE;
      (void)decide(&state_machine,input);
      ptr++;
    }
    output = decide(&state_machine,I_FINISHED);
    return output;
  }

Die zugehörige Automatendatei sieht dann folgendermaßen
aus:

  [options]
    c file = testid.c			# C-Datei
    h file = testid.h			# Header-Datei
    reduced file = testid2.au
    transition function = decide
    reset function = reset_decide
  [states]
    S_START		# Der Start-Zustand, der beim Reset eingestellt wird
    S_OK		# Wir befinden uns innerhalb eine Identifieres
    S_ERROR		# Der String ist kein Identifier
  [inputs]
    I_ANY		# Ein beliebiges Zeichen
    I_UNDERSCORE	# Der Unterstrich
    I_CHARACTER		# Ein Buchstabe
    I_DIGIT		# Eine Zahl
    I_FINISHED		# Kennzeichen, dass der String komplett verarbeitet ist
  [outputs]
    O_OK		# bisheriger String ist ein Identifier
    O_ERROR		# bisheriger String ist kein Identifier
  [rules]
    *		*		S_ERROR		O_ERROR
    *		I_FINISHED	S_START		O_ERROR
    S_START	I_UNDERSCORE	S_OK		O_OK
    S_START	I_CHARACTER	S_OK		O_OK
    S_OK	I_UNDERSCORE	S_OK		O_OK
    S_OK	I_CHARACTER	S_OK		O_OK
    S_OK	I_DIGIT		S_OK		O_OK
    S_OK	I_FINISHED	S_START		O_OK

