2017-06-24 2 views
1

ich pyparsing benutze und einen Text zu analysieren, habe ich eine Grammatik, und es funktioniert wie erwartet, aber für einen Ausdruck wie dieser:Python Parsing Expression und Ersetzen mit einem anderen Ausdruck

OR(OR(in1, in2), in3) 

I will den verschachtelten Ausdruck, auf einen „Alias“ ersetzen und dann einen Ausdruck für diesen Alias, in einfachen Worten erstellen:

# I have this expression (OR(OR(in1, in2), in3)) 
# Which I parsed to 
parsed = ["OR", [["OR", ["in1", "in2"]], "in3"]] 

# I want to have 
exp1 = ["OR", ["in1", "in2"]] 
exp2 = ["OR", ["exp1", "in3"]] 

Dies ist ein minimales Beispiel, aber ich kann keinen verschachtelten „Ausdrücke“ hat (mit nur zwei Argumente). Gibt es eine Möglichkeit, dies zu tun?

Antwort

1

Hier ist ein Parser, der wahrscheinlich ähnlich der ist, dass Sie schreibt:

import pyparsing as pp 

LPAR, RPAR = map(pp.Suppress, "()") 
OR = pp.Keyword("OR") 
term = pp.pyparsing_common.identifier 

or_expr = pp.Forward() 
or_expr <<= pp.Group(OR + pp.Group(LPAR + pp.delimitedList(or_expr | term)) + RPAR) 

Wenn es den String parst Sie gabst es den gleichen verschachtelten Ausgang zur Verfügung stellt.

die „expn“ Ausdruck Namen zu erstellen, können Sie eine Parse-Aktion verwenden, um die Ausdrücke zu sammeln, und die damit verbundenen Ausdruck id, in einer globalen Liste var:

# add parse action to convert OR's to exprs 
exprs = [] 
def generate_expr_definition(tokens): 
    expr_name = "exp{}".format(len(exprs)+1) 
    exprs.append((expr_name, tokens.asList()[0])) 
    return expr_name 
or_expr.addParseAction(generate_expr_definition) 

Wenn Sie diesen Parser ausführen, die erstellte Ergebnisse sind nicht der wichtige Teil. Was wichtig ist, ist die exprs Liste, die gebaut wurde, während Analyse:

or_expr.parseString(sample) 

# generate assignments for each nested OR expr 
for name, expr in exprs: 
    print("{} = {}".format(name, expr)) 

Das gibt:

exp1 = ['OR', ['in1', 'in2']] 
exp2 = ['OR', ['exp1', 'in3']] 

Jetzt sehe ich das, und fragen: „Wie werde ich wissen, der Unterschied zwischen 'exp1' das war analysiert aus dem Eingang vs. 'exp1', das angeblich einen analysierte Ausdruck darzustellen Wenn dies als eine Python Zuordnung zu interpretieren ist, sollte es wirklich lesen.

exp2 = ['OR', [exp1, 'in3']] 

ohne Anführungszeichen um den Variablennamen.

Um dies zu tun, müssen wir ein Objekt aus der Analyse Aktion, die repr als Name ohne die umgebenden Anführungszeichen wird zurückgeben. Wie folgt aus:

class ExprName: 
    def __init__(self, name): 
     self._name = name 
    def __repr__(self): 
     return self._name 

Ändern der return-Anweisung in der Parse-Aktion:

return ExprName(expr_name) 

und die resultierende Ausgabe sieht nun wie:

exp1 = ['OR', ['in1', 'in2']] 
exp2 = ['OR', [exp1, 'in3']] 

Jetzt können Sie die generierten expN Vars unterscheiden von geparsten Eingaben.

+0

Wow, es funktioniert wie ein Zauber, wusste nicht, dass Pyparsing so mächtig war, ich dachte daran, den Parse Baum zu durchqueren, um die Ausdrücke zu bekommen, und das macht tatsächlich das, was ich von Anfang an wollte Ausdruck von unten nach root – dpalma

+0

Ich habe noch eine Frage, was passiert, wenn ich keinen verschachtelten Ausdruck habe? weil ich Namen nicht ersetzen möchte, wenn ich einen einfachen Ausdruck wie ODER habe (in1, in2) – dpalma

+0

Ist das geschehen? Ich glaube nicht, dass mein Test das tut (schau dir die gepostete Ausgabe in meiner Antwort an). – PaulMcG

Verwandte Themen