PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Optimierender Delphi Compiler



DrNiels
26.04.2002, 11:57
Hier mal was ganz großes:

Ziel ist es einen Aufruf- und Sprach Compatiblen Compiler zu Delphi6 (und vollgende) zu bauen welcher nicht "OnePass" ist und Optimierungen vornehmen kann. (und alles anderre halt um speicher und cpu zu sparen was ein so einfällt)

DrNiels
26.04.2002, 12:10
@Bunny: Oberon ???
Sorry hatte hatte die überschrift ignoriert

erklär mal was du meinst
PS: kenne die sprache nicht !

Bunny
26.04.2002, 13:50
1. Um Was geht es hier?
2. Warum solltest du mit machen?
3. Aufbau eine solchen Compilers
4. Open Source?

1.1 Delphianwendungen sind extrem groß!

Vergleicht man Delphianwendungen mit anderen den Anwendungen andere höheren Programmiersprachen, fällt einen das extrem große Übergewicht eines Delphianwendung auf. Das zeugt wahrscheinlich auf einer guten Sicherheitsstrategie, aber auch von einer schlechten Verwaltung benötigter Standarten. D.h. es werden unbenötigte Elemente eingebunden die für die Anwendung selbst keine Rolle spielen.
Zwar wird ab Delphi das Konzept der Packages praktiziert. Nur sehe ich darin keine wirkliche Ökofunktion, wenn ich mir mal z.B. die VCL*.DPL anschaue.
Meiner Meinung sollte z.B. die ganzen Funktionen wie z.B. IntToStr in einer Datenbank liegen. Aus der Compiler die jeweiligen benötigten Opcode und Fehlerbehandlungsroutinen usw. einbinden kann.

1.2 Der Delphicompiler ist ein einfacher Ein-Pass-Compiler!

Ein einfacher Ein-Pass-Compiler ist ein Compiler der in nach einem Durchlauf des Quellcodes eine fertiges Programm liefert. Das ist natürlich sehr schnell und Borland rühmt sich damit das es der schnellste Compiler der Welt ist. Aber seinen wir doch mal ehrlich. Was hat man davon? Einen Kunden wird es bestimmt nicht interessieren ob das Übersetzen jetzt doppelt so lange braucht. Hauptsache er hat ne optimale Anwendung. Es handelt sich ja schließlich hier nicht um einen Interpeter.
Um das eigentliche Problem um das es hier geht zu verstehen möchte ich ein kleines Bespiel aufzeigen:



001: …
002: … c := GetTickCount;
003: … Caption := IntToStr(C);
004: // Weiter bearbeiten



Der Ein-Pass-Compiler wird den die zweite Zeile so übersetzen das er die API-Funktion GetTickCount mit einem Call aufruft. Diese liefert eax das Resultat zurück. Das Resultat speichert das Programm mit einem mov in die Speicherstelle „c“. In der dritten Zeil soll C dann ausgeben werden. Dafür muss C im Akkumulator stehen. Dafür schiebt die Anwendung C nach EAX. Das ist aber Schwachsinn, da dieser Wert da ja schon steht. Also wird ein unnötiger Befehl ins Programm eingefügt…. Klar?

1.3 Viele Funktionen sind nicht richtig Optimiert!

Dazu möchte ich jetzt nicht so viel sagen. Schaut ins Delphi Forum und sucht nach Hexview.

1.4 Was dir schon immer nicht an Delphi gefallen hat!

Bring bitte deine Ideen ein. Nur so können wir was fertig stellen was auch einen Sinn hat und das sollte meiner Meinung nach, so ein Projekt haben. Also, Alle Delphihasser können sich jetzt austoben.

2. Warum solltest du mit machen?

Ich glaub wenn du uns nicht hilfst wirst du nie wieder richtig schlafen können. Dein Gewissen wird die zerfleischen. Du wirst grün. Dir fallen dir Ohren ab. Deine Zähen werden abfaulen.
Vielleicht wird das auch nicht passieren. Dann wirst du aber ne gute Gelegenheit verpassen etwas über das Programmieren, Compilerbau usw. zu lernen.

3. Aufbau eine solchen Compilers

