tChyba addArgument( char *key ) { //kopirovani argumentu //nalezeni funkce v globalce TItem *item = htSearch( ptrhtGlobal, porovnani ); if(!item){ return S_SEMANTICKA_CHYBA_NEDEF; } //projiti parametru funkce v jeji deklaraci for (int i = 0; i < item->data->param.numParam; ++i){ //nalezeni paramtru ve funkci TItem *item2 = htSearch( ptrhtLocal, item->data->param.param[i] ); if( item2 ){ //nalezeni data argumentu v predchozi funkci TItem *item3 = searchFrames(key, ptrhtLastLocal, ptrhtGlobal ); if( item3 ){ item2->data = item3->data; } else{ item2->data = createData( token.stav, key ); //nenalezeno, zadana raw hodnota } item2->init = true; return S_BEZ_CHYB; } } return S_SEMANTICKA_CHYBA_NEDEF; }
TItem* searchFrames( char *key, tHTable *ptrLocal, tHTable *ptrGlobal ) { TItem *tmp = htSearch( ptrLocal, key ); if( !tmp ){ tmp = htSearch( ptrGlobal, key ); } return tmp; }
tChyba ROZHODNI() { int analyza2; int analyza; int analyza1; TItem *pt; //ROZHODNI->DTYPE if((analyza = DTYPE()) == S_BEZ_CHYB) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } return S_BEZ_CHYB; } //ROZHODNI->PROM VESTAV EXPR else { //volani funkce na vestavene funkce analyza2 = VESTAV(); if(analyza2 != S_BEZ_CHYB && analyza2 != S_EPS) { return analyza2; } //pokud je epsilon pokracujeme dal if(analyza2 == S_BEZ_CHYB) { return S_BEZ_CHYB; } if((porovnani = malloc(strlen(token.data)+1)) == NULL) { return S_INTERNI_CHYBA; } //ulozeni hodnoty token.data do globalni promenne porovnani strcpy(porovnani, token.data); pt = htSearch(ptrhtGlobal, token.data); //kontrola jestli id je v tabulce globalni if(pt != NULL && pt->druh == ID_FUNCTION) { //pokud ano a je to funkce vola se prom analyza1 = PROM(); if(analyza1 != S_BEZ_CHYB) { return analyza1; } free(porovnani); return S_BEZ_CHYB; } else {//jinak se vola precedencni analyza2 = precedencniSA(); if(analyza2 != S_BEZ_CHYB) { return analyza2; } //instrukce pro prirazeni, tmp1 je vysledek precedencni, tmp3 cilove id generateInstruction( OC_PRIRAZENI, searchFrames(neterminal.polozkaTS.key, ptrhtLocal, ptrhtGlobal), NULL, searchFrames(id, ptrhtLocal, ptrhtGlobal) ); return S_BEZ_CHYB; } } }
tChyba DOPREDNE() { int ret; TItem *nasel; //DOPREDNE->forward if(!strcmp(token.data, "forward") && token.stav == s_klicove) { //neinicializovana pokud se jedna o doprednou deklaraci init = false; token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } return S_BEZ_CHYB; } //DOPREDNE->ACT_LIST else { //initla, pokud se nejedna o doprednou init = true; // check velikost tabulky if( currFuncSize == funcSize ){ ret = resizeFuncField(); if(ret != S_BEZ_CHYB) { return ret; } } //nastaveni klice funkce func[currFuncSize].key = allocString(funkce); //inicializace tabulky ret = htInit(&func[currFuncSize].table ); if(ret != S_BEZ_CHYB) { return ret; } //vytovreni listu instrukci InitList( &(func[currFuncSize].instrList) ); //nastaveni ukazatele na prave vytvoreny list instrukci listIntrukci = &(func[currFuncSize].instrList); //nastaveni ukazatele na aktualni tabulku symbolu ptrhtLocal = func[currFuncSize].table; //inkrementace indexu currFuncSize++; nasel = htSearch(ptrhtGlobal, funkce); if(nasel != NULL) { //nakopirovani parametru do lokalniho ramce for(int i=0; i < nasel->data->param.numParam; i++) { htDeclInsert(ptrhtLocal, nasel->data->param.param[i], nasel->data->param.typeParam[i], ID_PARAM); } } return ACT_LIST(); } }
tChyba copyTable( TFunction *source ) { TItem *tmp; int ret; for (int i = 0; i < MAX_HTSIZE; ++i){ tmp = (*(source->table))[i]; if( tmp ){ //dmnce karlova if( tmp->druh == ID_FUNCTION ){ ret = htInsert( ptrhtLocal, tmp->key, copyData( tmp->druh, tmp->data), tmp->type, tmp->druh ); } else if( tmp->druh == ID_PARAM ){ ret = htInsert( ptrhtLocal, tmp->key, NULL, tmp->type, tmp->druh ); } else ret = htInsert( ptrhtLocal, tmp->key, copyData( tmp->type, tmp->data), tmp->type, tmp->druh ); if(ret != S_BEZ_CHYB) { return ret; } //ret = htCompleteInsert(ptrhtLocal, tmp->key, tmp->druh, tmp->type, tmp->init); //if(ret != S_BEZ_CHYB) { // return ret; //} } } //zkopiruje cely list instrukci ret = CopyList( &(source->instrList) ); if(ret != S_BEZ_CHYB) { return ret; } //ustanoveni dat tItemPtr ptr = listIntrukci->First; while(ptr){ TItem *item; if( ptr->instruction.instructionType == OC_COLL ){ ptr->instruction.instructionType = OC_CALL; //nastaveni navratovky item = (TItem*)ptr->instruction.address1; ptr->instruction.address3 = htSearch( ptrhtLocal, item->key ); } else if( ptr->instruction.instructionType == OC_NEPRIRAZENI ){ ptr->instruction.instructionType = OC_PRIRAZENI; //navratovka je zdroj ptr->instruction.address1 = item; //htSearch( ptrhtLastLocal, id ) //dodelat nalezeni cile ulozeni } else{ if( ptr->instruction.address1 ){ TItem *tmp1 = (TItem*)ptr->instruction.address1; //write if( tmp1->druh != PRINTSTR ){ ptr->instruction.address1 = htSearch( ptrhtLocal, tmp1->key ); } } if( ptr->instruction.address2 ){ TItem *tmp2 = (TItem*)ptr->instruction.address2; ptr->instruction.address2 = htSearch( ptrhtLocal, tmp2->key ); } if( ptr->instruction.address3 ){ TItem *tmp3 = (TItem*)ptr->instruction.address3; ptr->instruction.address3 = htSearch( ptrhtLocal, tmp3->key ); } } ptr = ptr->nextItem; } return S_BEZ_CHYB; }
tHTItem* item = (*ptrht)[index]; while(item != NULL) { if(strcmp(item->key, key) == 0) return item; item = item->ptrnext; } return NULL; } void htInsert ( tHTable* ptrht, tKey key, tData data ) { tHTItem *new, *item = htSearch(ptrht, key); if(item == NULL) { int index = hashCode(key); item = (*ptrht)[index]; new = malloc(sizeof(tHTItem)); if(new == NULL) { //TODO } new->ptrnext = item; new->data = data; new->key = malloc(strlen(key)+1);
tChyba TERM2() { int analyza; TItem *pt2; TItem *pt; bool nasel = false; //TERM2->( DRUH TERM2 if(token.stav == s_leva_zavorka) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } if(token.stav == s_cele_cislo || token.stav == s_desetinne_cislo || token.stav == s_logicka_hodnota || token.stav == s_string || token.stav == s_identifikator) { analyza = DRUH(); if(analyza != S_BEZ_CHYB) { return analyza; }//pokud nejsme v definici funkce, pridej do nove vznikleho ramce zadany argument if(byla_funkce == false) { int ret = addArgument(token.data); if( ret != S_BEZ_CHYB ){ return ret; } } //vyhledani volane funkce pt = htSearch(ptrhtGlobal, porovnani); //vyhledani funkce, ve ktere se vola funkce pt2 = htSearch(ptrhtGlobal, funkce); if(token.stav == s_identifikator) { //pokud to bylo id if(pt != NULL) { for (int i = 0; i < pt2->data->param.numParam; ++i){ //prochazime pole parametru if(!strcmp(token.data, pt2->data->param.param[i])) { //pokud najdeme parametr tak nastavime na true if(pt->data->param.typeParam[i] != pt2->data->param.typeParam[i]) { //kontrolujeme jestli datove typy parametru jsou stejne return S_SEMANTICKA_CHYBA_TYPOVA; } nasel = true; break; } } if(nasel != true) { //POKUD NENI PARAMETR PROJDEME pt2 = searchFrames(token.data, ptrhtLocal, ptrhtGlobal); if(pt2 != NULL) { //kontrola datovych typu parametru funkce a argumentu if(pt->data->param.typeParam[pocitadlo] != pt2->type) { return S_SEMANTICKA_CHYBA_TYPOVA; } } else { return S_SEMANTICKA_CHYBA_NEDEF; } } } else { return S_SEMANTICKA_CHYBA_NEDEF; } nasel = false; } else { if(pt != NULL) { if(token.stav != pt->data->param.typeParam[pocitadlo]) { return S_SEMANTICKA_CHYBA_TYPOVA; } } else { return S_SEMANTICKA_CHYBA_NEDEF; } } token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } pocitadlo++; return TERM2(); } } //TERM2->, DRUH TERM2 else if(token.stav == s_carka) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } //pridani argumentu do vznikle tabulky if(byla_funkce == false) { int ret = addArgument(token.data); if( ret != S_BEZ_CHYB ){ return ret; } } if(token.stav == s_cele_cislo || token.stav == s_desetinne_cislo || token.stav == s_logicka_hodnota || token.stav == s_string || token.stav == s_identifikator) { analyza = DRUH(); if(analyza != S_BEZ_CHYB) { return analyza; } //vyhledani volane funkce pt = htSearch(ptrhtGlobal, porovnani); //vyhledani funkce, ve ktere se vola funkce pt2 = htSearch(ptrhtGlobal, funkce); if(token.stav == s_identifikator) { if(pt != NULL) { for (int i = 0; i < pt2->data->param.numParam; ++i){ if(!strcmp(token.data, pt2->data->param.param[i])) { //kontrola zda souhlasi datove typy parametru 2 funkci if(pt->data->param.typeParam[i] != pt2->data->param.typeParam[i]) { return S_SEMANTICKA_CHYBA_TYPOVA; } nasel = true; break; } } //pokud to neni parametr, kontrola jestli je id v tabulkach if(nasel != true) { pt2 = searchFrames(token.data, ptrhtLocal, ptrhtGlobal); if(pt2 != NULL) { if(pt->data->param.typeParam[pocitadlo] != pt2->type) { return S_SEMANTICKA_CHYBA_TYPOVA; } } else { return S_SEMANTICKA_CHYBA_NEDEF; } } } else { return S_SEMANTICKA_CHYBA_NEDEF; } nasel = false; } else {//kontrola datovych typu if(token.stav != pt->data->param.typeParam[pocitadlo]) { return S_SEMANTICKA_CHYBA_TYPOVA; } } } token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } pocitadlo++; return TERM2(); } else if(token.stav == s_prava_zavorka) { pt = htSearch(ptrhtGlobal, porovnani); //zjistime, zda pocet zadanych parametru odpovida poctu parametru pri deklaraci funkce if(pocitadlo != pt->data->param.numParam) { return S_SEMANTICKA_CHYBA_TYPOVA; } if(byla_funkce == true) {//pokud jsme v definici funkce //generovani instrukce fake call generateInstruction(OC_COLL, htSearch(ptrhtGlobal, porovnani ), NULL, NULL ); generateInstruction(OC_NEPRIRAZENI, NULL, NULL, NULL ); } else{ //vygenerovani instrukci InsertFirst for (int i = 0; i < MAX_HTSIZE; ++i){ if( (*ptrhtLocal)[i] ){ if( (*ptrhtLocal)[i]->druh == ID_FUNCTION ){ generateCopyInstr(OC_CPY, (*ptrhtLocal)[i], NULL, NULL ); } } } //predchozi list instrukci, protoze se volal push listIntrukci = &(ptrStack->top->lower->field); //htPrintTable(ptrhtGlobal); //param CALL, Funkce v GLOBALCE, NULL, NAVRATOVKA generateInstruction(OC_CALL, htSearch(ptrhtGlobal, porovnani ), NULL, htSearch( ptrhtLocal, porovnani ) ); //PRIRAZ, NAVRATOVKA, NULL, IDCKO generateInstruction(OC_PRIRAZENI, htSearch( ptrhtLocal, porovnani ), NULL, searchFrames( id, ptrhtLastLocal, ptrhtGlobal ) ); //nastaveni spravneho listu instrukci listIntrukci = &(ptrStack->top->field); //instrukce return na konci volane fce generateInstruction(OC_RET, NULL, NULL, NULL ); } //globalni promenna -> musime nulovat pocitadlo = 0; token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } return S_BEZ_CHYB; } return S_SYNTAKTICKA_CHYBA; }
tChyba FUNKCE() { int analyza; //opet lokalni promenna, stejna funkce jako ve funkci nahore TItem *nasel; // FUNKCE-> begin ACT_LIST if(!strcmp(token.data, "begin") && token.stav == s_klicove) { token = getNextToken(); //pres strcmp porovnavam data tokenu (prakticky primo to, co se nacte) if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } //po zavolani funkce se getToken nevola, protoze kazda funkce, nez vrati hodnotu, nacte dalsi token analyza = ACT_LIST(); if(analyza != S_BEZ_CHYB) { return analyza; } return S_BEZ_CHYB; } //FUNKCE->function id PARAMS : DTYPE ; DOPREDNE ; FUNKCE else if(!strcmp(token.data, "function") && token.stav == s_klicove) { //pamatujeme si, ze jsme v definici funkce byla_funkce = true; token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } if(token.stav == s_identifikator) { //pokud id ma nazev stejny jako tyto 2 funkce, jedna se o chybu if(!strcmp(token.data, "length") || !strcmp(token.data, "copy")) { return S_SEMANTICKA_CHYBA_NEDEF; } if((funkce = malloc(strlen(token.data)+1)) == NULL) { return S_INTERNI_CHYBA; } //nulovani poctu parametru funkce TData *dat = (TData*)malloc(sizeof(TData)); dat->param.numParam = 0; strcpy(funkce, token.data); //pokud id funkce j*z je v globalni hash tabulce a nejedna se o doprednou deklaraci -> chyba nasel = htSearch(ptrhtGlobal,funkce); if(nasel != NULL ) { if(nasel->init == true) { return S_SEMANTICKA_CHYBA_NEDEF; } nasel->init = true; } //vlozeni nazvu funkce do globalni hash htInsert(ptrhtGlobal,funkce,dat, TYPEUNDEF , ID_FUNCTION); token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } //funkce na kontrolu a ukladani parametru funkce analyza = PARAMS(); if(analyza != S_BEZ_CHYB) { return analyza; } else if(token.stav == s_dvojtecka) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } //funkce na kontrolu datovych typu analyza = DTYPE(); if(analyza != S_BEZ_CHYB) { return analyza; } if(!strcmp(token.data, "integer")) { dtype = TYPEINT; } else if(!strcmp(token.data, "real")) { //do docasne promene nacteme datovy typ funkce dtype = TYPEDOUBLE; } else if(!strcmp(token.data, "string")) { dtype = TYPESTR; } else if(!strcmp(token.data, "boolean")) { dtype = TYPEBOOL; } token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } else if(token.stav == s_strednik) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } //zjisteni, zda se jedna o doprednou deklaraci funkces analyza = DOPREDNE(); if(analyza != S_BEZ_CHYB) { return analyza; } //pokud neni dopredna, vkladame do globalni hash tabulky a zaroven i do lokalni hash tabulky if(init == true) { htCompleteInsert(ptrhtGlobal,funkce, ID_FUNCTION, dtype, true); htInsert(func[currFuncSize-1].table, funkce, dat, dtype, ID_FUNCTION); }//pokud se jedna o doprednou deklaraci, ukladame jen do globalky hlavicku funkce else if (init == false) { htCompleteInsert(ptrhtGlobal,funkce, ID_FUNCTION, dtype, false); //vlozeni navratove hodnoty do lokalni tabulky } if(token.stav == s_strednik) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } else { //nastaveni ukazatele lokalni tabulky na vrchol zasobniku ptrhtLocal = ptrStack->top->ptrht; listIntrukci = &(ptrStack->top->field); // nastaveni tabulky instrukci v mainu byla_funkce = false; //rekurzivni volani return FUNKCE(); } } } } } //pokud se nacte token, ktery podle pravidla tam nepatri, vrati se syntakticka chyba return S_SYNTAKTICKA_CHYBA; } //FUNKCE->var DEKLARACE FUNKCE else if(!strcmp(token.data, "var") && token.stav == s_klicove) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } //volani funkce na kontrolu a ukladani globalnich id analyza = DEKLARACE(); if(analyza != S_BEZ_CHYB) { return analyza; } return FUNKCE(); } return S_SYNTAKTICKA_CHYBA; }