From 724cc003460ec67eda269911da85c9f9e40aa6cf Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Fri, 30 Sep 2016 16:57:23 +0200 Subject: Add extracted sources from floppy disk images Some files have no textual representation (yet) and were added as raw dataspaces. --- doc/programming/programmierhandbuch.2a | 1845 ++++++++++++++++++++++++++++++++ 1 file changed, 1845 insertions(+) create mode 100644 doc/programming/programmierhandbuch.2a (limited to 'doc/programming/programmierhandbuch.2a') diff --git a/doc/programming/programmierhandbuch.2a b/doc/programming/programmierhandbuch.2a new file mode 100644 index 0000000..a204091 --- /dev/null +++ b/doc/programming/programmierhandbuch.2a @@ -0,0 +1,1845 @@ +#headandbottom("1","EUMEL-Benutzerhandbuch","TEIL 2 : ELAN","2")# +#pagenr("%",1)##setcount(1)##block##pageblock# +#headeven# +#center#EUMEL-Benutzerhandbuch +#center#____________________________________________________________ + +#end# +#headodd# +#center#TEIL 2 : ELAN +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +2 - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right# 2 - % +#end# + +TEIL 2: ELAN + +2.1 Besondere Eigenschaften von ELAN + +Kerneigenschaften von ELAN sind das #ib#Paketkonzept#ie# und die Methode des +#ib#Refinements#ie#. + +#on("b")#Paketkonzept:#off("b")# +ELAN bietet die Möglichkeit, neue Datentypen sowie Prozeduren und Operatoren auf +diesen Datentypen zu definieren. Eine solche Definition von Algorithmen und Daten­ +typen kann zu einer logischen Einheit, einem Paket, zusammengefaßt werden. Pakete +können in einer Task vorübersetzt werden und erweitern damit automatisch den +Sprachumfang. + +#on("b")#Methode des Refinements:#off("b")# +Die Methode des Refinements erlaubt das schrittweise Herleiten von Problemlösungen +von der jeweils geeigneten Terminologie herunter zu den von ELAN standardmäßig +angebotenen Sprachelementen. Durch diese Vorgehensweise wird in äußerst starkem +Maße ein strukturierter Programmentwurf gemäß dem Top-Down-Prinzip gefördert. + +Die Programmiersprache ELAN wird im EUMEL-System zu folgenden Zwecken +eingesetzt: + +- Systemimplementationssprache +- Kommandosprache +- Anwenderprogrammiersprache +#page# + +2.2 Lexikalische Elemente + +Unter lexikalischen Elementen einer Programmiersprache versteht man die Elemente, +in denen ein Programm notiert wird. + +In ELAN sind dies: + +- Schlüsselwörter +- Bezeichner +- Sonderzeichen +- Kommentare + + + + +2.2.1 Schlüsselwörter + +Einige Wörter haben in ELAN eine feste Bedeutung und können somit nicht frei +gewählt werden. Solche Wörter werden im EUMEL-System in Großbuchstaben +geschrieben, Leerzeichen dürfen nicht enthalten sein. + +Beispiele: + + +VAR +INT +WHILE + + +Wie später beschrieben wird, gibt es in ELAN auch die Möglichkeit, neue Schlüssel­ +wörter einzuführen. + + +#page# + +2.2.2 Bezeichner + +Bezeichner oder Namen werden benutzt, um Objekte in einem Programmtext zu +benennen und zu identifizieren (z.B: Variablennamen, Prozedurnamen). + +Namen werden in ELAN folgendermaßen formuliert: + +Das erste Zeichen eines Namens muß immer ein Kleinbuchstabe sein. Danach dürfen +bis zu 254 Kleinbuchstaben, aber auch Ziffern folgen. Zur besseren Lesbarkeit können +Leerzeichen in einem Namen erscheinen, die aber nicht zum Namen zählen. Sonder­ +zeichen sind in Namen nicht erlaubt. + +Beispiele für #on("b")#korrekte#off("b")# Bezeichner: + + +das ist ein langer name +x koordinate +nr 1 + + + +Beispiele für #on("b")#falsche#off("b")# Bezeichner: + + +x*1 +1 exemplar +Nr 1 +#page# + +2.2.3 Sonderzeichen + +Sonderzeichen sind Zeichen, die weder Klein- oder Großbuchstaben, noch Ziffern +sind. Sie werden in ELAN als Trennzeichen oder als Operatoren benutzt. + +In ELAN gibt es folgende Trennungszeichen: + +- das Semikolon (';') trennt Anweisungen +- der Doppelpunkt (':') trennt Definiertes und Definition +- der Punkt ('.') wird als Endezeichen für bestimmte Programmabschnitte, als Dezi­ + malpunkt und als Selektor-Zeichen für Datenstrukturen benutzt +- das Komma (',') trennt Parameter +- Klammernpaare ('(', ')') werden zum Einklammern von Parameterlisten oder Teil­ + ausdrücken benutzt +- mit Anführungszeichen ('"') werden Text-Denoter umrahmt +- eckige Klammernpaare ('[', ']') werden zur Subskription benutzt. + + +Als Operatornamen sind folgende Sonderzeichen erlaubt: + +- ein Sonderzeichen, sofern es nicht als Trennzeichen benutzt wird: + ! $ % & ' * + - / < = > ? § ^ ' ~ +- eine Kombination von zwei Sonderzeichen. Diese Kombination muß jedoch bereits + in ELAN existieren: + := <= >= <> ** + +#page# + +2.2.4 Kommentare + +Kommentare dienen ausschließlich der Dokumentation eines Programms. Sie werden +vom Compiler überlesen und haben somit keinen Einfluß auf die Ausführung eines +Programms. Sie dürfen an beliebigen Stellen eines Programmtextes geschrieben +werden, jedoch nicht innerhalb von Schlüsselwörtern und Namen. Ein Kommentar darf +über mehrere Zeilen gehen. In ELAN sind Kommentare nur in wenigen Fällen notwen­ +dig, da Programme durch andere Mittel gut lesbar geschrieben werden können. + +Ein Kommentar in ELAN wird durch Kommentarklammern eingeschlossen. Es gibt +folgende Formen von Kommentarklammern: + +(* Kommentar *) +{ Kommentar } +\#( Kommentar )# + +Die letzte Version '\#( Kommentar )\#' wird im EUMEL-System nicht +unterstützt; statt dessen gibt es noch folgende Möglichkeit: + +\# Kommentar \# + +Da bei der Kommentarkennzeichnung mit \# für Kommentaranfang und -ende das +gleiche Zeichen benutzt wird, ist eine Schachtelung hier nicht möglich. +#page# + +2.3 Datenobjekte + +Eine Klasse von Objekten mit gleichen Eigenschaften wird in Programmiersprachen +Datentyp genannt. Dabei hat ein Datentyp immer einen Namen, der die Klasse von +Objekten sinnvoll kennzeichnet. Als ein Datenobjekt wird ein Exemplar eines Daten­ +typs (also ein spezielles Objekt einer Klasse) bezeichnet. + +Datentypen sind in ELAN ein zentrales Konzept. Jedes der in einem ELAN- +Programm verwandten Datenobjekte hat einen Datentyp; somit kann man Datentypen +auch als Eigenschaften von Datenobjekten ansehen. Für jeden Datentyp sind nur +spezielle Operationen sinnvoll. Man kann nun Compilern die Aufgabe überlassen zu +überprüfen, ob stets die richtige Operation auf einen Datentyp angewandt wird. + + + +2.3.1 Elementare Datentypen + +Einige Datentypen spielen bei der Programmierung eine besondere Rolle, weil sie +häufig benötigt werden. + +In ELAN sind das die Datentypen für + +- ganze Zahlen (INT) +- reelle Zahlen (REAL) +- Zeichen und Zeichenfolgen (TEXT) +- Wahrheitswerte (BOOL). + +Diese Datentypen sind von der Sprache ELAN vorgegeben und werden elementare +Datentypen genannt. Für effiziente Rechnungen mit elementaren Datentypen gibt es +in den meisten Rechnern spezielle Schaltungen, so daß die Hervorhebung und be­ +sondere Rolle, die sie in Programmiersprachen spielen, gerechtfertigt ist. Zudem hat +man Werte-Darstellungen (Denoter) innerhalb von Programmen für die elementaren +Datentypen vorgesehen. + + + +2.3.1.1 Denoter für elementare Datentypen + +Die Darstellung eines Werts in einem Rechner zur Laufzeit eines Programms wird +Repräsentation genannt. Wenn es eindeutig ist, daß es sich nur um die Repräsenta­ +tion im Rechner handelt, spricht man kurz von Werten. Um mit Objekten elementarer +Datentypen arbeiten zu können, muß es in einem Programm die Möglichkeit geben, +Werte eines Datentyps zu bezeichnen (denotieren). Die Werte-Darstellungen, die in +ELAN Denoter genannt werden, sind für jeden Datentyp unterschiedlich. Wie bereits +erwähnt, haben alle Datenobjekte in ELAN (also auch Denoter) nur einen - vom +Compiler feststellbaren - Datentyp. Aus der Form eines Denoters ist also der Daten­ +typ erkennbar: + + + +INT-Denoter: +Sie bestehen aus einer Aneinanderreihung von Ziffern. + +Beispiele: + + +17 +007 +32767 +0 + + +Führende Nullen spielen bei der Bildung des Wertes keine Rolle (sie werden vom +ELAN-Compiler überlesen). Negative INT-Denoter gibt es nicht. Negative Werte +werden durch eine Aufeinanderfolge des monadischen Operators '-' (siehe 2.4.1.1) +und eines INT- Denoters realisiert. + + +REAL-Denoter: +Hier gibt es zwei Formen: +Die erste besteht aus zwei INT-Denotern, die durch einen Dezimalpunkt getrennt +werden. + +Beispiele: + + +0.314159 +17.28 + + +Der Dezimalpunkt wird wie ein Komma in der deutschen Schreibweise benutzt. Nega­ +tive REAL-Denoter gibt es wiederum nicht. + +Die zweite Form wird als "wissenschaftliche Notation" bezeichnet. Sie findet dann +Verwendung, wenn sehr große Zahlen oder Zahlen, die nahe bei Null liegen, darge­ +stellt werden müssen. + +Beispiele: + + +3.0 e5 +3.0e-5 + + +Der INT-Denoter hinter dem Buchstaben #on("b")#e#off("b")# gibt an, wie viele Stellen der Dezimal­ +punkt nach rechts (positive Werte) bzw. nach links (negative Werte) zu verschieben +ist. Dieser Wert wird Exponent und der Teil vor dem Buchstaben #on("b")#e#off("b")# Mantisse genannt. + + +TEXT-Denoter: +Sie werden in Anführungszeichen eingeschlossen. + +Beispiele: + + +"Das ist ein TEXT-Denoter" +"Jetzt ein TEXT-Denoter ohne ein Zeichen: ein leerer Text" +"" + + +Zu beachten ist, daß das Leerzeichen ebenfalls ein Zeichen ist. Soll ein Anführungs­ +zeichen in einem TEXT erscheinen (also gerade das Zeichen, welches einen Denoter +beendet), so muß es doppelt geschrieben werden. + +Beispiele: + + +"Ein TEXT mit dem ""-Zeichen" +"Ein TEXT-Denoter nur mit dem ""-Zeichen:" +"""" + + +Manchmal sollen Zeichen in einem TEXT-Denoter enthalten sein, die auf dem +Eingabegerät nicht zur Verfügung stehen. In diesem Fall kann der Code-Wert des +Zeichens angegeben werden. + +Beispiel: + + +"da"251"" + + +ist gleichbedeutend mit "daß". Der Code-Wert eines Zeichens ergibt sich aus der +EUMEL-Code-Tabelle (siehe 5.2.4.1), in der jedem Zeichen eine ganze Zahl zuge­ +ordnet ist. + + +BOOL-Denoter: +Es gibt nur zwei BOOL-Denoter: +TRUE für "wahr" und FALSE für "falsch". + + + +2.3.1.2 LET-Konstrukt für Denoter + +Neben der Funktion der Abkürzung von Datentypen (siehe 2.6.3) kann das LET- +Konstrukt auch für die Namensgebung für Denoter verwandt werden. + +Die LET-Vereinbarung sieht folgendermaßen aus: + + +#on("i")##on("b")#LET#off("i")##off("b")# Name #on("i")##on("b")#=#off("i")##off("b")# Denoter + + +Mehrere Namensgebungen können durch Komma getrennt werden. + + +____________________________________________________________________________ + .......................... Beispiele: ......................... + LET anzahl = 27; + LET pi = 3.14159, + blank = " "; +____________________________________________________________________________ + + +Der Einsatz von LET-Namen für Denoter hat zwei Vorteile: + +- feste Werte im Programm sind leicht zu ändern, da nur an einer Stelle des Pro­ + gramms der Denoter geändert werden muß + (z.B.: In Vereinbarungen von Reihungen (siehe 2.6.1) können LET-Denoter, im + Gegensatz zu Konstanten, als Obergrenze angegeben werden. Dieser + Wert kann dann auch an anderen Stellen des Programms, z.B. in Schlei­ + fen (siehe 2.4.2.5), benutzt werden. Bei Änderung der Reihungsgröße + braucht dann nur an einer Stelle des Programms der Wert geändert zu + werden.) +- der Name gibt zusätzliche Information über die Bedeutung des Denoters. + + + +2.3.2 Zugriffsrecht + +Von manchen Datenobjekten weiß man, daß sie nur einmal einen Wert erhalten +sollen. Sie sollen also nicht verändert werden. Oder man weiß, daß in einem Pro­ +grammbereich ein Datenobjekt nicht verändert werden soll. Um ein unbeabsichtigtes +Verändern zu verhindern, wird in ELAN dem Datenobjekt ein zusätzlicher Schutz +mitgegeben: das Zugriffsrecht oder Accessrecht. + +In der Deklaration eines Datenobjekts können folgende Accessattribute angegeben +werden: + +- #on("i")##on("b")#VAR #off("i")##off("b")# für lesenden und schreibenden (verändernden) Zugriff + +- #on("i")##on("b")#CONST#off("i")##off("b")# für nur lesenden Zugriff. + + + +2.3.3 Deklaration + +Damit man Datenobjekte in einem Programm ansprechen kann, gibt man einem +Datenobjekt einen Namen (wie z.B. einen Personennamen, unter der sich eine wirk­ +liche Person "verbirgt"). Will man ein Datenobjekt in einem Programm verwenden, so +muß man dem Compiler mitteilen, welchen Datentyp und welches Accessrecht das +Objekt haben soll. Das dient u.a. dazu, nicht vereinbarte Namen (z.B. verschriebene) +vom Compiler entdecken zu lassen. Weiterhin ist aus dem bei der Deklaration ange­ +gebenen Datentyp zu entnehmen, wieviel Speicherplatz für das Objekt zur Laufzeit zu +reservieren ist. + +Eine Deklaration oder Vereinbarung besteht aus der Angabe von + +- Datentyp +- Zugriffsrecht ( #on("i")##on("b")#VAR#off("i")##off("b")# oder #on("i")##on("b")#CONST#off("i")##off("b")#) +- Name des Datenobjekts. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR mein datenobjekt; + +____________________________________________________________________________ + + +Verschiedene Datenobjekte mit gleichem Datentyp und Accessrecht dürfen in einer +Deklaration angegeben werden; sie werden durch Kommata getrennt. Mehrere Dekla­ +rationen werden - genauso wie Anweisungen - durch das Trennzeichen Semikolon +voneinander getrennt. + +____________________________________________________________________________ + .......................... Beispiele: ......................... + INT VAR mein wert, dein wert, unser wert; + BOOL VAR listen ende; + TEXT VAR zeile, wort; + +____________________________________________________________________________ + + +2.3.4 Initialisierung + +Um mit den vereinbarten Datenobjekten arbeiten zu können, muß man ihnen einen +Wert geben. Hat ein Datenobjekt noch keinen Wert erhalten, so sagt man, sein Wert +sei undefiniert. Das versehentliche Arbeiten mit undefinierten Werten ist eine beliebte +Fehlerquelle. Deshalb wird von Programmierern streng darauf geachtet, diese Fehler­ +kuelle zu vermeiden. Eine Wertgebung an ein Datenobjekt kann (muß aber nicht) +bereits bei der Deklaration erfolgen. In ELAN wird dies Initialisierung genannt. Für mit +CONST vereinbarte Datenobjekte ist die Initialisierung die einzige Möglichkeit, ihnen +einen Wert zu geben. Die Initialisierung von Konstanten ist zwingend vorgeschrieben +und wird vom Compiler überprüft. + +Die Initialisierung besteht aus der Angabe von + +- Datentyp +- Zugriffsrecht ( #on("i")##on("b")#VAR#off("i")##off("b")# oder #on("i")##on("b")#CONST#off("i")##off("b")#) +- Name des Datenobjekts +- Operator #on("i")##on("b")#::#off("i")##off("b")# oder #on("i")##on("b")#:=#off("i")##off("b")# +- Wert, den das Datenobjekt erhalten soll (Denoter, Ausdruck). + +____________________________________________________________________________ + .......................... Beispiele: ......................... + INT CONST gewuenschtes gehalt :: 12 000; + TEXT VAR zeile :: ""; + REAL CONST pi :: 3.14159, zwei pi := 2.0 * pi; + BOOL VAR bereits sortiert :: TRUE; +____________________________________________________________________________ +#page# + +2.4 Programmeinheiten + +Neben Deklarationen (Vereinbarungen) sind Programmeinheiten die Grundbestandteile +von ELAN. + + +Programmeinheiten können sein: + +#on("b")#- elementare Programmeinheiten #off("b")# + - Ausdruck + - Zuweisung + - Refinementanwendung + - Prozeduraufruf + +#on("b")#- zusammengesetzte Programmeinheiten #off("b")# + - Folge + - Abfrage + - Auswahl + - Wiederholung + +#on("b")#- abstrahierende Programmeinheiten #off("b")# + - Refinementbvereinbarung + - Prozedurvereinbarung + - Operatorvereinbarung + - Paketvereinbarung. +#page# + +2.4.1 Elementare Programmeinheiten + + +2.4.1.1 Ausdruck + +Ausdrücke sind eine Zusammenstellung von Datenobjekten (Denoter, VAR- oder +CONST-Objekte) und Operatoren. Jeder korrekte Ausdruck liefert einen Wert. Der +Typ des Ausdrucks wird bestimmt durch den Typ des Wertes, den der Ausdruck +liefert. + + +Operatoren + +Operatoren werden in ELAN durch ein oder zwei Sonderzeichen oder durch Groß­ +buchstaben als Schlüsselwort dargestellt (siehe 2.4.3.3). + +Als Operanden (also die Datenobjekte, auf die ein Operator "wirken" soll) dürfen +VAR- und CONST-Datenobjekte, Denoter oder Ausdrücke verwendet werden. Typ +der Operanden und des Resultats eines Operators werden in der Operatorvereinba­ +rung festgelegt (siehe 2.4.3.3). + +Man unterscheidet zwei Arten von Operatoren: + +#on("b")#- monadische Operatoren #off("b")# + Monadischen Operatoren haben nur einen Operanden, der rechts vom Operator­ + zeichen geschrieben werden muß. + + Beispiel: + + + - a + NOT x + + + Der '-' - Operator liefert den Wert von a mit umgekehrten Vorzeichen. a muß + dabei vom Datentyp INT oder REAL sein. + Der Operator 'NOT' realisiert die logische Negation. y muß vom Datentyp BOOL + sein. + + +#on("b")#- dyadische Operatoren #off("b")# + Dyadische Operatoren haben zwei Operanden. Das Operatorzeichen steht zwi­ + schen den beiden Operanden. + + Beispiele: + + + a + b + a - b + a * b + a DIV b + a ** b + x < y + x <> y + x AND y + x OR y + + + In den ersten fünf Beispielen werden jeweils die Werte von zwei INT-Objekten a + und b addiert (Operatorzeichen: '+'), subtrahiert ('-'), multipliziert ('*'), dividiert + (ganzzahlige Division ohne Rest: 'DIV') und potenziert ('**'). + Im sechsten und siebten Beispiel werden zwei BOOL-Werte x und y verglichen + und im achten und neunten Beispiel die logische Operation 'und' (Operator 'AND') + bzw. 'oder' (Operator 'OR') durchgeführt. + + +Priorität von Operatoren + +Es ist erlaubt, einen Ausdruck wiederum als Operanden zu verwenden. Praktisch +bedeutet dies, daß mehrere Operatoren und Datenobjekte zusammen in einem Aus­ +druck geschrieben werden dürfen. + +Beispiele: + + +a + 3 - b * c +- a * b + + +Die Reihenfolge der Auswertung kann man durch Angabe von Klammern steuern. + +Beispiel: + + +(a + b) * (a + b) + + +Es wird jeweils erst 'a + b' ausgewertet und dann erst die Multiplikation durchge­ +führt. In ELAN ist es erlaubt, beliebig viel Klammernpaare zu verwenden (Regel: die +innerste Klammer wird zuerst ausgeführt). Es ist sogar zulässig, Klammern zu ver­ +wenden, wo keine notwendig sind, denn überflüssige Klammernpaare werden überle­ +sen. Man muß jedoch beachten, daß Ausdrücke, und damit auch z.B. #on("b")#(a)#off("b")#, immer +Accessrecht CONST haben. + +Beispiel: + + +((a - b)) * 3 * ((c + d) * (c - d)) + + +Somit können beliebig komplizierte Ausdrücke formuliert werden. + +Um solche Ausdrücke einfacher zu behandeln und sie so ähnlich schreiben zu kön­ +nen, wie man es in der Mathematik gewohnt ist, wird in Programmiersprachen die +Reihenfolge der Auswertung von Operatoren festgelegt. In ELAN wurden neun Ebe­ +nen, Prioritäten genannt, festgelegt: + + +#on("bold")#Priorität Operatoren +#off("bold")# + + 9 alle monadischen Operatoren + 8 ** + 7 *, /, DIV, MOD + 6 +, - + 5 =, <>, <, <=, >, >= + 4 AND + 3 OR + 2 alle übrigen, nicht in dieser Tabelle aufgeführten + dyadischen Operatoren + 1 := + +(Die erwähnten Operatoren in der Tabelle werden in der Beschreibung der Standard­ +prozeduren und -Operatoren besprochen). + +Operatoren mit der höchsten Priorität werden zuerst ausgeführt, dann die mit der +nächst niedrigeren Priorität usw.. Operatoren mit gleicher Priorität werden von links +nach rechts ausgeführt. Dadurch ergibt sich die gewohnte Abarbeitungsfolge wie beim +Rechnen. + +Beispiel: + + +-2 + 3 * 2 ** 3 + +a) -2 +b) 2 ** 3 +c) 3 * (2 ** 3) +d) ((-2)) + (3 * (2 ** 3)) + + +Wie bereits erwähnt, ist es immer erlaubt, Klammern zu setzen. Ist man sich also +über die genaue Abarbeitungsfolge nicht im Klaren, so kann man Klammern verwen­ +den. + + + +2.4.1.2 Zuweisung + +Ein spezieller Operator ist die Zuweisung. + +Form: + + +Variable #on("i")##on("b")#:=#off("i")##off("b")# Wert + + +Dieser Operator hat immer die geringste Priorität, wird also immer als letzter einer +Anweisung ausgeführt. Die Zuweisung wird verwendet, um einer Variablen einen +neuen Wert zu geben. Der Operator ':=' liefert kein Resultat (man sagt auch, er +liefert keinen Wert) und verlangt als linken Operanden ein VAR-Datenobjekt, an den +der Wert des rechten Operanden zugewiesen werden soll). Der Wert des linken Oper­ +anden wird also verändert. Der rechte Operand wird nur gelesen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + a := b; + +____________________________________________________________________________ + + +Hier wird der Wert von 'b' der Variablen 'a' zugewiesen. Der vorher vorhandene Wert +von 'a' geht dabei verloren. Man sagt auch, der Wert wird überschrieben. + +Als rechter Operand des ':='-Operators darf auch ein Ausdruck stehen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + a := b + c; + +____________________________________________________________________________ + + +Hier wird das Resultat von 'b + c' an die Variable 'a' zugewiesen. Man beachte +dabei die Prioritäten der Operatoren '+' (Priorität 6) und ':=' (Priorität 1): die Addition +wird vor der Zuweisung ausgeführt. Die Auswertung von Zuweisungen mit Ausdrücken +muß immer so verlaufen, da die Zuweisung stets die niedrigste Priorität aller Operato­ +ren hat. + +Oft kommt es vor, daß ein Objekt auf der linken und rechten Seite des Zuweisungs­ +operators erscheint, z.B. wenn ein Wert erhöht werden soll. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + a := a + 1; + +____________________________________________________________________________ + + +Hier wird der "alte", aktuelle Wert von 'a' genommen, um '1' erhöht und dem Objekt +'a' zugewiesen. Man beachte, daß hier in einer Anweisung ein Datenobjekt unter­ +schiedliche Werte zu unterschiedlichen Zeitpunkten haben kann. + + + +2.4.1.3 Refinementanwendung + +In ELAN ist es möglich, Namen für Ausdrücke oder eine bzw. mehrere Anweisungen +zu vergeben. Das Sprachelement, das diese Namensgebung ermöglicht, heißt Refi­ +nement. Die Ausführung eines solchen Namens heißt Refinementanwendung, die +Namensgebung heißt Refinementvereinbarung (siehe 2.4.3.1). Die Ausdrücke oder +Anweisungen bilden den Refinementrumpf. Ein Refinement kann man in einem Pro­ +gramm unter dem Refinementnamen ansprechen. Man kann sich die Ausführung so +vorstellen, als würden der Refinementrumpf immer dort eingesetzt, wo der Name des +Refinements als Operation benutzt wird. + + + +2.4.1.4 Prozeduraufruf + +Eine Prozedur ist eine Sammlung von Anweisungen und Daten, die zur Lösung einer +bestimmten Aufgabe benötigt werden. Eine Prozedur wird in einer Prozedurvereinba­ +rung definiert (siehe 2.4.3.2). Eine solche Prozedur kann man in einem Programm +unter einem Namen (eventuell unter Angabe von Parametern) ansprechen. Man +spricht dann vom Aufruf einer Prozedur oder einer Prozeduranweisung. + +Formen des Prozeduraufrufs: + +- #on("b")#Prozeduren ohne Parameter#off("b")# werden durch den Prozedurnamen angesprochen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + pause; + +____________________________________________________________________________ + + + (Die Prozedur 'pause' wartet bis ein Zeichen eingegeben wird) + + +- #on("b")#Prozeduren mit Parameter#off("b")# werden durch + + + Prozedurnamen #on("i")##on("b")#(#off("i")##off("b")# aktuelle Parameterliste #on("i")##on("b")#)#off("i")##off("b")# + + + aufgerufen. Eine Parameterliste ist entweder ein Datenobjekt oder mehrere durch + Kommata getrennte Datenobjekte. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + pause (10); + +____________________________________________________________________________ + + + (Mit der Prozedur 'pause (INT CONST zeitgrenze)' kann für eine Zeitdauer von + 'zeitgrenze' in Zehntel-Sekunden gewartet werden. Die Wartezeit wird durch + Erreichen der Zeitgrenze oder durch Eingabe eines Zeichens abgebrochen) + + + Bei den aktuellen Parametern ist folgendes zu beachten: + + a) Wird ein VAR-Parameter in der Definition der Prozedur vorgeschrieben, darf + kein Ausdruck als aktueller Parameter "übergeben" werden, weil an einen + Ausdruck nichts zugewiesen werden kann. Ausdrücke haben - wie bereits + erwähnt - das Accessrecht CONST. + +____________________________________________________________________________ + ........................ Gegenbeispiel: ....................... + TEXT VAR text1, text2; + text1 := "Dieses Beispiel "; + text2 := "Fehlermeldung"; + insert char (text1 + text2, "liefert eine", 17); + +____________________________________________________________________________ + + + (Die Prozedur 'insert char (TEXT VAR string, TEXT CONST char, INT CONST + pos)' fügt das Zeichen 'char' in den Text 'string' an der Position 'pos' ein) + + b) Wird ein CONST-Parameter verlangt, dann darf in diesem Fall ein Ausdruck + als aktueller Parameter geschrieben werden. Aber auch ein VAR-Datenobjekt + darf angegeben werden. In diesem Fall wird eine Wandlung des Accessrechts + (CONSTing) vorgenommen: der aktuelle Parameter erhält sozusagen für die + Zeit der Abarbeitung der Prozedur das Accessrecht CONST. + + + In ELAN sind auch Prozeduren als Parameter erlaubt. Die Prozedur als aktueller + Parameter wird in der Parameterliste folgendermaßen angegeben: + + + Resultattyp #on("i")##on("b")#PROC#off("i")##off("b")# #on("i")##on("b")#(#off("i")##off("b")# virtuelle Parameterliste #on("i")##on("b")#)#off("i")##off("b")# Procname + + + Die Angabe des Resultattyps entfällt, wenn es sich nicht um eine wertliefernde + Prozedur handelt. Die virtuelle Parameterliste inklusive der Klammern entfällt, falls + die Prozedur keine Parameter hat. Die virtuelle Parameterliste beschreibt die + Parameter der Parameterprozedur. Es werden Datentyp und Zugriffsrecht eines + jeden Parameters angegeben, jedoch ohne Namen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + wertetabelle (REAL PROC (REAL CONST) sin, + untergrenze, obergrenze, schrittweite); + + + (Die Prozedur 'sin' wird an die Prozedur 'wertetabelle' übergeben) + +____________________________________________________________________________ + + +2.4.2 Zusammengesetzte Programmeinheiten + + +2.4.2.1 Folge + +Mehrere in einer bestimmten Reihenfolge auszuführende Anweisungen werden als +Folge bezeichnet. In ELAN kann man eine oder mehrere Anweisungen in eine Pro­ +grammzeile schreiben oder eine Anweisung über mehrere Zeilen. Das setzt jedoch +voraus, daß die Anweisungen voneinander getrennt werden. Die Trennung von Anwei­ +sungen erfolgt in ELAN durch das Trennsymbol Semikolon. Es bedeutet soviel wie: +"führe die nächste Anweisung aus". + +____________________________________________________________________________ + ........................... Beispiel: ......................... + put ("mein"); + put (1); + put (". Programm") + +____________________________________________________________________________ + + +(Die Prozedur 'put' gibt den als Parameter angegebenen Wert auf dem Ausgabegerät +aus) + + + +2.4.2.2 Abfrage + +Mit Abfragen steuert man die bedingte Ausführung von Anweisungen. Abhängig von +einer Bedingung wird in zwei verschiedene Programmabschnitte verzweigt. + +Der formale Aufbau einer Abfrage sieht folgendermaßen aus: + + +#on("i")##on("b")#IF#off("i")##off("b")# Bedingung + #on("i")##on("b")#THEN#off("i")##off("b")# Abschnitt + #on("i")##on("b")#ELSE#off("i")##off("b")# Abschnitt +#on("i")##on("b")#END IF#off("i")##off("b")# + + +Der ELSE-Teil darf dabei auch fehlen. Anstelle von #on("i")##on("b")#END IF#off("i")##off("b")# darf auch die Abkürzung #on("i")##on("b")#FI#off("i")##off("b")# (IF von hinten gelesen) benutzt werden. + +In folgenden Beispielen wird der Absolutbetrag von 'a' ausgegeben: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR a; + get (a); + IF a < 0 + THEN a := -a + END IF; + put (a) + +____________________________________________________________________________ + + +Die Umkehrung des Vorzeichens von a im THEN-Teil wird nur durchgeführt, wenn +der BOOLesche Ausdruck ('a < 0') den Wert TRUE liefert. Liefert er den Wert +FALSE, wird die Anweisung, die der bedingten Anweisung folgt (nach END IF), ausge­ +führt. Das obige Programm kann auch anders geschrieben werden: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR a; + get (a); + IF a < 0 + THEN put (-a) + ELSE put (a) + END IF + +____________________________________________________________________________ + + +Der THEN-Teil wird wiederum ausgeführt, wenn die BOOLesche Bedingung erfüllt +ist. Liefert sie dagegen FALSE, wird der ELSE-Teil ausgeführt. + +Die bedingte Anweisung ermöglicht es, abhängig von einer Bedingung eine oder +mehrere Anweisungen ausführen zu lassen. Dabei können im THEN- bzw. ELSE- +Teil wiederum bedingte Anweisungen enthalten sein. + + +Abfragekette +Bei Abfrageketten kann das ELIF-Konstrukt eingesetzt werden. (ELIF ist eine Zu­ +sammenziehung der Worte ELSE und IF). + +Anstatt + +____________________________________________________________________________ + ........................... Beispiel: ......................... + IF bedingung1 + THEN aktion1 + ELSE IF bedingung2 + THEN aktion2 + ELSE aktion3 + END IF + END IF; + +____________________________________________________________________________ + + +kann man besser + +____________________________________________________________________________ + ........................... Beispiel: ......................... + IF bedingung1 + THEN aktion1 + ELIF bedingung2 + THEN aktion2 + ELSE aktion3 + END IF; + +____________________________________________________________________________ + + +schreiben. + + + +2.4.2.3 Auswahl + +Die Auswahl wird benutzt, wenn alternative Anwendungen in Abhängikeit von Werten +eines Datenobjekts ausgeführt werden sollen. + +Der formale Aufbau der Auswahl sieht folgendermaßen aus: + + +#on("i")##on("b")#SELECT#off("i")##off("b")# INT-Ausdruck #on("i")##on("b")#OF#off("i")##off("b")# + #on("i")##on("b")#CASE#off("i")##off("b")# 1. Liste von INT-Denotern #on("i")##on("b")#:#off("i")##off("b")# Abschnitt + #on("i")##on("b")#CASE#off("i")##off("b")# 2. Liste von INT-Denotern #on("i")##on("b")#:#off("i")##off("b")# Abschnitt + . + . + . + #on("i")##on("b")#CASE#off("i")##off("b")# n. Liste von INT-Denotern #on("i")##on("b")#:#off("i")##off("b")# Abschnitt + #on("i")##on("b")#OTHERWISE#off("i")##off("b")# Abschnitt +#on("i")##on("b")#END SELECT#off("i")##off("b")# + + +Eine Liste von INT-Denotern besteht aus einem oder mehreren durch Kommata ge­ +trennten INT-Denotern. Der OTHERWISE-Teil darf auch fehlen. Man sollte ihn +jedoch verwenden, um Fehlerfälle abzufangen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + SELECT monat OF + CASE 2: IF schaltjahr + THEN tage := 29 + ELSE tage := 28 + END IF + CASE 4, 6, 9, 11: tage := 30 + CASE 1, 3, 5, 7, 8, 10 ,12: tage := 31 + OTHERWISE kein monat + END SELECT; + +____________________________________________________________________________ + + +(In diesem Programmausschnitt werden die Tage eines Monats bestimmt) + + + +2.4.2.4 Wertliefernde Abfrage und + wertliefernde Auswahl + + +Soll eine Abfrage oder eine Auswahl einen Wert liefern, dann darf der ELSE- bzw. +der OTHERWISE-Teil nicht fehlen und alle Zweige müssen einen Wert liefern. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + SELECT monat OF + CASE 2: IF schaltjahr + THEN 29 + ELSE 28 + END IF + CASE 4, 6, 9, 11: 30 + CASE 1, 3, 5, 7, 8, 10 ,12: 31 + OTHERWISE kein monat; 0 + END SELECT; + +____________________________________________________________________________ + + +2.4.2.5 Wiederholung + +Die Wiederholung dient zur mehrfachen Ausführung von Anweisungen, meist in Ab­ +hängigkeit von einer Bedingung. Darum wird die Wiederholungsanweisung oft auch +Schleife genannt und die in ihr enthaltenen Anweisungen Schleifenrumpf. + +Es gibt verschiedene Schleifentypen: + +- Endlosschleife +- abweisende Schleife +- nicht abweisende Schleife +- Zählschleife. + + +Endlosschleife +Bei der Endlosschleife wird nicht spezifiziert, wann die Schleife beendet werden soll. + +Form: + + +#on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#END REPEAT#off("i")##off("b")# + + +Anstelle von #on("i")##on("b")#REPEAT#off("i")##off("b")# darf die Abkürzung #on("i")##on("b")#REP#off("i")##off("b")# und anstelle von #on("i")##on("b")#END REPEAT#off("i")##off("b")# +das Schlüsselwort #on("i")##on("b")#PER#off("i")##off("b")# (REP von hinten gelesen) +benutzt werden. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + break; + REPEAT + fixpoint; + pause (18000) + END REPEAT + +____________________________________________________________________________ + + +Wird dieses Programm in einer Task im SYSUR-Zweig ausgeführt, so führt diese +Task Fixpunkte im Abstand von 30 Minuten durch. + + + +Abweisende Schleife +Bei der abweisenden Schleife wird die Abbruchbedingung an den Anfang der Schleife +geschrieben. + +Form: + + +#on("i")##on("b")#WHILE#off("i")##off("b")# Bedingung #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#END REPEAT#off("i")##off("b")# + + +Bei jedem erneuten Durchlauf der Schleife wird überprüft, ob der BOOLesche Aus­ +druck den Wert TRUE liefert. Ist das nicht der Fall, wird die Bearbeitung mit der +Anweisung fortgesetzt, die auf das Schleifenende folgt. Die Schleife wird abweisende +Schleife genannt, weil der Schleifenrumpf nicht ausgeführt wird, wenn die Bedingung +vor Eintritt in die Schleife bereits FALSE liefert. + + +Nicht abweisende Schleife +Anders verhält es sich bei der nicht abweisenden Schleife. Bei der nicht abweisenden +Schleife wird die Abbruchbedingung an das Ende der Schleife geschrieben. + +Form: + + +#on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#UNTIL#off("i")##off("b")# Bedingung #on("i")##on("b")#END REPEAT#off("i")##off("b")# + + +Hier wird der Schleifenrumpf auf jeden Fall einmal bearbeitet. Am Ende des Rumpfes +wird die BOOLesche Bedingung abgefragt. Liefert sie den Wert FALSE, wird die +Schleife erneut abgearbeitet. Liefert die Bedingung den Wert TRUE, wird die Schleife +abgebrochen und mit der ersten Anweisung hinter der Schleife in der Bearbeitung +fortgefahren. + +Bei den beiden letztgenannten Arten der Wiederholungsanweisung ist es wichtig, daß +Elemente der BOOLeschen Bedingung in der Schleife verändert werden, damit das +Programm terminieren kann, d.h. die Schleife abgebrochen wird. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + TEXT VAR wort, satz :: ""; + REPEAT + get (wort); + satz CAT wort; + satz CAT " " + UNTIL wort = "." PER; + +____________________________________________________________________________ + + +Dises Programm liest solange Wörter ein und verbindet diese zu einem Satz, bis ein +Punkt eingegeben wurde. + + + +Zählschleife +Zählschleifen werden eingesetzt, wenn die genaue Anzahl der Schleifendurchläufe +bekannt ist. + +Form: + + +#on("i")##on("b")#FOR#off("i")##off("b")# Laufvariable #on("i")##on("b")#FROM#off("i")##off("b")# Anfangswert #on("i")##on("b")#UPTO#off("i")##off("b")# Endwert #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#END REPEAT#off("i")##off("b")# + + +Bei Zählschleifen wird eine Laufvariable verwendet, die die INT-Werte von 'Anfangs­ +wert' bis 'Endwert' in Schritten von 1 durchläuft. 'Anfangswert' und 'Endwert' können +beliebige INT-Ausdrücke sein. Diese Schleife zählt "aufwärts". Wird anstatt #on("i")##on("b")#UPTO#off("i")##off("b")# +das Schlüsselwort #on("i")##on("b")#DOWNTO#off("i")##off("b")# verwendet, wird mit Schritten von 1 "abwärts" gezählt. + +Form: + + +#on("i")##on("b")#FOR#off("i")##off("b")# Laufvariable #on("i")##on("b")#FROM#off("i")##off("b")# Endwert #on("i")##on("b")#DOWNTO#off("i")##off("b")# Anfangswert #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#END REPEAT#off("i")##off("b")# + + +Die Laufvariable darf in der Schleife nicht verändert werden. Nach dem normalen +Schleifenende ist der Wert der Laufvariablen nicht definiert. + + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR summe :: 0, i; + FOR i FROM 1 UPTO 100 REPEAT + summe INCR i + END REPEAT + +____________________________________________________________________________ + + +Dieses Programm berechnet die Summe der natürlichen Zahlen von 1 bis 100. + + +Die verschiedenen Schleifenarten können kombiniert werden: + + +#on("i")##on("b")#FOR#off("i")##off("b")# Laufvariable #on("i")##on("b")#FROM#off("i")##off("b")# Anfangswert #on("i")##on("b")#UPTO#off("i")##off("b")# Endwert +#on("i")##on("b")#WHILE#off("i")##off("b")# Bedingung #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#END REPEAT#off("i")##off("b")# + + + +#on("i")##on("b")#FOR#off("i")##off("b")# Laufvariable #on("i")##on("b")#FROM#off("i")##off("b")# Anfangswert #on("i")##on("b")#UPTO#off("i")##off("b")# Endwert #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#UNTIL#off("i")##off("b")# Bedingung #on("i")##on("b")#END REPEAT#off("i")##off("b")# + + + + + +#on("i")##on("b")#WHILE#off("i")##off("b")# Bedingung #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#UNTIL#off("i")##off("b")# Bedingung #on("i")##on("b")#END REPEAT#off("i")##off("b")# + +#page# + +2.4.3 Abstrahierende Programmeinheiten + + +2.4.3.1 Refinementvereinbarung + +In ELAN ist es möglich, Namen für Ausdrücke oder eine bzw. mehrere Anweisungen +zu vergeben. Das Sprachelement, das diese Namensgebung ermöglicht, heißt Refi­ +nement. Die Ausführung eines solchen Namens heißt Refinementanwendung (siehe +2.4.1.3), die Namensgebung heißt Refinementvereinbarung. Die Ausdrücke oder +Anweisungen bilden den Refinementrumpf. + +Werden in einem Programm Refinements benutzt, dann wird der Programmteil bis +zum ersten Refinement durch einen Punkt abgeschlossen. Die Refinementvereinba­ +rung sieht folgendermaßen aus: + + +Name #on("i")##on("b")#:#off("i")##off("b")# + Abschnitt #on("i")##on("b")#.#off("i")##off("b")# + + + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR a, b, x; + einlesen von a und b; + vertauschen von a und b; + vertauschte werte ausgeben. + + einlesen von a und b: + get (a); + get (b). + + vertauschen von a und b: + x := a; + a := b; + b := x. + + vertauschte werte ausgeben: + put (a); + put (b). + +____________________________________________________________________________ + + +Für den Namen 'einlesen von a und b' werden die Anweisungen 'get (a); get (b)' vom +ELAN-Compiler eingesetzt. Man kann also die ersten vier Zeilen des Programms als +eigentliches Programm ansehen, wobei die Namen durch die betreffenden Anwei­ +sungen ersetzt werden. Ein Refinement hat also keinen eigenen Datenbereich, d.h. +Vereinbarungen, die in Refinements gemacht werden, gelten auch außerhalb des +Refinements. + + + +Vorteile der Refinementanwendung +Durch die sinnvolle Verwendung von Refinements wird ein Programm im Programm +und nicht in einer separaten Beschreibung dokumentiert. Weiterhin kann ein Pro­ +gramm "von oben nach unten" ("top down") entwickelt werden: Das obige - zuge­ +geben einfache - Beispielprogramm wurde in drei Teile zerlegt und diese durch +Namen beschrieben. Bei der Beschreibung von Aktionen durch Namen wird gesagt +was gemacht werden soll. Es wird noch nicht beschrieben wie, denn auf dieser Stufe +der Programmentwicklung braucht man sich um die Realisierung der Refinements +(noch) keine Sorgen zu machen. Das erfolgt erst, wenn das Refinement programmiert +werden muß. Dabei können wiederum Refinements verwendet werden usw., bis man +auf eine Ebene "heruntergestiegen" ist, bei der eine (jetzt: Teil-) Problemlösung sehr +einfach ist und man sie direkt hinschreiben kann. Man beschäftigt sich also an jedem +Punkt der Problemlösung nur mit einem Teilaspekt des gesamten Problems. Zudem +sieht man - wenn die Refinements einigermaßen vernünftig verwendet werden - +dem Programm an, wie die Problemlösung entstanden ist. + +Die Verwendung von Refinements hat also eine Anzahl von Vorteilen. +Refinements ermöglichen: + +- "top down" - Programmierung +- Strukturierung von Programmen und damit effiziente Fehlersuche und gute Wart­ + barkeit +- Dokumentation im Programmtext. + + +Wertliefernde Refinements +Refinements können auch dort verwendet werden, wo ein Wert erwartet wird, z.B. in +einem Ausdruck oder einer 'put'-Anweisung. In diesem Fall muß die letzte Anwei­ +sung des Refinements einen Wert liefert. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR a :: 1, b :: 2, c :: 3; + put (resultat). + + resultat: + (a * b + c) ** 3. + +____________________________________________________________________________ + + +Man kann auch ein wertlieferndes Refinement mit mehreren Anweisungen schrei­ +ben. + +Allgemeine Regel: +Die letzte Anweisung eines Refinements bestimmt, ob es einen Wert liefert - und +wenn ja, von welchen Datentyp. + + + +2.4.3.2 Prozedurvereinbarung + +Eine Prozedur ist eine Sammlung von Anweisungen und Daten, die zur Lösung einer +bestimmten Aufgabe benötigt werden. + +Der formale Aufbau einer Prozedur sieht folgendermaßen aus: + + +#on("i")##on("b")#PROC#off("i")##off("b")# Prozedurname #on("i")##on("b")#:#off("i")##off("b")# + Prozedurrumpf +#on("i")##on("b")#END PROC#off("i")##off("b")# Prozedurname + + +Der Prozedurrumpf kann Deklarationen, Anweisungen und Refinements enthalten. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC loesche bildschirm ab aktueller cursorposition: + out (""4"") + END PROC loesche bildschirm ab aktueller cursorposition + +____________________________________________________________________________ + + +Verwendung von Prozeduren +Prozeduren werden verwendet, wenn + +- Anweisungen und Datenobjekte unter einem Namen zusammengefaßt werden + sollen ("Abstraktion") +- gleiche Anweisungen von mehreren Stellen eines Programms verwandt werden + sollen (Codereduktion), u.U. mit verschieden Datenobjekten (Parameter) +- Datenobjekte nur innerhalb eines Programmteils benötigt werden und diese nicht + von dem gesamten Programm angesprochen werden sollen. + +In den folgenden Programmfragmenten werden zwei Werte vertauscht. In der ersten +Lösung wird ein Refinement, in der zweiten eine Prozedur verwandt. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + IF a > b + THEN vertausche a und b + END IF; + put (a); + put (b); + vertausche a und b. + + vertausche a und b: + INT CONST x :: a; + a := b; + b := x. + +____________________________________________________________________________ + + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC vertausche a und b: + INT CONST x :: a; + a := b; + b := x + END PROC vertausche a und b; + + IF a > b + THEN vertausche a und b + END IF; + put (a); + put (b); + vertausche a und b; + +____________________________________________________________________________ + + +Beim ersten Hinsehen leisten beide Programme das Gleiche. Es gibt jedoch drei +wichtige Unterschiede: + +1) Das Refinement 'vertausche a und b' wird zweimal (vom ELAN-Compiler) ein­ + gesetzt, d.h. der Code ist zweimal vorhanden. Die Prozedur dagegen ist vom Code + nur einmal vorhanden, wird aber zweimal - durch das Aufführen des Prozedur­ + namens - aufgerufen. + +2) Die Variable 'x' ist in der ersten Programmversion während des gesamten Ablauf + des Programms vorhanden, d.h. ihr Speicherplatz ist während dieser Zeit belegt. + Solche Datenobjekte nennt man statische Datenobjekte oder auch (aus Gründen, + die erst etwas später offensichtlich werden) Paket-Objekte. Das Datenobjekt 'x' + der rechten Version dagegen ist nur während der Bearbeitung der Prozedur vor­ + handen, sein Speicherplatz wird danach freigegeben. Solche Datenobjekte, die nur + kurzfristig Speicher belegen, werden dynamische Datenobjekte genannt. + + Prozeduren sind also ein Mittel, um die Speicherbelegung zu beeinflussen. + +3) Da Refinements keinen eigenen Datenbereich haben, kann die Variable 'x' in der + ersten Programmversion - obwohl sie in einem Refinement deklariert wurde - + von jeder Stelle des Programms angesprochen werden. Solche Datenobjekte + werden globale Datenobjekte genannt. Das Datenobjekt 'x' der Prozedur dagegen + kann nur innerhalb der Prozedur angesprochen werden, es ist also ein lokales + Datenobjekt der Prozedur. Innerhalb der Prozedur dürfen globale Datenobjekte + (also Objekte, die außerhalb von Prozeduren deklariert wurden) auch angespro­ + chen werden. + + Eine Prozedur in ELAN bildet im Gegensatz zu Refinements einen eigenen Gültig­ + keitsbereich hinsichtlich Datenobjekten und Refinements, die innerhalb der Pro­ + zedur deklariert werden. Prozeduren sind somit ein Mittel, um die in ihr dekla­ + rierten Datenobjekte hinsichtlich der Ansprechbarkeit nach Außen "abzuschotten". + + + +Prozeduren mit Parametern +Prozeduren mit Parametern erlauben es, gleiche Anweisungen mit unterschiedlichen +Datenobjekten auszuführen. + +Form: + + +#on("i")##on("b")#PROC#off("i")##off("b")# Prozedurname #on("i")##on("b")#(#off("i")##off("b")# formale Parameterliste #on("i")##on("b")#)#off("i")##off("b")# #on("i")##on("b")#:#off("i")##off("b")# + Prozedurrumpf +#on("i")##on("b")#END PROC#off("i")##off("b")# Prozedurnamen + + +Die Parameterliste besteht aus einem oder mehreren durch Kommata getrennten Para­ +metern. Ein Parameter wird mit Datentyp, Accessrecht und Namen angegeben. +Ähnlich wie bei der Datendeklaration braucht man für aufeinanderfolgende Parameter +mit gleichem Datentyp und gleichem Accessrecht die Attribute nur einmal anzugeben. +Parameter mit Accessrecht #on("i")##on("b")#CONST#off("i")##off("b")# sind Eingabeparameter, Parameter mit Access­ +recht #on("i")##on("b")#VAR#off("i")##off("b")# realisieren Ein-/Ausgabeparameter. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC vertausche (INT VAR a, b): + INT VAR x :: a; + a := b; + b := x + END PROC vertausche; + + INT VAR eins :: 1, + zwei :: 2, + drei :: 3; + vertausche (eins, zwei); + vertausche (zwei, drei); + vertausche (eins, zwei); + put (eins); put (zwei); put (drei) + +____________________________________________________________________________ + + +Die Datenobjekte 'a' und 'b' der Prozedur 'vertausche' werden formale Parameter +genannt. Sie stehen als Platzhalter für die bei einem Prozeduraufruf einzusetzenden +aktuellen Parameter (in obigen Beispiel die Datenobjekte 'eins', 'zwei' und 'drei'). + + + +Prozeduren als Parameter +Es ist auch möglich, Prozeduren als Parameter zu definieren. + +Eine Prozedur als Parameter wird folgendermaßen in der Parameterliste spezifiziert: + +Resultattyp #on("i")##on("b")#PROC#off("i")##off("b")# #on("i")##on("b")#(#off("i")##off("b")# virtuelle Parameterliste #on("i")##on("b")#)#off("i")##off("b")# Prozedurname + + +Die Angabe des Resultattyps entfällt, wenn es sich nicht um eine wertliefernde Proze­ +dur handelt. Die virtuelle Parameterliste inklusive der Klammern entfällt, falls die +Prozedur keine Parameter hat. Die virtuelle Parameterliste beschreibt die Parame­ +ter der Parameterprozedur. Es werden Datentyp und Zugriffsrecht eines jeden Para­ +meters angegeben, jedoch ohne Namen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC wertetabelle (REAL PROC (REAL CONST) funktion, + REAL CONST untergrenze, obergrenze, + schrittweite): + + REAL VAR wert; + putline ("W E R T E T A B E L L E"); + putline ("-----------------------"); + wert := untergrenze; + REPEAT + put (text (wert, 10, 5)); + put (text (funktion (wert), 10, 5)); + line; + wert INCR schrittweite + UNTIL wert > obergrenze PER + + END PROC wertetabelle; + + (* Prozeduraufruf: *) + wertetabelle (REAL PROC (REAL CONST) sin, 0.0, pi, 0.2) + +____________________________________________________________________________ + + +Wertliefernde Prozeduren +Eine wertliefernde Prozedur sieht folgendermaßen aus: + + +Resultattyp #on("i")##on("b")#PROC#off("i")##off("b")# Prozedurname #on("i")##on("b")#(#off("i")##off("b")# formale Parameterliste #on("i")##on("b")#)#off("i")##off("b")# #on("i")##on("b")#:#off("i")##off("b")# + wertliefernder Prozedurrumpf +#on("i")##on("b")#END PROC#off("i")##off("b")# Prozedurnamen + + + +Die Parameterliste inklusive Klammerung kann fehlen. Der Prozedurrumpf muß einen +Wert mit dem in Resultattyp angegeben Datentyp liefern. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT PROC max (INT CONST a, b): + IF a > b + THEN a + ELSE b + END IF + END PROC max; + + put (max (3, 4)) + +____________________________________________________________________________ + + +(In diesem Beispiel wird das Maximum von 'a' und 'b' ermittelt und ausgegeben) + +#page# + +2.4.3.3 Operatorvereinbarung + +Operatoren können in ELAN ähnlich wie Prozeduren definiert werden. Operatoren +müssen einen und können maximal zwei Operatoren besitzen (monadische und dyadi­ +sche Operatoren). + +Form: + + +Resultattyp #on("i")##on("b")#OP#off("i")##off("b")# Opname #on("i")##on("b")#(#off("i")##off("b")# ein oder zwei Parameter #on("i")##on("b")#)#off("i")##off("b")# #on("i")##on("b")#:#off("i")##off("b")# + Operatorrumpf +#on("i")##on("b")#END OP#off("i")##off("b")# Opname + + +Der Resultattyp wird nur bei wertliefernden Operatoren angegeben. + +Als Operatornamen sind erlaubt: + +- ein Sonderzeichen, sofern es nicht als Trennzeichen benutzt wird: + ! $ % & ' * + - / < = > ? § ^ ' ~ +- eine Kombination von zwei Sonderzeichen. Diese Kombination muß jedoch bereits + in ELAN existieren: + := <= >= <> ** +- ein Schlüsselwort (siehe 2.2.1). + + + +Vereinbarung eines monadischen Operators +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT OP SIGN (REAL CONST argument): + IF argument < 0.0 THEN -1 + ELIF argument = 0.0 THEN 0 + ELSE 1 + FI + END OP SIGN + +____________________________________________________________________________ + + +(Der Operator 'SIGN' liefert abhängig vom Vorzeichen des übergebenen Wertes den +INT-Wert -1, 0 oder 1) + + + +Vereinbarung eines dyadischen Operators +____________________________________________________________________________ + ........................... Beispiel: ......................... + TEXT OP * (INT CONST anzahl, TEXT CONST t): + INT VAR zaehler :: anzahl; + TEXT VAR ergebnis :: ""; + WHILE zaehler > 0 REP + ergebnis := ergebnis + t; + zaehler := zaehler - 1 + END REP; + ergebnis + END OP *; + +____________________________________________________________________________ + + +(Der Operator '*' verkettet 'anzahl'- mal den Text 't') + + + +2.4.3.4 Paketvereinbarung + +Pakete sind in ELAN eine Zusammenfassung von Datenobjekten, Prozeduren, Opera­ +toren und Datentypen. Diese bilden den Paketrumpf. Elemente eines Pakets (Prozedu­ +ren, Operatoren, Datentypen) können außerhalb des Pakets nur angesprochen werden, +wenn sie in der Schnittstelle des Pakets, die auch "interface" genannt wird, aufge­ +führt werden. Mit anderen Worten: es können alle Elemente eines Pakets von außen +nicht angesprochen werden, sofern sie nicht über die Schnittstelle "nach außen ge­ +reicht" werden. Pakete können separat übersetzt werden, so daß der "Zusammen­ +bau" eines umfangreichen Programms aus mehreren Paketen möglich ist. + +Der formale Aufbau eines Pakets sieht folgendermaßen aus: + + +#on("i")##on("b")#PACKET#off("i")##off("b")# Paketname #on("i")##on("b")#DEFINES#off("i")##off("b")# Schnittstelle #on("i")##on("b")#:#off("i")##off("b")# + Paketrumpf +#on("i")##on("b")#END PACKET#off("i")##off("b")# Paketname + + +In der Schnittstelle werden Prozeduren und Operatoren nur mit ihrem Namen, durch +Kommata getrennt, angegeben. Weiterhin können Datentypen und mit CONST verein­ +barte Datenobjekte in der Schnittstelle aufgeführt werden, aber keine VAR-Datenob­ +jekte, weil diese sonst über Paket-Grenzen hinweg verändert werden könnten. + +Im Gegensatz zu einer Prozedur kann ein PACKET nicht aufgerufen werden (nur die +Elemente der Schnittstelle können benutzt werden). + +Pakete werden zu folgenden Zwecken eingesetzt: + +- Spracherweiterung +- Schutz vor fehlerhaftem Zugriff auf Datenobjekte +- Realisierung von abstrakten Datentypen. + + + +Spracherweiterung +____________________________________________________________________________ + ........................... Beispiel: ......................... + PACKET fuer eine prozedur DEFINES swap: + + PROC swap (INT VAR a, b): + INT CONST x :: a; + b := a; + a := x + END PROC swap + + END PACKET fuer eine prozedur + +____________________________________________________________________________ + + +Dies ist ein Paket, das eine Tausch-Prozedur für INT-Datenobjekte bereitstellt. Das +PACKET kann übersetzt und dem ELAN-Compiler bekannt gemacht werden +(EUMEL: "insertieren"). Ist das geschehen, kann man 'swap' wie alle anderen Proze­ +duren (z.B. 'put', 'get') in einem Programm verwenden. Tatsächlich werden die mei­ +sten Prozeduren und Operatoren (aber auch einige Datentypen), die in ELAN zur +Verfügung stehen, nicht durch den ELAN-Compiler realisiert, sondern durch solche +PACKETs. Um solche Objekte einigermaßen zu standardisieren, wurde in der +ELAN-Sprachbeschreibung festgelegt, welche Datentypen, Prozeduren und Operato­ +ren in jedem ELAN-System vorhanden sein müssen. Solche Pakete werden Stan­ +dard-Pakete genannt. Jeder Installation - aber auch jedem Benutzer - steht es +jedoch frei, zu den Standard-Paketen zusätzliche Pakete dem Compiler bekannzu­ +geben, und damit den ELAN-Sprachumfang zu erweitern. + + + +Schutz vor fehlerhaftem Zugriff auf Datenobjekte +____________________________________________________________________________ + ........................... Beispiel: ......................... + PACKET stack handling DEFINES push, pop, init stack: + + LET max = 1000; + ROW max INT VAR stack; (* siehe Kapitel Reihung, 2.6.1. *) + 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 kann man über die Prozeduren 'init +stack', 'push' und 'pop' benutzen. +#page# +____________________________________________________________________________ + ........................... Beispiel: ......................... + init stack; + werte einlesen und pushen; + werte poppen und ausgeben. + + werte einlesen und pushen: + INT VAR anzahl :: 0, wert; + REP + get (wert); + push (wert); + anzahl INCR 1 + UNTIL ende kriterium END REP. + + werte poppen und ausgeben: + INT VAR i; + FOR i FROM 1 UPTO anzahl REP + pop (wert); + put (wert) + END REP. + +____________________________________________________________________________ + + +Die Datenobjekte 'stack' und 'stack pointer' haben nur Gültigkeit innerhalb des +PACKETs 'stack handling'. + +Anweisungen wie z.B. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + put (stack [3]); + stack [27] := 5 + +____________________________________________________________________________ + + + +außerhalb des PACKETs 'stack handling' sind also verboten und werden vom +ELAN-Compiler entdeckt. + +Ein PACKET bietet also auch einen gewissen Schutz vor fehlerhafter Verwendung von +Programmen und Datenobjekten. Wichtig ist weiterhin, daß die Realisierung des +Stacks ohne weiteres geändert werden kann, ohne daß Benutzerprogramme im 'main +packet' geändert werden müssen, sofern die Schnittstelle nicht verändert wird. Bei­ +spielsweise kann man sich entschließen, den Stack nicht durch eine Reihung, son­ +dern durch eine Struktur zu realisieren. Davon bleibt ein Benutzerprogramm unbe­ +rührt. + + + +Realisierung von abstrakten Datentypen +Der Vollständigkeit halber wird folgendes Beispiel hier gezeigt. Wie neue Datentypen +definiert werden, wird in Kapitel 2.7.1. erklärt. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PACKET widerstaende DEFINES WIDERSTAND, REIHE, PARALLEL, + :=, get, put: + + TYPE WIDERSTAND = INT; + + OP := (WIDERSTAND VAR l, WIDERSTAND CONST r): + CONCR (l) := CONCR (r) + END OP :=; + + PROC get (WIDERSTAND VAR w): + INT VAR i; + get (i); + w := WIDERSTAND : (i) + END PROC get; + + PROC put (WIDERSTAND CONST w): + put (CONCR (w)) + END PROC put; + + WIDERSTAND OP REIHE (WIDERSTAND CONST l, r): + WIDERSTAND : ( CONCR (l) + CONCR (r)) + END OP REIHE; + + WIDERSTAND OP PARALLEL (WIDERSTAND CONST l, r): + WIDERSTAND : + ((CONCR (l) * CONCR (r)) DIV (CONCR (l) + CONCR (r))) + END OP PARALLEL + + END PACKET widerstaende + +____________________________________________________________________________ + + +Dieses Programm realisiert den Datentyp WIDERSTAND und mit den Operationen +eine Fachsprache. + + + +2.4.4 Terminatoren für Refinements, + Prozeduren und Operatoren + + +Das LEAVE-Konstrukt wird verwendet, um eine benannte Anweisung (Refinement, +Prozedur oder Operator) vorzeitig zu verlassen. Es ist auch möglich, geschachtelte +Refinements zu verlassen. + +Form: + +#on("i")##on("b")#LEAVE#off("i")##off("b")# Name + + +Durch eine (optionale) WITH-Angabe kann auch eine wertliefernde benannte Anwei­ +sung verlassen werden. + +Form: + +#on("i")##on("b")#LEAVE#off("i")##off("b")# Name #on("i")##on("b")#WITH#off("i")##off("b")# Ausdruck + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT OP ** (INT CONST basis, exp): + IF exp = 0 + THEN LEAVE ** WITH 1 + ELIF exp < 0 + THEN LEAVE ** WITH 0 + FI; + + INT VAR zaehler, ergebnis; + ergebnis := basis; + FOR zaehler FROM 2 UPTO exp REP + ergebnis := ergebnis * basis + PER; + ergebnis + END OP ** + +____________________________________________________________________________ + + +(Diese Operation realisiert die Exponentiation für INT-Werte) + + + +2.4.5 Generizität von Prozeduren + und Operatoren + + +In ELAN ist es möglich, unterschiedlichen Prozeduren bzw. Operatoren gleiche +Namen zu geben. Solche Prozeduren (Operatoren) werden generische Prozeduren +(Operatoren) genannt. Die Identifizierung erfolgt durch Anzahl, Reihenfolge und Daten­ +typ der Parameter (Operanden). + +Deshalb werden Prozeduren und Operatoren unter Angabe des Prozedur- bzw. des +Operatorkopfes dokumentiert. + +Beispiele: + + +INT OP MOD (INT CONST l, r) +REAL OP MOD (REAL CONST l, r) + + +Der MOD-Operator liefert den Rest einer Division. Er ist sowohl für INT- wie auch +für REAL-Datenobjekte definiert. + + + +PROC put (INT CONST wert) +PROC put (REAL CONST wert) +PROC put (TEXT CONST wert) + + +Die put-Prozedur ist für INT-, REAL- und TEXT-Datenobjekte definiert. + + + +Priorität von generischen Operatoren +Bei der Neudefinition von Operatoren kann man bereits benutzte Sonderzeichen oder +Schlüsselwörter benutzen. In diesem Fall bekommt der neudefinierte Operator die +gleiche Priorität wie der bereits vorhandene Operator. + + + +2.4.6 Rekursive Prozeduren + und Operatoren + + +Alle Prozeduren und Operatoren dürfen in ELAN rekursiv sein. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT PROC fakultaet (INT CONST n): + IF n > 0 + THEN fakultaet (n-1) * n + ELSE 1 + END IF + END PROC fakultaet + +____________________________________________________________________________ + + +Die Fakultätsfunktion ist kein gutes Beispiel für eine Rekursion, denn das Programm +kann leicht in eine iterative Version umgewandelt werden: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT PROC fakultaet (INT CONST n): + INT VAR prod :: 1, i; + FOR i FROM 2 UPTO n REP + prod := prod * i + END REP; + prod + END PROC fakultaet + +____________________________________________________________________________ + + +Die Umwandlung von einem rekursiven Programm in ein iteratives ist übrigens immer +möglich, jedoch oft nicht so einfach, wie in dem Beispiel der Ackermann-Funktion: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT PROC acker (INT CONST m, n): + IF m = 0 + THEN n + 1 + ELIF n = 0 + THEN acker (m-1, 0) + ELSE acker (m - 1, acker (m, n - 1)) + ENDIF + END PROC acker + +____________________________________________________________________________ + + +Das eigentliche Einsatzgebiet von rekursiven Algorithmen liegt aber bei den 'back­ +track'-Verfahren. Diese werden eingesetzt, wenn eine exakte algorithmische Lösung +nicht bekannt ist oder nicht gefunden werden kann und man verschiedene Versuche +machen muß, um zu einem Ziel (oder Lösung) zu gelangen. + -- cgit v1.2.3