This shows you the differences between two versions of the page.
cpl:labs:02 [2015/12/06 21:26] laura.vasilescu [Instructiuni compilare si executie folosind flex si bison] |
cpl:labs:02 [2016/10/05 23:18] (current) bogdan.nitulescu [Secțiunea de declarații Bison] |
||
---|---|---|---|
Line 14: | Line 14: | ||
* LALR(1) - Look Ahead Left to Right with a one-token lookahead | * LALR(1) - Look Ahead Left to Right with a one-token lookahead | ||
* GLR - Generalized Left to Right | * GLR - Generalized Left to Right | ||
- | Majoritatea parserelor folosesc LALR(1), care are mai putine capabilitati, insa este semnificativ mai rapid si mai usor de folosit decat GLR. Si noi, vom genera tot parsere LALR. | + | Majoritatea parserelor folosesc LALR(1), care are mai putine capabilitati, insa este semnificativ mai rapid si mai usor de folosit decat GLR. Si noi vom genera tot parsere LALR. |
''Bison'' este varianta GNU a ''yacc'' (Yet Another Compiler-Compiler). | ''Bison'' este varianta GNU a ''yacc'' (Yet Another Compiler-Compiler). | ||
Line 72: | Line 72: | ||
* simbolul de start al gramaticii (opțional) | * simbolul de start al gramaticii (opțional) | ||
<code C> | <code C> | ||
- | %start <tip> nume1 nume2 | + | %start <tip> nume |
</code> | </code> | ||
Line 98: | Line 98: | ||
%type <int_value> exp | %type <int_value> exp | ||
</code> | </code> | ||
- | Dacă este suficient să întroarcem valori de tip int, și nu definim un union de tipuri, atunci ''<token_type>'' este omis în declararea tokenilor. | + | Dacă este suficient să întoarcem valori de tip int, și nu definim un union de tipuri, atunci ''<token_type>'' este omis în declararea tokenilor. |
* Precedența %left. Aceasta va fi detaliată intr-un subcapitol ulterior. | * Precedența %left. Aceasta va fi detaliată intr-un subcapitol ulterior. | ||
- | O listă completă cu simbolii ''bison'' găsiți [[http://www.gnu.org/software/bison/manual/html_node/Table-of-Symbols.html|aici]] | + | O listă completă cu simbolurile ''bison'' găsiți [[http://www.gnu.org/software/bison/manual/html_node/Table-of-Symbols.html|aici]] |
| | ||
==== Secțiunea de reguli gramaticale ==== | ==== Secțiunea de reguli gramaticale ==== | ||
Line 134: | Line 134: | ||
{C statements} | {C statements} | ||
</code> | </code> | ||
- | <note>Bison nu verifica corectitudinea codului C din acțiuni ci doar îl copiaza în fișierul .c al parserului, unde va fi verificat de compilatorul de C. Așadar erorile de C vor fi raportate abia la compilarea parserului.</note> | + | <note>Bison nu verifică corectitudinea codului C din acțiuni ci doar îl copiaza în fișierul .c al parserului, unde va fi verificat de compilatorul de C. Așadar erorile de C vor fi raportate abia la compilarea parserului.</note> |
Acțiunea poate fi plasată la sfârșitul unei alternative sau chiar în interiorul acesteia. | Acțiunea poate fi plasată la sfârșitul unei alternative sau chiar în interiorul acesteia. | ||
* ''$$'' reprezinta rezultatul, adica valoarea ce va fi atribuită neterminaului de la stânga regulii, cel la care se va reduce regula. | * ''$$'' reprezinta rezultatul, adica valoarea ce va fi atribuită neterminaului de la stânga regulii, cel la care se va reduce regula. | ||
* ''$n'' este al n-lea termen din regula sintactica. | * ''$n'' este al n-lea termen din regula sintactica. | ||
- | Acțiunile definite în mijlocul unei reguli se folosesc numai în anumite situații, pot folosi doar simbolii anteriori acesteia (fiindcă se execută înainte ca simbolii următori regulii să fie parsați) și sunt o sursă de conflicte. Vom reveni asupra acestora în laboratorul urmator. | + | Acțiunile definite în mijlocul unei reguli se folosesc numai în anumite situații, pot folosi doar simboluri anterioare acesteia (fiindcă se execută înainte ca simbolurile următoare regulii să fie parsați) și sunt o sursă de conflicte. Vom reveni asupra acestora în laboratorul următor. |
==== Secțiunea de cod C ==== | ==== Secțiunea de cod C ==== | ||
Secțiunea de cod C trebuie să conțină: | Secțiunea de cod C trebuie să conțină: | ||
Line 175: | Line 175: | ||
</note> | </note> | ||
- | ====== Conflicte si ambiguitati ====== | + | ====== Conflicte și ambiguități ====== |
**Conflictele** sunt rezultatul unei gramatici ambigue. Conflictele pot fi fie shift/reduce, fie reduce/reduce | **Conflictele** sunt rezultatul unei gramatici ambigue. Conflictele pot fi fie shift/reduce, fie reduce/reduce | ||
- | * Intr-un conflict shift/reduce actiunea implicita este cea de shift. | + | * Într-un conflict shift/reduce acțiunea implicită este cea de shift. |
- | * Intr-un conflict reduce/reduce actiunea implicita este de a reduce folosind prima regula aplicabila a gramaticii. | + | * Într-un conflict reduce/reduce acțiunea implicită este de a reduce folosind prima regulă aplicabilă a gramaticii. |
- | Exemplu de conflict shift/reduce datorat ambiguitatii ''dangling else'': | + | Exemplu de conflict shift/reduce datorat ambiguității ''dangling else'': |
- | Cand token-ul ''else'' este citit si devine token-ul lookahead, ceea ce a fost deja citit se potriveste pe prima regula si ar putea fi redus. Dar, este de asemenea legal sa shiftam else-ul, pentru ca sirul de tokeni de la intrare s-ar putea potrivi pe a doua regula. | + | Când token-ul ''else'' este citit și devine token-ul lookahead, ceea ce a fost deja citit se potrivește pe prima regulă și ar putea fi redus. Dar, este de asemenea legal să shiftam else-ul, pentru ca șirul de tokeni de la intrare s-ar putea potrivi pe a doua regulă. |
- | Deoarece parser-ul prefera sa shifteze, else-ul va fi atasat if-ului cel mai imbricat. | + | Deoarece parser-ul preferă sa shifteze, else-ul va fi atașat if-ului cel mai imbricat. |
- | Daca parser-ul ar alege sa reduca, atunci cand poate, si nu sa shifteze, else-ul va fi atasat if-ului exterior(primul). | + | Dacă parser-ul ar alege să reducă, atunci când poate, și nu să shifteze, else-ul va fi atașat if-ului exterior(primul). |
<code C> | <code C> | ||
Line 194: | Line 194: | ||
</code> | </code> | ||
- | Cu aceasta gramatica, secventa de intrare ''if (exp1) if (exp2) stmt1 else stmt2'' poate fi parsata in 2 moduri diferite: | + | Cu această gramatică, secvența de intrare ''if (exp1) if (exp2) stmt1 else stmt2'' poate fi parsată în 2 moduri diferite: |
<code C> | <code C> | ||
Cazul 1: if (e1) { if (e2) s1 else s2 } | Cazul 1: if (e1) { if (e2) s1 else s2 } | ||
Line 201: | Line 201: | ||
</code> | </code> | ||
- | Acesta este un asa zis conflict shift/reduce legitim. Exista cazuri in care gramatica genereaza astfel de conflicte pentru că a fost scrisa ambiguu, desi se putea scrie si intr-o forma neambigua. In aceste cazuri se recomanda rescriere regulilor cu conflicte. | + | Acesta este un asa zis conflict shift/reduce legitim. Există cazuri în care gramatica generează astfel de conflicte pentru că a fost scrisa ambiguu, deși se putea scrie și într-o formă neambiguă. În aceste cazuri se recomandă rescriere regulilor cu conflicte. |
<code C> | <code C> | ||
- | expr : expr ’+’ expr | + | expr |
+ | : expr ’+’ expr | ||
| expr ’*’ expr | | expr ’*’ expr | ||
| ’-’ expr | | ’-’ expr | ||
Line 210: | Line 211: | ||
; | ; | ||
</code> | </code> | ||
- | Gramatica expresiilor genereaza conflicte cand uitam sa implementam asociativitatea si precedenta tokenilor. | + | Gramatica expresiilor generează conflicte când uitam să implementăm asociativitatea și precedența tokenilor. |
- | Sunt 2 moduri de a specifica precedenta si asociativitatea pentru o gramatica: implicit si explicit. Cand o specificam implicit trebuie sa introducem un simbol neterminal pentru fiecare nivel de precedenta. Iata mai jos solutia implicita: | + | Sunt 2 moduri de a specifica precedența și asociativitatea pentru o gramatică: implicit și explicit. Când o specificăm implicit trebuie să introducem un simbol neterminal pentru fiecare nivel de precedenta. Iată mai jos soluția implicită: |
<code C> | <code C> | ||
- | expr: expr '+' factor | + | expr |
- | | factor | + | : expr '+' factor |
+ | | factor | ||
; | ; | ||
- | factor: factor '*' term | + | factor |
- | | term | + | : factor '*' term |
+ | | term | ||
; | ; | ||
- | term: '-' term | + | term |
- | | ID | + | : '-' term |
- | | NUMBER | + | | ID |
- | ; | + | | NUMBER |
; | ; | ||
</code> | </code> | ||
- | Gramatica devine mai stufoasa, dar neambigua. Metoda explicita presupune folosirea explicita a regulilor de precedenta suportate de Bison. | + | Gramatica devine mai stufoasă, dar neambiguă. Metoda explicită presupune folosirea explicită a regulilor de precedență suportate de Bison. |
- | **Asociativitatea** si **precedenta** pot fi specificate in urmatorul mod: | + | **Asociativitatea** și **precedența** pot fi specificate în următorul mod: |
* Pentru asociativitate se pot folosi: ''%left'', ''%right'', ''%nonassoc'' | * Pentru asociativitate se pot folosi: ''%left'', ''%right'', ''%nonassoc'' | ||
- | * Precedenta operatorilor binari: | + | * Precedența operatorilor binari: |
- | * Se specifica asociativitatea folosind ''%left'' | + | * Se specifică asociativitatea folosind ''%left'' |
- | * Operatorii din acelasi grup au aceeasi precedenta, iar intre grupuri, precedenta creste in jos. | + | * Operatorii din același grup au aceeași precedență, iar între grupuri, precedența crește în jos. |
- | * Pentru a stabili precedenta operatorilor unari se foloseste ''%prec''. Acesta schimba precedenta unei reguli la precedenta tokenului urmator. | + | * Pentru a stabili precedența operatorilor unari se foloseste ''%prec''. Acesta schimbă precedența unei reguli la precedența tokenului următor. |
<code C> | <code C> | ||
%left ’+’ ’-’ | %left ’+’ ’-’ | ||
%left ’*’ ’/’ | %left ’*’ ’/’ | ||
... | ... | ||
- | expr : expr ’+’ expr | + | expr |
+ | : expr ’+’ expr | ||
| expr ’*’ expr | | expr ’*’ expr | ||
| ’-’ expr %prec ’*’ | | ’-’ expr %prec ’*’ | ||
Line 248: | Line 252: | ||
</code> | </code> | ||
- | **Exercitiu**: Incercati sa rezolvati conflictul shift/reduce pentru ''dangling else'' folosind reguli de precedenta. | + | **Exercițiu**: Încercați să rezolvați conflictul shift/reduce pentru ''dangling else'' folosind reguli de precedență. |
| | ||
Line 260: | Line 264: | ||
</code> | </code> | ||
- | ====== Exerciții de laborator (10p) ====== | + | ====== Exerciții de laborator (13p) ====== |
În rezolvarea laboratorului folosiți arhiva de sarcini {{ :cpl:labs:lab02_simple_ops.zip | lab02_simple_ops.zip }} | În rezolvarea laboratorului folosiți arhiva de sarcini {{ :cpl:labs:lab02_simple_ops.zip | lab02_simple_ops.zip }} | ||
Line 271: | Line 275: | ||
===== Exercițiul 2 - variables (5p) ===== | ===== Exercițiul 2 - variables (5p) ===== | ||
- | Extindeți exercițul anterior astfel încât calculatorul să accepte instrucțiuni de atribuire și variabile și să poată evalua expresii care conțin variabile cărora le-a fost atribuită o valoare. Pentru a implementa această extensie, veți avea nevoie de o **tabelă de simboli** cu ajutorul căreia să țineți minte variabilele cărora li s-a atribuit o valoare și din care să citiți valoarea curentă a unei variabile în cazul în care variabila este operand al unei expresii. Tabela de simboli o puteți implementa folosind ''std::map<char *, int>''. | + | Extindeți exercițiul anterior astfel încât calculatorul să accepte instrucțiuni de atribuire și variabile și să poată evalua expresii care conțin variabile cărora le-a fost atribuită o valoare. Pentru a implementa această extensie, veți avea nevoie de o **tabelă de simboli** cu ajutorul căreia să țineți minte variabilele cărora li s-a atribuit o valoare și din care să citiți valoarea curentă a unei variabile în cazul în care variabila este operand al unei expresii. Tabela de simboli o puteți implementa folosind ''std::map<char *, int>''. |
+ | ===== Exercițiul 3 (bonus - 3p) ===== | ||
+ | Extindeți exercițiul anterior astfel încât calculatorul să accepte parantezarea expresiilor și operatorul unar minus (-), având în vedere prioritatea operatorilor. |