Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Programmierung eines ByteCode-Parsers


BenBE - Di 30.11.04 11:33
Titel: Programmierung eines ByteCode-Parsers
Also, mein Problem besteht darin, dass ich für eine Skripting-Sprache (für Omorphia [http://sf.net/projects/omorphia/])einen Parser schreiben will\muss, der SEHR flexibel auf eingegebenen Source reagieren können muss. Der Source kann also entweder eine komplette Delphi-Unit ODER auch nur eine enzelne Programmzeile sein.

Aus diesem eingegebenen Source sollen dann als Ausgabe "Bytecodes" erzeugt werden, die von einem entsprechenden Interpreter dann Sprachunabhängig ausgeführt werden können. Den Interpreter hab ich auch soweit fertig, da das relativ einfach ist.

Jedoch find ich keinen Ansatz, wie ich z.B. folgende Sourcezeile (für Pascalstyle-Parser) umwandeln kann:


Delphi-Quelltext
1:
C := A + Abs(-C + B);                    


Als Struktur für die Bytecodes gilt folgende Struktur:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
type
    TOCmdParserSourcePosition = packed record
        Name:String;
        Offset: DWORD;
        Line: DWORD;
        Column: DWORD;
    end;

    POCmdByteCode = ^TOCmdByteCode;
    TOCmdByteCode = packed record
        BackLink: POCmdByteCode;
        OPCode: DWord;
        OPSize: DWord;
        OPData: Pointer;
        OPType: PTypeInfo;
        SrcPos: TOCmdParserSourcePosition;
        SubItemCount: Integer; //Bei Funktionsaufrufen die Parameterliste
        SubItems: Array of POCmdByteCode;
    end;


Aus der oben angezeigten Source-Zeile müsste dann etwa folgende Bytecode-Struktur werden:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
OP: Assign Sub: 2 

 OP: Variable(C,Integer) Sub 0 () 
 OP: Sum Sub 2
 ( 
  OP: Variable(A,Integer) Sub 0 () 
  OP: FunctionCall(abs,TpyeInfo(System.Abs)) Sub 1 
  ( 
   OP: Sum Sub 2 
   ( 
    OP: Negate(nil, Integer) Sub 1 
    ( 
     OP: Variable(C,Integer) Sub 0 () 
    ) 
    OP: Variable(B,Integer) Sub 0 () 
   ) 
  ) 
 ) 
)


Den aktuellen Source und die weiteren Definitionen finden sich hier: http://cvs.sf.net/viewcvs.py/omorphia/omorphia/scripting/OCmdTypes.pas?rev=1.1&view=log

Ich wäre über jegliche Art von Tipps, Tuts oder (kostenloser) Litheratur dankbar.

TIA,
BenBE.


BenBE - Mi 28.01.09 18:59

Einfache Literatur gibt's z.B. bei DelphiGL im Wiki: http://wiki.delphigl.com/index.php/Tutorial#Skripte

Hab das aber erstmal noch nicht weiter verfolgt; wird wahrscheinlich später mal werden ^^


Florian H. - Mi 04.02.09 14:46

Sorry, aber der Link im ersten Post geht nicht mehr. Da kommt Access denied.

mfg Flö

PS: Würd mich sehr für den Source interessieren, da ich selbst auch gerade an ner kleinen Scriptsprache arbeite.

Kannst du mir ne PN schicken, dann geb ich dir meine Mail-Adresse, damit du mir die Sourcen vll. schicken kannst.


BenBE - Mi 04.02.09 15:23

Also ein gutes Beispiel sind im DelphiGL-Wiki die beiden Einträge\Tutorials
http://wiki.delphigl.com/index.php/Tutorial_Scriptsprachen_Teil_1
und
http://wiki.delphigl.com/index.php/Tutorial_Scriptsprachen_Teil_2
Für die Sources solltest Du Fagen (laut Wiki) an MyChaOS [http://wiki.delphigl.com/index.php/Benutzer:MyChaOS] wenden.

Der Link oben im ersten Post ist inzwischen umgezogen, aktuell ist das jetzt im SVN verwaltet:
https://omorphia.svn.sourceforge.net/svnroot/omorphia/trunk/omorphia/source/library/OCmd*.pas
Ist aber seither noch nicht weiter ausgebaut wurden, weil in der Lib erstmal noch andere Aspekte abzuarbeiten waren und daher an dem BEreich noch nichts weiter geschraubt wurde.


delfiphan - Mi 04.02.09 20:36

Ich hab mal vor einiger Zeit eine Art Runtime Compiler-Compiler geschrieben. Die Sprache kann man mehr oder weniger zur Laufzeit frei definieren (gewisse Konstrukte gehen wegen der verwendeten Parserart jedoch nicht). Der Parser verwendet sich selbst, um EBNF ähnliche Definitionen zu parsen und daraus einen Parser zusammenzustellen, der eben diese definierte Sprache parsen kann... Eine einfache Sprache mit Zuweisung, Funktionen, und mathematischen Operationen ist in der Demo dabei. Sehr schnell ist das ganze natürlich überhaupt nicht. Ich würde heute wohl einiges anders gestalten. Weiss nicht, ob's hilft, aber schaden tut's wohl auch nicht.

Demo [http://www.tyberis.com/download/RcDemo.exe] / Source [http://www.tyberis.com/download/RcSources.zip]

Die Delphi Grammatik findest du hier:
http://www.felix-colibri.com/papers/compilers/delphi_5_grammar/delphi_5_grammar.html

Der Scope (ganze Unit oder einzelne Zeile) sollte für einen Parser kein Problem sein. Ich denke man kann die Delphi-Grammtik auch in ein Pfeilchendiagramm umwandeln (finite state machine). Der Parser müsste also eigentlich lediglich wissen, wo er sich befindet.