Differences

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

Link to this comparison view

cpl:labs:03 [2015/10/20 19:00]
cristina.ciocan [Conținutul mini-lcpl-parser]
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>​ 
-# Factorial class 
-class Factorial ​ 
-  fact Int n -> Int : 
-    if n < 1 then 
-      1; 
-    else 
-      n * [fact n-1]; 
-    end; 
-  end; 
-end; 
- 
-# 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 ==== ==== Conținutul mini-lcpl-parser ====
Line 255: Line 230:
   * **lcpl-AST** ​   * **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.     * 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''​+    * pentru a compila biblioteca **lcpl-AST** intrați in directorul lcpl-AST ​si executati urmatorii pasi: 
 +            * mkdir build; cd build; ​cmake ..; make
     * în subdirectorul **include/​** sunt definițiile claselor care compun AST-ul     * în subdirectorul **include/​** sunt definițiile claselor care compun AST-ul
     * 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     * 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
Line 262: Line 238:
     * conține un schelet al parserului     * 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''​     * 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ă exemple ​''​simple.lcpl''​ si ''​factorial.lcpl''​, precum ​si fișierele ''​.ast''​ care corespund acestora. Pentru a genera fișierul ​simple.lcpl.ast, rulați ''​./​lcpl-parser ​simple.lcpl''​ +    * 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''​ 
-    * exemplul din simple.lcpl este cel care poate fi tradus în AST în starea actuală a parser-ului +    * 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)
-    * pentru ​a rezolva exercițiile, trebuie să reușiți să obțineți un AST corect pe fișierul ​factorial.lcpl+
     * 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:     * 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 ?       *  tokenii pe care trebuie să îi prelucrez sunt generați de analizorul lexical ?
Line 284: Line 259:
  
 {{ :​cpl:​labs:​ierarhie_clase_lcpl.png?​450 }} {{ :​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 291: 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>​ <​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.** **Ț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.**
Line 296: Line 276:
  
 ==== Analizorul sintactic ==== ==== Analizorul sintactic ====
-Analizorul sintactic va trebui extins astfel încât sa poată parsa: ​ 
-  * operatorul ''​new''​ 
-    * ce fel de expresie este "new <nume clasă>"​ ? Ce fel de operator este **new** in cazul acesta ? Urmăriți gramatica din lcpl.y 
-  * atribute inițializate 
-    * creați o regulă pentru a parsa "<​nume clasa> <nume obiect> = new <nume clasa>"​. Din nou, urmăriți gramatica și observați unde se încadrează 
-  * operatorii binari '​-'​ (se va completa regula din ''​lcpl.y''​ cu neterminalul ''​additive_expression''​) si '​*'​ (se va completa regula din ''​lcpl.y''​ cu neterminalul ''​multiplicative_expression''​) 
-  * expresii condiționale (if ... then ... else) conform sintaxei LCPL descrise în cadrul documentației de laborator 
-  * 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 
-<​note> ​ 
-Veți observa că unele reguli nu au acțiune asociată și totuși, dacă rulați "​./​lcpl-parser simple.lcpl"​ veți observa în fișierul rezultat (simple.lcpl.ast) noduri în AST create deși nu am asociat o acțiune regulii aplicate în momentul întâlnirii acelor simboluri. Acest lucru se întâmplă deoarece există o acțiune implicită asociată oricărei reguli (mai puțin regulii %empty). Acțiunea implicită este { $$ = $1; }  
-</​note>​ 
  
-Va trebui să adăugați urmatoarele noduri în 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 arborePentru 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 + 
-<​note>​ +==== Exercițiul 3 (4p) ==== 
-Pentru ​a vedea definițiile acestor clase, verificați headerele corespunzătoare din directorul lcpl-AST/​include/​Voi trebuie ​să adăugați nodurile (să instanțiați clasele pe care le găsiți definite în include/în momentul în care găsiți o regulă care se potrivește pe ceeea ce reprezintă informațiile din aceste clase și scrieți acțiunea corespunzătoare+ 
-</​note>​+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.1445356828.txt.gz · Last modified: 2015/10/20 19:00 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