 Hallo und herzlich willkommen zur Veranstaltung Programmierparadigmen im Sommersemester 2020 an der Uni Stuttgart. Das ist der zweite große Themenblock nach der allgemeinen Einführung und zwar geht es hier um Sündtags. Also der Frage, wie können wir überhaupt festlegen oder spezifizieren, was eigentlich Teile einer Programmiersprache ist. Dieser Block wird sechs Einheiten haben und das hier ist die erste von diesen sechs Einheiten. Und vielleicht ein bisschen den großen Kontext zu erklären. Also warum interessieren wir uns überhaupt dafür, wie die Sündtags einer Programmiersprache spezifiziert werden kann oder auch implementiert werden kann. Müssen wir uns erst mal mit der Frage beschäftigen, was heißt es überhaupt eine Programmiersprache zu spezifizieren? Das heißt im Prinzip zwei Dinge. Zum einen wollen wir festlegen, welche Arten von Coat sind denn Teil dieser Programmiersprache, also welche Zeichenketten gehörenden in diese Sprache und sind tatsächlich legale Programme. Und die zweite Frage ist, was ist die Bedeutung von diesem Coat? Also wenn ich ein Programm in dieser Sprache hinschreibe, was heißt das eigentlich und welches Verhalten erwarte ich denn dann zur Laufzeit? Diese beiden Fragen zu beantworten ist wichtig für mindestens zwei Sachen. Zum einen natürlich für Software Entwickler, weil die wollen wissen, was bedeutet das, wenn ich dieses oder jedes Statement in einer Sprache hinschreibe und darf ich das überhaupt hinschreibe, ist das überhaupt Teil der Sprache. Und zweitens natürlich für die Leute, die die Sprache implementieren und zum Beispiel Compiler oder andere Werkzeuge bauen, weil die müssen natürlich auch wissen, was das Programm machen soll und ob ein gegebener String, eine gegebener Zeichenkette überhaupt ein legales Programm in der bestimmten Sprache ist. Die Tatsache, dass wir Sprachen überhaupt so formal spezifizieren können, ist eine Besonderheit von Programmiersprachen, wenn wir das zum Beispiel vergleichen mit natürlichen Sprachen, dann sehen wir, dass die in der Regel nicht formal spezifiziert sind. Es gibt meistens so was wie den Duden auf Deutsch oder für Deutsch, der beschreibt, welche Wörter denn Teil dieser Sprache sind. Da sind dann manchmal nicht alle Wörter drin, weil das nie so richtig aktuell ist. Aber zumindest im Kroben ist da beschrieben, was Teil der Sprache ist, aber was das jetzt wirklich bedeutet und wie die Wörter zusammengesetzt werden können, das ist in der Regel nicht formal spezifiziert, ganz einfach, weil natürliche Sprachen auch noch mal ein ganz Stück komplexer und subtiler sind als Programmiersprachen. Diese zwei Fragen, die ich gerade schon kurz angesprochen habe, spiegeln sich im Prinzip in den zwei Begriffen Syntax und Semantik wieder. Also die Syntax einer Sprache beschreibt, was die Struktur des Chots ist, also welche Arten von Zeichenketten denn tatsächlich erlaubt sind und gegen die Semantik beschreibt, welche Bedeutung der Kot jetzt hat und was für eine Ausführungsverhalten wir bei einem gegebenen Programm denn eigentlich erwarten. Um das ein bisschen konkreter zu machen, habe ich hier unten mal ein kleines Beispiel. Also was wir hier sehen, ist die Grammatik einer kleinen ausgedachten Sprache, mit der wir Zahlen definieren können. Wir haben da drei Regeln, die eine Regel sagt, dass es Ziffern gibt und die bei Beinhalten alle Einzelziffern von 0 bis 9. Dann haben wir hier noch so ein anderes Konstrukt, was eine Non-zero-Digit, also ein Ziffer, die eben nicht 0 ist, beinhaltet. Und aus diesem können wir jetzt unsere Zahlen definieren, wo wir nämlich sagen, dass eine Zahl mit einer Nicht-Null-Ziffer anfängt und anschließend ein Null oder mehrere weitere Ziffern haben kann. Also dieses Konstrukt hier oben mit dem Sternchen bedeutet einfach nur Null oder mehrere von dem, was drunter steht, nämlich von dem Digit in dem Fall. Was das alles beschreibt hier drüben, ist jetzt die Syntax dieser kleinen Spielsprache und die andere Frage ist jetzt natürlich, was bedeutet das eigentlich? Und interessanterweise könnte dieser Syntax jetzt, könnte dieser Syntax verschiedene Bedeutung zugeordnet werden. Wir könnten sagen, was wir da gerade beschrieben haben, naja, das sind die natürlichen Zahlen und das wäre wahrscheinlich die intuitivste Semantik, die man für diese Syntax so erwarten würde. Es könnte aber auch ganz andere Bedeutung haben. Wir könnten zum Beispiel sagen, mal angenommen, die Woche hätte die sieben Tage, sondern zehn, dann könnten das vielleicht die Wochentage sein. Wir kodieren die einfach mit Hilfe dieser Zahlen, die wir da gerade definiert haben. Oder wir könnten sagen, dass wir Farben durch Zahlen kodieren. Und was wir da aufgeschrieben haben, ist eigentlich die Spezifikation von Farben. Und das wäre auch eine valide Bedeutung dieser Syntax, die wir gerade aufgeschrieben haben. Der Fokus von diesem Themenblock, in dem wir gerade drin sind, wird auf dem linken Teil sein, also auf der Syntax. Wir reden hier erst mal nur darüber, wie wir spezifizieren, was eigentlich ein legales Programm in einer Sprache ist und zwar legal nur im syntaktischen Sinne. Es gibt dann auch noch semantische Legalität und Illegalität von Programmen, mit der wir uns dann später zum Beispiel bei Typsystem genauer beschäftigen werden. Schauen wir uns vielleicht mal noch ein paar Beispiele aus echten Programmiersprachen an und wie Syntax und Semantik da zwischen verschiedenen Sprachen miteinander zusammenähnt. Was man oft hat, ist, dass verschiedene Sprachen die gleiche Semantik implementieren oder zumindest für bestimmte Sprachkonstrukte, die den gleichen semantischen, ja, die gleiche Bedeutung haben wollen, aber dafür verschiedene Syntax verlängten. Was wir hier sehen, ist ein Beispiel von Java und Bash, zwei Programmiersprachen, die bei jeweils sagen, okay, es gibt da eine Bedingung, nämlich wenn fu größer als 100 ist, dann mache etwas, was hier einfach nur durch Punkt, Punkt, Punkt dargestellt ist. Und obwohl das eigentlich ganz anders aufgeschrieben wird, ist die Semantik dieser beiden Code-Schnipsel genau das gleiche, eben einfach nur mit einer anderen Syntax aufgeschrieben. Was wir weniger oft, aber doch manchmal auch haben, ist, dass verschiedene Sprachen genau die selbe Syntax verwenden und damit aber andere Dinge meinen. Dieses if statement, was wir hier zum Beispiel sehen, das hat in Java eine andere Bedeutung als in Java Skript. In Java würden wir ein Typfehler bekommen, und zwar schon, wenn wir das Programm kompilieren wollen, also bevor wir das Programm überhaupt ausführen können, sagt uns der Compiler, weißt du, in Stringen und eine Zahl zu vergleichen, das geht einfach nicht. Und deswegen musste das auch gar nicht versuchen, auszuführen. Wohingegen in Java Skript auch Werte von verschiedenen Typen miteinander verglichen werden können. Das heißt, dieser Ausdruck, dieser Vergleich, der wird tatsächlich ausgeführt. Man wird feststellen dann zur Laufzeit, dass der String ABC eben nicht gleich der Zahl 5 ist. Und weil das genau die Bedingung ist, die in diesem if überprüft wird, wird der Zweig, der durch dieses Punkt, Punkt, Punkt dargestellt ist, in Java Skript dann ausgeführt. So, jetzt haben wir gesehen, wie Syntax und Symantec grob zusammenhängen. Im Rest des Blockes werden wir uns jetzt mehr mit oder hauptsächlich mit der Syntax beschäftigen. Und die erste Frage, die ich hier ein bisschen besprechen möchte, ist, wie wir überhaupt spezifizieren können, was Teil der Syntax einer Sprache ist. Da stellt sich raus, dass es insgesamt vier Konzepte gibt, mit denen man die Syntax einer Sprache spezifizieren kann. Und diese vier Konzepte, und was ist jetzt hier auf einmal, ist auch so ein bisschen den Überblick über das, was wir in dem Themenblock insgesamt behandeln werden. Da gibt es zum einen die Concatenation, also die Zusammensetzung von Teilen eines Programms. Also ich kann sozusagen sagen, Teil der Syntax ist dieses Stück Syntax und jenes Stück Syntax. Das zweite Konzept ist die Auswahl oder Alternation oder Choice, wo ich sage, als Teil meiner Syntax kann er in einer bestimmten Stelle im Programm zum Beispiel dieses oder jenes syntaktische Konstrukt erscheinen. Konzept Nummer vier ist Wiederholung, mit der ich festlegen kann, dass bestimmte Dinge in meinem Programm mehrmals auftreten und ein Weg, das zu tun ist dieses Sternchen, was wir vorhin ja auch schon kurz gesehen haben und was in der Regel als Clean closure bezeichnet wird. Und das vierte Konstrukt, was wir brauchen, um die Syntax von Programmen aufzuschreiben, ist Rekursion, weil wir oft die Situation haben, dass innerhalb eines syntaktischen Konstrukts dieselbe Art syntaktisches Konstrukt nochmal auftreten kann. Und der beste Weg, das auszudrücken, ist Rekursion. Jetzt gibt es zwei Arten von Spezifikationsmechanismen, die man benutzen kann, um diese syntaktischen Konstrukte zu verwenden und tatsächlich die Syntax eine Sprache zu spezifizieren. Das eine sind reguläre Ausdrücke und die helfen uns dabei, die ersten drei Konzepte auszudrücken. Wenn ich jetzt natürlich auch noch zusätzlich Rekursion brauche und wir werden Beispiele sehen, wo wir das brauchen. Also in der Regel braucht man das, wenn man tatsächlich vollständige Programme oder die Syntax von vollständigen Programmen spezifizieren will, dann reichen reguläre Ausdrücke nicht aus, sondern was wir da kennenlernen werden oder besprechen werden, sind kontextfreie Grammatiken. Die werden üblicherweise mit CFG abgekürzt. Also wenn die Abkürzung in Zukunft mal kommt, wissen Sie jetzt, was ich meine. Um festzustellen, ob ein gegebener String, also eine gegebene Zeichenkette Teil der spezifizierten Sprache sind, also sind taktisch korrekt sind, gibt es gewisse Werkzeuge, die das machen und zwar ist das im Falle von regulären Ausdrücken der sogenannte Scanner und wir werden uns anschauen, wie Scanner eigentlich funktionieren und sie werden in der Übung auch tatsächlich mal selber ein implementieren. Und das Gegenstück für die kontextfreien Grammatiken sind dann die Pasa, die überprüfen, ob ein gegebenes Programm oder ein gegebener String tatsächlich Teil der Sprache sind, die die kontextfreie Grammatik spezifiziert. Gut, ja, in den nächsten paar Minuten werden wir uns jetzt diese Konstrukte mal genauer anschauen und damit quasi diese zwei Mechanismen, um Sündung zu spezifizieren, genauer kennenlernen und als erstes schauen wir uns mal die regulären Ausdrücke an. Die regulären Ausdrücke werden in der Regel verwendet, um die kleinste Einheit innerhalb von Programm zu spezifizieren und das sind Tokens. Also im Prinzip kann man sich ein Token vorstellen als sozusagen die Wörter der Programmiersprache, also das sind so die kleinen Einheiten aus denen dann die Programme zusammengebaut werden und das sind so Dinge wie zum Beispiel Keywords, also if oder while, Identifier, also die Namen die Programmierer für Variablen verwenden, Konstanten, sowas wie True oder 25 und alle möglichen Operatoren, also plus, minus und so weiter. Man kann sich das also wirklich als die Wörter der Programmiersprache vorstellen. Als konkretes Beispiel sehen wir hier mal ein paar der Tokens, die in der C Sprache drin sind. C hat insgesamt mehr als 100 Tokens, die allein in der Sprache drin sind und dadurch das Programmierer natürlich selber Variablen Namen und so weiter festlegen können. Sind praktisch die Anzahl der Tokens unendlich viele, aber allein die, die standardmäßig in der Sprache schon dabei sind, sind auch schon über 100. Also das sind Keywords dabei, wie zum Beispiel dieses double oder if oder return und so weiter. Dann haben wir natürlich die Identifier und Literale, die die Programmierer selbst festlegen können und gleichzeitig auch Dinge wie Puncturators, also Klammern, Operatoren und so weiter, die einfach wichtig sind, um bestimmte Operationen oder Konstrukte in der Sprache ausdrücken zu können. Um solche Tokens zu spezifizieren, benutzt man reguläre Ausdrücke und zwar funktioniert das so, dass im Prinzip ein reguläre Ausdruck sagt, wie ein bestimmter Trocken aussehen kann und zum Beispiel festlegt, welche Namen für Variablen denn in der Sprache überhaupt legal sind. Was ist so ein regulärer Ausdruck? Also hier ist mal eine etwas informale Definition davon, was ein regulärer Ausdruck ist. Ein regulärer Ausdruck kann entweder ein einzelnes Zeichen beschreiben oder einen, den leeren String, der durch dieses Epsilon in der Regel ausgedrückt wird, beschreiben. Dann kann ich mehrere reguläre Ausdrücke, die ich schon haben, zusammenführen, indem ich sage, der reguläre Ausdruck umfasst zum Beispiel sowohl dieses eine Zeichen als auch dieses andere Zeichen, also sowas wie a und b hintereinander. Dann kann ich reguläre Ausdrücke miteinander verknüpfen durch ein logisches oder, da benutzen wir diesen senkrechten Strich, mit dem wir sagen, entweder dieses eine oder dieses andere gehört dazu. Und schlussendlich habe ich das Konzept der Wiederholung, indem ich diesen Clean Star verwende, also dieses Sternchen, mit dem ich sage, was ich da eben geschrieben hab, wird mehrmals ausgeführt, und zwar 0, 1, 2 oder oder mehrere Mal. Was wichtig ist an der Stelle, ist, dass wir eben in regulären Ausdrücken noch keine Rekursion darin haben. Also all das, was wir hier haben, erlaubt zwar Wiederholung, es erlaubt aber nichts zu sagen, dass ein syntaktisches Konstrukt dieselbe als syntaktisches Konstrukt nochmal enthält. Machen wir das mal ein bisschen konkreter, indem wir uns ein Beispiel dazu anschauen. Und zwar soll es in dem Beispiel darum gehen, Zahlen zu definieren, wie man sie zum Beispiel als Eingabe in ein Taschenrechner eingeben könnte. Also konkret geht es hier um numerische Konstanten, die man zum Beispiel in eine Taschenrechner-Applikation eingeben könnte. Also wenn Sie jetzt aus Spaß mal eine Taschenrechner-Applikation schreiben würden, dann könnten Sie zum Beispiel diesen, diesen regulären Ausdruck den wir jetzt aufschreiben benutzen, um überhaupt festzulegen, was kann man denn alles in diesen Taschenrechner eingeben. Was wir da eingeben wollen, sind Zahlen oder Number. Deswegen haben wir hier eine Regel, die beschreibt, was eine Number ist und jede dieser Regeln benutzt diese Fallnotation und in dem Fall sagen wir eine Regel kann entweder ein Integer sein, also eine Ganzzahl oder ein Real, also eine Zahl mit einem Komma drin. Die Integer Zahlen spezifizieren wir jetzt genauer, indem wir sagen, ein Integer besteht aus einer Ziffer, gefolgt von null oder mehr weiteren Ziffern, aber wir brauchen mindestens einen. Und das Gleiche machen wir für Real, wo wir sagen, dass eine Real-Zahl entweder ein Integer ist mit einem Exponenten hinten dran oder eine Dezimalzahl, also dann wirklich eine Zahl mit einem Komma und das ist optional auch wieder gefolgt von einem Exponenten oder dem leeren Wort, deswegen optional. Jetzt müssen wir noch aufschreiben, was diese Decimals denn eigentlich sind und das tun wir, in denen wir sagen, so ein Dezimal hat auf jeden Fall irgendwo ein Punkt in der Mitte, also das deutsche Komma und zwar kann erst dieser Punkt kommen und anschließend eine Ziffer oder ich habe eine Ziffer und anschließend den Punkt und davor und dahinter kann ich optional noch beliebig viele andere Ziffern haben und das mache ich, indem ich einfach noch mal Digit mit diesem Sternchen mit dem Klinenclosure davor und dahinter schreibe. Für den Exponenten müssen wir auch festlegen, wie der aussehen darf und hier sagen wir, man gibt erst mal durch den Bustabem E entweder groß oder klein an, dass es da überhaupt ein Exponenten gibt und anschließend kann man das Vorzeichen bestimmen als plus oder minus oder man kann es auch weglassen, dann ist es implicit plus, deswegen hier wieder das leere Wort epsilon und anschließend brauche ich eine ganz salen Integer um zu beschreiben, was der Exponent eigentlich genau ist und jetzt haben wir fast alles definiert, außer wie eigentlich eine Ziffer aussieht und das machen wir so ähnlich wie wir es gerade eben bei dem einfacheren Beispiel schon mal hatten, indem wir die einfach aufzählen und sagen, eine Ziffer ist entweder 0 oder 1 oder 2 und so weiter bis bis hoch zur 9. So, jetzt haben wir diesen regulären Ausdruck definiert und um einfach mal zu testen, ob das ganze jetzt angekommen ist, habe ich hier ein kleines Quiz, wo ich eine Reihe von Strings habe, die eventuell von diesem regulären Ausdruck akzeptiert werden, also legale Numbers entsprechend unserem regulären Ausdruck sind oder eben auch nicht und die Frage an Sie ist jetzt, welche von diesen Strings ist es tatsächlich legal entsprechend unseres regulären Ausdrucks? Ich lege das ganze mal so, ach nee, noch nicht, ich mache es erst mal so, ich lasse erst mal das hier stehen, Sie können auch gerne zurückgehen und mache jetzt mal dieses wunderschöne Pause-Symbol an mit der Idee, dass Sie jetzt Pause drücken und anschließend im Ilias abstimmen, welche dieser Strings denn tatsächlich Teil des regulären Ausdrucks sind. So und nachdem Sie jetzt hoffentlich abgestimmt haben, schauen wir uns das ganze nochmal genauer an und ich verrate Ihnen, welche Strings jetzt tatsächlich dazugehören. Und zwar ist das nur der erste und der letzte und alle anderen eben leider nicht. Warum das so ist, schauen wir einfach mal kurz durch. Also 2, 3 ist eine legale Zahl entsprechend unserem regulären Ausdruck, weil es einfach ein Integer ist, der ja aus mindestens einem Digit und dann noch mehr Digits bestehen kann, wir haben jetzt 2 Digits, nämlich 2 und 3 wunderbar, also ist das eine Zahl. Der zweite String ist keine Zahl entsprechend unseres regulären Ausdrucks und zwar aus dem Grund, dass wir da zweimal den Punkt drin haben. Der einzige Weg, wo wir Punkte her bekommen können, entsprechend dem, was wir hier aufgeschrieben haben, ist über dieses Konstrukt, was in Decimal auftaucht. Decimal taucht aber nur hier auf und kann da auch nur einmal auftauchen, also da ist nirgends wo das Sternchen dran, das heißt, es kann einfach nicht sein, dass wir zweimal den Punkt da drin haben. Das dritte Beispiel hat ein Exponenten, der selbst wieder ein Punkt enthält. Wenn wir uns jetzt anschauen, wie Exponent definiert ist, dann sehen wir, dass das hinten ein Integer haben muss und Integer haben eben keine Punkte drin, weil das ganze Zahlen sind, das heißt, das dritte Beispiel ist auch nicht dabei. Schauen wir uns das Vörter an, das ist E75. E75 müsste aus diesem Exponent kommen. Der Exponent an sich tritt hier auf und da, das heißt, er muss immer von einem Integer oder von einem Decimal eingeleitet werden und sowohl Integer als auch Decimal können nicht zum leeren Wort abgeleitet werden, das heißt, einfach nur E75 gibt es nicht. Das vorletzte Beispiel enthält zweimal das große E und das geht auch wieder nicht, weil wir dafür zwei Exponenten bräuchten und Exponent aber eben überall nur ohne Sternchen dran auftaucht und schlussendlich ist das letzte 003 eine legale Zahl, denn das sind einfach nur drei Digits. Wir haben nicht die Bedingungen hier drin stehen, dass es mit einer nicht null Digit losgehen muss, sondern es kann tatsächlich mit zwei Nullen losgehen und von daher ist 003 ein legaler String nach unserem regulären Ausdruck. Jetzt haben wir diese Söntags hier unten rechts ja relativ ausführlich hingeschrieben, also mit relativ vielen Zeichen und eine Frage die man sich vielleicht stellen kann ist ob das wirklich so sein muss oder ob es nicht vielleicht noch ein bisschen kompakteren Weg gibt, reguläre Ausdrücke aufzuschreiben und die Antwort dafür ist ja, es gibt kompakt ihre Wege und ein davon wollen wir uns jetzt mal ein bisschen genauer anschauen, also ein kompakteren, eine kompaktere Söntags für reguläre Ausdrücke. Um das ganze am Beispiel zu illustrieren verwende ich mal ein anderes Beispiel was wir später dann auch wieder verwenden werden und zwar definiere ich hier eine kleine Sprache die Tokens in einer fiktiven Programmiersprache sein könnten. Ich schreibe erst mal ein paar Beispiele auf und zeig dann die Regeln oder den regulären Ausdruck der das ganze beschreibt. Also wir wollen, dass C ein legaler Druck in unserer Sprache ist C, A, C oder auch C, B, C oder aber auch längere Zeichenketten zum Beispiel C, A, C, A, C oder C, B, C, B, C oder auch längere Zeichenketten wo A's und B's gemischt sind und zwar zum Beispiel C, A, C, B, C oder C, B, C, A, C und so weiter und so fort. Also das ganze soll natürlich auch noch mit noch längeren Token funktionieren. Wenn wir für diese Beispiele jetzt den regulären Ausdruck aufschreiben müssen, dann könnten wir das erst mal mit der ausführlichen Söntags die ich bis jetzt verwendet habe wie folgt machen. Wir sagen es geht immer mit einem C los und anschließend kommt noch mehr, was ich einfach mal in dieses Moor zusammenfasse. Und Moor ist so definiert, dass wir sagen es kommt da ein A oder ein B, was ich anschließend noch in einer anderen Regel definieren werde, gefolgt von einem C und dieser A oder B-Regel sagt genau das, was der Name sagt, nämlich dass es ein A oder ein B sein kann. Jetzt ist es wieder diese ausführliche Art und Weise, die regulären Ausdrücke aufzuschreiben. Eigentlich wollen wir das gerne ein bisschen kürzer. Und der Trick dabei ist folgende. Der Trick ist ganz einfach, dass wir dadurch, dass wir ja keine Rekursionen haben, die verschiedenen regulären Ausdrücke ineinander verschachteln können, sodass wir schlussendlich nur einen großen regulären Ausdruck haben, wo das alles drin steht. Für das konkrete Beispiel sieht es also so aus, wir hätten unser A oder B in der Mitte, das hier wäre also quasi das A oder B. Dieses A oder B erscheint in der Regel für Moa und da ist dahinter noch ein C. Das heißt, dieses Konstrukt hier entspricht dann unserem Moa und was der Token, was jetzt ein Token ausmacht, ist, dass wir von diesen Moa Null oder mehr haben und davor noch ein weiteres C, also sprich alles ineinander geschachtelt und das ist dann genau die Definition von Tokens. So, was haben wir uns angeschaut, wie reguläre Ausdrücke genutzt werden können, um zu spezifizieren, welche Tokens überhaupt zu einer Sprache gehören. Jetzt schauen wir uns mal noch ein bisschen an, wie das in praktischen Sprachen denn tatsächlich genutzt wird. Eine interessante Frage dabei ist, inwiefern groß und Kleinschreibung eine Rolle spielt und insbesondere ist es wichtig, bei Tokens, die der Programmierer selbst wählen darf, also zum Beispiel Namen von Variablen. In manchen Sprachen spielt die Groß- und Kleinschreibung da überhaupt keine Rolle. Zum Beispiel in A da oder Common List spielt es keine Rolle, ob ich Fuh mit einem kleinen F schreibe oder mit einem großen F oder vielleicht nur mit Großbruchstaben. Das meint alles dasselbe und es ist immer dieselbe Variable. Wo ein Gegend zum Beispiel in Pearl oder C Groß- und Kleinschreibung durchaus eine Rolle spielt und das kleingeschriebene Fuh eben nicht dasselbe ist wie das großgeschriebene Fuh. Was die meisten Sprachen gemeinsam haben, ist dass neben Zeichen zum Beispiel auch Ziffern erlaubt sind für Identifier-Namen und dass auch der underscore verwendet werden kann um die, um mit Hilfe des Nailcase-Konventionen mehrere Wurte zu einem Namen zu verbinden. Neben den syntaktischen Regeln, die jede Sprache für Tokens hat, gibt es außerdem oft noch eine ganze Reihe von Konventionen, die jetzt nicht wirklich so von der Sprache verpflichtend verlangt werden, aber die einfach üblich sind, damit verschiedene Programmierer den Code von anderen Programmierern möglichst gut lesen können und ein Beispiel dafür ist zum Beispiel dass man in Java Klassennamen groß schreibt, Variablennamen klein schreibt, Feldnamen klein schreibt und so weiter. Eine andere interessante Frage was natürlich wichtig ist, ist dass sie die Regeln ihrer Sprache diese gerade verwenden gut kennen, denn nur dadurch kann man natürlich sicherstellen, dass sie die Regeln auch entsprechend umsetzen und gerade zum Beispiel die Großkleinschreibung ist wichtig, damit man nicht aus Versehen mal die falsche Variable verwendet. Eine andere interessante Frage ist inwiefern Formatierung eine Rolle spielt und hier haben verschiedene Sprachen auch wieder verschiedene Antworten. In manchen Sprachen ist die Formatierung Teil der Syntax und wichtig, weil sie weil sie festlegt was das Programm eigentlich bedeutet. Ein bekanntes Beispiel ist Python, in der Leerzeichen und Tabs tatsächlich etwas etwas bedeuten schauen wir uns gleich noch am Beispiel an oder so ähnlich verhält es sich auch mit Line Breaks die in manchen Sprachen zum Beispiel JavaScript oder Python Statements voneinander trennen und anstelle von Semikolons verwendet werden können. Als kleines Beispiel für die Bedeutung von Dubai den Python schauen wir uns mal diese diese paar Zahlen Python Code an und was wir hier machen ist, wir haben eine Variable in die wir initial mal s schreiben dann haben wir so eine Bedingung und wenn die Bedingung wahr ist schreiben wir noch was anderes in die Variable und geben das Ganze dann dann aus. Wenn wir das jetzt mal ausführen da muss ich erst mal das richtige Terminal aufmachen wenn wir das Ganze jetzt ausführen dann sollte jetzt erst mal gar nichts passieren und zwar aus dem Grund dass diese Bedingung hier einfach falsch ist und dass die 2 Statements in Zeile 4 und 5 eben von dieser Bedingung geschützt werden wenn ich das jetzt umdreh also die Bedingung plötzlich wahr wird dann gibt der Code Yeah aus weil eben diese 2 Statements in Zeile 4 und 5 beide ausgeführt werden. Was interessant ist bezüglich der Söntags von Python ist das am Ende dieser Zeile keine Semikolon steht wie man das zum Beispiel in Java oder C haben müsste sondern stattdessen reicht dieser Line Break einfach aus um anzuzeigen dass hier ein neues Statement beginnt. Wenn ich das Ganze jetzt auf dieselbe Zeile schreiben möchte und das einfach so mache dann funktioniert das nicht weil Python davon ausgeht dass pro Zeile eben genau ein Statement da ist. Ich kann jetzt aber doch ein Semikolon einsetzen und dann würde ich anzeigen dass hier ein neues Statement beginnt und Print S eben das zweite Statement ist. Der andere interessante Aspekt ist dass diese Leerzeichen hier vorne nicht nur schöne Formatierung sind sondern tatsächlich auch eine Bedeutung haben dafür was das was das Programm macht wenn ich jetzt die zum Beispiel wegnehmen würde dann würde jetzt drehe ich auch nochmal das die Bedingung um was jetzt passiert das wollte ich nicht was jetzt passiert ist dass wir plötzlich die Ausgabe buh sehen und der Grund dafür ist dass die diese Zeile hier weiterhin von dem von der Bedingung geschützt wird die er jetzt falsch ist deswegen wird das nicht ausgeführt aber weil wir das Print Statement in Zeile 5 nicht mehr eingerückt haben wird es plötzlich doch ausgeführt denn die Tatsache ob wir das einrücken oder nicht verändert die Bedeutung von dem von dem Code also der Widespace spielt hier eine Rolle und das ist so eine Besonderheit von Python und auch noch ein paar anderen Sprachen die ganz interessant ist und die man auf jeden Fall wissen sollte wenn man in der Sprache oder in den Sprachen programmiert ja und damit sind wir auch schon am Ende dieser ersten Einheit im Block Synthax Sie wissen jetzt also hoffentlich was reguläre Ausdrücke sind und wie man die verwendet um die Tokens also so die kleinsten Einheit die innerhalb eine Programmiersprache zu spezifizieren und was wir uns dann in der nächsten Einheit anschauen werden ist wie wir nun auch noch den Rest von Programmi spezifizieren können weil die Tokens sind zwar schön und gut aber die allein reichen ja nicht aus sondern wir wollen die jetzt auch noch zusammensetzen zu zum Beispiel Ausdrücken und Statements in unsere Programmiersprache und damit vielen Dank und bis zum nächsten Mal