NOTE: Local - Declared anywhere Global - Declared in main routine Intializator - Check if rval exists
Za upoznavanje sa strukturom ulaznog formata, djelomično će se razviti kompajler za programski jezik B, prethodnika jezika C. Jezik nema tipove. Unutar funkcije, lokalne varijable se deklarišu ključnom rječju auto, a globalne treba navest uz ključnu riječ extrn. Operatori dodjeljivanja su malo drugačiji nego u C, umjesto += koristi se =+ , a unutar stringova * je escape simbol. Sintaksa uslova, izraza i petlji gotovo je ista kao u C.
Opis jezika u coco/r počinje listom vrste znakova, nakon čega slijede definicije tokena u EBNF. Tokeni mogu da imaju kontekst, simbol koji ako se pojavi iza predstavlja značenje tokena u dva različita slučaja (vidi u sljedećem primjeru kako se razlikuje identifier i gotolabel). Nakon tokena definiše se način pisanja komentara u jeziku za koji se piše skener i parser, lista blanko simbola.
Zatim se definišu sintaksna pravila jezika u PRODUCTIONS sekciji. U sintaksu se mogu dodati specijalne olakšice sintaksne analize: SYNC predstavlja mjesta gdje se sintaksna analiza nastavlja ako je došlo do sintaksne greške, radi boljeg oporavka od grešaka WEAK predstavlja simbole koji se često greškom ispuste, pa se tako olakšava oporavak od grešaka. IF (=) omogućava razrješavanje dvoznačnosti gramatike.
Sada treba dodati elemente semantičke analize. B je jezik vrlo limitirane semantike, nekoliko očiglednih pravila su:
- Varijabla u potprogramu mora biti deklarisana prije upotrebe, kao lokalna (auto) ili kao globalna (extrn).
- goto labela ne smije biti dupla i mora postojati
- case vrijednost ne smije biti dupla
- dodijeliti vrijednost se može samo varijabli, pointeru ili elementu niza
Trebaće nekoliko potprograma koji će biti ugrađeni kao metode klase Parser.cpp. Metode su IsDeclaredLocal (provjerava da li je varijabla već deklarisana na bilo koji način u potprogramu), IsAuto (da li je stek tipa),IsDeclaredGlobal (provjerava da li je varijabla već deklarisana u glavnom programu), UndecErr (prijavljuje grešku nedeklarisanosti), AlreadyError (prijavljuje grešku duple deklarisanosti), GetNodeName (vraća ime čvora u AST, parametar je pozicija u stringu koji ga simulira), ElemPos (vraća poziciju u stringu koji predstavlja AST za navedeni redni broj elementa čvora)
Napišite funkciju bool Assignable(int position) unutar methods.inc koja treba da vrati true ako je rezultat GetNodeName na proslijeđenoj poziciji bio L"VAR", L"INDEX" ili L"PTR" i dodajte semantičku provjeru
CondExpr
[(
"="
AssignExpr (. if (!(Assignable(position))) { SemErr(L"Not assignable"); }.)
(. ParseList.insert(position,L"(MOV " ); .)
(. ParseList.append(L") " );.)
| "=*"
Datu liniju za provjeru dodajte iza svih AssignExpr slučajeva. Dodajte je i u UnaryExpr i PostfixExpr za operatore inkrementiranja i dekrementiranja.
Napišite funkciju koja provjerava da li je goto labela već definisana i promijenite pravilo Label da to testira.
Dobijeno apstraktno stablo sintakse sa semantičkim provjerama, se može dalje iskoristiti za generisanje asemblerskog koda Po uzoru na ADD, lako realizujte generisanje asemblerskog koda za AND, OR, XOR i MUL. Probajte i SUB (pazite na nekomutativnost)