Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cpl:labs:03 [2015/10/20 01:35]
cristina.ciocan [Analizorul sintactic]
cpl:labs:03 [2016/10/05 23:17] (current)
bogdan.nitulescu [Introducere in LCPL]
Line 1: Line 1:
 ====== 03. Bison Advanced ====== ====== 03. Bison Advanced ======
-In acest laborator vom aprofunda cunoștințele de bison și vom incepe să discutăm despre prima temă.+În acest laborator vom aprofunda cunoștințele de bison și vom incepe să discutăm despre prima temă.
  
 ====== Bison ====== ====== Bison ======
Line 11: Line 11:
 ''​yylex()''​ citește caracterele dintr-un file pointer (FILE*) numit yyin. Dacă nu setați yyin, acesta va pointa către intrarea standard (stdin). Rezultatul este transmis către yyout, care, implicit, pointează către ieșirea standard (stdout). ​ ''​yylex()''​ citește caracterele dintr-un file pointer (FILE*) numit yyin. Dacă nu setați yyin, acesta va pointa către intrarea standard (stdin). Rezultatul este transmis către yyout, care, implicit, pointează către ieșirea standard (stdout). ​
  
-Fiecare apel către ''​yylex()''​ returnează un întreg, care reprezintă tipul token-ului (id unic). Astfel, bison-ul știe ce token a primit. Token-ul poate avea o valoare, care trebuie ​sa fie pusă în variabila ''​yylval''​.+Fiecare apel către ''​yylex()''​ returnează un întreg, care reprezintă tipul token-ului (id unic). Astfel, bison-ul știe ce token a primit. Token-ul poate avea o valoare, care trebuie ​să fie pusă în variabila ''​yylval''​.
  
 Implicit, yylval este de tip ''​int'',​ tip care, însă, se poate schimba redefinind YYSTYPE în fișierul bison. Implicit, yylval este de tip ''​int'',​ tip care, însă, se poate schimba redefinind YYSTYPE în fișierul bison.
Line 77: Line 77:
 După ce s-a recunoscut ''​ LET '​('​ var '​)'​ '',​ este executată prima acțiune. Se salvează o copie a contextului curent (lista variabilelor disponibile). Apoi, se apelează ''​declare_variable''​ care adaugă ''​var''​ la lista curentă. În acest moment s-a terminat execuția acțiunii din mijlocul regulii, și se va parsa ''​stmt''​. Această acțiune este componenta numărul 5 a regulii, iar ''​stmt''​ este componenta numărul 6. Dupa ce s-a parsat și ''​stmt''​ se execută acțiunea de la sfârșitul regulii, care scoate variabila din tabela de simboli. ​ După ce s-a recunoscut ''​ LET '​('​ var '​)'​ '',​ este executată prima acțiune. Se salvează o copie a contextului curent (lista variabilelor disponibile). Apoi, se apelează ''​declare_variable''​ care adaugă ''​var''​ la lista curentă. În acest moment s-a terminat execuția acțiunii din mijlocul regulii, și se va parsa ''​stmt''​. Această acțiune este componenta numărul 5 a regulii, iar ''​stmt''​ este componenta numărul 6. Dupa ce s-a parsat și ''​stmt''​ se execută acțiunea de la sfârșitul regulii, care scoate variabila din tabela de simboli. ​
  
