AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Konzept - BBCode Parser

Ein Thema von Prototypjack · begonnen am 14. Mai 2007 · letzter Beitrag vom 12. Okt 2007
Antwort Antwort
Prototypjack

Registriert seit: 2. Feb 2003
611 Beiträge
 
Delphi 2009 Professional
 
#1

Konzept - BBCode Parser

  Alt 14. Mai 2007, 12:58
Moin!

Ich plane momentan eine Komponente zu erstellen, die mit BBCode zurechtkommt und diesen auch erwartungsgemäß darstellen kann.

Was ich mich diesen Thread erreichen will ist, ob das, was ich bis jetzt geplant habe, überhaupt Sinn ergibt, verbesserungswürdig ist, oder tatsächlich gut ist.

Meine Überlegungen:

Zitat:
Da gibt es eine Funktion ( ), sie hat einen Parameter, in dem gespeichert ist, welche Formatierung gerade aktiv ist (Record, mit Werten wie Bold(Boolean) usw.) und einen Widestring-Wert, der den jeweiligen zu parsenden Text enthält.

Eine Funktion liest den gesamten Text, sie übergibt jeden einzelnen Buchstaben in ein Mehrdimensionales Array (Zweidimensional, also array of array of TExtendedchar). Falls ein BBCode-Tag gefunden wird, wird zuerst überprüft ob es ein passendes End-Tag gibt (wenn nicht wird es einfach ignoriert und nach dem nächsten BB-Tag gesucht), sollte dies der Fall sein, wird das Tag geparsed, entschieden, welches Formatierungszeichen zulässig ist (bei [b] zum Beispiel Record.Bold := True), dann wird der Startparameter der Funktion genommen (Lokale-Kopie), um dieses BB-Tag erweitert (Beispiel: Attribut Bold := True wird hinzugefügt) und ALLES was zwischen dem Start und dem End-Tag liegt wird an die Funktion (Rekursiv) selbst übergeben (zusammen mit dem Lokalen-Start Parameter).

Wenn die Funktion beendet ist, habe ich in der ersten Dimension des Arrays alle Lines des Memos, in der zweiten (jeweiligen) einen Record (TExtendedChar), welcher dann alle Attribute, die in diesem Moment aktiv waren und den Char enthält.

Später kann ich dieses Array durchgehen, und alle Buchstaben einzeln (oder, vielleicht, immer den Pack, wo die Formatierung gleich ist, also z.B. die drei Einheiten des Arrays der 2ten Dimension, welche alle Bold und Italic beinhalten), per TextOut und vorheriger anpassung der Attribute eines Canvas ausgeben.
Kann man das so umsetzen? Gibt es bereits etwas brauchbares? Gibt es Performancebedenken? Haltet ihr mich für verwirrt und versteht nicht was ich meine?

Gruß,
Max
Max
„If you have any great suggestions, feel free to mail me, and I'll probably feel free to ignore you.“ . Linus Torvalds
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#2

Re: Konzept - BBCode Parser

  Alt 14. Mai 2007, 13:33
Hi,
an sich würde ich Dir erstmal den Tipp geben, dass Du Dich ein wenig mit den Grundlagen des Parser-/Compilerbaus beschäftigst. Da gibt es bestimmte Vorgehensweisen, die sich als sehr nützlich erwiesen haben und im Prinzip für alle Parser verwendet werden können. An sich kannst Du hier front- und Backend unterscheiden und bis einschließlich der Parser kann eigentlich immer alles auf gleiche Art und Weise gemacht werden. Je nach Grammatik sind bestimmte Parser dabei dann sicherlich effizienter als andere und je nach Implementierung gilt das dann auch noch mal, aber das ist egal (kannst Du leicht ergooglen, wenn Du nach Bei Google suchenparser oder so suchst)