3.1 Lexikalische Analyse
3.2 Syntaxanalyse
3.3 semantische Analyse
3.4 Zwischencode Erzeugung
3.5 Code Optimierung
3.6 Code Erzeugung

4. Open Source?

Ich weiß ja nit wie sich das jetzt Dr.Niels vorstellt. Aber ich bin der Meinung man sollte das erstmal nur den freiwilligen Programmieren den Code aushändigen. Ich habe nämlich keine Lust Delphi 7.0 zu entwickeln und dafür 500 Euro zu bezahlen, gell.

Bunny
26.04.2002, 13:58
Oberon entstand unter Weiterentwicklung von Turbo-Pascal und unter Einfluß von MODULA und C+ an der Universität Linz unter Leitung von Prof. Wirth.

Ok, ich weiß jetzt nit ob "Oberon-Compiler" die richtige Wahl ist. Nur wird Delphi ein eingetragnes Warenzeichen sein. Vielleicht ein ganz neues Wort.

mfg Benjamin

Lazarus
26.04.2002, 14:00
Dies ist mein erster Beitrag seit langem (seit dem neuen Board war ich irgendwie ... weg).

Dieses Projekt interessiert mich wahnsinnig. Die Probleme von Delphi sind mir (leider) bekannt.

Wenn ich helfen kann, tue ich das gerne, man muss mir nur sagen wie bzw. was zu tun ist. vielleicht per Mail oder sonstiger Basis.... egal. Mal sehen.

Also falls es funktioniert wäre ich gerne dabei.

So long
Lazarus

DrNiels
26.04.2002, 14:43
1. man mus es ja nicht delphi nennen
ich würde nur gerne nen Delphi compiler in Delphi bauen :)

der DFMs und DCUs und den ganzen kram genauso wie Delphi macht (rechtlich ist das kein problem)

2. OpenSource ist erstmal egal.

3. Es sollte neben den DCUs (OBJs) noch eine zwischenschicht geben in der ein "Zwischencode" abgelegt wird...
... somit kann man die Optimierung einfach zwischenschalten und
evtl. auch mal anderre CPUs unterstützen.

usw...

PS: ich bin per MSN unter DrNiels@sub7city.de (ebenfals meine email) erreichbar.

würde gerne zum anfang nen ganz billigen parser bauen der schon ne exe generieren kann ...

Bunny
26.04.2002, 14:57
Ok, fangen wir erstam mit einem Parser an. Hast du schon einen Aufbau?

DrNiels
26.04.2002, 15:56
Ich ? einen Aufbau ?

wie wärs wenn wir das erstmal diskutieren ... :)

... ich werde bis morgen mal nen bischen source produzieren.


PS: was hälts du von sowas wie Lex und Yacc ?
habe sowas nie benutzt, und auch nichts sinnvolles gefunden. Könnte aber ne menge arbeit sparen.

Bunny
26.04.2002, 19:15
PS: was hälts du von sowas wie Lex und Yacc ?

Kannte ich bis heute garnicht. Aber ehrlich gesagt finde ich das nit so doll.


Yacc erhält als Eingabe eine Grammatik, die die korrekte syntaktische Struktur der vom Parser zu analysierenden Eingabetexte beschreibt. Der Generator erzeugt daraus einen tabellengesteuerten Bottom-Up-Parser in Form eines C- (oder C++ -)Quelltexts. Der wesentliche Bestandteil des generierten Parsers ist die Definition der Analysefunktion


Dann müsten wir ja alles wieder nach Delphi übersetzen. Wäre ja auch wieder arbeit.


Es darf nicht der Eindruck entstehen, mit Tools wie Lex und Yacc könnte der Compilerbau automatisiert
werden. Durch Eingabe einer Spezifikation der kontextfreien Grammatik der Sprachsyntax
und durch Eingabe von regulären Ausdrücken für die lexikalische Analyse erhält man zwar den Quellcode
des Gerüstes eines Compilers. Jedoch sind damit hauptsächlich nur Routineaufgaben erledigt
und es fehlt noch sehr viel zum fertigen Compiler!
Die semantischen Aktionen des Parsers müssen ja in der Yacc-Sprache nach wie vor im C-Quellcode
von Hand eingetragen werden. Dazu gehören
•Symboltabellenmanipulationen
•Semantische Prüfungen (Typprüfungen etc.)
•Zwischencode-Erzeugung
Gegenüber der Technik des rekursiven Abstiegs, wo verschiedene Verwaltungsaufgaben durch den
Compiler erleichtert werden, müssen hier manche Stacks selbst verwaltet werden.
Weitere Punkte von Interesse, die nicht der Automatisierung zugänglich sind, sind die Optimierung,
die Codeerzeugung und der Runtime-Support.


