Záznam - cvičení DU4

Úvodní kurz překladačů se soustřeďuje zejména na teoretické i praktické základy konstrukce přední části překladače. Součástí předmětu je i cvičení zaměřující se na základy práce s nástroji pro konstrukci překladačů. Po absolvování tohoto kurzu bude posluchač schopen sestrojit vlastní překladač do mezikódu nebo jiného jazyka.
ps
Matfyz(ák|ačka) level III
Příspěvky: 137
Registrován: 1. 6. 2006 08:47
Typ studia: Informatika Mgr.
Bydliště: Praha 4
Kontaktovat uživatele:

Záznam - cvičení DU4

Příspěvek od ps »

Zde jsou čerstvé poznámky ze cvičení na téma domácí úkol 4. Zkuste se s tím nějak psychicky srovnat. Podrobný popis zpracování konstant jsem už nezvládnul.

Bez záruky.

Kód: Vybrat vše

Pomocí makra YYSTYPE se definuje sémantický typ, v našem případě:

#define YYSTYPE mlc::MlaskalLval

Uvnitř tohoto typu se schovávají všechny množiny atributů pro symboly. Struktura
mlc::MlaskalLval obsahuje položku pro každý typ množiny (to může být další
struktura). Zde si musíme sami nadefinovat množiny v této struktuře.

Struktura je vystrčena ven v souboru du4lval.hpp. Tam je nadefinovaná a můžeme
si s ní dělat co chceme. Tento zdroják je součástí odevzdání práce.

Jak mohu symbolu v bisonu přiřadit nějakou množinu?

toto:
  %token DUTOK_UINT

přepíšu na:
  %token<int_ci_> DUTOK_UINT

dále např.:
  %token<dtge_> DUTOK_OPER_REL

atp.

A jak to udělat pro neterminály?

  %type<vyraz> vyraz, term, faktor
  
  kde "vyraz" v <> je položka mlc::MlaskalLval určijící typ neterminálu.
  Následuje výčet neterminálů (odělené mezerou nebo čárkou?)

V pravidlech potřebuju nějak pracovat s těmi atributy. Za poslední symbol
pravidla napíšu do složených závorek kód, který se vykoná při redukci podle
daného pravidla.

  N: A1 A2 A3 { /* zde kód */
              }
   ;
   
Znaky $$ reprezentují strukturu neterminálu N (toho na levé straně). Neterminály
na pravé straně jsou očíslovány od 1. Přístupuje se přes $N

  N: A1 A2 A3 {
                $$.typ = $1.typ
                /* ... */
              }
   ;

Do struktur $N nemá smysl zapisovat, protože pravá strana po redukci zanikne.

%N ... neterminálu (číslo řádky)

Pro komplikovanější kód je lepší vytvořit funkci a necpat to vše do Bisona. Na
to je určen soubor du4sem.cpp, kam si můžeme psát co chceme. Ten je nutno také
odevzdat.

Např. pro bloky budeme potřebovat zavolat příkazy uprostřed pravé strany.
Řešení: vytvoříme si nový neterminál, který se přepíše na prázdno:

 N: A1 XX A2 ...
 X2: /* empty */ { /* kód */ }


1. úkol: upravit rozhraní, do yylex přibyl parametr ctx. V této struktuře je
vyplněna položka ctx->tab, v ní jsou schovány tabulky literálů (ls_real). To
byly dříve globální proměnné, odteď nutno pracovat s touto strukturou. Jsou to
funkce, takže:

  ctx->tab.ls_read().add(...)
  
K této struktuře je k dispozici doxymentace.

Hlavním úkolem je plnění tabulek deklarací. Zde je rozdíl v bodování, záleží
co všechno budeme dávat do tabulek.

U konstant pozor, že tam jsou také znaménka. Příklad:
  const minus1 = -jedna;
Zde musím načíst z tabulky hodnotu konstanty jedna (zkontrolovat typ), aplikovat
znaménko, výsledek uložit do tabulky pro minus1.

Tabulky se skládají ze 3 částí

labels - návětší

symbols - do toho se schovávají jména a typy identifikátorů, např.:
  A VAR
  B TYPE
  C FUNKCE

