HTML-Generator. Markup-Parser, Templates?

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Spätestens wenn du verschachteln willst, solltest du dir besser eine Grammatik ausdenken und dann in Pyparsing oder PLY implementieren, das kommt warscheinlich etwas einfacher als eine dieser Libraries selbst nachzubauen :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
arghargh
User
Beiträge: 81
Registriert: Donnerstag 4. September 2008, 22:26

Tja, richtig wohl ist mir bei der Sache nicht. Eigentlich wollte ich was anderes machen als mich mit Parsern zu beschäftigen. Das liegt alles etwas hinter meinem Horizont.
Wär' gut wenn man 'einfach' Regeln definieren könnte. Weiss nicht, ob die Parser das können. Und einfach ist relativ.

Vielleicht kann ich mir hier noch was abgucken:
http://wiki.sheep.art.pl/Wiki%20Creole% ... n%20Python

Na vielleicht geht's am WE weiter.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Eigentlich sind Parser einfach. Ich verstehe nicht, warum so viele Leute das Verarbeiten von Programmen im Gegensatz zu anderen Daten zu fürchten. Eine Parsing-Expression-Grammar (PEG) kann man sich auch recht einfach ad-hoc bauen. Ich habe das in Postings hier schon 2x gemacht. PEGs sind eine Verallgemeinerung von regulären Ausdrücken und nicht ganz so mächtig wie kontextfreie Grammatiken (was man so landläufig in der Uni lernt) aber einfacher zu konstruieren, weil man keine komplexen Parsergeneratoren braucht.

Sobald du "zählen" willst - was z.B. schachteln heißt - reichen reguläre Ausdrücke nicht. Das zu beweisen lernt man an der Uni dann in Automatentheorie. Man lernt dann auch, dass wenn man einen Stapel (wir haben das damals noch Kellerspeicher genannt ;) hinzufügt, man doch zählen kann und entsprechende Automaten kontextfreie Grammatiken (nicht anderes bauen nämlich Parsergeneratoren wie Yacc oder Bison). Alternativ kann man Rekursion statt eines Stapels einsetzen und landet dann bei rekursiv absteigenden Parsern, wie man sie von Hand schreiben kann, oder wie sie Tools wie Coco/R bauen. Ich schweife aber total ab.

Mein Vorschlag wäre, Einrückungen gesondert über einen Stapel zu behandeln. Prüfe bei jeder Zeile die Einrückung. Zähle die Leerzeichen. Sind es mehr als die aktuelle Einrückung, erzeuge ein <div class="indent"> o.ä. und mache weiter. Ist es weniger, entferne solange Einrückungen vom Stapel, bis es wieder passt. Dann mache weiter.

Code: Alles auswählen

output = []
indents = []

def set_indent(i, begin, end):
    indents.append((i, end))
    output.append(begin)
    
def need_indent(indent):
    while indent < indents[-1][0]:
        output.append(indents.pop()[1])
    return indent > indents[-1][0]

def parse(lines):
    set_indent(0, "<body>", "</body>")
    for line in lines.splitlines():
        if line.strip():
            indent = len(line) - len(line.lstrip()); line = line[indent:]
            if need_indent(indent):
                if line.startswith("* "):
                    set_indent(indent, "<ul>", "</ul>")
                else:
                    set_indent(indent, "<div class='indent'>", "</div>")
            if line.startswith("* "):
                set_indent(indent + 2, "<li>", "</li>")
                line = line[2:]
            output.append(line)
    while indents:
        output.append(indents.pop()[1])
    
    return "\n".join(output)

print parse("""
Line.
    Indented Line.
      * List1
         * Sublist 1
         * Sublist 2
      * List2
        Line in List
    Indented Line.
""")
Stefan

PS: Ich überlasse es dem Leser, die häßliche globale Variable output zu entfernen.
Antworten