AGB  ·  Datenschutz  ·  Impressum  







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

Wer zeigt mir, wie ich parsen muss?

Ein Thema von torud · begonnen am 12. Apr 2006 · letzter Beitrag vom 12. Apr 2006
Antwort Antwort
torud

Registriert seit: 26. Jul 2002
Ort: Sachsen
1.198 Beiträge
 
Delphi XE5 Professional
 
#1

Wer zeigt mir, wie ich parsen muss?

  Alt 12. Apr 2006, 07:41
Hallo Wissende,

da ich immer wieder Probleme mit meinem eigenen CSS-Editor habe, will ich nun das System des Zerschneiden des Inhaltes von { bis } und dem restlichen Löschen nun ein Ende bereiten und richtig parsen, denn ich verspreche mir davon, dass es endlich besser wird.

Wer von Euch hätte denn die Güte mir bei diesen ersten Schritte ne Krücke zu reichen?

Ich gebe mal einfach folgenden CSS-Code vor, der sich in einem meiner SynEdits befinden würde und anschliessend geparst werden sollte...


Zitat:
body{ font-family:verdana;font:size:12px;}

/* Dann ein Kommentar zum üben */

.class, #id {
color:green;
border: 1px solid gray;
}
Ich denke, dass das ein kleiner Anfang wäre. ich weiss nun nicht genau, wie das funktionieren müsste, brauche aber alle Elemente, die in diesem Fall body, .class und #id wären. Der Kommentar müsste natürlich herausgefiltert werden und Fehler müssten in einer weiteren Ausbaustufe auch gefunden werden. => zum Beispiel nicht abgeschlossene Elemente (Anzahl { > } ).

Also wer erbarmt sich und erklärt mir was es mit token und co auf sich hat, oder wie man dieses Thema mit reglären Ausdrücken "erledigen" kann.
Danke
Tom
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

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

Re: Wer zeigt mir, wie ich parsen muss?

  Alt 12. Apr 2006, 07:55
Oje... mal sehen (Kurzform):
1. Ein 'Scanner' zerlegt die Eingabe in Token.
2. Ein 'Token' ist die Grundeinheit oder ein 'Wort' der zu parsenden Sprache.
3. Ein Parser implementiert die Grammatik der zu parsenden Sprache.

So einfach ist das. Bleiben nur noch 3 Kleinigkeiten:
1. Wie schreibt man einen Scanner?
2. Was ist denn eine Grammatik?
3. Und wie implementiert man dann den Parsers?

Ein Scanner liefert also die Wörter des Inputs. Für jedes Wort kann man einen regulären Ausdruck angeben, der genau dieses Wort beschreibt. Den Scanner kann man mit einem 'Deterministischen Endichen Automaten' (DEA) implementieren (reguläre Ausdrücke sind selbst DEA ), der Zeichen für Zeichen gegen die regulären Ausdrücke prüft und bei Erkennen eines vollständigen Wortes dieses 'Token' an den Parser übergibt.

[Edit] Der Kommentar wird z.B. von Scanner erkannt und als 'white Space' an den Parser übergeben [/edit]

Der Parses muss nun noch prüfen, ob die Token-Folge der zu prüfenden Sprache genügt. Dabei erstellt er zwangsweise einen Syntaxbaum, der dann, sozusagen 'en passant' auch die von Dir gewünschte Information enthält.

Wie Du siehst, kommen mit jeder Erklärung neue Begriffe hinzu, was den Schluss zulässt, das 'Parsen' und 'Scannen' nicht so einfach sind. Also, einfach ist es schon, aber nicht trivial. Na ja, trivial ist es auch. Wenn man es kann

Sooo schwer ist das allerdings nicht. Wenn Du einen Scanner geschrieben hast, dann besorge Dir erstmal eine Definition der Sprache, am besten in Backus-Naur-Form. Denn diese Form hilft Dir ungemein bei der Implementierung eines prozeduralen Parsers, der bei einfachen Sprachen am Schnellsten zu implementieren ist.

Hier im Forum habe ich aber schon fertige 'Scanner' und auch einige Artikel über 'Parser' gesehen, sodaß Dir die Foren-Suche weiterhelfen sollte.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
torud

Registriert seit: 26. Jul 2002
Ort: Sachsen
1.198 Beiträge
 
Delphi XE5 Professional
 
#3

Re: Wer zeigt mir, wie ich parsen muss?

  Alt 12. Apr 2006, 09:03
Hm, also das scheint mir doch relativ komplex zu sein. Aber um vielleicht nochmal zur Praxis zurückzukommen... Wie könnte ich es denn Codetechnisch angehen?

Ich habe sicher nicht alles von dem verstanden, was Du geschrieben hast, habe auch diverse Google-Pages durchgelesen, aber auch hier im Forum kein wirkliches Codebeispiel finden können. Mir ist schon klar, dass ich nichts für mir sofort brauchbares finden kann, da es hier sicher noch keinen Scanner für CSS, so ich das denn richtig verstanden habe, gibt, aber wie wäre es denn mit einem kleinen Beispiel für Scanner, Grammatikfestlegung und Parser...?

So wie ich es verstanden habe, findet der Scanenr nur die Worte. Das wären, um bei meinem Beispiel zu bleiben folgende:

body, font-family,verdana,font,size,12px
/* Dann ein Kommentar zum üben */
.class, #id ,color, green, border, 1px, solid, gray,

Das wäre doch im Prinzip alles ausser , ; : (Komma, Semikolon und Doppelpunkt) Wie würde aber das mit der lexikalischen Analyse funktionieren oder wie wäre das mit den regulären Ausdrücken. Das sind alles so unklare Formulierungen. Ich bin da immer der Freund des praktischen Beispieles, weil da wohl meine Vorstellungskraft nicht ausreicht.

Im Prinzip habe ich es bisher wie folgt gemacht.
Delphi-Quellcode:
procedure ReadElemente;
var
  Stringliste:TStringList;
  Pos_A,Pos_E:integer;
  Element,Inhalt:String;
begin
  ParserError:=False;
   //erstmal alles leeren
    myClass.Clear;
    myHTML.Clear;
    myIndi.Clear;
   //der inahlt dieser stringlisten wir in einen Treeview geschrieben,
   //wo man dann zugeordnet sehen kann, welche klassen, id´s oder html-elemende man hat
    myTClass.Clear;
    myTHTML.Clear;
    myTIndi.Clear;

  Stringliste:=TStringList.Create;
  Stringliste.AddStrings(MainForm.SynEdit1.Lines); //holt inhalt vom synedit

  if MainForm.SynEdit1.Lines.Count > 0 then

  Inhalt:=ClearCommentarTStrings(Stringliste); //löscht die kommentare

  while length(Inhalt) > 0 do //zerkaut den inhalt bis keiner mehr da ist
    begin
      {und hier das abarbeiten des Codes}
        Pos_A:= pos('{',Inhalt); //begin des formatierten elementes gefunden
        if Pos_A = 0 then
          begin
            Inhalt := '';
            Stringliste.Free;
            ParserError:=True;
            exit;
          end;
        Pos_E:= pos('}',Inhalt); //ende des formatierten elementes gefunden
     if Pos_E > 0 then
       begin
        //ermittelt den elementnamen
        Element:=Trim(midstr(Inhalt,0,Pos_A-1));
        //ShowMessage(Element);
        //ermittelt den elementtyp
        //hier klasse
        if (leftstr(Element,1) = '.') or (pos('.',Element) > 1) then
          begin
            myClass.Add(Element);
          end
        //hier ID
        else if (leftstr(Element,1) = '#') or (pos('#',Element) > 1) then
          begin
            myIndi.Add(Element);
          end
     else
       begin
        //ansonsten HTML-Element
         myHTML.Add(Element);
       end;

        //löscht das element mit allen angaben aus der liste
        Delete(Inhalt,1,Pos_E);

        Stringliste.Text:=Inhalt;
       end
     else
      begin
       ParserError:=True; //setzt globalen bool
       exit;
      end;
    end;
    Stringliste.Free;
end;
Leider ist diese Routine nicht so perfekt, hier fehlt auch noch diverses Zeugs, was zeigt, wie es weitergeht mit dem Code. Eines meiner Hauptprobleme ist, dass parsen während der Codeeingabe. Da geht mir immer wieder der Fokus von der SynEdit verloren, so dass man mitten im Schreiben einfach nicht weiter arbeiten kann.
Danke
Tom
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.117 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: Wer zeigt mir, wie ich parsen muss?

  Alt 12. Apr 2006, 22:09
Moin Tom,

also ich würde es, stilisiert, so angehen:

Delphi-Quellcode:
while i <= length(sBuffer) do begin
  case sBuffer[i] of
    'a'..'z' : begin // Bezeichner möglich
      // alle Zeichen aus dem Buffer auslesen, bis zum ersten Auftreten
      // eines Zeichens, dass nicht in einem Bezeichner vorkommen kann
      // Hierbei i entsprechend hochzählen (muss am Ende den Index des letzten
      // gültigen Zeichens enthalten
      // Jetzt kann geprüft werden, ob es sich nun um ein Keyword oder eine Variable
      // handelt, und der Wert entsprechend weggeschrieben werden.
    end;
    ';',',' : begin // Delimiter
      // Kann direkt als Token geschrieben werden
    end;
    '/' : begin // Evtl. beginnt hier ein Kommentar
      if i < length(sBuffer) then begin
        // folgt ein * ?
        // Ja, dann bis */ suchen, sonst direkt / übernehmen
      end else begin
      // i = Bufferlänge => Es kann kein Kommentar sein
      end;
    end;
    #32,#10,#13,#09 :; // Whitespace, es gibt nichts zu tun
  end;
  inc(i);
end;
Das nur einmal als grobes Beispiel. Das Auslesen eines Bezeichners sollte auch nicht direkt in der Schleife geschehen, sondern als Funktion ausgelagert werden, die, beispielsweise, als DEA ausgeführt ist, um einen gültigen Bezeichner zu extrahieren.
Unter dem Begriff "Zustandsautomat" kannst Du auch einiges als Erklärung für einen DEA finden.

Vielleicht kannst Du für CSS auch so etwas finden, wie die Referenz für C bzw. C++, z.B. bei MS.
Dort werden die verschiedenen Phasen eines Compilerdurchlaufes in Einzelheiten beschrieben.

BTW:
Ein Token setzt sich, i.d.R., aus zwei Teilen zusammen, nämlich Symbol und Attribut, wobei letzteres nur bei Variablen Werten erforderlich ist.
Beispielweise könnte das Token für Addition als (+,) dargestellt werden, da hier nur das Symbol interessiert, wohingegen das Token für eine Variable als (var,MyVar) dargestellt werden kann, wobei var das Symbol für eine Variable im allgemeinen steht, und MyVar den Namen des Bezeichners angibt.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  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 13:24 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