Zadanie 1
Napisać prosty preprocesor. Ma on czytać pliki, zaczynając od pliku
podanego w linii polecenia. Pliki czytamy linia po linii, "normalne"
linie kopiując na wyjście. Niektóre linie są dyrektywami dla preprocesora:
.include "nazwa.pliku"
.set zmienna wartość
.if zmienna
.endif
.label nazwa
.goto nazwa
Znaczenie dyrektyw jest następujące:
- .include jest zastępowane treścią podanego pliku. Jeden plik
(jedna nazwa) może być użyty w wielu dyrektywach .include
- .set nadaje zmiennej wartość. Wartości albo liczbami całkowitymi,
albo wartościami zmiennych albo wyrażeniami. Wyrażenia zawierają
dokładnie jeden operator i dwa argumenty (które są liczbami albo
zmiennymi). Dozwolone operatory to '+', '-', '*', '/', '%'.
- .if testuje czy zmienna ma niezerową wartość. Jeśli wartość
zmiennej jest zerem, to część wejscia do odpowiedniego .endif jest
pomijana. Jeśli wartość jest niezerowa linie pomiędzy .if a .endif
są przetwarzane normalnie. Dyrektywy .if można zagnieżdżać, przy tym
każdy .if musi mieć odpowiadający mu .endif.
- .label deklaruje etykietę.
- .goto powaduje że plik będzie dalej czytany od linii po etykiecie.
Jest błędem jeśli bieżący plik nie zawiera etykiety z podaną nazwą
(nie ma skoków między plikami).
Zalecana implementacja: każdy plik wczytać do tabeli przy pierwszym
odwołaniu do pliku. Po wczytaniu sprawdzić czy .if balansują się z
.endif i zbudować tabelę etykiet (hasz podający numer linii w
której była etykieta). Potem przetwarzać plik wejściowy linia po
linii, używając wyrażeń regularnych do rozpoznawania dyrektyw.
Użyć oddzielną tablelę asocjacyjną (hasz) by pamiętać zawartość
przeczytanych plików.
Uwaga: Referencje pozwalają ładnie zorganizować potrzebne struktury
danych.