This is an old revision of the document!
În cadrul acestei teme de casă veţi implementa partea de analiză lexicală şi sintactică a unui compilator pentru limbajul LCPL descris mai jos.
Pentru orice nelămuriri cu privire la această temă, puteţi posta un mesaj pe lista de discuţii, de preferinţă având subiectul mesajului de forma [Tema1] ….
.
Va trebui să realizaţi în limbajul C++, folosind Flex și Bison, porţiunea responsabilă cu analiza lexicală şi sintactică a codului sursă pentru un compilator al limbajului LCPL. Programul vostru va trebui să primească la intrare codul sursă LCPL şi să furnizeze la ieşire informaţii (un AST) pentru analiza semantică.
Documentaţia principală în cadrul acestei teme va fi manualul limbajului LCPL. Rezultatul programului realizat de voi va fi folosit de restul compilatorului în temele următoare.
În cadrul analizei lexicale, va trebui să urmăriţi următoarele puncte:
În cadrul analizei sintactice, va trebui să urmăriţi următoarele puncte:
În urma compilării temei, va trebui să rezulte un fişier executabil bin/lcpl-parser
, ce va conţine funcţia main()
asociată programului. Programul va citi de la linia de comandă numele unui fişier LCPL, pe care îl va procesa, şi numele unui fişier în care se va scrie AST-ul. Pentru a formata corespunzător AST-ul, vă punem la dispoziţie o serie de clase ce descriu un AST; acestea vor fi serializate în format JSON, folosind biblioteca rapidjson, ce se găseşte în arhivă. Secţiunea următoare prezintă conţinutul arhivei cu codul pe care va trebui să-l extindeţi/folosiţi.
Exemplu:
class Main inherits IO main : [out "Hello world!"]; end; end;
La ieşire nu vă interesează atât de mult formatul, pentru că aveţi în arhivă codul care generează acest text:
{ "NodeType": "Program", "NodeID": 0, "LineNumber": 1, "Classes": [ { "NodeType": "Class", "NodeID": 1, "LineNumber": 1, "Name": "Main", "Parent": "IO", "Features": [ { "NodeType": "Method", "NodeID": 2, "LineNumber": 2, "Name": "main", "ReturnType": "Void", "Body": { "NodeType": "Block", "NodeID": 3, "LineNumber": 3, "Expressions": [ { "NodeType": "Dispatch", "NodeID": 4, "LineNumber": 3, "Name": "out", "Arguments": [ { "NodeType": "StringConstant", "NodeID": 5, "LineNumber": 3, "Value": "Hello world!" } ] } ] } } ] } ] }
Pentru a rezolva această temă va trebui să porniţi de la această arhivă.
Structura arhivei este următoarea:
bin
- directorul care va conține binarul generat (lcpl-parser
)lcpl-AST
- directorul ce conține implementarea arborelui sintactic și funcționalitatea de serializare a acestuia în format JSON.lcpl-AST/include
- definițiile claselor care compun arborele sintacticlcpl-AST/src
- implementarea funcționalității de serializare în format JSONtest
- trei programe simple scrise in LCPLMakefile
- Secvența de comenzi necesară pentru a compila biblioteca ce oferă arborele sintactic și parserulREADME
- Descrieți implementarea voastră în acest fișier.Fişierele sursă prezente în arhivă sunt următoarele
lcpl.l
- specificația Flex a analizorului lexical pentru LCPLlcpl.y
- specificația Bison a analizorului sintactic pentru LCPLlcpl-AST/include/*
- câte o clasă pentru fiecare nod din AST; nodul care se va afla în rădăcina arborelui va fi de tip Program
.Puteți modifica orice fișier din aceasă arhivă, va trebui să descrieți în fișierul README aceste modificări. Nu vă este impusă o structură anume a programului, atâta vreme cât programul vostru face corect analiza sintactică.
Acest bonus va fi punctat doar dacă ați implementat complet varianta de 100 puncte. Puteți obține un punctaj bonus de 25 puncte dacă implementați o extensie pentru limbajul LCPL care să permită folosirea vectorilor.
Implementarea NU trebuie să introducă noduri noi în AST, ci trebuie să funcţioneze cu AST-ul existent.
Sugerăm ca acest cod LCPL suplimentar scris de voi să fie plasat în arhivă într-un fișier numit src/Vector.lcpl
.
Sintaxa obiectelor de tip vector ar trebui să fie compatibilă cu exemplele următoare:
String[] myArray;
myArray = new String[8];
myArray[3] = "Hello";
String myValue = myArray[3];
Nu este necesar să suportaţi array-uri de tip Int, însă va trebui să introduceţi în AST noduri de tip CAST necesare pentru compatibilitatea tipurilor.
Pentru definirea unui obiect de tip stivă cu ajutorul vectorilor se poate folosi următorul program LCPL extins:
class StringStack var String[] st; Int index; end; init Int size -> StringStack : st = new String[size]; self; end; # adăugarea în stivă push String o : st[index] = o; index = index + 1; end; # extragerea din stivă pop -> String : index = index - 1; st[index]; end; end;
Clasa Main folosită la testare:
class Main inherits IO var Stack stack = [(new Stack).init 8]; end; main : [stack.push "Hello"]; [stack.push "smile"]; [out [stack.pop][1,5]]; # "mile" end; end;
Testarea temei de casă va folosi o serie de teste ce vor fi disponibile pe vmchecker. Modul în care este distribuit punctajul pentru această temă este următorul:
La punctajele de mai sus se adaugă bonusul de 25 puncte dacă acesta este implementat complet şi trece toate testele.
Q: Clasele din AST sunt documentate undeva? De unde încep?
A: De la clasa “Program”. Conține o listă de “Class”, care conține o listă de “Feature”, ce pot fi “Attribute” sau “Method” … și așa mai departe.
Q: Cum tratăm erorile sintactice?
A: Mesajul de eroare generat de Bison este suficient.
Q: Dacă există diferențe între teste și textul temei, care e rezultatul corect?
A: În general, dacă descoperiți diferențe între teste și manual, comportamentul din teste e cel bun. Dacă le raportați, noi vom corecta manualul și actualiza change log-ul.