-====== Introducere ​in CMake ======+====== Introducere ​în CMake ======
  
 CMake este un meta-sistem de build independent de platformă. Acesta citeste niște fișiere de configurare (''​CMakeLists.txt''​) care descriu procesul de build într-un [[https://​cmake.org/​Wiki/​CMake/​Language_Syntax|limbaj specific]], și pe baza acestora generează toate fișierele necesare pentru a face build-ul folosind un anumit tool: make, Ninja, Eclipse, Visual Studio etc. Pentru a vedea sistemele de build suportate pe o anumită platformă, puteți rula ''​cmake -help''​ (secțiunea ''​Generators''​). CMake este un meta-sistem de build independent de platformă. Acesta citeste niște fișiere de configurare (''​CMakeLists.txt''​) care descriu procesul de build într-un [[https://​cmake.org/​Wiki/​CMake/​Language_Syntax|limbaj specific]], și pe baza acestora generează toate fișierele necesare pentru a face build-ul folosind un anumit tool: make, Ninja, Eclipse, Visual Studio etc. Pentru a vedea sistemele de build suportate pe o anumită platformă, puteți rula ''​cmake -help''​ (secțiunea ''​Generators''​).
Line 95: Line 95:
  
 Fișierele generate se vor afla în directorul de unde a fost rulat CMake. Este recomandat ca acesta să fie diferit de cel în care se află sursele proiectului. Fișierele generate se vor afla în directorul de unde a fost rulat CMake. Este recomandat ca acesta să fie diferit de cel în care se află sursele proiectului.
-====== Introducere ​in LCPL ======+====== Introducere ​în LCPL ======
 În această secțiune vom prezenta un subset al limbajului LCPL, atât cât este necesar pentru rezolvarea exercițiului din laborator. Descrierea completă a limbajului o veți primi în prima temă. În această secțiune vom prezenta un subset al limbajului LCPL, atât cât este necesar pentru rezolvarea exercițiului din laborator. Descrierea completă a limbajului o veți primi în prima temă.
  
Line 221: Line 221:
  
 Cunvinte cheie: ''​class,​ inherits, if, then, else, end, new, var''​. Cunvinte cheie: ''​class,​ inherits, if, then, else, end, new, var''​.
-====== Exerciții de laborator (10p) ======+====== Exerciții de laborator (13p) ======
  
 În rezolvarea laboratorului folosiți arhiva de sarcini {{ :​cpl:​labs:​lab03_mini_lcpl_parser.zip | lab03_mini_lcpl_parser.zip }} În rezolvarea laboratorului folosiți arhiva de sarcini {{ :​cpl:​labs:​lab03_mini_lcpl_parser.zip | lab03_mini_lcpl_parser.zip }}
  
-Pornind de la scheletul parserului pentru LCPL aflat in directorul ''​mini-lcpl-parser'',​ va trebui să completați acest parser astfel incât să poată parsa următorul cod LCPL: 
  
-<​code>​ +==== Conținutul mini-lcpl-parser ==== 
-# Factorial class +În directorul ''​mini-lcpl-parser''​ există două sub-directoare:​ 
-class Factorial ​ +  ​* **lcpl-AST**  
-  ​fact Int n -> Int : +    ​* conține structurile de date ale arborelui sintactic, precum și codul care serializează nodurile din arbore. Pe parcursul exercițiului veți construi noduri din arborele sintactic folosind aceste structuri. 
-    ​if n < 1 then +    * pentru a compila biblioteca **lcpl-AST** intrați in directorul lcpl-AST si executati urmatorii pasi: 
-      1+            * mkdir build; cd build; cmake ..make 
-    ​else +    ​* în subdirectorul **include/​** sunt definițiile claselor care compun AST-ul 
-      ​n ​[fact n-1]; +    cui corespund aceste clase ? Gândiți-vă cum ați structurat gramatica în laboratorul trecut și de ce informații ați avea nevoie, informații pe care să le preluați în momentul executării unei acțiuni asociate unei reguli 
-    ​end; +    ​* hint: cum ați ales neterminalii în momentul în care ați gandit logica gramaticii ? Urmând acest fir, cum ar trebui să fie "​traduși"​ acești neterminali în AST: ar trebui să apară în AST sau nu ?  
-  ​end; +  ​* **lcpl-parser** ​ 
-end;+    * conține un schelet al parserului 
 +    * pentru a compila parserul intrați in directorul lcpl-parser și dați comanda ''​make''​. În urma compilării rezultă executabilul ''​lcpl-parser''​ 
 +    * tot in acest director veți găsi două foldere, unul cu teste pentru fiecare exercițiu exemple, precum și rezultatul de referință. Pentru a genera fișierul .ast, rulați ''​./​lcpl-parser path_fisier''​ 
 +    * pentru ușurință puteți să folositi scriptul compare.sh, ce generează fișierul .ast și îl compară cu referința. (ex: ./​compare.sh basic sau ./​compare.sh all, pentru rularea tuturor testelor) 
 +    * pe măsură ce preluați câte un exercițiu pe care trebuie să îl rezolvați, gândiți-vă la următorii pași: 
 +      *  tokenii pe care trebuie să îi prelucrez sunt generați de analizorul lexical ? 
 +        * dacă da, continuați 
 +        * dacă nu, modificați în consecință fișierul lcpl.l și/sau lcpl.y pentru a recunoaște noii tokeni **și** tipul lor 
 +      * analizorul sintactic (gramatica) conține reguli conform cu ceea ce vreau să interpretez ?  
 +        * dacă da, acțiunile asociate sunt cele pe care le urmăresc ? Sunt complete ? 
 +        * dacă nu, găsiți **unde** se potrivesc noile reguli în cadrul gramaticii, conform sintaxei LCPL descrise în documentația laboratorului 
 +        * puteți modifica regulile existente cum credeți de cuviință, sunt scrise pentru a vă ghida, dar nu toate sunt complete 
 +      * în momentul scrierii acțiunii asociate unei reguli, luați în calcul următoarele:​ 
 +        * ce reprezintă elementele regulii curente ? o expresie, o propoziție,​ o adunare, o grupare, o instanțiere ? după caz, conform limbajului de intrare 
 +        * care va fi rezultatul expresiei curente și cum o evaluez ? Tipul asociat este recunoscut in cadrul analizorului ? Unde trebuie definit acest tip ? 
 +        * cum arată un nod în cadrul AST-ului care va reprezenta regula/​elementele regulii curente ? În cazul scheletului de laborator, căutați aceste clase in directorul lcpl-AST/​include/,​ ele sunt deja implementate
  
-# Main class 
-class Main inherits IO 
-  var 
-    Factorial f = new Factorial; 
-  end; 
-  ​ 
-  main : 
-    [out [f.fact 10]]; 
-  end; 
-end; 
-</​code>​ 
  
-==== Conținutul mini-lcpl-parser ==== + 
-În directorul ''​mini-lcpl-parser''​ exisă două sub-directoare:​ +Ierarhia ​de clase care reprezintă noduri ​ale AST-ului este formată dupa cum urmează (din lcpl-AST/​include/​):​ 
-  * lcpl-AST conține structurile ​de date ale arborelui sintactic precum și codul care serializează nodurile din arbore. Pe parcursul exercițiului veți construi ​noduri din arborele sintactic folosind aceste structuri. Pentru a compila biblioteca ​lcpl-AST ​intrați in directorul lcpl-AST și dați comenzile ''​cmake ​.''​ urmată de ''​make''​. + 
-  * lcpl-parser conține un schelet al parseruluiPentru a compila parserul intrați in directorul ​lcpl-parser ​și dați comanda ''​make''​. În urma compilării rezultă executabilul ''​lcpl-parser''​. Tot in acest director veți găsi două exemple ''​simple.lcpl''​ si ''​factorial.lcpl'',​ precum si fișierele ''​.ast''​ care corespund acestoraPentru a genera fișierul simple.lcpl.ast,​ rulați ''​./lcpl-parser simple.lcpl''​. ​+ 
 +{{ :​cpl:​labs:​ierarhie_clase_lcpl.png?450 }} 
 + 
 +Ulterior rulării "./lcpl-parser ​simple.lcpl",​ urmăriți cum a fost parsat ​conținutul fișierului simple.lcpl și AST-ul rezultat (pe acesta îl găsiți în simple.lcpl.ast) 
 +<note tip>​Observați legătura dintre clasele reprezentând nodurile AST-ului și elementele gramaticii definite în Bison.</note>
 ==== Analizorul lexical ==== ==== Analizorul lexical ====
 Va trebui să completați analizorul lexical astfel încât să recunoască și să paseze către analizorul sintactic următorii atomi lexicali: Va trebui să completați analizorul lexical astfel încât să recunoască și să paseze către analizorul sintactic următorii atomi lexicali:
Line 262: Line 269:
   * operatorul logic <   * operatorul logic <
   * operatorii binari * și -   * operatorii binari * și -
 +  * operatorul de asignare =
 +  * operatorul de atribuire al tipului de retur din funcție ->
 +<​note>​Luați în calcul implicațiile faptului că '​-'​ este atât operator, cât și parte a sintaxei de definire a unei metode</​note>​
 +**Țineți cont de faptul că o parte dintre ei sunt deja implementați. Trebuie doar să îi căutați pe cei care lipsesc și să adăugați codul corespunzător.**
 +
  
 ==== Analizorul sintactic ==== ==== Analizorul sintactic ====
-Analizorul sintactic va trebui extins astfel încât sa poată parsa: ​ 
-  * atribute inițializate 
-  * definiții de metode cu parametri formali 
-  * operatorii binari '​-'​ (expresie aditivă) si '​*'​ (expresie multiplicativă) 
-  * apeluri de metode cu argumente 
-  * apeluri de metode cu obiect pe care se apelează metoda (dispatch) 
-  * definiții de clase care moștenesc alte clase 
-  * operatorul ''​new''​ 
  
-Va trebui sa construiți urmatoarele noduri ​din arborele sintactic: +Pentru fiecare nod nou adaugat urmăriți modul de inițializare al acestora ​din folderul lcpl-AST/​include. 
-  * Class + 
-  * Attribute +==== Exercițiul 1 (3p) ==== 
-  * Method + 
-  * FormalParam +Pentru operatorii '​-',​ '*', '<'​ și metode cu valoare de retur va trebui să adaugați reguli de parsare și noi noduri, de tipul '​BinaryOperator',​ respectiv 'Method', în arbore. De asemenea, adaugați regula de parsare . Urmăriți exemplul pentru operatorul '​+',​ respectiv metoda fara valoare de retur, și indicațiile marcate cu "TODO 1". 
-  * Block + 
-  * IntConstant +==== Exercițiul 2 (3p) ==== 
-  * BinaryOperator + 
-  ​* ​Dispatch +Pentru statementul if va trebui să adaugați o nouă regulă de parsare și nodul aferent, de tipul '​IfStatement',​ în arbore. Pentru simplitate regula va trebui să evalueze doar structuri de forma: if <​cond>​ then <​expr>​ else <​expr>​ end. De asemenea va trebui să definiți tipul intors de această regulă. Urmăriți indicațiile marcate cu "TODO 2". 
-  * NewObject+ 
 +==== Exercițiul 3 (4p) ==== 
 + 
 +Adaugați reguli de parsare și nodurile aferente pentru apelul de funcție ('Dispatch') de forma : [id expr1 expr2 ...], de asemenea va trebui să definiți tipul intors de aceste reguli. Urmăriți indicațiile marcate cu "TODO 3". 
 + 
 +==== Exercițiul bonus (4p) ==== 
 + 
 +Extindeți exercițiul anterior, astfel încât gramatica sa accepte asignarea variabilelor și moștenirea unei clase. Urmăriți indicațiile marcate cu "TODO BONUS"​. 
cpl/labs/03.1445294115.txt.gz · Last modified: 2015/10/20 01:35 by cristina.ciocan
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0