Drzewa składniowe oraz analiza semantyczna
Marcin Orchel
1 Wstęp
1.1 Drzewa składniowe
Wynikiem analizy składniowej (parsowania) jest drzewo składniowe. Drzewa składniowe dla wyrażeń arytmetycznych zawiera w węzłach wewnętrznych operatory, dzieci węzła reprezentują operandy, a liście są stałymi i identyfikatorami zmiennych. Jest to uprosz- czone drzewo wyprowadzenia, gdzie są pominięte elementy pomocnicze. W drzewie wy- prowadzenia węzły odpowiadają symbolom nieterminalnym.
Przykład 1. Drzewo składniowe dla wyrażenia 9 − 5 + 2 +
- 9 5
2
Drzewo składniowe dla instrukcji while(expr) stmt może wyglądać następująco.
while expr stmt
Węzły mogą być implementowane jako obiekty klasy N ode z klasami potomnymi Expr dla wyrażeń i Stmt dla instrukcji. Dla każdego typu instrukcji można utworzyć klasę pochodną z klasy Stmt. Np. dla operatora whilemożna utworzyć klasę W hile.
1.2 Analiza semantyczna
Analiza semantyczna służy do sprawdzania poprawności programu na poziomie instruk- cji i całości programu. Może to być sprawdzanie typów, czy pojawiła się deklaracja identyfikatorów, czy instrukcje i wyrażenia mają sens oraz kontrola nazw.
W programie np. w instrukcji przypisania wyróżniamy l-wartości i r-wartości, te które są właściwe dla lewej i prawej strony przypisania. Lewa strona przypisania powinna być lokalizacją, a prawa wartością. A zatem np. stała po lewej stronie nie byłaby właściwa.
1.3 Tablica symboli
Tablica symboli zawiera informacje o zmiennych, o różnych ich atrybutach, np. typie, zakresie widzialności. W trakcie analizowania deklaracji x wstawiane są informacje o
1
identyfikatorze. W innych instrukcjach pobierane są informacje o identyfikatorze, np.
typ.
2 Zadania
1. Zadanie wprowadzające. Zaimplementować kalkulator, jeśli jeszcze nie był zaimple- mentowany w ten sposób, że jest generowane drzewo składniowe. W dokumentacji do PLY jest wskazówka jak można to zrobićhttps://www.dabeaz.com/ply/ply.
html#ply_nn34.
2. Zaimplementować wizualizację drzewa składniowego dla wybranych wyrażeń. Wi- zualizacja może być w formie tekstowej, a najlepiej w formie graficznej.
3. Zaimplementować możliwość deklarowania typów dla zmiennych, np. int, float, boolean, string.
4. Zaimplementować sprawdzanie semantyczne typów, m.in. czy operatory artyme- tyczne w kalkulatorze działają na wartościach tego samego typu np. int, float., w instrukcji if powinno znaleźć się wyrażenie typu boolean.
5. Zaimplementować instrukcję przypisania wartości do zmiennej np. x := x + y.
6. Zaimplementować przeciążanie operatorów wraz ze sprawdzanie typów. Np. dla wyrażenia z = x + y, gdzie np. x jest int a y string, powinien być błąd. Gdy wszystkie zmienne są typu są int, powinno być dodawanie, a gdy wszystkie zmienne są typu string powinna być konkatenacja.
7. Zaimplementować w kalkulatorze sprawdzanie poprawności deklaracji zmiennych, czy zmienne zostały wcześniej zadeklarowane i czy zostały zadeklarowane dokład- nie raz, używając do tego tablicy symboli, czy nie zawierają słów zastrzeżonych jako identyfikatorów, np. if,while.
8. Zaimplementować sprawdzanie poprawności instrukcji, m.in. l-wartości i r-wartości, np. l-wartością nie może być stała.
9. Zaimplementować konwersję typów za pomocą dodatkowego operatora, np. inttofloat.
2.1 Wskazówki
•
Literatura
2