next up previous contents
Next: Datensicherheit Up: L3 Benutzerhandbuch Previous: Textverarbeitung

ELAN

ELAN ist eine Programmiersprache aus der ALGOL-Familie. Ursprüglich als Schulsprache entworfen, hat ELAN Stärken in Hinsicht auf Lesbarkeit, Sicherheit und Ausdrucksmöglichkeit. Durch Anforderungen, die im Laufe der L3 Entwicklung erwuchsen, ist jedoch die 'reine Lehre' zugunsten wichtiger Leistungen an manchen Stellen aufgeweicht worden.

Elemente der Sprache

Lexikalische Elemente einer Programmiersprache sind die Elemente, in denen ein Programm notiert wird.

ELAN besteht aus folgenden Elementen:

Schlüsselwörter

Schlüsselwörter besitzen in ELAN eine festgelegte Bedeutung. Sie werden in Großbuchstaben geschrieben und dürfen keine Leerzeichen enthalten.

Beispiele:

VAR, CONST,
INT, REAL, BOOL, TEXT,
IF THEN ELSE ENDIF

Bezeichner

Bezeichner werden benutzt, um Objekte (zum Beispiel Variablen oder Prozeduren) in einem Programmtext zu benennen und zu identifizieren. Sie formulieren Bezeichner in ELAN folgendermaßen :

Korrekte Bezeichner:

das ist ein langer name
x koordinate
nr 1

Falsche Bezeichner:

x*1
1 exemplar
Nr 1

Sonderzeichen

Sonderzeichen sind Zeichen, die weder Klein- oder Großbuchstaben, noch Ziffern sind. Sonderzeichen dienen in ELAN vorrangig als Trennzeichen oder als Operatoren.

ELAN kennt folgende Trennzeichen:

Erlaubte Sonderzeichen sind:

