Table of Contents

Tema de casă 1 - Analiza sintactică

Î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] …..

Informaţii organizatorice

Enunţ

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.

Analiza lexicală

În cadrul analizei lexicale, va trebui să urmăriţi următoarele puncte:

Analiza sintactică

În cadrul analizei sintactice, va trebui să urmăriţi următoarele puncte:

Formatul datelor

Î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!"
                  }
                ]
              }
            ]
          }
        }
      ]
    }
  ]
}

Prezentarea arhivei

Pentru a rezolva această temă va trebui să porniţi de la această arhivă.

Structura arhivei este următoarea:

Fişierele sursă prezente în arhivă sunt următoarele

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ă.

Vectori

Implementarea operațiilor pe vectori va fi punctată doar dacă varianta de 100 de puncte este implementată corect si complet.

Implementarea NU trebuie să introducă noduri noi în AST, ci trebuie să funcţioneze cu AST-ul existent.

Cum limbajul LCPL nu suportă implicit operații pe obiecte de tip vector, va trebui să vă definiți o clasă ajutătoare pentru a simula aceste funcționalități; puteţi apoi ca în timpul parsării să adugaţi codul acestei clase la fişierul LCPL primit la intrare. Clasa trebuie implementată folosind doar facilităţile oferite de limbajul LCPL de bază.

Sugerăm ca acest cod LCPL suplimentar scris de voi să fie plasat în arhivă într-un fișier numit src/Vector.lcpl.

Sintaxă

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.

Exemplu de utilizare

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 şi notarea

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ă 25 puncte dacă operațiile pe vectori sunt implementate complet și parserul trece toate testele.

Change Log

FAQ

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.

Download