• Keine Ergebnisse gefunden

Beispiele für die Konstruktion der Abstrakten Syntax 1

Zur Abbildung der abstrakten Syntax 0 auf die abstrakte Syntax 1 wird eine Funktion Mapping definiert, die durch die Signatur

Mapping: DefinitionAS0 DefinitionAS1

deklariert wird. Diese Funktion besteht aus einem einzigen case-Ausdruck, der für alle relevan-ten Muster der abstrakrelevan-ten Syntax 0 einen Ausdruck angibt, der den entsprechenden Knorelevan-ten der abstrakten Syntax 1 konstruiert.

Für die meisten Konstrukte ist die Abbildung in der informalen Semantik ohne spezielle Er-läuterung im englischen Text definiert, da in der Einleitung von [Z.100-00] eine allgemeine Re-gel aufgestellt wird: Wenn keine speziellen Aussagen getroffen werden, dann wird das Nichtterminal <x> der konkreten Syntax auf die gleichnamige Regel X der abstrakten Syntax 1 abgebildet. Ein Beispiel für eine derartige Abbildung wird in Abschnitt 7.4.1 gegeben. Die Ab-schnitte 7.4.2 und 7.4.3 geben Beispiele für nicht-triviale Abbildungen.

7.4.1 Gleichheit von Ausdrücken

In der abstrakten Syntax 0 ist die Gleichheit und Ungleichheit von Ausdrücken durch die Gram-matikregel

<equality expression> ::

<expression> { <equals sign> | <not equals sign> } <expression>

definiert. Nach dieser Regel hat der Knoten <equality expression> zwei Formen: Wird zwischen den beiden Ausdrücken der Knoten <equals sign> (in der konkreten Syntax „=“) verwendet, tes-tet der Ausdruck auf Gleichheit. Wird der Knoten <not equals sign> („/=“) verwendet, testes-tet der Ausdruck auf Ungleichheit.

In der abstrakten Syntax 1 lautet die entsprechende Regel

Equality-expression :: First-operand Second-operand First-operand = Expression

Second-operand = Expression

Mit dieser Syntax kann nur noch die Gleichheit von Ausdrücken erfasst werden. Die Semantik des Knotens <not equals sign> wird durch ein Transformationsmodell erklärt:

<equality expression>(x, <not equals sign>, y)

=8=> <expression gen primary>(not, <equality expression>(x, <equals sign>, y))

Mit diesem Modell wird ein Ausdruck, der den Operator „/=“ verwendet, in einen Ausdruck transformiert, der den Operator „=“ verwendet, und das Ergebnis negiert.

Damit muss sich die Abbildung auf die abstrakte Syntax 1 nur noch mit dem Fall <equals sign> beschäftigen. Da die Knoten der abstrakten Syntax genauso heißen wie die der konkreten Syntax, wird im Haupttext von [Z.100-00] keine weitere Regel angegeben. Die Formalisierung der Abbildung lautet

| <equality expression>(first, <equals sign>, second)

=> mk-Equality-expression(Mapping(first), Mapping(second))

Mit dieser case-Alternative der Funktion Mapping wird aus einem Knoten <equality expressi-on> ein Knoten Equality-expression erzeugt. Für die beiden Argumentausdrücke wird die Funk-tion Mapping aufgerufen, die die Entsprechung der Argumente in der abstrakten Syntax 1 ermittelt.

7.4.2 Unterscheidung von Assignment und Assignment Attempt

Zur Umwandlung einer Referenz auf einen Basistyp in eine Referenz auf eine Ableitung dieses Typs (assignment attempt) wird in SDL in der konkreten Syntax das Zuweisungszeichen be-nutzt, genau wie bei einer normalen Zuweisung (siehe Abschnitt 3.4). In der abstrakten Syntax

1 wird zwischen diesen beiden Formen der Zuweisung jedoch unterschieden. Die abstrakte Syn-tax lautet hierfür

Assignment :: Variable-identifier Expression Assignment-attempt :: Variable-identifier Expression

Zur Konstruktion der abstrakten Syntax aus der konkreten wird in der informalen Grammatik die folgende Formulierung verwendet:

If the <identifier> has been declared with an object sort and the sort of the <expression> is a (direct or indirect) supersort of the sort of the <identifier>, the <assignment> represents an Assignment-attempt. Otherwise, the <assignment> represents an Assignment.

