HTML-Generator. Markup-Parser, Templates?

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
arghargh
User
Beiträge: 81
Registriert: Donnerstag 4. September 2008, 22:26

Beitragvon arghargh » Dienstag 30. September 2008, 09:40

Danke für deinen Beitrag, ich kann hoffentlich am Wochenende wieder mit der Schlange spielen.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Dienstag 30. September 2008, 15:44

Na, da wird Mutti aber nicht begeistert sein :lol:
arghargh
User
Beiträge: 81
Registriert: Donnerstag 4. September 2008, 22:26

Beitragvon arghargh » Mittwoch 1. Oktober 2008, 21:20

Ich habe gerade die "Schalter" gefunden. Gehören an den Anfang!

(?...)
This is an extension notation (a "?" following a "(" is not meaningful otherwise). The first character after the "?" determines what the meaning and further syntax of the construct is. Extensions usually do not create a new group; (?P<name>...) is the only exception to this rule. Following are the currently supported extensions.

(?iLmsux)
(One or more letters from the set "i", "L", "m", "s", "u", "x".) The group matches the empty string; the letters set the corresponding flags (re.I, re.L, re.M, re.S, re.U, re.X) for the entire regular expression. This is useful if you wish to include the flags as part of the regular expression, instead of passing a flag argument to the compile() function.

Note that the (?x) flag changes how the expression is parsed. It should be used first in the expression string, or after one or more whitespace characters. If there are non-whitespace characters before the flag, the results are undefined.


Und hier die Flags
I
IGNORECASE
Perform case-insensitive matching; expressions like [A-Z] will match lowercase letters, too. This is not affected by the current locale.

L
LOCALE
Make \w, \W, \b, \B, \s and \S dependent on the current locale.

M
MULTILINE
When specified, the pattern character "^" matches at the beginning of the string and at the beginning of each line (immediately following each newline); and the pattern character "$" matches at the end of the string and at the end of each line (immediately preceding each newline). By default, "^" matches only at the beginning of the string, and "$" only at the end of the string and immediately before the newline (if any) at the end of the string.

S
DOTALL
Make the "." special character match any character at all, including a newline; without this flag, "." will match anything except a newline.

U
UNICODE
Make \w, \W, \b, \B, \d, \D, \s and \S dependent on the Unicode character properties database. New in version 2.0.

X
VERBOSE
This flag allows you to write regular expressions that look nicer. Whitespace within the pattern is ignored, except when in a character class or preceded by an unescaped backslash, and, when a line contains a "#" neither in a character class or preceded by an unescaped backslash, all characters from the leftmost such "#" through the end of the line are ignored.
arghargh
User
Beiträge: 81
Registriert: Donnerstag 4. September 2008, 22:26

Beitragvon arghargh » Freitag 3. Oktober 2008, 19:55

arghargh
User
Beiträge: 81
Registriert: Donnerstag 4. September 2008, 22:26

Beitragvon arghargh » Montag 6. Oktober 2008, 11:47

Also der Trick mit dem zeilenweisen Ersetzen und darauffolgendem Verschmelzen ist ganz gut, aber doch etwas eingeschränkt.

Problematisch sind vor allem vorhandene Tags / verschachtelte Strukturen. Die lassen sich schlecht ignorieren. Es muss wohl auch eine Art Priorität geben, damit z.B. Listen nicht zusätzlich auch ein <br/> angehängt bekommen. Es muss auch zwischen Zeilenumbruch und Absatz entscheiden werden.

Reguläre Ausdrücke sind gut geeignet um einzelne Elemente zu finden und zu ersetzen (z.B. Links). Da kann ich mir was zusammenschustern ;-)

Aber für den Rest muss ich wohl noch tiefer in die Materie einsteigen. Andererseits brauche ich eigentlich gar nicht 'viel' mehr, als das, was Stefans Code kann.

Es fehlen noch Zeilenumbrüche, die Möglichkeit vorhandene Tags zu berücksichtigen/ignorieren (da wird's wohl schwieriger, evtl. mit XML-Parser?) und Blöcke mit weiteren Angaben zu erstellen (spricht für XML).

Naja, ich bleibe dran.
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Montag 6. Oktober 2008, 17:42

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 Modvoice
arghargh
User
Beiträge: 81
Registriert: Donnerstag 4. September 2008, 22:26

Beitragvon arghargh » Dienstag 7. Oktober 2008, 18:54

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

Beitragvon sma » Mittwoch 8. Oktober 2008, 13:15

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.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder