Einzelnen Beitrag anzeigen

alzaimar
(Moderator)

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

Re: [Mission Impossible] CSS Parser erstellen...

  Alt 12. Aug 2006, 07:27
Hi Daniel,

So schwer ist das auch nicht. Wie Du schon richtig erkannt hast, besteht ein Parser aus zwei Teilen: Dem Tokenizer und dem 'Spracherkenner', dem Parser. Der Tokenizer überführt die Eingabe (meist eine Zeichenkette) in eine Token-Kette. Aus
Procedure Foobar (Param1 : Integer); Wird
Code:
Keyword PROCEDURE
Identifier FooBar
Symbol (
Identifier Param1
Symbol :
Identifier Integer
Symbol )
Symbol ;
Der Tokenizer ('Scanner') erkennt die Symbole, aus denen die zu parsende Sprache besteht. Die Delphi-Sprache basiert ja auf Symbolen ('Token') wie 'Procedure', 'Identifier','Number'. 'String' etc.

Ein Kommentar ist ein Sonderfall und wird i.A. vom Scanner verschluckt.

Wenn dein Tokenizer diese Routinen zur Verfügung stellt, dann kannst Du damit alle Sprachen erkennen.
Delphi-Quellcode:
Function GetNextToken : TToken; // liefert das nächste Token und bewegt den Eingabezeiger
Function UngetToken (aToken : TToken); // Bewegt den Eingabezeiger zurück, sodaß der nächste Aufruf von GetNextToken das aToken liefert.
Function PeepNextToken : TToken; // Liefert das nächste Token, ohne den Eingabezeiger zu bewegen.
Ein spezielles Token ist das 'EOF'-Token, das das Ende der Eingabe bezeichnet.

Der Parser überführt nun widerum die Eingabe (hier eine Token-Liste) in einen Syntax-Baum.
Der Compiler überführt den Syntax-Baum in die Übersetzung (meist ASM, kann aber auch z.B. 'C' sein. Oder formatierter Delphi-Code. Oder ein Manual, Crossref etc.).
Der Interpreter überführt den Syntax-Baum in eine E/A-Relation, führt also das Programm aus.

Für einen einfachen Parser musst Du nicht studiert haben, aber bei Sprachen wie Delphi sollte man schon mal etwas von 'formalen Sprachen' gehört haben. Bei deinem Beispiel würde ich die Grammatik der Sprache direkt in Delphi überführen:
Code:
Selektor { Eigenschaft-A: Wert-A; Eigenschaft-B: Wert-B; } /* Kommentar */
Code:
CSS-Code ::= <CSS-Statement> [ <CSS-Code> ]
                | Epsilon
Das ist die sog. Backus-Naur-Notation. Es bedeutet:
Zitat von Backus-Naur:
Ein CSS-Code besteht aus einem CSS-Statement gefolgt von CSS-Code (oder auch nicht, das sind die [...]). CSS-Code darf auch leer sein (das beduetet das Epsilon).
Code:
CSS-Statement ::= <Selektor> '{' <Propertylist> '}'
Selektor ::= Identifier
PropertyList ::= <PropertyDesc> [<PropertyList>] | Epsilon
PropertyDesc ::= <Property> ':' <Value> ';'
Property := Identifier
Value ::= Identifier | Integer-Number | Floating-Point-Number
Ein '|' steht für: Alternative.
Ein Identifier ist unsere übliche Definition eines Bezeichners. Das kann man zwar auch noch backusnaurnotationstechnisch beschreiben, aber das schenken wir uns, oder doch nicht:
Code:
Identififer ::= <Letter> [ <Letter-Or-Digit> ]
Letter ::= 'A' | 'B' | 'C' ... 'Z' | 'a' | ... | 'z'
Digit ::= '0' | ... '9'
Letter-Or-Digit ::= <Letter> | <Digit>
Soooo, jetzt das Programm:
Delphi-Quellcode:
Function CSSCode : Boolean;
Begin
  Result := False;
  If CSSStatement Then
     While CSSCode Do;
End;

Function CSSStatement : Boolean;
Var
  Selector : TToken;

Begin
  Result := False;
  If IsIdentifier (Selector) Then
    If IsSymbol ('{') Then
     If IsPropertyList Then
       If IsSymbol ('}') Then
         Result := True;
End;
...
Klar? Die Backus-Naur-Form wird einfach 1:1 in Delphi-Code umgesetzt. Natürlich fehlen im o.g. Beispiel geeignete Rückgabewerte, denn irgendwie muss der erkannte Code ja in einen Syntax-Baum. Nebenbei klappt das mit dieser Art der Parserprogrammierung nur, weil die CSS-Sprachdefinition so einfach ist, ich glaube das betrifft die LL(0)-Sprachen, weil sie von Links nach Rechts geparst werden können und keinen '(0)' Look-Ahead benötigen, aber das ist schon bald 15 Jahre her, also nagt der Zahn der Zeit an diesem Teil des Hirns.

EDIT: Oder kukstu hier
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat