Suche Informationen über -- Text - lexer - parser --

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Danke, Danke...

nichts desto trotz, werde ich mir deinen gesamten Code ma durchschauen... werde ihn analysieren und schauen, ob ich was davon brauchen kann.

Der Ansatz ist jedenfalls sehr gut.

Die Generierung von BBCode aus der dauCMS-Wiki-Syntax gefällt mir ebenso sehr gut.

Wenn ich mich reingefitzt habe werde ich ma schaun, ob ich was dazu beitragen kann.

Es ist jedenfalls mehr geworden, als ich gedacht habe :D


Herzlichen Dank, von meiner Seite aus. Und führe das bitte weiter... das verspricht etwas sehr interessantes zu werden :D

MfG EnTeQuAk
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

EnTeQuAk hat geschrieben: nichts desto trotz, werde ich mir deinen gesamten Code ma durchschauen... werde ihn analysieren und schauen, ob ich was davon brauchen kann.
Aber keinen Schock kriegen. Bin leider nicht dazu gekommen den Code zu dokumentieren was ich bereue, da es stellenweise doch ziemlich Strange ist :D
EnTeQuAk hat geschrieben: Der Ansatz ist jedenfalls sehr gut.
In der Entwurfsphasen gefiel mir mein Code auch gut, aber nun nicht mehr so. Mit der Möglichkeit der Ableitung von ``BasisLexer`` um neue Lexer zu implemnetieren die das gleiche Interface nutzen, finde ich persönlich gut, aber den ganzen AST kram ist echt nicht so gewordene wie erhofft und auch überflüssig :-/ -- Ich werde mir demnächst mal doch das Drachenbuch kaufen :D
EnTeQuAk hat geschrieben: Die Generierung von BBCode aus der dauCMS-Wiki-Syntax gefällt mir ebenso sehr gut.
Danke. Dient aber nur als Beispiel, da ich nun nicht nicht nachschlagen wollte für HTML (HTML und XHTML ist schon sehr lange her und BBC habe ich im Kopf ^^). Da sich aber die tags eigentlich fast ähneln, kann man das auch leicht anpassen. EDIT: Aber es ist so konzipiert das es in jedes beliebige Textformat überführt werden kann, das mindestens gleich mächtig ist wie daucms-Wiki-Syntax.
EnTeQuAk hat geschrieben: Herzlichen Dank, von meiner Seite aus. Und führe das bitte weiter... das verspricht etwas sehr interessantes zu werden :D
Auf jedenfall :) Ich werde wenn ich wider Zeit habe einen neune Ansatz versuchen der sauberer ist als mein jetziger. Aber dazu muss ich mich mehr mit regex beschäftigen :D

Aber als nächstes kommt erstmal Ubuntu auf meine Kiste, das wird mich erstmal die nächste Wochen genug beschäftigen ;)

...

Seid ihr eigentlich nun dabei daucms mit pylucid zu fusionieren und beide Wiki-Syntaxen zusammenzuführen?

Und noch eine Frage: Mir ist aufgefallen das ihr auch [[[ fobar ]]]-Tags habt. Sind die dafür da um Listen zu erzeugen?

lg
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Seid ihr eigentlich nun dabei daucms mit pylucid zu fusionieren und beide Wiki-Syntaxen zusammenzuführen?
Im Moment nein. Eine Direkte Fusionierung wird es meiner Meinung nach nicht geben.
Es wird später mal ein Plugin für PyLucid geben, um es wie dauCMS benutzen zu können. Also Lokal den Content erstellen und diesen in HTML überführen und dann via FTP etc. hochladen.

Allerdings erst später, da zumindest ich, für meinen Teil gerne erstmal eine Stabile Version erreichen möchte.
Und noch eine Frage: Mir ist aufgefallen das ihr auch [[[ fobar ]]]-Tags habt. Sind die dafür da um Listen zu erzeugen?
Die sind nur so zum Spaß da ;)
Die sind Übergangsweise da... unser Listenparser ist noch nicht fertig... um die Dokumentation aber ansehnlicher zu gestalten haben wir diese Tags eingefügt... sie werden aber entfernt, sobald wir offiziell Listen unterstützen.

MfG EnTeQuAk
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

oke.-... das erste, was schonmal nicht ganz ohne Probleme klappt...

Ich habe folgende Regex:

Code: Alles auswählen

