Smython - ein Python 3.x-Parser in Java

Du hast eine Idee für ein Projekt?
Antworten
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Dienstag 14. April 2009, 10:20

In einem anderen Thread fabulierte ich über die Google App Engine für Java und die Möglichkeit, darüber Scriptsprachen auszuführen.

In den letzten Tagen habe ich einen Parser für Python 3.x in Java geschrieben. Er versteht z.B. `[a + 1 for a in b if 2 if 3]` oder `c(a+1 for a in b for c in d)`, auch wenn ich noch eine Reihe von Fehlern beseitigen muss. Der Parser erzeugt einen AST, den man dann im nächsten Schritt interpretieren (oder in Bytecode kompilieren) könnte.

Aus dem ersten Beispiel wird z.B.

Code: Alles auswählen

ListCompr(
  Add(Var("a"), Lit(1)),
  ComprIf(Lit(3),
    ComprIf(Lit(2),
      ComprFor(ExprList(Var(a)), Var(b)))))
Leider ist die Liste der Dinge, die noch nicht gehen, viel, viel länger :) Da ich schon einmal einen Python 1.4-Interpreter in Java geschrieben habe, ist vieles davon aber Fleißarbeit.

Speziell für die GAE wird eine Sache einfacher: Es gibt keine Threads und man kann hemmungslos den Zustand des Systems in globalen Variablen halten. Auch definiert der Einsatzfall, einen WSGI-artigen HTTP-Request zu bearbeiten, recht genau, was man von der Standardbibliothek braucht und auf was man verzichten kann.

Für die folgenden beiden Probleme hätte ich gerne Rat (oder auch Tat): Ich kann recht leicht einen rekursiven AST-Evaluator bauen, doch damit kann ich AFAIK keine Generatoren implementieren. Was tun? Wie setzt man am besten (und dennoch effizient) Pythons Objektmodell mit all den vielen "under-under"-Methoden um oder sollte man auf diese und die Möglichkeit, Unterklassen vorhandener Klassen bauen zu können, verzichten? Wie würde sich das auf Webanwendungen auswirken?

Stefan
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Dienstag 14. April 2009, 23:03

Du hast da in der Scanner.java zwischen for und from in Zeile 12 eine Leerzeichen zuviel, vllt bringt dir das einen leeren String in dem "Array" ein.
doch damit kann ich AFAIK keine Generatoren implementieren.
Nur ein paar Gedanken dazu, ohne sich großartig auszukennen:

Man kann aber jeden Generator als einen Iterator ansehen, der dann entsprechenden "State" trägt. Zumindest sowas musst du sowieso implementieren. Eventuell könnte man Generatoren entsprechend umwandeln? Das könnte aber natürlich auch sehr schnell recht kompliziert werden, wenn man bedenkt, was für Dinge man mit Generatoren relativ leicht ausdrücken kann. Wird da also wohl keine allgemeingültige Methode geben. Oder du siehst einfach jede Funktion als Generator an, nur die "normalen" als einen mit nur einem yield Ausdruck und sofortiger Auswertung, dann brauchst du nur Generatoren richtig umzusetzen. Das könnte aber wiederrum langsam werden.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Samstag 18. April 2009, 09:33

str1442 hat geschrieben:Du hast da in der Scanner.java zwischen for und from in Zeile 12 eine Leerzeichen zuviel, vllt bringt dir das einen leeren String in dem "Array" ein.
Danke, ist korrigiert.

Das man zu einem Generator einen zustandsbehafteten Iterator finden kann, ist richtig, allerdings kenne ich nur dann eine automatische Transformation, wenn ich ein "goto" in der Sprache habe:

Code: Alles auswählen

def g():
    yield 1
    while cond1:
        yield 2
        if cond2:
            yield 3
=>
def g():
    class G:
        state = 0
        def next(self):
            if self.state == 0:
                self.state = 1
                return 1
                L1:
                while cond1:
                    self.state = 2
                    return 2
                    L2:
                    if cond2:
                        self.state = 3
                        return 3
                        L3:
            if self.state == 1:
                goto L1
            if self.state == 2:
                goto L2
            if self.state == 3:
                goto L3
            raise StopIteration
So etwas kann ich aber AFAIK nicht mit einem rekursiven AST-Interpreter realisieren. Die einzige Möglichkeit für "goto" in Java sind Exceptions. Erst wenn ich jede Python-Funktion in JVM-Bytecode übersetzen würde, könnte ich obiges Schema verwenden.

Stefan
BlackJack

Samstag 18. April 2009, 10:06

Könnte man das ``goto`` nicht mit Ausnahmen nachbasteln? Das `goto`-Modul für Python verwendet IIRC Ausnahmen dafür. :-)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Samstag 18. April 2009, 10:24

Ja, das könnte man (schrieb ich doch), doch praktikabel ist das nicht.
BlackJack

Samstag 18. April 2009, 10:57

Argh, sorry, habe ich überlesen. :oops:
Antworten