Jedenfalls arbeitet man häufig nach einem sehr einfachen Prinzip, Du gehst in mehreren Stufen durch. Du hast Code der geparst werden soll, die Eingabe. Die Eingabe wird erstmal durch einen Scanner bearbeitet. Ein solcher Scanner zerlegt die Eingabe in Token. Ein Token ist dabei ein Teil der Eingabe, der um eine Qualifizierung erweitert wird. Das heißt, dass wenn Du ein BBCode-Tag findest, Du einfach ein Record (o.Ä.) hast, wo Du einen Wert und seine Eigenschaft speichern kannst. Findest Du einen String
Code:
"Ein Test String mit [i]BBCode[/i]"
So kannst Du den hier den BBCode ([i]) einfach qualifizieren, Dir also merken, dass es ein öffnendes und ein schließendes i-Tag gibt. Der Rest ist dann einfach normaler Text (ebenfalls eine Qualifizierung). Der Scanner erstellt Dir also aus einer Eingabe einfach eine Liste von Token (Typ + Wert).
Hast Du jetzt diese Liste von Token, kannst Du diese einfach an einen Parser weiterreichen.
Ein Parser hat in der Regel auch zwei einfache Aufgaben, er erstellt aus der Liste von Token einen Syntaxbaum und kann dabei die Korrektheit der Eingabe überprüfen. Hier hast Du dann die Möglichkeit, dass Du Top-Down oder Bottom-Up arbeitest. I.d.R. dürfte Bottom up effizienter zu realisieren sein, allerdings gibt es auch funktionale, monadische Parser, die einen anderen Weg gehen (und auch ordentlich flink arbeiten!).
Jedenfalls solltest Du Dir hier überlegen, wie streng Du sein möchtest, je strenger desto leichter lässt sich so ein Parser realisieren. Statt einer Matrix solltest Du übrigens wirklich lieber zu einem Baum greifen, da kannst Du die Verschachtelung der Tags leichter abbilden. Das Hauptproblem hier ist dann eine unsaubere Verschachtelung, bei der man Tags nicht in der Reihenfolge schließt, in der sie geöffnet wurden (ich würde das erstmal einfach nicht zulassen/ignorieren).

Ein solcher Baum könnte dann die Form haben:
[code]
|-(TEXT)
|-- Ein Test String mit
|-- (Italic)
|-- BBCode
|-- (END ITALIC)
[code]

Den eigentlichen Sinn erkennt man vielleicht eher bei stärkerer Verschachtelung, allerdings kannst Du halt sehr einfach eine solche Struktur traversieren und nach festen Regeln auf jeden Knoten im Baum reagieren und die Formatierung entsprechend anpassen.

Gruß Der Unwissende
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#3

Re: Konzept - BBCode Parser

  Alt 14. Mai 2007, 13:35
Beschäftige Dich einfach mal mit der grundlegenden Funktionsweise eines Scanners und eines Parsers. Dann klappt der Rest von Alleine.

Ein Scanner zerlegt einen Inputstring in seine Sprachbestandteile ('Wörter'). Bei BBCode (Kenn nich nicht, aber egal) wären das z.B. 'BeginTag', 'EndTag' und 'String'.

Der Parser nimmt nun diese Wort-Sequenz und erstellt einen sog. Syntaxbaum. Immer wenn eine logischer Block abgearbeitet wird, kann dieser Baum dann von einem 'Compiler' in die Zielsprache (z.B. RTF) übersetzt werden.

Wenn man die Theore richtig umsetzt, kann gar nichts schiefgehen.

[Edit] Der_Unwissende ist auch Der_Schnellere[/edit]
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
CCRDude
(Gast)

n/a Beiträge
 
#4

Re: Konzept - BBCode Parser

  Alt 14. Mai 2007, 13:37
Und ein bißchen kommts auch noch auf das Format an, in dem die Sachen weiterverarbeitet werden sollen. Ginge es beispielsweise um eine TMemo/TRichEdit-ähnliche Komponente zu gestalten, würds ja schon fast ausreichen, die BBCodes einfach stumpfsinnig mit RTF-Anweisungen auszutauschen.
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#5

Re: Konzept - BBCode Parser

  Alt 14. Mai 2007, 13:39
Zitat von CCRDude:
Ginge es beispielsweise um eine TMemo/TRichEdit-ähnliche Komponente zu gestalten, würds ja schon fast ausreichen, die BBCodes einfach stumpfsinnig mit RTF-Anweisungen auszutauschen.
Wobei man auch dieses stumpfsinnige Austauschen dem von alzaimar bereits erwähnten Compiler überlassen sollte, ermöglicht es das Frontend leichter auszutauschen (falls es mal doch etwas anderes wird)
  Mit Zitat antworten Zitat
Prototypjack

Registriert seit: 2. Feb 2003
611 Beiträge
 
Delphi 2009 Professional
 
#6

Re: Konzept - BBCode Parser

  Alt 14. Mai 2007, 13:43
Moin!

Ok. Wow. Dazu wirkt mein Routinchen ja geradezu erschreckend primitiv.

Hmm, ich werde mich dann wohl mit dem von euch genannten Thema weiter auseinandersetzen. Ich nehme an, sowas wird hier (Weiterführende Erklärungen usw.) im Forum zu finden sein. Dennoch ermutige ich euch gutes Material auch hier zu posten .

CCRDude, das ganze wird, wie bereits oben erwähnt, per Canvas ausgegeben, ich selbst zeichne den Text, also ist leider nichts mit primitivem Anweisungs-ersetzen. Leider

