6 Stimmen

Wie parst man Code (in Python)?

Ich muss einige spezielle Datenstrukturen parsen. Sie liegen in einem irgendwie ähnlichen C-Format vor, das ungefähr so aussieht:

Group("GroupName") {
    /* C-Style comment */
    Group("AnotherGroupName") {
        Entry("some","variables",0,3.141);
        Entry("other","variables",1,2.718);
    }
    Entry("linebreaks",
          "allowed",
          3,
          1.414
         );
}

Ich kann mir mehrere Möglichkeiten vorstellen, dies zu tun. Ich könnte den Code mit regulären Ausdrücken "tokenisieren". Ich könnte den Code zeichenweise lesen und eine Zustandsmaschine verwenden, um meine Datenstruktur zu erstellen. Ich könnte die Komma-Zeilenumbrüche weglassen und den Code Zeile für Zeile lesen. Ich könnte ein Konvertierungsskript schreiben, das diesen Code in ausführbaren Python-Code umwandelt.

Gibt es eine schöne pythonic Weg, um Dateien wie diese zu parsen?
Wie würden Sie es analysieren?

Dies ist eher eine allgemeine Frage zum Parsen von Zeichenketten und nicht so sehr zu diesem speziellen Dateiformat.

7voto

PaulMcG Punkte 59178

Mit pyparsing (Mark Tolonen, ich wollte gerade auf "Beitrag einreichen" klicken, als Ihr Beitrag durchkam) ist das ziemlich einfach - siehe die in den Code eingebetteten Kommentare unten:

data = """Group("GroupName") { 
    /* C-Style comment */ 
    Group("AnotherGroupName") { 
        Entry("some","variables",0,3.141); 
        Entry("other","variables",1,2.718); 
    } 
    Entry("linebreaks", 
          "allowed", 
          3, 
          1.414 
         ); 
} """

from pyparsing import *

# define basic punctuation and data types
LBRACE,RBRACE,LPAREN,RPAREN,SEMI = map(Suppress,"{}();")
GROUP = Keyword("Group")
ENTRY = Keyword("Entry")

# use parse actions to do parse-time conversion of values
real = Regex(r"[+-]?\d+\.\d*").setParseAction(lambda t:float(t[0]))
integer = Regex(r"[+-]?\d+").setParseAction(lambda t:int(t[0]))

# parses a string enclosed in quotes, but strips off the quotes at parse time
string = QuotedString('"')

# define structure expressions
value = string | real | integer
entry = Group(ENTRY + LPAREN + Group(Optional(delimitedList(value)))) + RPAREN + SEMI

# since Groups can contain Groups, need to use a Forward to define recursive expression
group = Forward()
group << Group(GROUP + LPAREN + string("name") + RPAREN + 
            LBRACE + Group(ZeroOrMore(group | entry))("body") + RBRACE)

# ignore C style comments wherever they occur
group.ignore(cStyleComment)

# parse the sample text
result = group.parseString(data)

# print out the tokens as a nice indented list using pprint
from pprint import pprint
pprint(result.asList())

Drucke

[['Group',
  'GroupName',
  [['Group',
    'AnotherGroupName',
    [['Entry', ['some', 'variables', 0, 3.141]],
     ['Entry', ['other', 'variables', 1, 2.718]]]],
   ['Entry', ['linebreaks', 'allowed', 3, 1.4139999999999999]]]]]

(Leider kann es zu Verwirrung kommen, da pyparsing eine "Group"-Klasse definiert, um den geparsten Token eine Struktur zu geben - beachten Sie, wie die Wertelisten in einem Eintrag gruppiert werden, weil der Listenausdruck von einer pyparsing Group eingeschlossen ist).

2voto

Mark Tolonen Punkte 146757

Auschecken pyparsing . Es hat eine Menge Parsing-Beispiele .

1voto

Makis Punkte 11700

Das hängt davon ab, wie oft Sie das brauchen und ob die Syntax gleich bleibt. Wenn die Antworten "ziemlich oft" und "mehr oder weniger ja" lauten, würde ich nach einer Möglichkeit suchen, die Syntax auszudrücken und einen speziellen Parser für diese Sprache mit einem Tool wie PyPEG ou LEPL . Die Definition der Parser-Regeln ist eine große Aufgabe. Wenn Sie also nicht oft dieselbe Art von Dateien parsen müssen, ist dies nicht unbedingt effektiv.

Aber wenn Sie sich die PyPEG-Seite ansehen, erfahren Sie, wie Sie die geparsten Daten in XML ausgeben können. Wenn Ihnen dieses Tool also nicht genug Leistung bietet, können Sie es verwenden, um das XML zu generieren und dann z.B. lxml zum Parsen der XML-Datei.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X