[Tutorial] Jak napisać kompilator?

shoock12

Użytkownik
Dołączył
Styczeń 24, 2009
Posty
123
+---------------------------------------------------------------------------+
| Jak napisać kompilator? by Shock |
+---------------------------------------------------------------------------+
| Zakaz kopiowania bez mojej zgody!!! |
+---------------------------------------------------------------------------+

1.Czym jest kompilator?
Kompilator (ang. compiler) to program służący do automatycznego tłumaczenia kodu napisanego w jednym języku (języku źródłowym) na równoważny kod w innym języku (języku wynikowym) [1].
Proces ten nazywany jest kompilacją.
W informatyce pojęciem kompilatora określa się najczęściej program do tłumaczenia kodu źródłowego w języku programowania na język maszynowy.
Niektóre z nich tłumaczą najpierw do języka asemblera, a ten na język maszynowy jest tłumaczony przez asembler.
źródło: wikipedia.org

2.Piszemy kompilator
Nasz kompilator będziemy pisać w Pascalu.

Zaczynamy!

program kompilator;

uses crt;

Teraz deklarujemy zmienne.
+--------------------+
|zrodlowy : string; |
|wynik : string; |
|out : string; |
|bajty : integer; |
+--------------------+

Teraz napiszemy procedurę Welcome.

procedure Welcome;
begin

następnie ustawimy kolor textu na biały

textcolor(15);
clrscr; // wyczyscimy ekran

teraz napiszemy jakby "logo kompilatora"

Writeln('+------------------------------------------------------------------------+');
Writeln('| L++ Compilator |');
Writeln('| v0.1 by Shock |');
Writeln('+------------------------------------------------------------------------+');

Opuszczamy jedną linijkę.
WriteLn('');

Teraz prosimy o wpisanie ścieżki do pliku źródłowego i pliku wynikowego.

Write('Plik źródłowy: ');
textcolor(10);
ReadLn(zrodlowy);
textcolor(15);
Write('Plik wynikowy(.com): ');
textcolor(10);
ReadLn(wynik);
textcolor(15);
WriteLn('Kompilacja rozpoczęta.');
end;

Teraz piszemy funkcję zamieniającą hex na ascii

function hex2ascii( a : string ) : string;
var
tmp, tab, tmp2 : string;
i, ii, j, pos, sum, k : integer;

begin
tab := '0123456789abcdef';
tmp2 := '';
k := 1;

if length(a) mod 2 = 0 then tmp := (a)
else tmp := '0' + (a);
ii := length(tmp) div 2;

for i := 1 to ii do
begin

pos := 0;
for j := 1 to length(tab) do
if tmp[k] = tab[j] then pos := j - 1;
sum := pos * 16;

pos := 0;
for j := 1 to length(tab) do
if tmp[k + 1] = tab[j] then pos := j - 1;
sum := sum + pos;

tmp2 := tmp2 + chr(sum);
k := k + 2;

end;

hex2ascii := tmp2;
end;

Nie mój kod. Funkcja znaleziona w internecie. Nie będę jest tłumaczył.

Teraz procedure xout. Będzie ono dodawać kod do pliku wynikowego, będzie
trzeba jako paramert podać kod w hexach.

procedure xout(text : string);
begin
out:=out+hex2ascii(text); // dodajemy text i konwertujemy na ascii
bajty:=bajty+1; // zwiększamy liczbę bajtów o 1
end;

Teraz najważniejsza procedura kompiluj.

procedure kompiluj;
var
plik : text; // tutaj deklarujemy zmienne
komenda : string;
i : integer;
tmp : integer;
komenda2 : string;
komenda3 : string;
l : integer;
l2 : integer;
l3 : integer;
wait : integer;
wait2 : integer;
loop : integer;
loop2 : integer;
begin // rozpoczynamy kod programu
bajty:=0; // do bajty przypisujemy 0
assign(plik, zrodlowy); // czytamy kod źródłowy
reset(plik); // takie w pascalu musi być i tyle

I teraz będziemy przetwarzać linijka po linijce

while not eof(plik) do // jeśli nie koniec pliku to
begin

ReadLn(plik, komenda); // czytaj linijkę z pliku i przypisz do komenda


Teraz najtrudniejsza część. Będziemy pisać "co ma dać do pliku jeśli taka komenda?"

if(komenda='end') then // jeśli komeda end to
begin
xout('b4'); // tutaj wpisujemy to do pliku kod w hexach
xout('4c');
xout('cd');
xout('21');

end;

Każdy nasz program będzie musiał być zakończony end!

if Pos('wait', komenda) > 0 then // jeśli komenda zaczyna się na wait to
begin // ta komenda czeka x sekund 1=10 nie działa na procesorach szybszych nić 200MhZ
delete(komenda, 1, 5); // skasuj 5 znakow z komenda
val(komenda, wait, wait2); // StrToInt
xout('b4'); // dodaj kod w hexach
xout('86');
xout('b9');
bajty:=bajty+1; // zwiększ bajty o 1
out:=out+chr(wait); // dodaj do programu kod

{ tutaj wartosc to potem }
xout('00');
xout('cd');
xout('15');
end;

if Pos('large', komenda) > 0 then
begin // ta komenda zwiększa ilość o x bajtów
delete(komenda, 1, 6);
val(komenda, l2, l3);
for l := 1 to l2 do
begin
xout('90'); // komenda nop
end;
end;
if(komenda='nope') then
begin
xout('90'); // to nic nie robi, znajmuje miejsce
end;

Teraz komenda czyszcząca ekran
if(komenda='cls') then // jeśli komenda to cls
begin // to
xout('b8'); // dodajemy ten kod w hexach.
xout('00');
xout('06');
xout('b7');
xout('07');
xout('b9');
xout('00');
xout('00');
xout('ba');
xout('4f');
xout('18');
xout('cd');
xout('10');
xout('b4');
xout('02');
xout('b7');
xout('00');
xout('ba');
xout('00');
xout('00');
xout('cd');
xout('10');
end;

Teraz komenda przenosząca kursor na daną pozycję. Nie będę jej tłumaczył

if Pos('goto', komenda) > 0 then
begin
delete(komenda, 1, 5);
tmp:=Pos(',', komenda);
komenda2:=copy(komenda, 1, tmp-1);
komenda3:=copy(komenda, tmp+1, length(komenda));
xout('b4');
xout('02');
xout('b7');
xout('00');
xout('b6');
xout(komenda2);
xout('b2');
xout(komenda3);
xout('cd');
xout('10');
end;

Teraz komenda wypisująca kod maszynowy do pliku. Nie będę jest opisywał.
if Pos('mov', komenda) > 0 then
begin
delete(komenda, 1, 4);
xout(komenda);
end;

if(komenda='pause') then // ta komenda oczekuje na wciśnięcie klawisza
begin
xout('b4');
xout('07');
xout('cd');
xout('21');

end;

I wreszcie komenda wyświetlająca text.

if Pos('write', komenda) > 0 then
begin

delete(komenda, 1, 6);
for i := 1 to length(komenda) do
begin
bajty := bajty + 1;
xout('b4');
xout('0e');
xout('b0');
out:=out+komenda;
xout('b7');
xout('00');
xout('b3');
xout('02');
xout('cd');
xout('10');
end;

Jej także nie będę tłumaczył. Nie chce mi się.

I kończymy procedurę.

end;



end;
end;

Teraz procedura zapisu do pliku wynikowego(*.com).

procedure zapisz;
var // zmienne
plik : text;
begin
assign(plik, wynik); // w plik mamy plik wynikowy
rewrite(plik); // musi być
write(plik, out); // zapisujemy
close(plik); // zamykamy uchwyt do pliku
end;

Teraz procedure koniec.

procedure koniec;
var
tmp : string;
begin
WriteLn(''); // opuszczamy linię
WriteLn('Kompilacja zakończona!'); // piszemy
Str(bajty, tmp); // IntToStr
WriteLn('Bajtów: ' + tmp); // wyświetlamy ilość bajtów
ReadLn; // czekamy na naciśnięcie Entera.
end;

I teraz begin i end.

begin
{ tu wywołujemy procedury }
Welcome;
Kompiluj;
zapisz;
koniec;

end.

I to tyle.

Artykuł pochodzi z: http://6667.pl
 

kanar123

Użytkownik
Dołączył
Marzec 27, 2008
Posty
451
I z literówkami
<
mógłbyś to w tagi wstawić
<
 
Do góry Bottom