p.s. schau dir das mal an: http://www.buva.sowi.uni-bamberg.de/lehre/inf2/material/skript/node103.html

DrNiels
26.04.2002, 21:01
muss ja nicht C rauskommen weil:
mann könte ein eigennes bauen, oder einen nehmen welcher Pascal erzeugt. (ich glaube da gabs nähmlich was fertiges für Pascal und auch was für Java ...)

Nur weil damit die arbeit nicht getan ist, heist das nicht das es das ganze nicht vereinfacht.

Ich finde wir solten da noch weiter diskutieren/informieren.

Bunny
26.04.2002, 21:17
Habe ben auch über einen was im Netz gelesen, Der hieß happy oder so.

Hab noch was gefunden. Siehe Anhang.

DarkTom
27.04.2002, 00:17
Happy ist ein Parser-Generator für Haskell und entspricht etwa yacc für C. Hier mal ein Link: http://haskell.cs.yale.edu/happy/

Falls ihr Haskell verwenden wollt (?) hilft euch vielleicht auch diese Liste von Compilerbau-Tools: http://haskell.org/libraries/#compilation

ChaosCreator
27.04.2002, 02:34
also ich melde mich hier mal als der erste delphi-hasser zu wort....
muß dazu sagen , programmieren kann ich delphi so gut wie nicht , bloß allein wenn man sich exe´s von delphi im disassembler anguckt reicht das schon um nen beitrag zu schreiben.....

also , das mit den doppelten und unnötigne befehlen hat bunny ja schon erwähnt...
dazu kommt das doppelt und dreifache importieren von dll-funktionen .
und was mich auch noch gewundert hat was ich erst vor ein paar tagen gesehn hab , delphi kann man im gegensatz zu c++ zu großen teilen (was die programmstruktur und die fenster angeht) decompilieren und erhällt teilweise sogar noch die funktionsnamen die sich der programmierer ausgedacht hat....
ich kann mir eigenltich nicht vorstellen das angaben wie funktionsnamen oder ähnliches in ner exe noch benötigt werden , also das sollte in unserm compiler auch wenn möglich net vorkommen....

was die dcu´s angeht , also da seh ich net ganz nen grund , wieso wir nicht wie jeder anständige compiler *.obj und *.lib-datein verwenden sollten , denn im gegensatz zu dcu sind diese beiden formate genormt und standart....
dcu´s sind so viel ich weiß bei jeder delphi-version etwas anders aufgebaut,wasses eigentlich unnötig für uns macht unbedingt die dateiform zu benutzen , da man se dann trotzdem nur auf einer version von delphi einsetzen kann....
also dcu´s importieren ja , aber dcu´s erzeugen , eher nein....

fehler verbessert und gepostet....;)

Chaos

Bunny
27.04.2002, 08:18
was die dcu´s angeht , also da seh ich net ganz nen grund , wieso wir nicht wie jeder anständige compiler *.obj und *.lib-datein verwenden sollten , denn im gegensatz zu dcu sind diese beiden formate genormt und standart....

Kannst du mal was dazu suchen. Das wäre cool. Wobei ich gerne von einem Standart wegen der oben genannten Idee weg will.


also dcu´s importieren ja , aber dcu´s erzeugen , eher nein....

Sehe ich auch so.


fehler verbessert und gepostet....

:t

DrNiels
27.04.2002, 13:44
DCUs: auch nen import kann man sich erstmal sparen...


zu den namen in der exe:

ist stehen keine funktionsnamen drinn sondern
klassen-namen und diese müssen da rein wegen der
RTI von delphi sonst würde z.B. das mit den DFMs nicht so gehen wie es geht. (und das ist ja der hauptvorteil an der VCL gegenüber VC)

