Attributgrammatik Werkzeuge -Das JastAdd Semantikspezifikationswerkzeug- Hauptseminar WS06/07 „Methoden zur Spezifikation der Semantik von Programmiersprachen“ Christoff Bürger 1 Inhalt Einleitung Attributgrammatiken – Formal Mindestspezifikation in Werkzeugen – maschinelle Bearbeitung durch impliziten Kontext Werkzeuge für Attributgrammatiken Warum / Wofür Werkzeuge Werkzeugfunktionalitäten und Entwicklungsziele Beispielwerkzeug : JastAdd JastAdds Werkzeugfunktionalitäten und Entwicklungsziele JastAdd Spezifikationen ✔ AST Spezifikationen ✔ Semantikmodul- / Aspektspezifikationen Beispiele Vergleich JastAdds mit anderen Werkzeugen (Eli) Eli Werkzeugfunktionalitäten und Entwicklungsziele Fazit 2 Einleitung – Attributgrammatiken - Formal Formale Attributgrammatikspezifikationen beruhen auf einer mathematischen Spezifikationssprache (mathematischen Notationen), welche Typen, Wertebereiche, Berechnungsfunktionen, Attribute und Auswertungsregeln festlegt. Sie sind daher vollständig und prüfbar, jedoch umfangreich. Eine Attributgrammatik AG basiert auf einer kontextfreien Grammatik G = (N, T, Z, P) mit N ... Nichtterminale T ... Terminale Z ... Startregel P ... Produktionenen der Form A -> S1 S2 S3 ... Sn AG = (G, D, B, R, C) mit D = (K, , , , ) ... Semantischer Bereich B = (S-Att, I-Att, Att, S, I, A, 0, W) ... Attributbeschreibung R ... Semantische Regeln C ... Semantische Bedingungen (Prädikative Regeln) 3 Einleitung – Attributgrammatiken - Formal D = (K, , , , ) ... Semantischer Bereich K ... endliche Menge von Sorten; Typen ... Wertemenge; ordnet jeder Sorte (Typ) alle möglichen Werte zu ... Operationssymbole (vergleichbar C++ Funktionsdeklaration); Abbildung von Argumenten auf Ergebnis, daher ✔ A x A2 x A3 x ... x An -> E 1 ... Prädikatssymbole (vergleichbar C++ Funktionsdeklaration mit Rückgabewert boolean) ... Interpretationsfunktion; Implementierung der Funktionen aus und 4 Einleitung – Attributgrammatiken - Formal Bsp.: K = {String, Char} (Char) = {a, b, c,...,z,A,...,Z} (String) = {w|w = w1w2...wn mit n ≥ 0 und w1,w2,..,wn} = {concat(String x String -> String), ...} (concat) : (String) x (String) -> (String) mit concat(s1, s2) = w1w2...wiwi+1...wn wenn s1 = w1w2...wi und s2 = wi+1...wn 5 Einleitung – Attributgrammatiken - Formal B = (S-Att, I-Att, Att, S, I, A, 0, W) ... Attributbeschreibung S-Att ... Menge der synthetischen Attribute I-Att ... Menge der inheriten Attribute Att = S-Att ∪ I-Att S : N -> {s | sS-Att} ... Zuordnungsfunktion; Ordnet den Nichtterminalen der kontextfreien Grammatik ihre synthetischen Attribute zu. I : N -> {i | iI-Att} ... Zuordnungsfunktion A(X) = S(X) ∪ I(X) mit XN 0S(Z) ... Bedeutungsattribut; synthetische Attribut an der Wurzel des Parsebaumes W : Att -> K ... Zuordnungsfunktion; Ordnet jedem Attribut eine Sorte / Typ zu 6 Einleitung – Attributgrammatiken - Formal Für jede Produktion pP gibt es eine Menge von semantischen Regeln R(p), so dass alle p zugeordneten innen Attribute Ai abhängig von außen Attributen berechnet werden. |R(p)| = |Ai|. Sei p : X0 -> w0X1w1X2...wn-1Xnwn+1 mit wiT* und XiN Eine semantische Regel hat den Aufbau : <a0, jo> = f (<a1, j1>, <a2, j2>,...,<an, jn>) mit n 0 und für n > 0 ist <ai, ji> außen Attribut s <aiA(Xi), i> ... i bezogen auf Indizes von X bei Produktion i i ... i Für eine Produktion auszuwertende synthetische und inherite Attribute (innen Attribute). f(W(a1),...,W(an), W(a0)) semantische Operation 7 Einleitung – Mindestspezifikation in Werkzeugen – impliziter Kontext Werkzeuge für AG müssen in der Lage sein formale Spezifikationen umzusetzen. Es ist jedoch schwierig die Mächtigkeit und damit Einfachheit mathematischer Notationen bereitzustellen. Formale Spezifikationen sind zu umfangreich : Vereinfachung durch impliziten Kontext, welcher Vollständigkeit und Prüfbarkeit von Werkzeugspezifikationen erlaubt, jedoch bestimmte Spezifikationsteile aus anderen herleitet bzw. zusammenlegt bzw. vorweg nimmt. Impliziter Kontext : Vordefinierte und implementierte atomare Operationen und Typen. Alle weiteren Operationen und Typen beruhen auf diesen. Legt implizite Spezifikationssemantik und Syntax fest. Der implizite Kontext muss existieren, da nur er eine maschinelle Implementierung und Auswertung erlaubt! 8 Einleitung – Mindestspezifikation in Werkzeugen – impliziter Kontext AG = (G, D, B, R, C) mit D = (K, , , , ) ... Semantischer Bereich B = (S-Att, I-Att, Att, S, I, A, 0, W) ... Attributbeschreibung R ... Semantische Regeln C ... Semantische Bedingungen (Prädikative Regeln) Farblich hervorgehobene Teile sind explizit zu definieren in einer Spezifikation für eine maschinelle Spezifikationssprache für AG. Ihre Semantik wird durch die Sprache festgelegt (impliziter Kontext). Farblich gleich markierte Teile sind zusammenfassbar um die maschinelle Spezifikation zu vereinfachen. Man beachte, dass atomare Typen und deren Wertebereich durch die Sprache implizit festgelegt werden, daher K die Möglichkeit darstellt eigene Typen aufbauend auf atomaren zu definieren. Dies muss nicht möglich sein, ist aber Standard. Analoges gilt für Operationssymbole. 9 Einleitung – Mindestspezifikation in Werkzeugen – impliziter Kontext Durch die maschinelle Spezifikation kann sich eine AG Spezifikation folgendermaßen vereinfachen : AG = (G, K, , S, I, W, R) mit G ... kontextfreie Grammatik K ... Datentypen ... semantische Funktionen S ... Zuordnung von synthetischen Attributen zu Grammatiksymbolen I ... Zuordnung von inheriten Attributen zu Grammatiksymbolen W ... Zuordnung von Datentypen an Attribute R ... Semantische Regeln Der implizite Kontext (Spezifikationssprache) muss diese Teile definieren und schränkt sie ein (insbesondere Datentypen). Blau markierte Teile sinnvollerweise in einem Spezifikationsschritt durchführbar, daher jedes deklarierte Attribut wird bei der Deklaration gleichzeitig gebunden an Nichtterminal, Datentyp und Attributtyp : AG = (G, K, , A, R). 10 Einleitung - Zusammenfassung Fazit : Ein Werkzeug für AG steht und fällt mit seiner Spezifikationssprache. Zwei mögliche Sprachkonzepte : Spezifikationen erstellt von Menschen per Hand Maschinell erstellte Spezifikationen / Generatoren Spezifikationssprache impliziter Kontext Formal Maschinell Spezifikation Mathematik Logik proprietäre Werkzeugsprache Attributauswerter 11 Werkzeuge für Attributgrammatiken Werkzeuge für AG ermöglichen die automatisierte Generierung von Attributauswertern gemäß einer Spezifikation und die Prüfung derselben. Sie sind überall dort einsetzbar, wo Parsebäume kontextfreier Grammatiken semantisch ausgewertet werden müssen. Wichtige Qualitätskriterien sind : Verständlichkeit, Mächtigkeit der Spezifikationssprache Geschwindigkeit, Speicherverbrauch und Typ des Attributauswerters Integrierbarkeit von Syntaxanalysewerkzeugen Benutzerfreundlichkeit (GUI etc.) 12 Werkzeuge für Attributgrammatiken Wesentliche Entwicklungsziele sind : Möglichkeit Parsebäume der syntaktischen Analyse für die semantische aufzubereiten Möglichkeit semantische Spezifikationen (gängiger semantischer Aufgaben) wiederverwenden zu können und kombinieren zu können Bestehende semantische Spezifikationen leicht erweitern zu können (z.B. wenn Syntax erweitert wird) Leicht zu erlernende, aber mächtige Spezifikationssprache Attributauswertungsregeln einfach umzusetzen, ähnlich einer formalen Spezifikation auf dem Papier Spezifikationssprache sollte bekannt erscheinen Einfache Attributhandhabung (keine umständlichen Kopierregeln, einfache Sammlung von Attributen) Leicht integrierbarer Attributauswerter mit guten Schnittstellen 13 JastAdd - Entwicklungsziele JastAdds wesentliche Entwicklungsziel ist es, die Wiederverwendung von Semantikspezifikationen und deren Erweiterung zu ermöglichen (just to add semantics). Dabei wird ein objektorientiertes Entwicklungsmodell verwendet, sowie eine deklarative Spezifikationssprache. Orientierungspunkt ist die Java Sprachsyntax und Semantik. JastAdd konzentriert sich nur auf die semantische Auswertung. Es bietet Schnittstellen um Parser zu integrieren, welche die auszuwertenden Parsebäume generieren. Vom Parser bereitgestellte Parsebäume müssen einer abstrakten Syntaxbaumspezifikation genügen (AST-specification). 14 JastAdd – Funktionalitäten und Entwicklungsziele JastAdd ermöglicht die Spezifikation von AG wie von Knuth 1968 eingeführt und Generierung von Auswertern, erweitert diese Basiskonzepte jedoch um : Referenzierte Attribute (referenced attributes) Parametrisierte Attribute (parameterized attributes) Rekursive Attributauswertungsfunktionen (circular evaluation functions) Deklarative Spezifikationen (declarative specifications) Objekt orientierter Ansatz (object oriented design) Deklarative Parsebaumumschreibung (rewriting rules) Semantikmodule (semantic aspect weaving) 15 JastAdd – Spezifikationen Eine JastAdd Spezifikation besteht aus zwei wesentlichen Teilen : AST-Spezifikation ... Spezifiziert die Struktur von Syntaxbäumen, deren Semantik zu bestimmen ist (*.ast) Aspekt-Spezifikationen ... Spezifiziert die Attribute, deren Typen und Auswertungsregeln (*.jadd / *.jrag) AST-Spezifikationen definieren eine Java Klassenhierarchie und Aggregatabhängigkeiten. Sie spezifizieren eine abstrakte Grammatik. Vom Parser generierte Parsebäume müssen der AST-Spezifikation genügen, daher sie müssen eine Komposition aus Java Objekten darstellen. Aspekt-Spezifikationen sind Module, welche die Semantik (oder Teile davon) einer abstrakten Grammatik mithilfe von AG definieren. Daher spezifizieren sie Attribute, deren Typen (sowohl Daten- als auch Attributtyp) und Auswertungsregeln. 16 JastAdd – Spezifikationen Die AST-Spezifikationen werden in Java Klassen übersetzt, den ASTclasses. Die Übersetzung einer AST-Spezifikation resultiert in den ASTclass skeletons. Die Aspekt-Spezifikationen werden ebenfalls in Java Code übersetzt und anschließend auf Aspekt orientierte Art und Weise in die AST-class skeletons eingewoben, so das die finalen AST-classes entstehen. Die Semantik einer Sprache ist daher vollständig in den generierten ASTclasses spezifiziert. Die Attributauswertung steckt implizit in den finalen AST-classes. Für jedes Attribut gibt es eine gleichnamige Accessormethode. Wird diese aufgerufen, so sichert JastAdd ab, dass der korrekte Attributendwert geliefert wird. 17 JastAdd – AST-Spezifikationen Die genaue Definition und der Übersetzungsprozess von kontextfreien Grammatiken in AST-Spezifikationen stehen im zugehörigem paper. Vorteile : Typsicherheit; Objekt orientiert geg.: kontextfreie Grammatik A -> t1B ges.: AST-Spezifikation A ::= <t1> B; B -> t2 B B -> C D B -> D abstract B; B1 : B ::= <t2> B; B2 : B ::= C D; B3 : B ::= D; C -> C -> E C ::= [E]; D -> t4 D ::= t4; E ::= ; E -> 18 JastAdd – Aspekt-Spezifikationen Die genaue Definition von Aspekt-Spezifikationen steht im zugehörigem paper. Aspekt-Spezifikationen : Deklarative oder imperative Spezifikation von Attributen, deren Typen, der Zuordnung zu den Nichtterminalen (ASTclasses) und Auswertungsregeln. In den Aspekt-Spezifikationen steht die komplette Java-Syntax und Semantik zur Verfügung, genauso wie die Möglichkeit beliebigen weiteren Java Quellcode einzubinden. Schlüsselwörter : aspect syn, inh, lazy, eq refine rewrite, when, to 19 JastAdd – Aspekt-Spezifikationen Attributdeklaration : ATyp lazy JavaTyp ASTClass.attributName(JavaParameterListe); ATyp = {syn, inh} lazy ... optional, zum cachen berechneter Werte Attributauswertung (synthetische Attribute) : eq ASTClass.attributName = JavaExpression; eq ASTClass.attributName { //JavaCode return AttributOfASTClassType; } Attributauswertung (inherite Attribute) : eq ASTClass.getSubComponent().attributName = JavaExpression; eq ASTClass.getSubComponent().attributName { //JavaCode return AttributOfSubComponentASTClassType; } 20 JastAdd – Beispiel 21 JastAdd – Aspekt-Spezifikationen Aspekt-Spezifikationen sind unabhängig voneinander und es können beliebig viele semantische Aspekte in die Semantik integriert werden. Der Nutzer muss sich keine Gedanken darüber machen, in welcher Reihenfolge Attributauswertungen und Parsebaumumschreibungen vorgenommen werden, JastAdd regelt dies automatisch. Es ist garantiert, dass immer wenn auf einen Attributwert mit dessen Accessormethode zugegriffen wird, dieser berechnet wurde. Graph rewrite Schritte werden immer sobald wie möglich durchgeführt. Es ist möglich in einem Aspekt Attribute, welche in einem anderen Aspekt spezifiziert wurden, zu benutzen. Auswertungsfunktionen eines Aspektes können von einem anderen Aspekt überschrieben werden (refine). Der Objekt orientierte Ansatz erlaubt die Generalisierung und Spezialisierung von Semantikbestandteilen. 22 JastAdd – Zusammenfassung 23 JastAdd – Zusammenfassung Trotz aller Vorteile und der Einfachheit der Spezifikationssprache gibt es gerade bei komplexen Spezifikationen einige Hürden : Durch zirkulare Attributauswertungsfunktionen die Gefahr der Nichtterminierung -> Semantisch gesehen korrekt, da unendliche Rekursion keine Semantik besitzt. Potenziell zirkulare graph rewriting Regeln. Zirkularität durch eine Kombination der ersten beiden Typen (schwer nachzuvollziehen). Bindung von Attributen über Produktionen !!! Bug ? Feature ? Oder einfach nur ein fieser Hack. Eigener Aspektweber; Nutzung von AspectJ wäre besser. Die Erweiterungen des Basiskonzeptes von AG sind sinnvoll, führen jedoch zu einem größeren theoretischen Hintergrund -> Erhöhung der Komplexität der semantischen Spezifikationen, jedoch NICHT deren Größe (kleine Spezifikationen die viel machen). 24 Vergleich mit anderen Werkzeugen - Eli Älteres Tool, welches alle Phasen der Compilerentwicklung umfasst (Lexer, Parser, semantische Analyse). Ausgehend von Spezifikationen wird C Code mit passenden Makefiles generiert Stellt Sammlung vieler einzelner Tools dar -> LIDO ist die semantische Spezifikationssprache. Aus einer semantischen Spezifikation wird ein LIGA C Attributauswerter generiert. Viele Erweiterungsmodule (z.B. um Attributabhängigkeiten graphisch darzustellen) Attributdatentypen sind C Datentypen; Funktionen welche bei der Attributauswertung benutzt werden sind C Funktionen. Für diese Teile ist der Nutzer selbst zuständig. Sie werden in der Spezifikation nur benutzt / erwähnt. -> yacc ähnlich Der Ansatz der Spezifikationssprache LIDO ist derselbe wie der von yacc Spezifikationen. Es gibt eine externe graphische Benutzeroberfläche : LAMA 25 Vergleich mit anderen Werkzeugen - Eli Spezifikation von vom Kontext unabhängiger Berechnungen (symbol computations) -> in JastAdd möglich, indem Berechnungen an abstrakte AST-classes gebunden werden. Einsparen von copy rules möglich durch remote dependencies Berechnungen während der Parsebaumkonstruktion -> in JastAdd nicht möglich (nur über hacking ähnliche Umwege) Auswertung zirkulärer Attributabhängigkeiten möglich, wenn man den Test auf Zirkularität abstellt. Jedoch keine automatische Generierung notwendiger Fallunterscheidungen um eine Rekursion abzubrechen -> Abbruch (Fixpunkt) muss selbst kontrolliert werden -> imperativ Semantikmodule werden unterstützt und eine Bibliothek mit gängigen Semantikkonzepten liegt vor. 26 Vergleich mit anderen Werkzeugen - Fazit JastAdd ist ein aktives Projekt mit guten Aussichten für die Zukunft. Eli hat sich in der Vergangenheit bewährt, beruht jedoch auf überholten Entwicklungszielen. JastAdd kann alles was Eli kann, hat jedoch die intuitiver und verbreitetere Spezifikationssprache (Java ähnlich). Der Einstieg in JastAdd ist leichter, da der Objekt orientierte Ansatz verständlich ist. Mit Eclipse gibt es eine gute Entwicklungsumgebung. Die Java Klassenbibliothek erlaubt eine effiziente Implementierung komplizierter Attributauswertungsfunktionen. Die Ausnutzung natürlicher, durch die Java Spezifikation gegebener Vorteile ist der große Vorteil JastAdds (referenced attribute grammars in einer Sprache basierend auf Referenzen; Modularität und Wiederverwendbarkeit einzelner Aspekte (Kapselung) in einer Objekt orientierten Umgebung vs. Imperative). 27