Ich muss sagen, mir missfällt schon der
Originalcode, da ist es schwer, deinen Code zu bewerten. Pyparsing soll doch eigentlich lesbare Parser erzeugen. Das ist mit diesem Beispiel IMHO nicht wirklich gelungen. Mich stört insbesondere, dass überall geprüft wird, ob ein Argument wohl ein String (offenbar eine Variable wie p, q, r) oder etwas anderes (offenbar ein BoolOperand) ist. Statt da __nonzero__ zu überschreiben hielte ich es für sauberer, überall eine `eval()`-Methode (oder ähnliches) zu haben und keine solche komischen Fallunterscheidungen zu treffen. Diese sind unnötig, wenn den Parse-Tree richtig baut. Ich vermute, dass `operatorPrecedence` N-stellige und nicht nur zweistellige Operatoren kennt, denn nur so ist zu erklären, warum da überall Schleifen benutzt werden. Oder ist die Zahl da die Anzahl der Operanden? In diesem Fall verstehe ich nicht die Schleifen.
Ich hätte diesen AST erwartet:
Code: Alles auswählen
class And:
def __init__(self, t): self.a, self.b = t[0][0::2]
def eval(self): return self.a.eval() & self.b.eval()
class Or:
def __init__(self, t): self.a, self.b = t[0][0::2]
def eval(self): return self.a.eval() | self.b.eval()
class Not:
def __init__(self, t): self.e = t[0][1]
def eval(self): return not self.e.eval()
class Var:
def __init__(self, t): self.n = t[0][0]
def eval(self): return eval(self.n) # nun ja...
class Lit:
def __init__(self, t): self.v = t[0][0] == 'True'
def eval(self): return self.v
Für deinen Funktionsaufruf gibt es doch bei Pyparsing bestimmt einen besseren Ausdruck für eine kommaseparierte Liste, doch da die Doku mich nur auf ein O'Reilly-Buch verweist, habe ich keine Lust zu suchen. Ich würde minimal etwas wie `fooExpr + ZeroOrMore("," + fooExpr)` erwarten. Das wäre IMHO schöner als der jetzige Ansatz, der kein "," kennt. Ich hätte auch für den "Call" einen AST-Knoten erwartet und nicht eine direkte Funktion. Was mich auch wundert ist, dass du die Argumente gar nicht auswerten willst und es ausschließlich Strings sein können. Und warum das Ergebnis immer eine einelementige Liste mit einem String ist, wirst du am besten wissen. Ich finde es einfach nur komisch und der Kommentar "done!" klärt nichts auf.
Fehler mit "PRINT" zu melden geht schließlich IMHO gar nicht. Ich würde dort Exceptions werfen.
Stefan