Alzaimar, BBCodes sind dieses, welche du (auch hier im Forum) dazu verwenden kannst Text zu formatieren. [ b] Foo [ /b] wird also zu Foo.

Ok, dann mache ich mich mal auf die Suche, dennoch bitte fleißig weiterposen

Gruß,
Max

Edit: BBCode korrigiert -.- Da schreibt man einmal BBCode um was zu erklären und es funktioniert nicht.


Edit 2: Ok, ich bin mehr als erschlagen von den komplexen Strukturen und begreife langsam was ich da machen muss um an mein Ziel zu gelangen. (Eigentlich begreife ich (noch) gar nichts, aber ich denke ich kann den Aufwand sehr grob abschätzen)
Hilfe
Max
„If you have any great suggestions, feel free to mail me, and I'll probably feel free to ignore you.“ . Linus Torvalds
  Mit Zitat antworten Zitat
Prototypjack

Registriert seit: 2. Feb 2003
611 Beiträge
 
Delphi 2009 Professional
 
#7

Re: Konzept - BBCode Parser

  Alt 14. Mai 2007, 14:52
Moin,

Habe ich zumindest das Prinzip des Token-Parsers richtig verstanden?

Hier mal wie ich mir das vorstelle, anhand eines Beispiels:

Code:
Test 1, 2
[b]Hallo[/b] ich heiße Tokenizer.
[u]Meine Aufgabe ist es [i]Tokens[/i] zu erstellen.[/u]
Das war's schon wieder.
wird dann verarbeitet zu folgender Tokenlist:
Code:
Lexer-Begin

"Test 1, 2": String
[b]: Identifier [Begin]
"Hallo": String
[/b]: Identifier [End]
" ich heiße Tokenizer.": String
[u]: Identifier [Begin]
"Meine Aufgabe ist es ": String
[i]: Identifier [Begin]
"Tokens": String
[/i]: Identifier [End]
"zu erstellen.": String
[/u]: Identifier [End]
"Das war's schon wieder.": String

Lexer-End
Habe ich zumindest das Prinzip dieses (zugegebenermaßen kleinen) Abschnitts von Parsern verstanden?

Gruß,
Max
Max
„If you have any great suggestions, feel free to mail me, and I'll probably feel free to ignore you.“ . Linus Torvalds
  Mit Zitat antworten Zitat
mimi

Registriert seit: 1. Dez 2002
Ort: Oldenburg(Oldenburg)
2.008 Beiträge
 
FreePascal / Lazarus
 
#8

Re: Konzept - BBCode Parser

  Alt 12. Okt 2007, 14:03
ich hänge mal mein Soruce dran... der ist unter Lazarus geschrieben und getestet.

ich habe aber die [] zu <> ausgetauscht, weil unter Linux können Font Namen diese [] Zeichen Enthalten.

Das ganze war nur ein "einfacher" Test. der Paser kann folgende beispiel Texte Problemlos anzeigen:
Zitat:
Dies ist ein einfacher Beispiel Text ohne
Formatierung. Mal sehen ob er angezeigt wird.

Jetzt kommt die Formatierung:
<fg=red>Rot</fg> <fg=blue>Blau</fg>
<fg=orange>Dieser Test ist Orange und <fg=red2>Rot2 <fg=blue>Haus <fg=chocolate>Tane Tane Tane</fg>Haus Haus Haus</fg>
Garten Garten Garten</fg>u77utt5</fg>f
Text Text Text Text

Dieser Text ist fett und dieser ist nicht Fett.
Dieser Text ist kusif und dieser ist nicht Kusif
Dieser Text ist <u>unterstriechen</u> und dieser nicht
Dieser Text ist in <fn=new century schoolbook [adobe]>new century schoolbook [adobe]</fn> test test testheute

Diesist ein test von heute<u>test2</u> test3
<fg=blue> <bg=Red>Roter Hintergrund</bg> Test2 <bg=SlateBlue2> Test3 Test4<bg=black>Haus1Lilo</bg></bg></fg>
Hallo du bis ein Test von heute wie geht es dir so ?

<size=16>Dieser text wird in 16 angezeigt <size=30>und dieser in 30</size>
und dieser wieder in 16</size> und dieser wirder Normal.
LinkListen:
Wie geht es dir heute so ?<link=www.google.de>www.google.de</link> dies ist ein Test von Heute
Wie ist das Wetter ?<link=www.heise.de>www.heise.de</link> Morgen ?
Der Wald ist <link=www.lazarusforum.de>www.lazarusforum.de</link>gruen oder nicht ?
Das Wasser ist<link=www.suse.de>www.suse.de</link> aber nass.
Klick bitte auf diesen <link=www.suse.de>link</link> danke !

<fg=blue3>
test test test
<bg=black>
Wie geht es dir ?
</bg>
</fg>