Již je tam předdefinované např.:
  INTEGER TYP (s ukazatelem na typ integer do tabulky types)

Dávají se tam jen "veletypy".

types - Tabulka pro typy. Uvnitř jsou již zabudované typy bool, real, int,
 string. Potřebujeme tam vyrobit krabičku pro typ záznam. Uvnitř bude seznam
 položek daného typu. V případě záznamu budou z této krabičky odkazy na
 jednoduché typy (protože položky záznamu bývají jednoduché typy).

V této tabulce nejsou uloženy názvy symbolů. Kvůli tomu vede odkaz z tabulky
symbols (což je seznam identifikátorů), pokud je to typ, bzde to mít odkaz
do tabulky types.



LABELS

V Mlaskalu používáme jen deklaraci návěští.

ctx->tab.add_label_entry(int line, ls_int_index idx, ic_label lbl)

line - číslo řádky vezmu z lokace příkazu label (%N)
ls_int_index - iterátor do tabulek čísel

příklad:

 label 6;

 ctx->tab.add_label_entry(%1,$1,new_label(ctx));
 
 To vyrobí záznam v tabulce labels.



DEKLARACE PROMĚNNÉ

  var i,j: integer;
  
"i,j" řeším jedním neterminálem - seznam_id : typ ;

Vytvoříme si vektor, do kterého budeme v cyklu uvnitř seznam_id cpát jednotlivé
identifikátory. Tím to vše "vytlačíme" do společného místa. POZOR, do toho
seznamu si musíme u každé položky uchovávat na jaké je řádce (protože seznam
může být přes více řádků).

Jak najdu v tabulce types příslušný typ?

 find_symbol(ls_id_index idx)
 
Tato funkce vrátí symbol_pointer. Na ní je definován operátor vykřičník, tj.
if (!find_symbol(ls_id_index idx)) { /* symbol v tabulce nenalezen */ }.
Volám patřičnou chybu - špatné jméno typu.

Jak získat jméno identifikátoru? Použiju operátor * u interátoru typu
ls_id_index.
 
Pokud identifikátor v tabulce je, musím zjistit jeho typ:
ls_id_index.kind() vrací výčtový typ. Funkce access_XXX() (kde XXX je příslušný
typ) vrátí type_symbol_pointer. Na tom je definována funkce type(), která nás
odkáže na příslušnou ohrádku v tabulce types (mám v ruce šipku do tabulky
types).

Jak teď vložit identifikátor typu do tabulky symbols? Nyní mám třeba onen vektor
se seznamem identifikátorů. Když ho mám celý (prošel jsem seznam_id), přidávám
do tabulky symbols:

 add_var(int line, ls_id_index id, type_pointer p)
 
Specialita u procedur a funkcí, musíme navíc přidat seznam parametrů:

 add_proc(line,id,parameter_list * pl)
 
 k tomu je funkce create_parameter_list(), ta vrátí prázdný seznam parametrů, ten
 musíme naplnit. POZOR, parametr může být vařený nebo nevařený (tj. reference
 nebo nereference). Seznam má metody append_parameter_by_value(id,tp)
 a append_parameter_by_reference(...)

Když nemá funkce/procedure žádné parametry, musíme i tak vloži prázdný seznam.

Jak vyřešit zotavení z chyb, když se např. uvede chybný typ proměnných? Použije
se funkce logical_undef(). Tato funkce vrací ukazatel na speciální typ pro
"nedefinovaný typ".



BLOKY

Mechanismus překrývání globálních proměnných globálními za nás udělá tabulka
symbolů. Na konci deklarace hlavičky procedury/funkci je třeba zavolat
funkci tabulky symbolů enter(). Na konci bloku funkci leave(). Volání enter
si v tabulce poznamená pozici. Funkce leave smaže identifikátory až k naposledy
zapamatované pozici. enter() se musí volat až za add_proc, enter() má ještě jako
parametr identifikátor funkce.

STRUKTURY

 Podobně jako parametry funkcí/procedur.
 
 field_list * create_add_field_list
 type_pointer create_record_type(field_list * pl)
 
 type_pointer je ukazatel na typ zkonstruovaný v tabulce types.
 
