Lässt es sich mit cremefarbenem Papier, einer Tönung, mehr Kontrast oder größerer Schrift besser lesen? Wählen Sie Ihre Farben und Ihre Schrift, einmalig für alle Seiten.

Kostenlose Lektion

Einen Syntaxbaum direkt ausführen (Interpreter)

Nach dieser Lektion: Ich kann einen Syntaxbaum direkt ausführen.

Lektion, 50 Min.6 BefehleLab für Compilerbau und Rechnerarchitektur: gcc, flex, bison und RISC-V in einer VM

Eine Tarifregel aus dem Portal

Bei einem Stadtwerk tippt die Tarifabteilung ihre Preisregel selbst in ein Verwaltungsportal, etwa grundpreis + verbrauch * arbeitspreis. Die Regel ändert sich jedes Quartal.

Niemand will dafür das Abrechnungssystem neu kompilieren und neu starten. Das System behält stattdessen den Syntaxbaum der Regel und rechnet ihn für jede Rechnung Knoten für Knoten aus.

Am Ende dieser Lektion

Notiz

Ich kann einen Syntaxbaum direkt ausführen.

Schlüsselwörter

BegriffWas er bedeutetBeispiel
Interpreterein Programm, das ein anderes ausführt, ohne Maschinencode zu erzeugen
Knotenein Punkt in einem BaumBinOp
Auswertenden Wert eines Knotens ausrechnen
Blattein Knoten ohne Knoten darunterConstant(value=7)
Umgebungdie erreichbaren Namen und ihre Werte{'netto': 5}
Bindungein Name zusammen mit seinem Wert

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Python zeigt Ihnen seinen Baum

Python ist auch ein Compiler. Bevor es eine Zeile ausführt, zerlegt es sie in Tokens und baut daraus einen Syntaxbaum. Das Modul ast gibt diesen Baum für eine Zeile aus, die über eine Pipe kommt. --mode eval sagt: Die Zeile ist ein einzelner Ausdruck.

Jeder Knoten hat einen Namen. Ein Blatt hat nichts unter sich. Vergleichen Sie die zwei ersten Bäume.

Der Baum für 7 - 2 * 3

Befehl
echo "7 - 2 * 3" | python3 -m ast --mode eval

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Der Baum für (7 - 2) * 3

Befehl
echo "(7 - 2) * 3" | python3 -m ast --mode eval

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Ein Baum mit Namen

Befehl
echo "netto * menge" | python3 -m ast --mode eval

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Beispiel: die Knoten, die Python ausgab

KnotenWas er istWoher sein Wert kommt
Constant(value=7)Ein Blatt mit einer ZahlVon der Zahl selbst
Name(id='netto')Ein Blatt mit einem NamenVom Nachschlagen des Namens
BinOp(left, op, right)Eine Rechnung mit zwei SeitenVon beiden Seiten, dann vom op
Sub() oder Mult()Welche RechnungVon nichts: Es ist eine Markierung

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Erst die Kinder, dann der Knoten

Ein baumdurchlaufender Interpreter ist eine Funktion, die einen Knoten auswertet. Ein Blatt mit einer Zahl liefert die Zahl. Eine Rechnung wertet zuerst ihr linkes und ihr rechtes Kind aus und rechnet dann mit den zwei Ergebnissen.

Ein Kind kann selbst ein ganzer Baum sein, deshalb ruft die Funktion sich selbst auf. Das Beispiel kann nur - und * mit Zahlen.

Ein Auswerter, der den Baum durchläuft

Code: python
# Einen Syntaxbaum auswerten: eine Zahl oder [op, links, rechts].
def auswerten(baum):
    if type(baum) == int:
        return baum
    op = baum[0]
    # Erst beide Seiten ausrechnen: Das ist die Rekursion.
    links = auswerten(baum[1])
    rechts = auswerten(baum[2])
    if op == "-":
        return links - rechts
    if op == "*":
        return links * rechts
    return None


baum = ["-", 7, ["*", 2, 3]]
print(auswerten(baum))
# Aendern Sie baum in ["*", ["-", 7, 2], 3] und fuehren Sie erneut aus.

Ein häufiger Fehler

Warnung

Viele glauben, ein Interpreter mache heimlich Maschinencode aus dem Baum und führe den aus. Ein baumdurchlaufender Interpreter tut das nie. Er besucht die Knoten und erledigt die Arbeit unterwegs, bei jedem Lauf von Neuem. Deshalb ist er langsamer als kompilierter Code und kann dafür sofort starten.

Namen stehen in einer Umgebung

Ein Blatt mit einem Namen braucht einen Wert. Der Interpreter führt dafür eine Umgebung: jeden erreichbaren Namen mit seinem Wert. Jedes solche Paar ist eine Bindung.

Pythons eval nimmt die Umgebung als Dictionary. Mit einem zweiten Dictionary sucht Python zuerst dort. So verdeckt ein innerer Bereich einen äußeren Namen.

Mit einer Umgebung auswerten

Befehl
python3 -c "print(eval('netto * menge', {'netto': 5, 'menge': 3}))"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Einen Namen weglassen

Befehl
python3 -c "print(eval('netto * menge', {'netto': 5}))"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Eine innere Umgebung zuerst durchsuchen

Befehl
python3 -c "print(eval('netto * menge', {'netto': 5, 'menge': 3}, {'menge': 8}))"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Beispiel: netto * menge nachschlagen

Befehlnetto gefunden inmenge gefunden inAusgabe
ErsterDem einen Dictionary: 5Dem einen Dictionary: 315
ZweiterDem einen Dictionary: 5NirgendsNameError
DritterDem äußeren Dictionary: 5Dem inneren Dictionary: 840

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Weiterführend

Ergänzen Sie Ihren Auswerter um einen Knoten ["wenn", bedingung, dann, sonst]. Werten Sie die Bedingung aus. Ist sie nicht 0, werten Sie dann aus, sonst sonst.

Achten Sie darauf, dass immer nur einer der zwei Zweige ausgewertet wird. Schreiben Sie einen Test, der das beweist, mit einem Zweig, der sonst NameError werfen würde.

Über dieses Lab und seinen Quellcode: Lab für Compilerbau und Rechnerarchitektur: gcc, flex, bison und RISC-V in einer VM

Sie unterrichten eine Gruppe? Weisen Sie dieses Modul Ihren Studierenden zu, mit Handbuch für Lehrende, automatisch geprüften Aufgaben und einem Lab für jede Person.