+---------------------------------------------------------------------------+
| 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
| 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