was man machen könnte ist ne optimierungsstufe welche diese namen auf wunsch gegen fortlaufende nummern ersetzt (also sowohl in den dfm-daten als auch im source) damit würden
fast alle anwendungen (außer die die die RTI funktionen wie ".ClassName" selbst nutzen) genauso funzen.

ChaosCreator
28.04.2002, 16:06
also ich hab mich mal auf die suche gemacht , bloß bis jetzt hab ich nix gefunden was mich zufriedengestellt hat.....
ich hätt den aufbau gern in tabellenform weil das am einfachsten zu lesen is , bloß das einzigste was ich da gefunden hab war in russisch*lol*

andere frage , hat schon jemand den aufbau von pe-exe´n in ner annehmbaren form , oder soll ich die auch gleich mitsuchen ?


Chaos

DrNiels
28.04.2002, 16:19
PE docus habe ich nur mittelmäßige txts
(evtl. war in der MSDN was gutes ... aber such mal lieber ... schließlich hängt sehr viel davon ab)

PS: cool wäre wenn unser compiler ne zwischenstufe hat wo er z.B. NASM kompatiblen asm ausspucken kann.

ChaosCreator
28.04.2002, 16:47
also ich hab hier ein paar texte gefunden die man mitn bißchen überarbeitung glaub ich verwerten könnt....

hier über exe aller sorten
http://giscenter.icc.ru:8082/scripts/WWWBinV.dll/ShowR?EXE.rfi

hier über dcu
http://giscenter.icc.ru:8082/scripts/WWWBinV.dll/ShowR?DCU32.RFI

und hier über lib und obj
http://giscenter.icc.ru:8082/scripts/WWWBinV.dll/ShowR?coff.rfi
http://giscenter.icc.ru:8082/scripts/WWWBinV.dll/ShowR?COFF_LIB.rfi
http://giscenter.icc.ru:8082/scripts/WWWBinV.dll/ShowR?COFF_OBJ.rfi
http://giscenter.icc.ru:8082/scripts/WWWBinV.dll/ShowR?COFF_rel.rfi


naja , net grad das beste aber wenigstens etwas und relativ komplett....

das mit dem assemblercode fänd ich auch net schlecht....vor allem könnt man auch gucken ob der compiler gut optimiert hat....
ich weiß net genau , aber is nasm net der mit dieser komischen schreibweise die kein normaler mensch benutzt ??*nurmalsonachfrag*
ich wär für den standart den tasm benutzt....


Chaos

DrNiels
28.04.2002, 17:16
man könnte das ja umschaltmar machen (masn tasm nasm) wäre sicher kaum mehraufwand.

ChaosCreator
01.05.2002, 22:10
jo , das wär ne möglichkeit.....

dynamix
07.05.2002, 20:08
.. meine 5 Cent ..

... als ewiger Projektkritiker muss ich mich mal wieder zuwort melden. Ich frage mich wieso es immer gleich so grosse Sachen sein müssen. Es gibt ja einen OpenSource - Pascal Dialekt Compiler, nämlich FreePascal. Vielleicht wäre es eine bessere Idee den als Grundlage zu nehmen. ( Oder einen anderen verfügbaren )

Denn .. ein Compiler/Linker macht unheimlich Arbeit, ich denk ihr unterschätzt das etwas. Vorallem ist ja - denke ich - keiner von euch ein erfahrener Compilerbauer. Sicher es gibt viele Dokus etc, aber das muss ja alles erstmal umgesetzt werden. Auweia.

Ich bin selber ein grosser Delphi Fan, die Sprache dahinter ist sehr elegant, aber das macht die Konstruktion eine 100% kompatiblen und auch noch binärkompatiblen Compilers natürlich nicht leichter.

Andere Sache, ihr dürft die Klassenbiblos garnicht verwenden wenn ihr einen eigenen Compiler baut. ( einfach mal einen Blick ins Licence Agreement werfen).

möchte noch ein paar Dinge zu den einzelnen Punkten sagen.

1.1 Delphianwendungen sind extrem groß!

- Das hat garnichts mit Sichheitsstrategie zu tun.
- Man kann in Delphi auch Programme schreiben die genauso klein sind wie in anderen Hochsprachen, wenn man die VCL nicht benutzt, ganz einfach.
- Das Package Konzept ist gut, aber die Abhängigkeiten untereinander noch zu gross. Das Splitten der Core VCL würde hier sicher helfen.
- Schauen wir uns einmal die MFC an ( als Gegenpart zur VCL ). Hier braucht man immer zusätzliche DLLs. Das Programm bleibt nur klein weil die Funktionen in den MFC DLL's liegen. Die ja meist eh schon mit Windows mitkommen. Also nur eine nicht so offensichtliche Umverteilung. Ähnlich Java. Man muss die fette Runtime haben, sonst läuft auch hier nichts. Delphi bietet halt die Möglichkeit mit EINER Executable auszukommen, ohne alles andere. ( btw. es gibt auch die Möglichkeit die VCL auszulagern, dann sind die Excutables auch klein, nur man braucht DLL's )
- Viele Leute lassen einfach alle Debuginfos in der Exe
- man kann Exe Packer nutzen

1.2 Der Delphicompiler ist ein einfacher Ein-Pass-Compiler!


Stimmt. Aber das heisst doch natürlich nicht das er jede Zeile einzeln übersetzt. Natürlich gibt es einen Übersetzungspuffer. Dein Beispiel ist also leider falsch. ( probier es einfach mal aus ). Es gibt bei One Pass Compilern natürlich auch jede Menge Optimierungen. Der grosse Nachteil von One Pass Compilern ist eigentlich das man zB: Forwarder für Funktionen braucht die man irgendwo aufruft, aber erst später im Source deklariert. ( Prinzip gilt so noch für weitere Sachverhalte )
( einfach mal in comp.compilers schaun .. gibt es die Diskussion auch )

1.3 Viele Funktionen sind nicht richtig Optimiert!

Habe nach Hexview gesucht aber nichts gefunden. Wenn dann bitte schon konkrete Beispiele. Ich bin der Meinung das durchaus noch Spielraum zur Optimierung ist, aber die Entwickler schon etliches getan haben!

1.4 Was dir schon immer nicht an Delphi gefallen hat!

Das Design der Sprache ist sehr gut durchdacht, und neue Funktionen wurden ja nur spärlich über die Zeit hinzugefügt. Das hatte sicher seinen Grund. Mann kann nicht einfach sagen. Hey ich will Operator Overloading in Delphi, baut das "schnell" ein ohne sich vorher mal ein klares Bild über die Folgen zu machen.

2-4 .. :)

@ChaosCreator ..
- Was soll an der Dissasemblierung den so schlimm sein? Ich habe schon 1000de davon gesehen. Nur weil es kompliziert und nicht so einfach wie der ASM Code ist den ein C Compiler generiert heisst das nicht das das Ergrbinss schlecht ist. (Delphi Code ist Performant)
Der ASM Code sieht einfach etwas anderst aus.
- Doppelt und Dreifach importieren?? Hast du dafür ein Beispiel zur Hand?
- zu großen teilen decompilierbar??? Also da sagt mir meine Erfahrung was anderes. Nur weil sich die Formularsourcen und einige Funktionsnamen einfach extrahieren lassen, ist es noch lange nicht "decompilierbar". Vielleicht zu 5%. Den Delphisourcecode kannst du nicht wieder gewinnen.
Und die Klassen bekommst du auch nur wenn sie von TObject geerbt sind 100%ig. Nur dann haben sie einen selfpointer in ihrer VMT. Aber du bekommst ja NICHT den Sourcecode der Klassen.



andere Compiler die Pascal Dialekte compilieren
TMT Pascal
Think Pascal (droped)
TinyPascal ( gibt inc. gesamten Sourcecode )
FreePascal ( inc Sourcen )
P32
GNU Pascal ( auch Source verfügbar )
Vector Pascal ( Idee wie Vector C, inc. Source verfügbar )

Anlaufpunkte:
http://www.compilers.net/
http://www.decompiler.com

Die comp.compilers Newsgroup

..

Bunny
08.05.2002, 16:50
Dein Beispiel ist also leider falsch. ( probier es einfach mal aus ).


Haha, meinst du ich habe mir das aus den Finger gesaugt? Ich habe es ausprobiert(Delphi6) ;)

Aber bis jetzt ist ja auch noch nix passiert.

DrNiels
09.05.2002, 05:52
SO:

ich beginne gerade einen Lexer zu schreiben, und werde das ergebniss demnächst posten.

1. Entwurfsentscheidung:
ich denke das wird den kompletten Source einer unit im ram halten können, Oder ?
ist ja meißst höchstenz 1 MB pro Unit.
So sparen wir uns ne intelligente nachladung.

So: erster entwurf
ziel ist es das die function "NextToken"
bei jedem aufruf den nächsten "Token" auf der eingabe unit
zurückgiebt um den Parser möglichst simpel zu halten sollten
die informationen aus dem Lexer möglichst detailiert sein.
also alle schlüsselwörter bereits erkennen.

Bitte um kommentare!!!



unit Lexer;

interface

uses
Classes, SysUtils;

const
c_tok_Bez = 1;
c_tok_Integer = 2;

c_tok_Programm = 11;
c_tok_Unit = 12;
c_tok_Interface = 13;
c_tok_Implementation = 14;
c_tok_Begin = 15;
c_tok_End = 16;

s_tok_Programm = 'programm';
s_tok_Unit = 'unit';
s_tok_Interface = 'interface';
s_tok_Implementation = 'implementation';
s_tok_Begin = 'begin';
s_tok_End = 'end';

type
TnsBaseToken = class(TObject)
Kind : integer;
Text : string; //nur fuer Debug zwecke
end;

TnsBezToken = class(TnsBaseToken)
BezID : integer;
end;

TnsIntegerToken = class(TnsBaseToken)
Value : integer;
end;

TnsSymbolTable = class(TObject)
constructor Create;
destructor Destroy; override;
procedure Add( aStr: string; aID: integer); overload;
function Add( aStr: string ):integer; overload;
function Search( aStr: string ):integer;
function ID( aStr: string ):integer;
private
FStringList: TStringList;
FList : TList;
FLastBez : integer;
end;

TnsLexer = class(TObject)
constructor Create;
destructor Destroy; override;
procedure LoadFile( aFileName: string );
function NextToken: TnsBaseToken;
private
FFileName : string;
FData : string;
FPos : integer;
FTable : TnsSymbolTable;

class function isDigit(a_Char: Char):Boolean;
class function isLetter(a_Char: Char):Boolean;
class function isDigLet(a_Char: Char):Boolean;
class function isOperand(a_Char: Char):Boolean;
end;

implementation

{ TnsLexer }

constructor TnsLexer.Create;
begin
FTable := TnsSymbolTable.Create;
with FTable do
begin
Add( s_tok_Programm, c_tok_Programm );
Add( s_tok_Unit, c_tok_Unit);
Add( s_tok_Interface, c_tok_Interface);
Add( s_tok_Implementation, c_tok_Implementation);
Add( s_tok_Begin, c_tok_Begin);
Add( s_tok_End, c_tok_End);
end;
end;

destructor TnsLexer.Destroy;
begin
FTable.Free;
inherited;
end;

class function TnsLexer.isDigit(a_Char: Char): Boolean;
begin
Result := a_Char in ['0'..'9'];
end;

class function TnsLexer.isDigLet(a_Char: Char): Boolean;
begin
Result := isDigit(a_Char) or isLetter(a_Char);
end;

class function TnsLexer.isLetter(a_Char: Char): Boolean;
begin
Result := a_Char in ['a'..'z','A'..'Z','_'];
end;

class function TnsLexer.isOperand(a_Char: Char): Boolean;
begin
Result := a_Char in
['+','-','*','/','(',')','[',']','^','''','&',','];
end;

procedure TnsLexer.LoadFile(aFileName: string);
var
a_FileStream : TFileStream;
begin
FFileName := aFileName;
a_FileStream := TFileStream.Create(FFileName, fmOpenRead + fmShareDenyNone);
SetLength( FData, a_FileStream.Size );
a_FileStream.Read( FData[1], a_FileStream.Size );
a_FileStream.Free;
FData := FData + #0;
FPos := 0;
end;

function TnsLexer.NextToken: TnsBaseToken;
var
a_State : integer;
a_done : Boolean;
a_Char : Char;
a_Str : string;
a_Integer : integer;
begin
a_State := 0;
a_done := false;
a_Str := '';
repeat
inc(FPos);
a_Char := FData[FPos];
case a_State of
0:
begin
if isDigit(a_Char) then
begin
a_State := 1;
a_Str := a_Str + a_Char;
end
else if isLetter(a_Char) then
begin
a_State := 2;
a_Str := a_Str + a_Char;
end;
end;
1:
begin
if isDigit(a_Char) then
a_Str := a_Str + a_Char
else if a_Char = '.' then
begin
a_Str := a_Str + a_Char;
a_State := 3;
end
else
break;
end;
2:
begin
if isLetter(a_Char) then
a_Str := a_Str + a_Char
else
break;
end;
3:
begin
if isDigit(a_Char) then
a_Str := a_Str + a_Char
else
break;
end;
end;
until a_done;

case a_State of
2: //Bezeichner oder Schlüsselwort
begin
a_Integer := FTable.ID( a_Str );
if a_Integer > 0 then
begin
Result := TnsBaseToken.Create;
Result.Kind := a_Integer;
end
else
begin
Result := TnsBezToken.Create;
Result.Kind := c_tok_Bez;
TnsBezToken(Result).BezID := -a_Integer;
end;
Result.Text := a_Str;
end;
1: //Integer
begin
Result := TnsIntegerToken.Create;
Result.Text := a_Str;
Result.Kind := c_tok_Integer;
TnsIntegerToken(Result).Value := StrToInt(a_Str);
end;
3: //Float
begin

end;

end;
end;

{ TnsSymbolTable }

procedure TnsSymbolTable.Add(aStr: string; aID: integer);
begin
FStringList.Add(AnsiLowerCase(aStr));
FList.Add(Pointer(aID));
end;

function TnsSymbolTable.Add(aStr: string): integer;
begin
dec(FLastBez);
Add( AnsiLowerCase(aStr), FLastBez);
Result := FLastBez;
end;

constructor TnsSymbolTable.Create;
begin
FStringList:= TStringList.Create;
FList := TList.Create;
FLastBez := 0;
end;

destructor TnsSymbolTable.Destroy;
begin
FStringList.Free;
FList.Free;
inherited;
end;

function TnsSymbolTable.ID(aStr: string): integer;
begin
Result := Search(aStr);
if Result = 0 then
Result := Add(aStr);
end;

function TnsSymbolTable.Search(aStr: string): integer;
var
i: integer;
begin
i := FStringList.IndexOf(AnsiLowerCase(aStr));
if i >= 0 then
Result := integer(FList[i])
else
Result := 0;
end;

end.

PhrAtoR
09.06.2002, 19:06
Hallo!

Habe nicht alle Beiträge gelesen, also sorry, wenns schon gesagt wurde.

- Delphi optimiert! wenn auch nur begrenzt.
- Die Größe der exe Dateien entsteht durch VCL und andere imports.
Eine Konsolenanwendung, bei der man benutzte API-Calls direkt über die ensprechenden DLLs realisiert, ist nicht viel größer als das gleiche programm in C/C++. Gleiches gilt, bei GUI-Anwendungen ohne VCL.

Ich wünsche Euch viel spass beim schreiben eines Compilers, der auch noch optimert. ;)
Den Schwierigkeitsgrad solltet Ihr nicht unterschätzen. Da gehört ne ganze menge mehr dazu als ein bloßer parser. Der ist sicherlich noch das Einfachste.

Will euch ja nicht die Träume zerstören, aber ....... naja. Viel Spaß ;)

PhrAtoR

DrNiels
10.06.2002, 14:39
Alles ganz langsam ...

ich arbeite sporadisch an an dieser idee weiter, und beleuchte ständig neue aspeckte dieser Thematik.

Smartie
23.09.2002, 22:06
gibts was Neues ?

dynamix
27.09.2002, 04:03
habe ich am Ende wohl doch recht behalten :D