Im nächsten Abschnitt 3-4-2 möchte ich Ihnen
nicht eine Methodik vorstellen, sondern das entsprechende Werkzeug hintergrund.
Und zwar deswegen, weil wir keine Compiler-Technik als solches
in dem Umfang unserer Lehrveranstaltungen haben. Und deswegen das hier
mal kurz darstellen wollt. Wir haben hier Fragen dazu,
nämlich die Frage 5 und 6. Welche Bestandteile eines Compilers
werden auf der Code bei Analyse auf der Kohlebene eingesetzt?
Und eine Frage zum abstrakten Syntaxbaum. Das ist das,
was wir dabei ins Nutzer zunutze machen wollen
Zunächst möchte ich Ihnen vorstellen, wie ein typischer Compiler aussieht.
So ein typischer Compiler ist hier dargestellt, als so eine
Art Durchlauf, eine hintenannte Aneinanderreihung von Verarbeitungsschritten. Und das,
was da durchgeht, ist zu Anfang, es startet mit einem,
hier vorne geht quasi der Programmtext rein und wir gehen jetzt mal davon aus,
dass es ein Programmtext ist, mit Makros, wenn es mit Makros wäre,
würde der die Makros zunächst von dem Pre-Prozessor verarbeitet.
Solche Makros haben wir zum Beispiel, wenn wir mit
C Plus Plus arbeiten
Wie auch immer, wenn wir selbst zumindest nicht wären,
dann kommt also hier der Quelltext, drei Programm, sechs heißt Quelltext.
Und dieser Quelltext ist erstmal eine Aneinanderreihung von Zeichen, von Charakters,
die mit Leerzeichen und Steuerzeichen wie White Spaces oder sowas,
glaube ich, würde hören, also neuer Zeilenvorschub, Teilenwechsel versehen sind.
Und die werden erstmal durchsucht von einem Programm,
das nennt sich Lexer, der macht die lexikalische Analyse und erkennt Schlüsselwörter.
Diese Schlüsselwörter werden als Token bezeichnet und alles,
was der dabei erkennt, wird dann als solches gekennzeichnet.
Und danach haben wir sogenannten Token Strom. Das bedeutet also,
alles, wenn Sie da zum Beispiel haben,
wenn Sie da Inteacher haben und Inteacher seinen Schlüssel wird,
dann ist das nicht mehr die Folge von Zeichen wie NTE-EKR und so weiter,
sondern das ist der Token Schlüsselwort, der Test als Token Inteacher.
Und wenn wir danach einen Bezeichner haben für einen Variablennamen,
die klasse Kunde oder so etwas, dann bleiben das das,
wird vom Next noch nicht erkannt, weil der Kunde ist kein Token,
das bleiben erstmal Einzelzeichen. Dann wird das Ganze analysiert,
und zwar lexikalisch mit anhand der von Regeln der Grammatik analysiert,
und dieses Werkzeug ist ein Parser, der Parsa kennt die Grammatik,
bekommt die Grammatikstruktur als Inpute.
Also wenn wir den Datenstrom so wollten, können wir auch sagen,
okay, hier beim Lexer kommen die Menge der Schlüsselwörter rein,
beim Parsa, die Zusammenhänge zwischen den Schlüsselwörtern und der Parsa baut daraus einen abstrakten Syntaxbau.
Diesen Begriff hatten wir eben schon in den Fragen.
Wir werden also gleich sagen, wir sind abstrakter Syntaxbaum ist.
Dann macht typischerweise wird eine semantische Analyse durchgeführt. Semantik heißt
jetzt hier, wie hängen die Sachen zusammen? Ja,
und dann werden wir zu deinem Verstand zum Beispiel,
ach das, was dort als Typ definiert ist,
ist dann dort der Typ, der dort instanziert wird,
als bei der Inzenzierung einer Variable benutzt wird.
Manchmal bildet hier eine, bei manchen Sprachen gibt es einen Generator dazwischen,
Sprache, manchmal gibt es eine Lösung, Optimierung,
auf jeden Fall werden hinterher diese Dinge,
die man hier im Syntagsbaum hat, umgesetzt in Code-Bestandteile und es wird ausführbarer Code hinten rausgegeben.
Das ist dann eben wirklich der Code in einer Maschinensprache,
Binärcode, wenn sie so wollen. Ja,
wir gehen nicht genauer drauf ein, was da alles ist,
was es für Grammatiken gibt, wie solche Compiler,
es gibt auch noch andere Compiler-Strukturen,
wir konzentrieren uns eigentlich auf den oberen Teil hier,
weil dieser Teil hilft uns, Analyse von Programmen durchzuführen.
Natürlich könnten wir auch Analyse dadurch machen, dass wir Schlüsselwörter suchen.
Aber wenn sie nur Schlüsselwörter suchen, finden sie nicht,
wo sind denn die Zusammenhänge. Deswegen muss man hier,
ist der Paarsack, der für uns interessanteste Teil der für die Analyse genutzt werden kann.
Und das haben wir hier auf dem nächsten, auf dem nächsten Bild.
Ja, wir versuchen, wir nutzen die lexikalische Analyse,
die Schlüsselwörter erkennen dann den grammatikalischen, die lexikalische Analyse,
um mit dem Parser den abstrakten Syntagsbaum zu finden
Und versuchen, die Syntax dann zu analysieren, um eine statische Struktur des Programms zu bekommen.
Danach würden wir nicht Code einbauen, zusammensetzen für Ausbildbare,
sondern wir würden eben Analysen darauf durchführen, im Sinne von,
wir haben dann Annotationen, die dann sagen,
was passiert denn hier, wo ist etwas,
besondere Strukturen oder was wir auch immer wissen wollen.
Und das gibt uns am Ende, hier steht jetzt Wissensbasis auf dieser Folie,
es ist ein bisschen hochgestochen, wir bekommen Informationen über dieses Programm.
Damit Das ist schon mal das, was wir hier wesentlich meinen.
Also die Bestandteile eines typischen Compilers, die wir dazu brauchen können,
sind vor allen Dingen Lexa und Parser, insbesondere der Parser,
der uns hilft, hier etwas zu tun.
So, die weichlichste Frage zieht wir aber auf den abstrakten
Syntaxbaum und das ist das, was uns eigentlich interessiert.
Das ist das, was ich Ihnen in diesem Abschnitt nahe bringen möchte. Dieser abstrakte Syntaxbaum,
ich habe hier mal ein Beispiel genommen von einem Kollegen,
der eine Pascal und Fortran ähnliche Sprache genommen hat und zwar
diese Sprache ist dadurch gekennzeichnet, Also Typ,
dass ich einen Deklarationsteil habe und einen Anweisungsteil.
Und Sie sehen schon, hier arbeitet man mit Beginn und End.
Bei Jarra wäre das Geschlecht für Klammer aufgeschweifte Klammer zu.
Aber, und das ist Deklarieren,
haben wir in Java nur so durch die Reihenfolge gegeben.
Hier in dieser Sprache ist es also so,
dass man einen Deklarationsteil hat und dann einen Anweisungsteil.
Und was wir hier sehen, ist total minimal.
Ja, also bei Einweisungsteil gibt es gerade mal
eine Anweisung und die ist auch nun wirklich eigentlich trivial.
Ihr müsst ja wenigstens eine Mariate stehen oder sowas.
Aber wir haben immer das Problem, wir wollen das so,
dass es auf eine Folie passt und schon dieses
winzige Beispiel füllt diese Folie fast vollständig
Lassen Sie uns mal angucken, was wir über die Grammatik hieraus erfahren.
Eigentlich müssten wir ja, und das hatte das Vorgehende,
beim vorgehenden Bild, hätte ich das ja gesagt,
hier beim Paser fließt auch die Grammatik mit ein.
Und beim nächsten oder die Menge der Schlüsselwörter. Der Lexer ist nicht so spannend,
aber der Paser ist interessanter, weil dort die Grammatik,
die Regeln der Sprache, der Aufbau der Sprache mit reinfließen.
Und das haben wir jetzt hier nicht auf der Folie,
aber wir können es ahnen, aufgrund der Struktur des Syntaxbaums.
Zunächst sehen wir hier, es gibt zu Anfang ein Deklarationsteil in deinen Anweisungsteil.
Das Ganze ist hier aufgeteilt, Block Und hier die Declarations und die Statements,
so kann man diese Abkürzung jetzt hier in diesem Beispiel interpretieren.
Und es geht für uns auch nur darum,
dass sie ein Gefühl dafür kriegen,
was ist denn für Informationen in diesem abstrakten Syntagsbaum enthalten?
Ja, also der Blog, das Ganze ist der Blog,
der besteht aus Deklarationen und Anweisungen und auf der Deklarationsseite
haben wir erstmal Zweier, also eine Sequenz, nämlich 1, 2.
Und diese Sequenz besteht, das erste ist eine Typleklaration,
das ist diese Zeile.
Und dieser Typ da, und dann als zweites haben wir
eine Variable in Deklaration.
Die Variable V ist von Typ
Das ist nun hinreichend simpel. Ja, das ist so,
neid auch so ein bisschen Hello-World-Beispiel. Wenn wir aber ein komplizierteres Programm haben,
würde der Beispiel über das Ding hier nicht mehr draufpassen.
So, wir können, es reicht uns aber trotzdem,
dass wir uns das anschauen können.
Bei dem Typ Deklaration ist es ja so,
dem Typ T wird dieser Typ vordefinierter Typ Intergeorg zugewiesen.
Ja, und diese Typ Zuweisung passiert hier über einen Typ Deklaration.
Wir haben den vordefinierten Typ Intergeorg, das wäre nebenbei Märkt
so ein Schlüsselwort, die das Alexa erkannt hat oder erkennen sollte.
Und dann haben wir eine ID, das T, eben nicht,
das ist kein Schlüssel mit der Sprache und deswegen sagt man,
wird der Compiler dann, der Passer dann das unterstellen.
Das ist eine ID, ein Bezeichner. So wie der
Bezeichner Tee, dem wird der Typ Intager hier zugewiesen.
Das ist diese Anweisung. Wir haben in der Sequenz eine weitere Anweisung,
nämlich eine Variablen,
eine Deklaration und da wird der Variable mit dem Identifier,
mit dem Bezeichner V, wird ein Typ mit dem Bezeichner Tee zugewiesen.
Mehr sagt diese Teile erstmal hier nicht und das ist die
grammatikalische Information, die man da rausziehen kann
Wir ignorieren, Sie sehen,
hier gibt es noch so kleine Pfeile in Grün und Blau,
die ignorieren wir erst mal in diesem Schritt.
Das wäre aus dem nächsten Schritt, wenn es darum geht,
die Semantik zu ignorisieren. Wenn wir erst mal weitergehen bei
der Syntaxanalyse, dann kommt jetzt hier der zweite Teil.
Das ist der Anweisungsteil und da gibt es keine Sequenz,
weil es gibt nur eine einzig Anweisung.
Diese Anweisung ist eine Zuweisung, Assignment und Zuweisung
halt eine linke Seite und eine rechte Seite.
Neftenside, Write-Hand-Side, kann man hier diese Interpret,
kann man das interpretieren? Also das ist in Informationen,
die offensichtlich aus der Grammatik stammt und die Grammatik ist uns
jetzt hier nicht mitgegeben
Und die linke Seite ist, da gibt es nur eine Variable mit
dem Bezeichner V und auf der rechten Seite gibt es eine Addition.
Und diese Addition hat auch eine linke und eine rechte Seite,
in dem Fall, es könnte auch eine größere Addition geben,
auch in dem Fall ist es nur diese beiden Elemente,
und zwar in dem Fall werden zwei literale,
und zwar nun mehrerische literale addiert.
Dass es ein bisschen sinnfrei ist, lassen wir ja jetzt mal darauf hin,
es geht uns jetzt darum, die Struktur hier abzubilden.
Und hier gibt es, literal hat hier einen Wert,
während eben eine Variable
ein Identifier hat
Soweit, das entspricht dem, das ist der abstrakte Syntaxbaum,
dieser Paar wenigen Anweisungen. Wenn wir jetzt mal nochmal vergleichen,
hier haben wir hinterher noch eine semantische Analyse,
wo Anattationen dazukommen, wo ich vorhin ja gesagt habe,
da wird vermittelt, was gehört denn zusammen und das ist das,
was sie durch die Pfeile dargestellt wird.
Also hier zum Beispiel gibt es einen Pfeil,
dass die Typdeklaration hier dem hier verwendet wird. Ja,
also der Compiler kriegt also die Information daraus oder kann diese Information aus dem Syntaxbaum entnehmen,
dieses Tee, was hier definiert wird, hier,
das ist was hier, dem Foul zugewiesen wird.
Diese Information ist hierdurch den blauen Pfeil dargestellt. Das Gleiche
trifft hier für die Variable V zu, die Variable V,
die hier in dem Statement, in dieser Additionsanweisung verwendet wird,
die bezieht sich hier auf diese Deklaration, auf diese Variablendeklaration.
Und das ist auch wieder eine etwas, was während der Analyse
des Prokrammtexts Startelf statische Weise in der statischen Analyse gefunden werden kann.
Ja, die anderen Pfeile, die hier drin sind,
das sind dann Punkte, diese gestrichelten grünen Pfeile,
die können sie zu interpretieren, dass es hier Bezüge gibt,
ob etwas gültig ist.
Zum Beispiel ein Literal, das muss zu dem Typ passen.
Nämlich hier, eine 2 ist Intacher, um diese Typdeklaration
des Intacher, ja, das passt. Die Additionsoperation,
die wir hier haben, passt auch zum Typ Intacher,
ja, das ist in Ordnung, ja,
und hier die Variablen, passt zu der Typdeklaration.
Auch das ist soweit in Ordnung. Ja, also das sind Sachen,
da würde der Compiler beim Compilerlauf dann sonst einen Typ Fehler bringen,
das sind diese grünen Linien und bei dem anderen würde,
wenn das nicht fahren hier,
würde er sagen,
das ist
irgendwie nicht definiert
Also das sind Informationen, die wir in dem abstrakten Syntagsbaum
kriegen und die sind doch noch viel besser zugänglich,
als wenn wir das jetzt hier mit Stringsuche bearbeiten würden.
Hier haben wir die Struktur und was besonders für uns
wichtig ist, die Formatierung spielt keine Rolle.
Also wenn wir das jetzt hier ganz anders formatieren,
selbst wenn wir das alles in eine Zeile packen,
da kommt Pie für den Compiler-Werbes ja nun das Beste,
das Gleiche, aber für uns Menschen wäre es anders.
Hier ist das davon unbeeinflusst. Das ist das,
was uns dabei hilft. Zu den Fragen Welche Informationen enthält
ein abstrakter Sündtagsbaum? Können wir also die Antwort geben,
einen Sündtagsbaum enthält, die syntaktische und semantischen Informationen eines Programmtextes.
Was er nicht enthält, sind Steuerzeichen,
Formatierungen und eben auch keine Kommentare. Die Bezeichnisse sind vorhanden,
Kommentare sind nicht vorhanden, weil sie ja kein Bedeutungsträger im
Sinne der Syntax ist