Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi JVRichEdit parsen - Hilfe?! (https://www.delphipraxis.net/78352-jvrichedit-parsen-hilfe.html)

Yheeky 3. Okt 2006 17:09


JVRichEdit parsen - Hilfe?!
 
Hi,

ich möchte in meinem Programm die JVRichEdit Komponente verwenden, da ich gerne Bitmaps in mein RichEdit einbauen möchte. Ich habe mit dem "Messenger-Beispiel" von den JV-Beispielen gearbeitet und die Bitmapanzeige geht auch schon soweit. Die Eingabe des Textes erfolgt auch über ein JVRichEdit. Dies sieht z.B. wiefolgt aus:
Zitat:

Hallo! Das ist ein Test :-D
Was nun noch per Hand gemacht werden muss, ist der Parser. Ich muss den oben dargestellten String durchgehen und schauen, ob ein Smiley bzw. ein eigenes Schlüsselwort enthalten ist...und hier liegt das Problem:

Das Messenger Beispiel hat wohl schon vorgefertigte Smileys, aber irgendwie blicke ich nicht so wirklich durch den Code. Ich weiss nicht wie ich eigene Definitionen einbauen kann.

Hier erstmal der komplette Code, unten drunter eine genauere Erklärung, was ich nicht verstehe:

Code:
procedure TfrmNachricht.ParseString(const S: string);
var
  P, Q: PChar;
  State: Integer;

  procedure AddImage(const SmileIndex, SmileLength: Integer);
  begin
    AddTextToRichEdit(Q, P - Q - SmileLength + 1, JVRichEdit2.Font);
    AddImageToRichEdit(SmileIndex);

    State := 0;
    Q := P + 1;
  end;
begin
  P := PChar(S);
  Q := P;

  State := 0;

  // State = 1.. then looking at ":-A" with A = @x)( etc.
  //         10..                 "LOL"
  //         20..                 "O :-)"
  //         30..                 "(blush)"
  //         40..                 ":'-("
  //         50..                 "8-)"
  //         60..                 ";-)"
  //         70..                 "readonly"
  //         80..                 "read-only on" or "read-only off"
  //
  // State = 1 -> ":" read
  // State = 2 -> ":-" read
  // State = 11 -> "LO" read
  // State = 22 -> "O :" read
  // State = 23 -> "O :-" read
  //
  // etc.

  while P^ <> #0 do
  begin
    case P^ of
      '$':
        if State in [2, 23] then
          AddImage(9, 3) // :-$
        else
          State := 0;
      '&':
        if State in [2, 23] then
          AddImage(4, 3) // :-&
        else
          State := 0;
      '(':
        case State of
          1, 22: AddImage(5, 2); // :(
          2, 23: AddImage(5, 3); // :-(
          40: AddImage(2, 3); // :,(
          41: AddImage(2, 4); // :'-(
        else
          State := 30;
        end;
      ')':
        case State of
          1, 22: AddImage(11, 2); // :)
          2: AddImage(11, 3); // :-)
          23: AddImage(6, 5); // O :-)
          35: AddImage(3, 7); // (blush)
          51: AddImage(1, 3); // 8-)
          61: AddImage(15, 3); // ;-)
        else
          State := 0;
        end;
      '*':
        if State = 1 then
          AddImage(7, 2) // :*
        else
          State := 0;
      ',':
        if State in [1, 22] then
          State := 40
        else
          State := 0;
      '-':
        case State of
          1, 22, 40, 50, 60: Inc(State);
          73: State := 80;
        else
          State := 0;
        end;
      '8': State := 50;
      '"': State := -1; // to prevent "read.." etc will be triggered by the program
      ':':
        if State = 21 then
          State := 22
        else
          State := 1;
      ';': State := 60;
      '@':
        case State of
          1, 22: AddImage(0, 2); // :@
          2, 23: AddImage(0, 3) // :-@
        else
          State := 0;
        end;
      'D':
        case State of
          1, 22: AddImage(8, 2); // :D = LOL
          2, 23: AddImage(8, 3) // :-D = LOL
        else
          State := 0;
        end;
      'L':
        if State = 11 then
          AddImage(8, 3) // LOL
        else
          State := 10;
      'O':
        if State = 10 then
          State := 11
        else
          State := 20;
      '\', '/':
        if State in [2, 23] then
          AddImage(14, 3) // :-\
        else
          State := 0;
      'a':
        if State = 71 then
          State := 72
        else
          State := 0;
      'b':
        if State = 30 then
          State := 31
        else
          State := 0;
      'd':
        if State = 72 then
          State := 73
        else
          State := 0;
      'e':
        if State = 70 then
          State := 71
        else
          State := 0;
      'h':
        if State = 34 then
          State := 35
        else
          State := 0;
      'l':
        if State in [31, 75, 82] then
          Inc(State)
        else
          State := 0;
      'o':
        case State of
          2, 23: AddImage(12, 3); // :-o
          73, 80, 85: Inc(State);
        else
          State := 0;
        end;
      'p':
        if State in [2, 23] then
          AddImage(13, 3) // :-p
        else
          State := 0;
      'r':
        if State <> -1 then
          State := 70
        else
          State := 0;
      's':
        if State = 33 then
          State := 34
        else
          State := 0;
      'u':
        if State = 32 then
          State := 33
        else
          State := 0;
      'x', 'X':
        if State in [2, 23] then
          AddImage(10, 3) // :-x
        else
          State := 0;
      ' ':
        case State of
          20, 84: Inc(State);
          11: State := 21;
        else
          State := 0;
        end;
    end;
    Inc(P);
  end;

  if Q < P then
    AddTextToRichEdit(Q, P - Q, JVRichEdit2.Font);
end;
Nehmen wir mal den Anfang des Parsers - hier fängt das erste Problem an:

Code:
while P^ <> #0 do
  begin
    case P^ of
      '$':
        if State in [2, 23] then
          AddImage(9, 3) // :-$
        else
          State := 0;
while P^ <> #0 - ist wohl die Abfrage, ob der String leer ist oder nicht, richtig?
case P^ of normale Case-Bedingung, prüft auf die kommenden Zeichen
'$': Wenn das Zeichen $ im String vorkommt, dann...
if State in [2, 23] then Hier nun ein Problem: Warum State in [2, 23]? Was hat die 2 und die 23 damit zu tun?

Ich verstehe auch nicht die Kommentare in der Funktion oben. Gibt´s da keine extra Hilfe, in der die States erklärt werden? Außerdem wird doch der Integer-Wert State vor dem Aufruf des Zeigers 0 gesetzt...

Wie ihr seht: Fragen über Fragen...vielleicht versteht ja einer von euch den Code und könnte ihn mir etwas erklären?! Wäre super nett! Danke!

marabu 3. Okt 2006 18:44

Re: JVRichEdit parsen - Hilfe?!
 
Hi Christian,

die Prozedur ParseString() implementiert einen Parser als Zustandsautomaten (Finite State Machine, FSM). Nach C-Manier wird der zu untersuchende String mit einem PChar-Zeiger (P) adressiert, der einfach per Zeigerarithmetik (Inc(P)) über den String geschoben werden kann. Da auf diese Weise immer nur ein Zeichen (P^) gesehen wird, die Grammatik aber die Zusammensetzung eines Smiley aus mehreren Zeichen erlaubt, muss sich der lexical analyser merken, welche Teil-Kombinationen er bisher erkannt hat (State). Auf diese Weise entfallen teure Stringvergleiche.

Hoffentlich habe ich mich einigermaßen verständlich ausdrücken können.

Grüße vom marabu

Yheeky 3. Okt 2006 19:03

Re: JVRichEdit parsen - Hilfe?!
 
Ja, bin inzwischen durchgestiegen...raffiniert diese Methode, aber richtig "sauber" ist sie doch nicht, oder?

marabu 3. Okt 2006 19:12

Re: JVRichEdit parsen - Hilfe?!
 
An der Methode ist nichts auszusetzen. Schwachstellen in der Umsetzung vermute ich, bin aber zu faul sie aufzuspüren.

Grüße, marabu

Yheeky 3. Okt 2006 19:38

Re: JVRichEdit parsen - Hilfe?!
 
Das bezog sich nicht auf die oben stehende Variante.
Trotzdem danke! Problem solved! :-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:30 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