<liste>
TestListe1
<addlevel>
Level 1
Level 2
<addlevel>
Level 2,1
<addlevel>
Level 3,1
Level 3,2
<fg=blue>Level 3,3</fg>
Level 3,4
</addlevel>
Level 2,2
Level 2,3
</addlevel>
Level 3
Level 4
Level 5
</addlevel>
</liste>


<liste>
TestListe2
Root1
Root2
Root3
Root4
</liste>

CodeBeispiel01
<bg=black>
<code>
procedure LoadText(const aTextFile:String; aCanvas:TCanvas; aBuffer:TBitMap;var aLinkListe:TLinkItems);
procedure BufferSizeChange;
var
oldTextItem:TTextItem;
oldY,oldH:Integer;
oldBitMap:TBitMap;
begin
oldBitMap:=TBitMap.Create;
oldBitMap.Width:=aBuffer.Width;
oldBitMap.Height:=aBuffer.Height;
oldBitMap.Canvas.Brush.color:=clWhite;
oldBitMap.Canvas.FillRect(0,0,oldBitMap.Width,oldB itMap.Height);
BitBlt(oldBitMap.Canvas.Handle,0,0,oldBitMap.Width ,oldBitMap.Height,aBuffer.Canvas.Handle,0,0,SRCCOP Y);

CanvasToTextItem(oldTextItem,aCanvas);
oldY:=aBuffer.Height;
oldh:=aCanvas.ClipRect.Bottom;
aBuffer.Height:=aBuffer.Height+aCanvas.ClipRect.Bo ttom;

aCanvas.Brush.color:=clWhite;

aCanvas.FillRect(0,oldY,aBuffer.Width,oldy+oldh);
TextItemToCanvas(oldTextItem,aCanvas);
BitBlt(aBuffer.Canvas.Handle,0,0,oldBitMap.Width,o ldBitMap.Height,oldBitMap.Canvas.Handle,0,0,SRCCOP Y);
oldBitMap.Free;
end;
</code>
</bg>

Die ist wieder ein Normaler Text ein Test von heute wie
geht es dir so ? Gut dann komme mich doch mal besuchen.
das würde dann so aussehen wie im anahng zu sehen. besonders schön finde ich die verschatlung von anweisungen wie [b] und soweiter....

es gibt leider noch den einen anderen anderen Anzeige Fehler, aber im Prinzip geht das schon ganz gut.
Der Paser kann folgendes im Moment:
b = Text Fett Dastellen
i = Text Kusif Dastellen
u = Text Unterstriechen Dastellen*
fg = wert foder grund Farbe setzten**
bg = wert Hintergrund Farbe setzten**
size=Text größe
liste = fängt eine Liste an die auch verschatelt werden kann
code = Zeigt einen Soruce an, so wie er geschrieben wurde, später soll er gehiglietet angezeigt werden.
link = kann ein einfacher Link erzeugt werden.

* Durchgestriechen geht leider nicht, weil das unter Linux bei den Font-Stylen noch nicht unterstütz wird
** werte werden immer mit red oder blue angeben.
der Paser hängt auto pl_ vorne dran.
Die dise Konstasen habe ich erstellt und in eine eigene Unit gepackt, weil mir 16 Farben etwas wenig vorkommen, so habe ich jetzt 641 Farben. *G*.

Du/ihr könnt es auch ja mal anschauen und sagen, was ihr davon haltet. mein Ziel war es eigentlich ein eigenen Hilfesystem für Anwendungen zu schreiben das Plottform übergreifend arbeitet.
und auch Soruce Beispiele richtig anzeigen kann also in mehrer Farben und so.

Später sollen halt noch einfache und Komplxere Tabellen hinzukommen. Grafiken, und Text Boxen.
evlt. habt ihr ja noch Vorschläge.... oder findet noch Fehler.....
im Anahngt befindet sich zwei Units und ein Bild.
Die Form1.pas enhält alles notwendiger, mit etwas anpassung müsstest du es unter Delphi Komplieren können

Nocheinmal: Das ganze Projekt habe ich unter Lazarus, Ubuntu angefangen... daher poste ich auch nur einzelne units und nicht das ganze Projekt.... weil das würde euch wenig weiter Helfen... da ihr es erst anpassen müsst, so ist das meine ich einfacher.....
Angehängte Grafiken
Dateityp: png bildschirmfoto-bb-code_paser_168.png (20,4 KB, 39x aufgerufen)
Angehängte Dateien
Dateityp: zip lazarus_530.zip (24,7 KB, 18x aufgerufen)
Michael Springwald
MFG
Michael Springwald,
Bitte nur Deutsche Links angeben Danke (benutzte überwiegend Lazarus)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz