• Keine Ergebnisse gefunden

Definition von Literalmengen durch Muster

Zur Definition von Sorten mit (potentiell unendlich) vielen Literalen gibt es in SDL-92 soge-nannte Namensklassen (name classes). Durch eine spezielle Syntax kann man damit eine Men-ge von Literalen beschreiben, die alle einem regulären Ausdruck [ASU86] entsprechen und damit zusammen eine reguläre Sprache bilden.

Beispiel 21. Mit dieser Technik werden die Literale der Sorte Integer definiert

value type Integer;

literals unordered nameclass (('0':'9')*) ('0':'9'));

...

endvalue type;

Die Regel legt fest, dass zur Sorte Integer Literale gehören, die aus beliebig vielen Ziffern bestehen, gefolgt von einer einzelnen Ziffer. Das Zeichen ’*’ bedeutet dabei den Kleene-Stern. Das Zeichen ’:’ kennzeichnet eine Menge von Zeichen eines Intervalls, entsprechend der Ordnung der Zeichen innerhalb der Sorte Character. Das Schlüsselwort unordered darf nur im Annex D verwendet werden, der die vordefinierten Datentypen erklärt.

Während der Entwicklung von SDL-2000 zeigte sich, dass dieses Konstrukt aus SDL-92 zwar in die neue Sprachversion übernommen werden sollte, aber dort nicht die gleiche Ausdrucks-kraft haben kann, wie das SDL-92-Konstrukt. So muss beispielsweise definiert werden, wie sich die Literale in Bezug auf die Operatoren verhalten. In SDL-92 wurden für die Daten des Typs Integer zu diesem Zweck folgende Axiome formuliert:

/* definition of literals */

<<type Integer>> 2== 1 + 1;

<<type Integer>> 3== 2 + 1;

<<type Integer>> 4== 3 + 1;

<<type Integer>> 5== 4 + 1;

<<type Integer>> 6== 5 + 1;

<<type Integer>> 7== 6 + 1;

<<type Integer>> 8== 7 + 1;

<<type Integer>> 9== 8 + 1;

/* literals other than 0 to 9 */

for all a,b,c in Integer nameclass (

spelling(a) == spelling(b) // spelling(c),

length(spelling(c)) == 1 ==> a == b * (9 + 1) + c;

);

Zusammen mit den anderen Axiomen für Addition und Multiplikation definieren diese Axiome das Dezimalsystem: Die Literale 2 bis 9 ergeben sich jeweils durch Addition von 1 aus ihrem Vorgänger. Die Literale aus mehreren Ziffern sind äquivalent zu dem Ausdruck 10*b+c, wobei c die letzte Ziffer des Literals ist. Der Operator spelling erlaubt die Umrechnung eines Literals in seine Zeichenfolge.

In SDL-2000 müssen Operatoren eine algorithmische Definition erhalten, das heißt, ein Al-gorithmus für die Addition müsste den Nachfolger des Literals bestimmen, welches als Argu-ment übergeben wurde. Es gibt jedoch keine inverse Operation zum Operator spelling.

Um die Namensklassen praktisch einsetzbar zu machen, wurde das neue Konzept der Na-mensklassenoperationen definiert, bei dem durch eine einzige Definition eine große Zahl von Operationen definiert werden. Dieses Konzept ist in der abstrakten Syntax 0 durch den Knoten

<name class operation> definiert. Die aus SDL-92 übernommenen Namensklassenliterale wer-den durch Knoten des Typs <name class literal> definiert:

<name class operation> :: <name> <regular expression>

<name class literal> ::<regular expression>

In beiden Konstrukten wird ein regulärer Ausdruck angegeben. Für <name class operation>-Knoten gibt es zusätzlich noch einen „internen“ Namen der Operation. In der konkreten Syntax wird eine solche Operation etwa wie folgt definiert:

operator vokal_endend in nameclass (’a’:’z’)+ -> Boolean { dcl sp Charstring := spelling(vokal_endend);

dcl last Character := sp[length(sp)];

return last = ’a’ or last = ’e’ or last = ’i’ or last = ’o’ or last = ’u’;

}

Mit diesem Namensklassenoperator werden Operatoren definiert, die sämtlich aus Kleinbuch-staben bestehen. Der Wert des Operators ist „wahr“, wenn der Operator mit einem Vokal endet.

Dazu muss in dem Operator seine Schreibweise ermittelt werden. An den Operator spelling wird hierzu der symbolische Operationsname übergeben. Diese wird dann durch die Zeichen des tatsächlichen Operatornamens ersetzt.

Namensklassenoperatoren müssen null-stellige Operatoren sein. Sie dürfen also keine Me-thoden sein und keine Argumente haben.

Die regulären Ausdrücke sowohl für Operationen als auch für Literale sind durch den Knoten

<regular expression> repräsentiert:

<regular expression> ::<or partial regular expression>+

Mit einem regulären Ausdruck wird eine Sprache definiert. Man sagt, dass ein Literal auf den Ausdruck passt, wenn es zu dieser Sprache gehört.

Die einzelnen Teilausdrücke werden in der konkreten Syntax durch das Schlüsselwort or verknüpft, welches die Vereinigung von zwei Teilsprachen definiert.

Beispiel 22. Die Literale der Sorte Real werden durch die Namensklasse

literals unordered nameclass

( ('0':'9')* ('0':'9') ) or ( ('0':'9')* '.'('0':'9')+ );

definiert. Das heißt, ein Real-Literal besteht entweder nur aus Ziffern, oder aus Ziffern, ge-folgt von einem Punkt, gege-folgt von wenigstens einer Ziffer.

Die verschiedenen Alternativen im regulären Ausdruck werden durch den Knoten <or partial regular expression> repräsentiert:

<or partial regular expression> ::<partial regular expression>+

Dieser Knoten wiederum ist eine Liste von <partial regular expression>. Diese Liste bedeutet Hintereinanderschreibung: Ein Literal passt auf den regulären Ausdruck, wenn es sich so in Teilliterale zerlegen lässt, dass jeder Teil auf den entsprechenden Knoten <partial regular ex-pression> passt, und die Verkettung der Teilliterale das Gesamtliteral ergibt. Jeder Teil wird durch die Regel

<partial regular expression> ::

<regular element> [<name> | <plus sign> | <asterisk>]

definiert. Ein solcher Teilausdruck ist ein Knoten vom Typ <regular element>, dem optional eine natürliche Zahl (in der abstrakten Syntax der Knoten <name>), ein Pluszeichen oder ein Stern folgt.

Der Stern bedeutet den Kleene-Stern. Auf den regulären Ausdruck passen Literale, die sich durch beliebige (auch nullfache) Wiederholung des regulären Ausdrucks <regular element> er-geben.

Das Pluszeichen bedeutet, dass die Wiederholung wenigstens einfach sein muss. Die Zahl bedeutet, dass die Wiederholung genau so oft erfolgen muss, wie die Zahl es angibt.

Beispiel 23. Mit folgendem Konstrukt werden Literale definiert, die aus einer geraden Anzahl von Zeichen bestehen:

literals nameclass ((’a’:’z’)2)+

Die Grundelemente eines regulären Ausdrucks sind die Knoten <regular element>:

<regular element> =

<regular expression>

| <character string>

| <regular interval>

Als erste Alternative kann ein beliebiger regulärer Ausdruck Grundelement sein. In der konkre-ten Syntax wird das durch Klammern notiert. Durch diese Konstruktion können verschachtelte reguläre Ausdrücke definiert werden. Die Alternative <character string> erlaubt die Verwen-dung eines einzelnen Zeichens oder einer Zeichenkette als Element eines regulären Ausdrucks.

Der Knoten <regular interval> erlaubt die Angabe eines Intervalls von Zeichen:

<regular interval> ::<character string> <character string>

In der konkreten Syntax werden die beiden Zeichenketten durch das Zeichen ’:’ getrennt. Beide Zeichenketten müssen die Länge 1 haben. Das Intervall bezeichnet dann die Menge aller Zei-chen zwisZei-chen dem ersten und zweiten Kindknoten des Intervalls, einschließlich der Intervall-enden.

Nur innerhalb eines Namensklassenoperators kann der Knoten <spelling term> verwendet werden, der in der konkreten Syntax durch den Operator spelling notiert wird.

<spelling term> :: <name>

Der in diesem Knoten angegebene Name muss die Operation bezeichnen; die Angabe eines Na-mens ist also, genau genommen, unnötig.