! $ % & ' * + - /
< = > ? @   `    
ä ü ö Ä Ü Ö ß

Vordefinierte Kombinationen von Sonderzeichen:

:: := <= >= <> **

Kommentare

Kommentare dienen ausschließlich der Dokumentation eines Programms. Sie werden vom Compiler überlesen und haben keinen Einfluß auf die Ausführung eines Programms. Kommentare können an jeder beliebigen Stelle eines Programms, außer in Schlüsselworten und Namen, eingefügt werden. Ein Kommentar darf mehrere Zeilen lang sein. Kommentare werden durch Kommentarklammern umschlossen:

(* *) oder { } oder # #.

Kommentare dürfen verschachtelt sein und alle beliebigen Zeichen enthalten.

Datentypen

Einfache Datentypen: BOOL, INT, REAL, TEXT

Für Datenobjekte dieser denotierbaren Datentypen gibt es eine eindeutig vorgeschriebene Werterepräsentation:

(*  INT *)    1   123   0x123fff     0b 1111 0000 1100 1010 
(* REAL *)    3.14     6.123456 
(* BOOL *)    TRUE   FALSE 
(* TEXT *)    "das ist ein Text"   "Leerer TEXT: " ""

Alle Datenobjekte müssen deklariert werden. Eine Initialisierung ist optional. Für Objekte, auf die Schreib- und Leserecht erteilt wird, muß das Zugriffsattribut VAR angegeben werden. Das Zugriffsattribut CONST für Objekte, auf die nur Leserecht erteilt wird, ist optional.

INT VAR i ;
REAL CONST pi := 3.1412 ;
REAL zehn :: 10.0 ;
BOOL VAR option := FALSE ;
TEXT VAR name := "Pulvermüller" ;
TEXT nix := "" ;

Zusammengesetzte Datentypen

Reihung:
feste Anzahl von Datenobjekten gleichen Typs ROW 10 INT VAR zahlen Der Zugriff erfolgt durch Subskription zahlen [3] := 42 ;

Struktur:
feste Anzahl von Datenobjekten unterschiedlichen Typs STRUCT (TEXT name, vorname, INT gehalt) VAR personal Zugriff durch Selektion personal.name := "Pulvermüller" ;

Anweisungen

Jede Anweisung liefert einen Wert, der auch »void« (= nichts) sein kann. Setzt sich eine Anweisung aus mehreren einzelnen zusammen, so liefert sie den Wert der letzten ausgeführten Anweisung.

Operatoren

Operatoren werden in ELAN durch ein oder zwei Sonderzeichen oder als Schlüsselwort (in Großbuchstaben) dargestellt.

Als Operanden (Datenobjekte, auf die ein Operator wirken soll) dürfen verwendet werden :

In der Operatorvereinbarung wird festgelegt, welchen Typ die Operanden und das Resultat der Operation haben sollen.

Man unterscheidet zwei Operator-Arten :

Monadische Operatoren:
Monadische Operatoren haben nur einen Operanden, der rechts vom Operatorzeichen stehen muß:
- a
NOT x

Der Operator - liefert den Wert von a mit umgekehrtem Vorzeichen. Dabei muß a vom Datentyp INT oder REAL sein.

Der Operator NOT realisiert die logische Negation. Dabei muß x vom Datentyp BOOL sein.

Dyadische Operatoren:
Dyadische Operatoren besitzen zwei Operanden. Das Operatorzeichen steht zwischen den beiden Operanden.

Beispiele: a, b sind beide vom Datentyp REAL bzw. INT (bei DIV nur INT) x, y sind vom Datentyp BOOL.

tabular1927

Priorität von Operatoren

Es ist erlaubt, einen Ausdruck wieder als Operanden zu verwenden. Praktisch bedeutet dies, daß Sie mehrere Operatoren und Datenobjekte zusammen in einen Ausdruck schreiben dürfen.

Beispiele:

a + 3 - b * c
- a * b
Die Reihenfolge der Auswertung entspricht den folgenden Prioritäten, wobei 9 die höchste Priorität hat, d.h. zuerst ausgeführt wird:

tabular1940

Operatoren mit gleicher Priorität werden von links beginnend ausgeführt.

Durch entsprechend gesetzte Klammern können Sie die Reihenfolge ändern.

Beispiel:

(a + b) * (a + b)

In diesem Beispiel wird zuerst a + b ausgewertet und dann die Multiplikation durchgeführt. Es dürfen auch geschachtelte Klammerungen verwendet werden. Dabei gilt: Die innerste Klammer wird immer zuerst ausgewertet. Sie dürfen Klammern auch dort verwenden, wo keine notwendig sind. Überflüssige Klammernpaare werden überlesen.

Beispiel:

((a - b)) * 3 * ((c + d) * (c - d))

Achtung: Ausdrücke, wie z. B. (a-b) oder (d**c) und auch (a) haben immer das Zugriffsrecht CONST. Einem Ausdruck kann also kein Wert zugewiesen werden.

Beispiel für die Abarbeitungsfolge einer Rechnung:

-2 + 3 * 2 ** 3     a) -2 
                    b) 2 ** 3 
                    c) 3 * (2 ** 3) 
                    d) (-2) + (3 * (2 ** 3))

Zuweisungen

Eine Zuweisung ist eine spezielle Operation, die einen Wert in eine Variable kopiert:

Variable := Wert

Diese Operation (Zuweisung) hat immer die geringste Priorität. Sie wird als letzte Operation einer Anweisung ausgeführt. Die Zuweisung wird verwendet, um einer Variablen einen neuen Wert zuzuweisen. Der Operator := liefert keinen Wert, sondern weist einem VAR-Datenobjekt den Wert des rechts vom Operator stehenden Operanden zu:

a := b;

Hier wird der Wert von b der Variablen a zugewiesen. Der vorher vorhandene Wert von a geht dabei verloren. Der Wert wird überschrieben.

Als rechter Operand des :=-Operators darf auch ein Ausdruck stehen:

a := b + c;

In diesem Beispiel wird das Resultat von b + c der Variablen a zugewiesen. Beachten Sie dabei die Prioritäten der Operatoren + (Priorität 6) und := (Priorität 1): die Addition wird vor der Zuweisung ausgeführt.

Es kann vorkommen, daß ein Objekt auf der linken und rechten Seite des Zuweisungsoperators erscheint, z. B. dann, wenn ein Wert erhöht werden soll.

a := a + 1;

Hier wird zunächst der alte (aktuelle) Wert von a genommen und um 1 erhöht. Dann wird der neue Wert der Variablen a zugewiesen.

Kontrollstrukturen

Sequenz
; trennt Anweisungen voreinander. Das Semikolon hat also die Bedeutung 'es folgt eine Anweisung'.

Abfrage
IF ... THEN ... END IF
IF ... THEN ... ELSE .... END IF

END IF kann als FI abgekürzt werden.

Abfragekette

IF ... THEN ...
ELSE IF ... THEN ... ELSE .... END IF

Auswahl

SELECT ... OF 
   CASE 1, 4: .... 
   CASE 5 :   .... 
   CASE 12 :  .... 
   OTHERWISE  ....
END SELECT

Wiederholung
REP ... END REP

WHILE ... REP ... END REP

REP ... UNTIL ... END REP

FOR intvar FROM a UPTO (*DOWNTO*) b REP ... END REP

Auch die Kombination ist zulässig. END REP kann als PER abgekürzt werden. Die politischere Äußerung END REP sollte gerade derzeit jedoch bevorzugt werden.

Refinements
zum Top-Down Problemlösen
  gesamtlösung: 
       teil a; 
       teil b; 
       teil c. 
 
       teil a: 
          teil a1; 
          teil a2. 
       teil b: 
          teil b1; 
          ..

Terminator
LEAVE beendet benannte Algorithmen (Prozeduren, Operatoren, Refinements).
INT OP ** (INT CONST basis, exp): 
   . 
   . 
   IF basis <> 0 AND exp = 0 
      THEN LEAVE ** WITH 1 
   END IF 
   . 
   . 
END OP **

Prozeduren
müssen parallel deklariert werden. Es ist also nicht zulässig, Prozeduren in Prozeduren zu deklarieren. Bei Parametern mit Schreibrecht muß das Zugriffsattribut VAR angegeben werden. Parameter werden durch Kommata getrennt.

Prozeduren und auch Operatoren sind prinzipiell generisch, d.h. Prozeduren dürfen gleiche Namen besitzen, wenn sie durch Anzahl und/oder Typ der Parameter unterscheidbar sind.

PROC prozedur (INT VAR par1, TEXT par2, par3):
PROC prozedur (TEXT VAR par 1, par2, par3):

Eine Prozedur kann Werte beliebigen Typs liefern.

INT PROC prozedur (TEXT par1):
STRUCT (TEXT name, vorname, INT gehalt) PROC liefere person:

Bei Werten liefernden Prozeduren ist zu beachten:

Man kann Prozeduren als Parameter übergeben, die (ggf. leere) Parameterliste muß angegeben werden.

PROC begin (TEXT name, PROC () startproc, TASK VAR t):

Auch monadische und dyadische Operatoren können selbst definiert werden. Der Operatortyp wird nur bei wertliefernden Operatoren angegeben.

Als Operatornamen sind erlaubt:

Beispiel für die Vereinbarung eines monadischen Operators:
INT OP SIGN (REAL CONST argument): 
  IF argument < 0.0 THEN  -1 
                    ELIF  argument = 0.0 
                      THEN  0 
                      ELSE  1 
  FI 
END OP SIGN

Pakete

Voneinander abgegrenzte Programmteile (»Moduln«) heißen in ELAN Pakete (PACKET). Sie bestehen aus einer Zusammenfassung von

Alle zusammen bilden den Paketrumpf. Elemente eines Pakets (Prozeduren, Operatoren, Datentypen) können außerhalb des Pakets nur dann benutzt werden, wenn sie in der Schnittstelle des Pakets, die auch interface genannt wird, aufgeführt werden. Die Elemente eines Pakets können von außen nur dann angesprochen werden, wenn sie über die Schnittstelle nach außen gereicht werden. Sie können Pakete separat übersetzen. Damit ist der Zusammenbau eines umfangreichen Programms aus mehreren Paketen möglich.

Der formale Aufbau eines Pakets sieht folgendermaßen aus:

PACKET paketname DEFINES schnittstelle : 
    paketrumpf 
END PACKET paketname

Schnittstelle ist die Liste der herausgereichten Objekte. In ihr werden Prozeduren und Operatoren nur mit ihrem Namen, durch Kommata getrennt, angegeben. Weiterhin können Datentypen und mit CONST vereinbarte Datenobjekte in der Schnittstelle aufgeführt werden. VAR-Datenobjekte können nicht aufgeführt werden, da diese sonst über Paket-Grenzen hinweg verändert werden könnten.

Pakete werden zu folgenden Zwecken eingesetzt:

Beispiel für eine Spracherweiterung:
         PACKET vertausche DEFINES swap: 
           PROC swap (INT VAR a, b): 
             INT CONST x :: a; 
                       b := a; 
                       a := x 
           END PROC swap 
         END PACKET vertausche

Das Beispiel-PACKET vertausche ist ein Paket, das eine Tausch-Prozedur für INT-Datenobjekte bereitstellt. Diese Prozedur heißt swap. Das Paket kann übersetzt und dem ELAN-Compiler bekannt gemacht werden. Dieser Vorgang wird Insertieren genannt. Ist das geschehen, kann man swap wie alle anderen Prozeduren (zum Beispiel put, get) in einem Programm verwenden. Der Quellcode kann gelöscht werden. Tatsächlich werden die meisten Prozeduren und Operatoren (aber auch einige Datentypen), die in ELAN zur Verfügung stehen, nicht durch den ELAN-Compiler realisiert, sondern durch solche PACKETs.

Schutz vor fehlerhaftem Zugriff auf Datenobjekte

Beispiel:

PACKET stack handling DEFINES push,pop,init stack: 
  LET max = 1000; 
  ROW max INT VAR stack; 
  INT VAR stack pointer; 

  PROC init stack: 
    stack pointer := 0 
  END PROC init stack; 

  PROC push (INT CONST dazu wert): 
    stack pointer INCR 1; 
    IF stack pointer > max 
      THEN errorstop ("stack overflow") 
      ELSE stack [stack pointer] := dazu wert 
    END IF 
  END PROC push; 
 
  PROC pop (INT VAR von wert): 
    IF stack pointer = 0 
      THEN errorstop ("stack empty") 
      ELSE von wert := stack [stack pointer]; 
           stack pointer DECR 1 
    END IF 
  END PROC pop 
 
END PACKET stack handling;

Dieses PACKET realisiert einen Stack. Den Stack können Sie über die Prozeduren initstack, push und pop benutzen.

Beispiel:

init stack; 
werte auf stack bringen; 
werte vom stack holen. 
 
werte auf stack bringen: 
  INT VAR anzahl :: 0, wert; 
  REP 
    get (wert); 
    push (wert); 
    anzahl INCR 1 
    UNTIL ende kriterium 
  END REP. 
 
werte vom stack holen: 
  INT VAR i; 
  FOR i FROM 1 UPTO anzahl REP 
                             pop (wert); 
                             put (wert) 
                           END REP.

Die Datenobjekte stack und stack pointer haben nur innerhalb des PACKETs stack handling Gültigkeit. Anweisungen wie

put (stack [3]);
stack [27] := 5

außerhalb des Paketes stack handling sind verboten und werden vom ELAN-Compiler zurückgewiesen. Ein Paket bietet also Schutz vor fehlerhafter Verwendung von Programmen und Datenobjekten. Wichtig ist außerdem: Wenn Sie die Schnittstelle nicht verändern, kann die Realisierung des Stacks ohne weiteres geändert werden. Dabei müssen Sie Benutzerprogramme nicht ändern. Beispielsweise könnten Sie sich entschließen, den Stack nicht durch eine Reihung, sondern durch eine Struktur zu realisieren. Alle Programme, die den Stack benutzen, können in diesem Fall unverändert bleiben.


next up previous contents
Next: Datensicherheit Up: L3 Benutzerhandbuch Previous: Textverarbeitung

Michael Hohmuth
Thu Mar 21 12:00:00 MET 1996