scan_re = re.compile(
            r"(?:"
            +  r"(?P<bold>\*\*)"
            +  r"|(?P<italic>\/\/)"
            +  r"|(?P<underline>__)"
            +  r"|(?P<headline>(={1,6})(.*)\1)"
            +  r"|(?P<url>(http|ftp|nntp|news|mailto)\:[^\s'\"]+\S)"
            +  r"|(?P<dauurl>#link\["
            +      r"((?:(?:https?|ftp|nntp|news|mailto)\:[^\s'\"])?(?:www.)?"
            +          r"(?:.*)"
            +      r"(?:\.[a-z]{2}){1,2}(?:[a-zA-Z0-9\/\\\.]*))"
            +      r"(\s[a-zA-Z0-9-_.:\/\\\s]*)?\])"
            +  r"|(?P<email>[-\w._+]+\@[\w.-]+)"
            +  r"|(?P<pre>(\{\{\{|\}\}\}))"
            + r")")
Er trifft alles wunderbar... mit ausnahme der Überschriften (gruppe 'headline')
Warum? Das ist die gleiche Regex, die ich immer verwendet habe...

Hat da jemand eine Idee?

MfG EnTeQuAk

EDIT:
oke... ich habe es gefunden. Die '\1' ist falsch... müsste anders lauten... '\5' oder so... nur da kommt nur quatsch raus ;)
Habe nun einiges verbessert... aber so richtig funktionieren tut es net...
http://daucms.de/trac/browser/dauCMS/tr ... py?rev=206
Benutzeravatar
Luzandro
User
Beiträge: 87
Registriert: Freitag 21. April 2006, 17:03

oke... ich habe es gefunden. Die '\1' ist falsch... müsste anders lauten... '\5' oder so... nur da kommt nur quatsch raus ;)
Du kannst der Gruppe mit den = auch einen Namen geben (sinnvolleren als hier) und diesen bei der Rückreferenz verwenden
EnTeQuAk hat geschrieben:

Code: Alles auswählen

            +  r"|(?P<headline>(?P<foo>={1,6})(.*)(?P=foo)"
[url=http://www.leckse.net/artikel/meta/profilieren]Profilieren im Netz leicht gemacht[/url]
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

achsoooo geht das :D

Na dann haben wir das nun gefixed :D

Herzlichen Dank!

Und weiter gehts, neue Sachen einzubauen.

@sape:

habe mich in deinen Parser/Lexer schonmal ein wenig reingearbeitet... ist auch ganz angenehm zu benutzen... nur die Doku ist wirklich etwas arg :D

Aber es funktioniert jedenfalls schon einmal.

MfG EnTeQuAk
BlackJack

Das "innere" der <dauurl> finde ich unnötig einschränkend. Diese ganzen Tests auf verschiedene Protokolle und ob da nun `www.` am Anfang steht oder nicht ist doch alles völlig egal. Das `#link` sagt aus, dass in den eckigen Klammern eine URL steht, das reicht doch vollkommen aus. Ist so ähnlich wie Typprüfung vs. "duck typing", Du schliesst damit alle URLs und Protokolltypen aus, an die Du jetzt gerade mal nicht gedacht hast. `aim:`, `icq:`, `telnet:`, `sftp:`, `sip:` und so weiter.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Habs geändert... da hast du natürlich Recht :D

War schwachsinnig... Aber na ja... kommt vor.

Danke!

MfG EnTeQuAk
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

EnTeQuAk hat geschrieben: @sape:

habe mich in deinen Parser/Lexer schonmal ein wenig reingearbeitet... ist auch ganz angenehm zu benutzen...
Ja der Zugriff ist relatiev Simple. Aber sobald du dich mit den Interna vom AST-Kram beschäftigst, kriegst du genau wie ich das grauen :D (€: Muss man ja aber auch nicht. Dafür gibt es ja ``ast_to_token_stream(ast)`` ^^)
EnTeQuAk hat geschrieben: nur die Doku ist wirklich etwas arg :D
Um nicht zu sagen richtig beschießen, da nicht vorhanden :D

BTW: Ehm Sorry, was ich noch vergessen hab zu erwähnen. Wenn tags nicht geschlossen werden, findet in irgend einem Abschnitt vom Lexer ``assert``s statt. Da gehören eigentlich exceptions, die ich nicht eingebaut hatte. Also nicht wundern :mrgreen: -- Saubere wäre aber eine Interpretierung als Literal, wie es bei BBC auch gemacht wird.

Also:
``basis.py`` Zeile 191 wird ``assert stack[-1] == None`` ausgelöst falls der stack nicht leer ist, was halt durch nicht geschlossene Tags zu Stande kommt. Wenn das der Fall ist, ist ebenfalls ``lexer_stream_line`` nicht leer und in dem befinden sich seit dem betreffenden offenen Tag alle tokens.

Das könnte z.B: so aussehen.

Code: Alles auswählen

[('MarkupBold', '**'), ('Literal', ' test'), ('MarkupLinebreak', '\n'), ('Literal', '    test2')]
Nun, müsste man diesen Inhalt komplett als Literal behandeln, so wie es in BBC auch gemacht wird.

Hier, der Patch. Damit wird dann falls der stack voll ist, der Inhalt von ``lexer_stream_line`` als Literal in `` self._lexer_stream`` hinzugefügt:
Zeile 191 löschen und dann folgendes einfügen:

Code: Alles auswählen

        if stack[-1] is not None:
            tmp = list()
            for token in lexer_stream_line:
                tmp.append(token[1])
            lexer_stream_line = [(TT.LITERAL, "".join(tmp))]
            self._lexer_stream.append(lexer_stream_line)
Den Rest bin ich auch nochmal durchgegangen und sollte alles soweit ohne Bugs sein.

Ich mache mich nun auch mal dran, ne neue und sauberere Version zu Progen ;D

lg
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Klappt ganz gut... ;) Danke, für den Fix.


nebenbei bastel ich an meiner Variante weiter... und komme nicht weiter.

Die Datei schaut so aus: http://paste.pocoo.org/show/949/


Immo funktioniert das ganze schon nicht so schlecht... nur habe ich ein Problem, mit der 'noparser' Syntax... also die stellen, die gar nicht erst durch den Parser laufen sollen... ich weiß net, wie ich die aussortieren soll.

Ich hatte es schonmal mit einer Umgebungsvariablen 'self.in_noparse' probiert... so, wie bei 'self.is_b' usw... aber das hat nicht so ganz funktioniert.

Habt ihr da ne Idee?

MfG EnTeQuAk

EDIT:
Habe es nun hinbekommen...
Fertige Datei: http://daucms.de/trac/browser/dauCMS/tr ... order=name
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

So, ich hab mal aus dem SVN die letzte Version genommen und bearbeitet:
http://paste.pocoo.org/reply/949/
diff: http://paste.pocoo.org/compare/969/

Ich habe damit die Trennung der Syntax vom eigentlichen Parser gemacht. Nun könnte ich eine eigene Syntax-Klasse für PyLucid bauen und benutzten. Ich denke das ist sauberer, als das selbe über erben zu machen, oder?

EDIT: Generell werden aber die Absätze nicht gut gemacht :( Alles wird über ein "<br />" gemacht. Die normalen "<p>"-Tags werden nicht genutzt. Das ist unschön.
In tinyTextile bilde ich die Absätzte mit einem blocks = re.split("\n{2,}", txt) siehe:
http://pylucid.net/trac/browser/trunk/P ... v=824#L195

Dadurch hat man sauberen HTML-Code.

z.B.:

Code: Alles auswählen

Eine Zeile
zweite Zeile

Nächster Block.
Und bla...
wird dann mit tinyTextile zu:

Code: Alles auswählen

<p>Eine Zeile<br />
zweite Zeile</p>

<p>Nächster Block.<br />
Und bla...</p>
in dauCMS dürfte das ungefähr so aussehen:

Code: Alles auswählen

Eine Zeile<br />
zweite Zeile<br />
<br />
Nächster Block.<br />
Und bla...
Ist per Hand "generiert" ;)

EDIT2: Ach... Irgendwie verstehe ich es nicht, was es mit dem self.is_ auf sich hat.

EDIT3: Zum thema paragraphs: http://www.python-forum.de/post-18944.html#18944
Zuletzt geändert von jens am Dienstag 13. Februar 2007, 18:28, insgesamt 1-mal geändert.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich hab den reST Kram mal abgetrennt: http://www.python-forum.de/topic-9498.html

Leider ist ein Beitrag von EnTeQuAk mit rausgetrennt worden. Deswegen diesen hier nochmal als Full-Quote:
EnTeQuAk hat geschrieben:Danke sape ;)

@ Jens:

Ich schau mir deine Lösung mal nachher genauer an.
€dit:schaut supa aus ;) Danke -- :D Passt perfekt zum PluginSystem für dauCMS :D (womit später mehrere Syntaxen ermöglicht werden... Syntax-Module sozusagen)

Das wegen den '<p>' 's ist mir auch schon aufgefallen... und war bisher nicht böse gemeint ;)

Es wird demnächst aber implementiert.


MfG EnTeQuAK

EDIT:
EDIT2: Ach... Irgendwie verstehe ich es nicht, was es mit dem self.is_ auf sich hat.
Damit werden z.B. zwischen '//' als öffnendes 'italic'-Tag und '//' als schließendes 'italic'-Tag unterschieden.
Dadurch wird aus der Liste, was _bold_replacer() etc. zurückgeben das richtige ausgewählt... (stelle 1 oder stelle 0)
Die self.is_ Sache durchblicke ich noch nicht so ganz. Aber vielleicht muß ich mir dazu nochmal den Quellentext ansehen.
Aber was anderes: Warum dieser Name "is_" ??? Sehr untypisch!

Und noch was anderes: Ich denke man sollte zwischen Block und Inline Sachen unterscheiden und das evtl. trennen.
Block-Teile sind für mich z.B.:
  • - Überschriften
    - Text-Absätzte (Also das was man in <p> Einschließen kann)
    - noparse-Areas
    - Listen
Mit Inline meine ich z.B.:
  • - bold
    - italic
    - URLs
Ich denke erst durch diese Trennung kann man saubere Absätze mit <p>-Tags erstellen.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Grundlegend ist der parser noch nicht das perfekte (gut, das gibet net aber egal...).

Er schaut halt immo nur Zeile für Zeile nach --> Da muss noch das Nachschauen für nächste Zeilen her ;)

Daran arbeite ich bereits ;) Mit deiner Standalone-Variante ist dann auch schon eine gute Trennung zwischen Syntax und Parser ansich getan.

Nur brauche ich jetzt erstmal einen Cache... ach na ja ;) Heute wird jedenfalls net so viel gemacht ;) Heut, Vallendienstag... lass ich mich verwöhnen ;) B-Day hat man ja net immer :D -- :=)

MfG EnTeQuAK
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Cache im Parser??? Das würde ich erstmal komplett außer acht lassen.

tinyTextile geht auch Zeilenweise den Text durch. Ist aber eigentlich sehr dumm, z.B. bei noparse Areas und Escape-Areas. Diese besonderen Blocks sollte man IMHO vorab heraus extrahieren. Evtl. so wie hier http://www.python-forum.de/post-18944.html#18944 mit extract und assamble...
Ich frage mich allerdings ob man nicht besser erst einmal die Block-Teile mit re.split auftrennen sollte. Dann hat man eine Liste mit den einzelnen Blocks. Über diese iteriert man dann und erledigt den Rest.

Mich würde interessieren, wie es pygments mit dem RegexLexer macht. Ich hatte da ja mal mit rumprobiert: http://www.python-forum.de/topic-9408.html

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Das mit dem Zeilenweisen durchgehen ist ansich ja kein Problem, für meinen Parser.

Ich muss solch Sachen wie noparse gar nicht mal im Vorhinein aussortieren. Sondern habe dafür meine Zustandsvariable 'self.in_noparse'. Damit weiß ich Parser dann, das er sämtliche Formatierungen überspringen soll, solange diese Variable gesetzt ist.

Ich finde, das ist eine ganz simple und funktionierende Lösung. ;)

Immo funktioniert es jedenfalls sehr gut und sehr perfomant obendrein... :)


MfG EnTeQuAk
Benutzeravatar
Mr_Snede
User
Beiträge: 387
Registriert: Sonntag 8. Februar 2004, 16:02
Wohnort: D-Dorf, Bo

jens hat geschrieben:Ich frage mich allerdings ob man nicht besser erst einmal die Block-Teile mit re.split auftrennen sollte. Dann hat man eine Liste mit den einzelnen Blocks. Über diese iteriert man dann und erledigt den Rest.
Die Idee gefällt mir.

Würde meinem Ansatz Listen zu erzeugen entgegenkommen:
--> Link

Der lebt davon, zu wissen ob die nächste Zeile wieder ein Listenelement ist oder nicht.
Oder hier halt, ob der Listenblock zu Ende ist.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

So... ich schaue mir gerade einige Parser anderer Systeme an, um meinen mit einigen Ideen zu erweitern.

Dabei ist mir aufgefallen, das MoinMoin eigentlich die gleiche Idee verfolgt. Basierend auf PikiiPikii ... ;) Nur halt im "gehobenen" Stil. Was mir persönlich die Hoffung gibt, das es nicht so extrem viel zu erweitern gibt.

Was ich im Moment am implementieren bin, ist "prä_parser", der mir den Text in eine Art AST verwandelt... es ist aber kein richtiger AST sondern im Prinzie **imho** nur der Text, in einzelne Zeilen gesplittet und mit einer Zeilennummer versehen.

Des weiteren werden nun an eine 'replacer'-Funktion volgende **optionale** Argumente übergeben:

- raw_txt (der gesamte Quelltext)
- match_obj (das match-Objekt, das beim Parsen entstand)
- match_str (der gesamte String, der gefunden wurde. Ein Tupel, aus String und Zeilennummer (und damit auch Index in der Liste 'pre_parsed_tokens'))

Die 'replacer' Funktionen können nun einen schließer oder öffner frei definieren
(was "früher" nur mit 'self.is_b', 'self.is_u', self.is_i' definiert wurde). So werden im Moment sehr zuverlässig die öffnenden und schließenden Tags gesetzt.
Damit wird auch das schreiben eines 'pre_replacer' 's wesentlich einfacher (grad ma 5 Zeilen--- ohne eingreifen in die 'parse'-Methode)


Na Ja... im Moment alles noch mehr Baustelle, als fertig aber... die Ideen sind da ;)

Demnächst werde ich mir auch mal die Text (BB-Code)-Parser in pocoo anschauen, wie die gelößt sind... sicherlich anders... aber ma schaun, vllt. übernimmt man das ein oder andere Konzept.


Jedenfalls muss ich einfach ma sagen, hab ich nen neues Hobby gefunden und es macht riesigen Spaß, sich mit dem Lexen/Parsen von Text zu befassen ;)

Sollten euch noch interessante Text(Wiki-Syntax)-Parser-Implementationen einfallen... nur her damit!

@sape:
wie schauts eigentlich bei dir aus? -- Gestoppt oder ist dein Parser noch in Entwicklung?

MfG EnTeQuAk
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

EnTeQuAk hat geschrieben:[...]
@sape:
wie schauts eigentlich bei dir aus? -- Gestoppt oder ist dein Parser noch in Entwicklung?
Hi.

Nach dem ersten Versuch mit dem ich nicht zufrieden war, habe ich mich an eine neun gewagt, der besser ist und ohne AST auskommt. Aber momentan bin ich mit einem Projekt beschäftige, das mich zeitlich beansprucht. Daher ist das Projekt erstmal ca. für 3 Monate auf Eis gelegt.

BTW: Der neue Parser wird mit Metaklassen realisiert werden. Habs endlich verstanden und bin auf einige Einsatzgebiete beim Testen gestoßen. Ich muss sagen Metaklassen sind sehr genial, man kann sich damit sehr viele Zeilen Code ersparen und vieles auf sehr elegante weise realisieren.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

drei Monate ist ne lange Zeit.... ginge es evneutell, das du ma zeigst, was du hast ? (was ist egal ;) ).

Weil immo suche ich noch nach ein paar Konzepten, womit ich unseren Parser einfach... besser, einfacher etc. machen kann.


PS: die Versionen im dauCMS-Trac sind veraltet und werden lokal bearbeitet!

MfG EnTeQuAk
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Möchte nur mal was anmerken.

Ihr wollt doch sicherlich auch irgendwann in DauCMS einen JS-Editor einbauen, siehe: http://www.python-forum.de/topic-8252.html

Dann sollte man da mal sehen, in wie fern sich die Syntax mit den Editoren vertragen.
Normalerweise spucken ja die Editoren direktes html aus. Ich weiß nicht ob es auch möglich ist, das diese aber die Markup-Syntax als Ergebnis zurück liefern. In Moin gibt es ja auch einen GUI Editor, gespeichert wird IMHO in Moin-Markup nicht in html.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten