Przebieg procesu kompilacji:

- analiza kodu, której wynikiem jest lista slów (klasa Analizator)
- rozpoznanie typów slów (klasa PascalParser)
- walidacja (klasa Validator)
- konwarsja kodu pascalowego na kod wykonywalny (klasa CodeConverter)

Przebieg procesu walidacji:

Proces walidacji skladni polega na sprawdzeniu kolejnosci wystepowania wyrazów w programie. Walidator pobiera dwa kolejne wyrazy, a nastepnie sprawdza czy pierwszy z nich jest wejsciem do walidacji jakiegos fragmentu programu (for, if, itd.). Jesli tak to rozpoczyna sie walidacja w oparciu o odpowiednia macierz przejsc (klasa ValidationMatrix).

Przykladowa macierz pokazano na rysunku 1. Wiersze zawieraja typy slów wejsciowych a kolumny wyjsciowych. Jedynka na przecieciu oznacza, ze dwa typy moga wystapic po sobie. Na przyklad po zmiennej moze wystapic nawias prawy badz przecinek

.
rysunek 1

Wyjscie z walidacji nastepuje w momencie natrafienia na slowo wyjsciowe. W przeciwnym wypadku sprawdzane sa kolejne wejscia do macierzy. Przy sprawdzaniu skladni dodatkowo sprawdzane sa inne zaleznosci (np. przy sprawdzaniu wyrazeń trzeba sprawdzic zgdnosc typów oraz deklaracje zmiennych). Jesli wystepuja bledy zglaszany jest wyjatek.

Przebieg procesu konwersji kodu pascalowego na wykonywalny:

Celem konwersji kodu jest:
- uzyskanie prostych instukcji, które beda latwe do zinterpretowania i wykonania przez klase Executor,
- uwzglednienie zagniezdzen przez wyliczanie adresów skoków
- utworzenie plilku, który moze byc od razu wykonany (aktualnie przez serializacje kodu)

Dostepne instrukcje:
- SET - ustalanie wartosci zmiennej, parametry: zmienna, :=, wyrazenie
- BLOCK_OPEN - otwarcie bloku - wykorzystywane tylko przy konwersji kodu
- BLOCK_CLOSE - zamkniecie bloku - wykorzystywane tylko przy konwersji kodu
- READ - odczyt z klawiatury, parametry: lista zmiennych
- READLN - odczyt z klawiatury, parametry: lista zmiennych
- WRITE - wyswietlanie na konsoli, parametry: zmienne, tekst
- WRITELN - wyswietlanie na konsoli, parametry: zmienne, tekst
- JUMP - skok bezwarunkwy
- COMPARE_VALUE - wyrazenie do porównania, parametry: :=, wyrazenie
- JUMPG, JUMPS, JUMPE, JUMPNE, JUMPEG, JUMPES - skoki warunkowe, parametry: adres, zmienna lub wartosc
- INC - inkrementacja zmiennych, parametry: lista zmiennych
- DEC - dekrementacja zmiennych, parametry: lista zmiennych
- JUMP_MODIFY - modyfikacja skoku, wykorzystywane tylko przy konwersji kodu, parametry: adres skoku do modyfikacji, :=, wyrazenie do sprawdzenia

Proces konwersji polega na:
- wybieraniu z kodu potrzebnych informacji
- zamianie instrukcji pascalowych na odpowiadajace im instrukcje
- wyliczeniu adresów skoków - przy uzyciu stosu (CodeStack)

Obsluga stosu na kod (klasa CodeStack):

Wkładanie linii kodu na stos odbywa sie przy petlach i warunkach.
Zdejmowanie przy instrukcjach i na koncach bloków.

Przykład 1.

Kod wejsciowy:

var
x: integer;
begin
for x:=1 to 10 do
writeln('loop');
writeln('end');
end.

Kod wynikowy:

0: SET X,:=,1
1: COMPARE_VALUE :=,10
2: JUMPG 6,:=,X
3: WRITELN 'loop'
4: INC X
5: JUMP 1
6: DEC X
7: WRITELN 'end'
8: HALT

Proces konwersji:
- znaleziono petle FOR
- ustalenie wartosci poczatkowej SET X,:=,1
- ustalenie wartosci do porównania COMPARE_VALUE :=,10
- zapisanie skoku warunkowego JUMPG - bez parametrów
- zapisanie na stosie DEC X - korekcja zmiennej, po wykonaniu petli x = 10
- zapisanie na stosie JUMP_MODIFY 2,:=,X - dla modyfikacjia skoku JUMPG
- zapisanie na stosie JUMP 1 - skok do poczatku petli COMPARE_VALUE
- zapisanie na stosie INC X - modyfikacja zmiennej petli
- dodanie do kodu WRITELN 'loop'
- sprawdzenie stosu, jesli nie jest pusty i wyraz na stosie nie jest END tzn, ze po petli nie wystapil blok, wiec trzeba zdjac kod ze stosu do napotkania END,

- zdjęcie kodu ze stosu, jesli natrafimy na JUMP_MODIFY modyfikujemy wszystkie paametry JUMPG

Wykonywanie programu przez Executor:

Executor pobiera kolejne linie kodu wskazywane przez programCounter

Dzialania podejmowane przez Executor:
- SET - oblicza wyrazenie (klasa ObliczWyraz) i ustala wartosc zmiennej
- READ - wywluje metode read, która jest nadpisywana przy tworzeniu instancji executora
READLN - wywluje metode read, która jest nadpisywana przy tworzeniu instancji executora, wyswietla wynik, ustawia wartosc zmiennej
- WRITE - wywoluje metode display(str), która jest nadpisywana przy tworzeniu instancji executora
- WRITELN - wywoluje metode display(str), która jest nadpisywana przy tworzeniu instancji executora
- JUMP - ustawia programCounter i blokuje jego modyfiakacje
- COMPARE_VALUE - oblicza wyrazenie (klasa ObliczWyraz) i ustala wartosc zmiennej do porównania
- JUMPG, JUMPS, JUMPE, JUMPNE, JUMPEG, JUMPES - oblicza wyrazenie (klasa ObliczWyraz), porównuje COMPARE_VALUE, jesli warunek skoku jest spelniony modyfikuje programCounter i blokuje jego modyfiakacje
- INC - pobiera zmienne i zmienia ich wartosc
- DEC - pobiera zmienne i zmienia ich wartosc

Dodatkowa funkcjonalnosc Executora (moze byc wykrzystana w kolejnych wersjach):

- dostepna modyfikacja wskaznika programu - dzieki temu mozemy sterowac wykonaniem programu
- dostepne wykonanie 1 linii kodu, wskazywanej przez wskaznik programu (metoda runStep())

Uruchamianie programu z wiersza poleceń:

Kompilacja
java -classpath ApInterPas.jar Compiler plik_wejsciowy.pas plik_wynikowy.run

Uruchomienie skompilowanego programu w konsoli
java -classpath ApInterPas.jar Executor plik_wynikowy.run

Uruchomienie skompilowanego programu z interfejsem graficznym
java -classpath ApInterPas.jar RunningFrame plik_wynikowy.run

Uruchomienie skompilowanego programu z interfejsem graficznym z opcja debug
java -classpath ApInterPas.jar RunningFrame plik_wynikowy.run debug

Uruchamianie projektu
javaw -jar ApInterPas