Pozn.: Funkce add_* přidávají do tabulky symbols, create_* do tabulky types.


KONSTANTY

Nově vzniklá konstanta přejímá typ původní konstanty (na pravé straně).
type_pointer.cat() vrací kategorii typu.



Domácí úkol č.4 se testuje na výpise tabulek překladače. K nim se dostaneme
použitím parametru "-B" výsledného překladače. 
Až dointegruju, chci do sběru
qwertie
Matfyz(ák|ačka) level III
Příspěvky: 103
Registrován: 4. 6. 2005 15:49
Typ studia: Informatika Bc.
Bydliště: Vyšehrad

Re: Záznam - cvičení DU4

Příspěvek od qwertie »

Dik, jsi zlaty..
df
Matfyz(ák|ačka) level III
Příspěvky: 194
Registrován: 5. 6. 2006 11:55

Re: Záznam - cvičení DU4

Příspěvek od df »

ja taky dekuju, sice jsem tam byl, mam to v sesite, ale za tu hodinu a pul se mi trikrat protocili voci kolem hlavy :roll:
jak bylo receno ... "tedko teprve zacina ta legrace"
Uživatelský avatar
hippies
Admin(ka) level I
Příspěvky: 990
Registrován: 29. 9. 2004 12:46
Typ studia: Informatika Mgr.
Bydliště: Mladá Boleslav
Kontaktovat uživatele:

Re: Záznam - cvičení DU4

Příspěvek od hippies »

nemel jsem silu ten podrobny popis docist az do konce (ostatne mam splneno, tak proc:)),
ale upozornil bych na jednu malou nepresnost, ktera mi pozdeji nekde zacala zlobit a dost
casu to zabralo: Po redukci ve skutecnosti prava strana nezanikne, protoze se to vsechno
provadi v bufferu. Takze casem se to nekde zase objevi na leve strane. (Jde hlavne o to,
pokud zacnete pouzivat ukazatele, popr. inicializacni hodnoty, tak je treba byt opatrny.)
Chjo, dovede te si představit svět, kde by byla každá harmonická diferenciální forma (jistého typu) nesingulární projektivní algebraické variety racionální kombinací kohomologických tříd algebraických cyklů..
Uživatelský avatar
Tacoud
Donátor
Donátor
Příspěvky: 53
Registrován: 16. 9. 2005 08:38
Typ studia: Informatika Bc.
Bydliště: Mladá Boleslav
Kontaktovat uživatele:

Re: Záznam - cvičení DU4

Příspěvek od Tacoud »

Pro získání čísla řádky se musí použít zavináč místo procenta. @N nebo @$ pro pozici celé skupiny.
Spojaři všech zemí, proletujte se!
Moe

Re: Záznam - cvičení DU4

Příspěvek od Moe »

const minus1 = -jedna;
to by som rad podotkol ze take pravidlo v mlaskale nieje..obrazok 1 a 8
definicia konstant je const (identifikator=konstanta)*

a konstanta je:
konstanta bez znamienka
| +/- cele/realne cislo bez znamienka

konstanta bez znamienka:
identifikator konstanty
| int, real alebo string

takze const M=20; N=-M

podla mna v jazyku nieje
Uživatelský avatar
hippies
Admin(ka) level I
Příspěvky: 990
Registrován: 29. 9. 2004 12:46
Typ studia: Informatika Mgr.
Bydliště: Mladá Boleslav
Kontaktovat uživatele:

Re: Záznam - cvičení DU4

Příspěvek od hippies »

Moe píše:konstanta je:
konstanta bez znamienka
| +/- cele/realne cislo bez znamienka

konstanta bez znamienka:
identifikator konstanty
| int, real alebo string

takze const M=20; N=-M

M=20 .. 20 je int ne? ;)
Chjo, dovede te si představit svět, kde by byla každá harmonická diferenciální forma (jistého typu) nesingulární projektivní algebraické variety racionální kombinací kohomologických tříd algebraických cyklů..
Moe

Re: Záznam - cvičení DU4

Příspěvek od Moe »

hippies píše:
Moe píše:konstanta je:
konstanta bez znamienka
| +/- cele/realne cislo bez znamienka

konstanta bez znamienka:
identifikator konstanty
| int, real alebo string

takze const M=20; N=-M

M=20 .. 20 je int ne? ;)

ano je, ale M neni int :), ale identifier ;)
Uživatelský avatar
hippies
Admin(ka) level I
Příspěvky: 990
Registrován: 29. 9. 2004 12:46
Typ studia: Informatika Mgr.
Bydliště: Mladá Boleslav
Kontaktovat uživatele:

Re: Záznam - cvičení DU4

Příspěvek od hippies »

jo tak:D .. uz jsem pochopil jak to myslel;) .. omlouvam se, myslel jsem, ze to jsou dva priklady co nejsou v jazyku, ne jeden.
Chjo, dovede te si představit svět, kde by byla každá harmonická diferenciální forma (jistého typu) nesingulární projektivní algebraické variety racionální kombinací kohomologických tříd algebraických cyklů..
qwertie
Matfyz(ák|ačka) level III
Příspěvky: 103
Registrován: 4. 6. 2005 15:49
Typ studia: Informatika Bc.
Bydliště: Vyšehrad

Re: Záznam - cvičení DU4

Příspěvek od qwertie »

tak tady je ma verze, berte to s rezervou..

Kód: Vybrat vše

DU4
#define YYSTYPE mlc::MlaskalLval
 - kazdy atribut je polozka teto struktury - muze byt i dalsi struktura..
 jako otypovat - priradit polozku termu/ netermu ? - 
 
 %token<polozka_z_YYSTYPE>	DUTOK_STRING
 (tzn pro terminaly: %token<ci_str_> DUTOK_STRING apod, %token<dtge_> DUTOK..skupina)
 
 netermy:
 %type<muj_atr> vyraz, tern, faktor
 
 - struktura ulozena ve du4lval.hpp
 
 bison ma zasobnik typu YYSTYPE - my mame pristup na tenhle zasobnik
 
 pravidlo: 
 A: B C D
 ;
 -chci spocitat atributy A z atributu B C D
 
 A: B C D { kod ktery se okopiruje  na spravne misto}
 ;
 
 minimalizovat delku kodu - funkce -  presun do du4sem.cpp a du4sem.h
 
 A: B C D {
 $$ ted symbolizuje A
 $1 -B, $2 - C...
 $$ = $1 + $3;
 
 }
 
 POZOR
 $3.q = $1.b;
 
 na konci redukce vsechny $neco zmizi..
 - zustane jen $$
 
 trik:
  - potrebuju provest akci jeste pred tim nez se dostanu k D
  A: BC {tenhle kod se provede s BC - vidim jen to co je vlevo} D { tenhle kod se provede az po nacteni D}
  
  tzn 
  A: B C {$1=$2} D {$$=$4}
  
  nebo ekvivalentne 
  
  A: B C n D {}
  
  n: {kod ktery bych chtel provest mezi.. ale nevidim na $1 $2}
  
  pr: 
  
  blok : zacatek_bloku 	obsah... konec bloku
  		
  zacatek_bloku : {kod administrativy}
  konec_bloku: {kod administrativy}
  
 to co se predava zleva by mely byt const reference (pri volani fce)...  to co zprava neconst ref..
 
 cislo radky - @$ a @1, @2....
 
 Ukoly:
 1.) rozhrani  li_str_.add(copridat) -> ctx->tab.li_str().add(copridat)
 
 typy:
 
 MlaskalCtx * ctx
 symbol_tables ctx->tab
 
 2.) naplnit tabulky symbolu - informacemi o typech
 
 program -B - vypise obsah tabulek
 program  NECO_CO_SI_NEPAMATUJE - vypise XML -v kanonickem formatu
 
 100b - deklarace procedur a fci (zadat do tabulek - existuje takova fce nazev parametry a navrat hodnota)
 	 	 deklarace promennych(zakladnich), labelu
 	 	 
 150b - konstanty (const a=-b;), vlastni typy - odvozene, zaznamy.., deklarace promennych typu zaznam..
 
 Tabulky symbolu
 symbol_tables 
 
 - uloziste na literaly ls_int apod..
 
 - krabicka na labely
 
 - krabicka symbolu
 
   identifikator - >  druh - fce, typ, promenna
   
   A= var odkaz do kraicky definice typu
   B =Type odkaz do kraicky definice typu
   C=PROC parametry
   
   to udelam pomoci 
   
   fce find_symbol  - hleda pro identif, symbol
   
   bool enter(int line, ls_id_index idx) - vola se po deklaraci hlavicky 
   										fce (tzn pred deklaraci lokalnich promennych apod)
   										(idx- je konst it na identifikator)
   	
   	void leave (int line) - zakonci lokalni blok (generuje varovani na nepouzitych labelech apod..)
   	
   	- tim se resi lokalni a globalni promenne..
   	NEVOLAT NA BLOK PROGRAMU!!!!! jen na fce..
   	

 - krabicka na deifinice typu 


   	___________________________________________________________________
   	
   	JAK na Labely
   	
   	v kodu label 1,2,3;
   	
   	pouziju : add_label_entry(cislo_radky_labelu,index do tabulky integeru pro cislo labelu, globalni new_label(ctx) -> tohle vyrobi prazdnou krabicku pro navesti);
 	
 	JAK na Promenne
 	
 	VAR i,j,k:integer;
 		l:string;
 
 	bison:
 	   var_line: seznam_id type
 	   
 	   - jak vyzvednu typ pro vsechno - musim to vedet zaroven s obsahem seznamu..
 	   
 	   seznam_id: ID
 	   			 |seznam_id , ID
 	   			 ;
 	   			 
 	   tzn pouziju std::vector<myid> ids_;
 	   str my_id {
 	   		ls_id_index i;
 	   		unsigned l;
 	   		}
 	   	
 	   	seznam_id: ID 		{$$.push_back(my_id($1,@1));} (je tam konstruktor)
 	   			 |seznam_id , ID {$$=$1; $$.push_back(my_id($2,@2));}
 	   			 ;
 
 		var_line: seznam_id type {
 			vycucam typ
 			foreach prez seznam{
 				add_var(const_iterator_z foreache_line, index z foreache, typ);
 			}
 					
 		}
 		
 JAK CUCAT TYPY a jine veci..
 	hledani v tabulce 
 	fce - find_symbol(ls_id_index id);
 	- vraci symbol_pointer -tzn ukazatel z tabulky symbolu
 	
 na symbol_pointer muzu zavolat: symbol_pointer->kind() - a to mi vrati konstantu SKIND_TYPE(na indetifikatoru typu)
 (v pripade SKIND_UNDEF - > prusvih neexistuje volat chybovku..., nebo neco jineho tez chybovka..)
 - my nerozlisujeme zda je to nas typ nebo INTEGER... jen zdali existuje nebo neexistuje..
 
 kdyz vim ze to je typ - tzn vratli se mi SKIND_TYPE - muzu na 
 	symbol_pointru zalvolat symbol_pointer->access_type (resp access_var, access_const apod)
 	
 access_type mi da type_symbol_pointer na nem je definovana fce type_symbol_pointer->type() ktera mi vrati
 type_pointer a ten se strka jako typ do add_var
 
 
 co kdyz typ neexistuje - zotaveni - funkce logical_undef() ktera mi vrati nahradni typ
 
 
 foreach a funktor je dobra myslenka na zpracovani..
 
JAK na procedury

 add_proc(cislo radky, ls_id_index_ i , parameter_list)
(a hned za tim enter..., jinak se to pokazi..)

globalni fce parametr_list create_parameter_list() - vytvori ptrazdny - vzdy musi byt alespon prazdny..

parametr_list->append_parametr_by_value
parametr_list->append_parametr_by_reference
parametr_list->append_and_kill - slepi dva a jeden znici..

na konci volam append.. a pak volam v rekurzi.. jen append and kill

Jak na Struktury

field_list->append_field(index,typ)
field_list->append_and_kill


VSE CO PRIDAVA DO SYMBOLS tak je to !add!

do Types je to create


TVORIME TYP record
TYPE T=RECORD
asd
asd
asd
asd
END;

type_pointer create_record_type(field_list)

add_type(const it identifikatoru, type_pointer)

KONSTANTY

add_const_int(line, ls_id_index,ls

P1=1;
M1=-P1; - ted musim - kouknout do tabulky symbolu - to mi vrati SKIND_CONST - access_const - vrati se mi const_symbol_pointer - musim se zeptat na typ konstanty
	- zase type(), z nej type_pointer, na nem type_pointer->cat() z toho TCAT_INT, TCAT_REAL, TCAT_RECORD
	- z const_symbol_pointeru muzu zavolat const_symbol_pointeru->access_int_const a znej -> int_const_symbol_pointer a na nem -> val()
	- na nej udelam minus - mam cislo - ulozim ls_int.add(hodnota) a tento iterator muzu pouzit pri add_const_int ...
	
kdyz na ls_id_index iterator hodim hvezdicku tak mi to da hodnotu te konstanty (takze jen *const_int mi da hodnotu..
hello, is anybody out there?

Re: Záznam - cvičení DU4

Příspěvek od hello, is anybody out there? »

Ahoj, nemáte náhodou někdo tušení, jak dostat do ls_int_index vlastní hodnotu?
Je to typedef pro ls_int_type::const_iterator a ls_int_type je typedef pro mlaskal::lit_storage< int >.
Obyčejnej iterator se z toho vytvořit moc nedá <code>error: ‘iterator’ is not a member of ‘mlaskal::lit_storage<int>’</code> a ten konstantní se celkem těžko mění.
Potřeboval bych to na zpracování zápornejch konstant.
Uživatelský avatar
Soptik
Matfyz(ák|ačka) level I
Příspěvky: 25
Registrován: 25. 12. 2004 12:15
Typ studia: Informatika Mgr.
Bydliště: Praha, Uhříněves
Kontaktovat uživatele:

Re: Záznam - cvičení DU4

Příspěvek od Soptik »

hello, is anybody out there? píše:Ahoj, nemáte náhodou někdo tušení, jak dostat do ls_int_index vlastní hodnotu?
Ahoj, ls_int_index neni urceny k meneni. Principielne by ten integer mohl byt odkazovany z vice mist a zamena hodnoty neni na miste. Misto toho, musis vyrobit / ziskat odkaz na zaznam pro integer s negovanou hodnotou.
Takze neco jako

Kód: Vybrat vše

new_iterator = ctx->tab->ls_int().add(- old_value)
hello, is anybody out there?

Re: Záznam - cvičení DU4

Příspěvek od hello, is anybody out there? »

Díky moc, tohle jsem z té dokumentace opravdu nevyčetl :? .
qk
Matfyz(ák|ačka) level III
Příspěvky: 181
Registrován: 24. 2. 2005 10:03
Typ studia: Informatika Mgr.
Kontaktovat uživatele:

Re: Záznam - cvičení DU4

Příspěvek od qk »

hello, is anybody out there? píše:Díky moc, tohle jsem z té dokumentace opravdu nevyčetl :? .
No z ty dokumentace jeste nevyctes veci :)...treba loni sem v ni uplne prehlidl funkci na vytvoreni argumentu a pak to padalo :)
Don't worry, be dead
Sharrow
Matfyz(ák|ačka) level I
Příspěvky: 8
Registrován: 16. 2. 2005 12:20

Re: Záznam - cvičení DU4

Příspěvek od Sharrow »

Deadline nedaleko a já se celý dnešek trápil svojí nechopností, proto prosím o radu (pracuju ve VS 8)

1; V du4g.y mi nejdou breakpointy, pokud odkážu na funkci v du4sem.* tak tam breakpointy fungují. Je to jen můj problém, nebo je to standardní stav?
2; Kod {ctx->tab->add_label_entry(%1,$1,new_label(ctx));} v du4g.y mi hodí chybu typu Project : error PRJ0002 : Error result 2 returned from 'C:\Program Files\Microsoft Visual Studio 8\VC\bin\cl.exe'.
Tady už jsem dost bezradný

Předem díky za jakoukoli radu.

EDIT
Člověk na všechno přijde až poté co se zeptá. Můj adresář se jmenoval "překladače" přejmenováním na "prekladace" problém zanikl. WTF!! Doufal jsem že u Microsoftů mají znakové sady zvládnuté
Odpovědět

Zpět na „SWI098 Principy překladačů“