Diese Beschreibung wurde durch folgende case-Variante in der Funktion Mapping formalisiert:

| <assignment>(var,expr)

=> if isAttempt(var.staticType, expr.staticType) then

mk-Assignment-attempt(Mapping(var), Mapping(expr)) else

mk-Assignment(Mapping(var), Mapping(expr)) endif

In diesem Ausdruck werden eine Reihe von Hilfsfunktionen verwendet:

• Die Funktion staticType ermittelt für einen Ausdruck den statischen (deklarierten) Daten-typ.

• Die Funktion isAttempt bestimmt für zwei Typen, ob der eine eine Spezialisierung des anderen ist. In diesem Fall wird ein Knoten vom Typ Assignment-attempt konstruiert, ansonsten einer vom Typ Assignment.

Beide Formen der Zuweisung besitzen in der abstrakten Syntax 1 zwei Kindknoten. In beiden Fällen ergeben sich diese durch Aufruf der Funktion Mapping für die Variable und den Aus-druck in der abstrakten Syntax 0.

7.4.3 Konstruktion von Object- und Value-Typen

Zur Darstellung von Datentypdefinitionen gibt es in der abstrakten Syntax 1 folgende Konstruk-te:

Data-type-definition = Value-data-type-definition

| Object-data-type-definition

| Interface-definition Value-data-type-definition :: Sort

Data-type-identifier Literal-signature-set

Static-operation-signature-set Dynamic-operation-signature-set Data-type-definition-set

Syntype-definition-set Exception-definition-set Object-data-type-definition :: Sort

Data-type-identifier Literal-signature-set

Static-operation-signature-set Dynamic-operation-signature-set Data-type-definition-set

Syntype-definition-set Exception-definition-set

Der Knotentyp Interface-definition entsteht, der allgemeinen Regel folgend, aus dem Knoten

<interface definition>. Schwieriger ist die Erzeugung der Knoten Value-data-type-definition und Object-data-type-definition. Obwohl es keine gleichnamigen Konstrukte in der konkreten Syntax gibt, wird in der informalen Semantik jedoch auch keine Konstruktionsregel für die ab-strakte Syntax angegeben.

Jedoch ist offensichtlich, dass diese Knoten zur Darstellung von Wertetypen und Objektty-pen gedacht sind. Auf dieser Interpretation basierend wurde folgende formale Abbildung defi-niert:

| <data type definition>(*, *, <data type heading>(value, name, *, *), base, body) =>

mk-Value-data-type-definition(Mapping(name), Mapping (base), { e Mapping(body).toSet: e Literal-signature },

{ e Mapping(body).toSet: e Static-operation-signature }, { e Mapping(body).toSet: e Dynamic-operation-signature }, { e Mapping(body).toSet: e Data-type-definition },

{ e Mapping(body).toSet: e Syntype-definition }, { e Mapping(body).toSet: e Exception-definition })

| <data type definition>(*, *, <data type heading>(object, name, *, *), base, body) =>

mk-Object-data-type-definition(Mapping(name), Mapping (base), { e Mapping(body).toSet: e Literal-signature },

{ e Mapping(body).toSet: e Static-operation-signature }, { e Mapping(body).toSet: e Dynamic-operation-signature }, { e Mapping(body).toSet: e Data-type-definition },

{ e Mapping(body).toSet: e Syntype-definition }, { e Mapping(body).toSet: e Exception-definition })

| <data type definition body>(entities, ctor, operations, *) =>

Mapping(entities) Mapping(ctor) Mapping(operations)

Nach dieser Abbildungsregel wird ein Knoten <data type definition> auf den Knoten Value-type-definition abgebildet, wenn im Knoten <data type heading> das erste Element value ist, an-sonsten entsteht ein Knoten Object-type-definition.

Die verschiedenen Elemente des Körpers der Datentypdefinition werden zunächst über die Regel für <data type definition body> auf eine Liste von Knoten abgebildet. Zur Konstruktion der Datentypdefinition werden dann die Listenelemente je nach Zugehörigkeit zu einem Kno-tentyp (Literal-signature, Static-operation-signature usw.) in die Kindknoten der DaKno-tentypdefi- Datentypdefi-nition eingefügt.