/* 5. Metodom potisnog automata izgraditi program koji ce prihvacati sve ispravno napisane aritmeticke izraze u infiks notaciji koristenjem operatora +, -, *, /, (, ), [,] te operanada. U izlaznoj datoteci pokazati konfiguraciju potisnog automata za zadani ulazni niz. Na temelju izgrad/enog potisnog automata izgradite ogovarajucu gramatiku. */ /* Dinko Korunic, 36355514 */ // $Id: afjjp1-3.cpp,v 1.18 2001/01/19 09:24:06 kreator Exp $ #include #include #include #include #include // polje svakog PTable sadrzi 3 jedinstvene oznake - (stanje, ulaz, stog) struct PAData { int State, // trenutno stanje NewState; // novi prijelaz char InputChar, // ulazni znak Stack, // stanje na stogu NewStack; // novo stanje stoga - nikakava promjena (NULL), novi znak ili // '\b' sto je brisanje sa stoga }; // struct PAData typedef struct PAData PAData_t; typedef vector PAData_Vector; typedef vector char_Vector; // tabela akcija potisnog automata. ona ce sadrzavati osim toga i vektor-stog class PA { char_Vector Stack; // implementacija stoga PAData_Vector PATable; string TransData; int CurrState; void ParseString(string); string TransliterateString(string); PAData_Vector::iterator FindTable(char **); public: void InputTransliterator(istream &); int ParseFile(istream &); friend ostream& operator<< (ostream &, PA &); friend istream& operator>> (istream &, PA &); }; // class PA // dva C-oidna rjesenje iz afjjp1-1a labosa // vlastiti strtoken char *strtoken(char **save, char *str, char *fs) { char *pos=*save, /* Zadnja pozicija (kod zadnjeg poziva) */ *tmp; if (str!=NULL) pos=str; /* Uu.. scanniramo novi string */ for (;pos && *pos && index(fs, *pos)!=NULL; ++pos); /* Izbjegni vodece sep. */ if (!pos || !*pos) return (pos=*save=NULL); /* Baah. String ima samo separatore */ tmp=pos; /* OK. Zadrzi poziciju tokena */ for (;*pos && index(fs, *pos)==NULL; ++pos); /* Izbjegni sadrzaj tokena */ if (*pos) *pos++=0; /* Makni prvi separator poslije tokena */ else pos=NULL; /* Gle! Kraj stringa :-) */ *save=pos; return(tmp); } // char *strtoken() // transliteracija stringa void trans_string(char *tmp, char *oldstring) { char *posp, *charp, *pos, *stringp; /* Polako scanniraj ulazni niz i transliteriraj, s time sto se ide po * razlicitim klasama za transliteriranje i zamjenjuje svaki znak koji * se pojavljuje */ for (stringp=strtoken(&posp, tmp, ";"); stringp!=NULL; stringp=strtoken(&posp, NULL, ";")) for (charp=stringp+1; *charp; ++charp) for (pos=oldstring; (pos=index(pos, *charp))!=NULL; *(pos++)=*stringp); } // void trans_string() // pretrazivac po listi PAData_Vector::iterator PA::FindTable(char **ParseCharPtr) { PAData_Vector::iterator i; for (i=PATable.begin(); i!=PATable.end(); ++i) if (i->State==CurrState && i->Stack==Stack.back()) { if (i->InputChar!='x') { if (**ParseCharPtr && i->InputChar==**ParseCharPtr) // postoji prijelaz { ++(*ParseCharPtr); return i; } } else // epsilon prijelaz return i; } return NULL; } // PAData_Vector::iterator PA::FindTable() // namijenjena iterativnom pozivanju void PA::ParseString(string myParseString) { CurrState=0; Stack.clear(); Stack.push_back('K'); char *ParseChar=(char *)myParseString.c_str(); PAData_Vector::iterator i; while ((i=FindTable(&ParseChar))!=NULL) { CurrState=i->NewState; switch(i->NewStack) { case 'b': Stack.pop_back(); break; case 'x': break; default: Stack.push_back(i->NewStack); break; } } cout << "Niz " << myParseString << " se " << ((!*ParseChar && !Stack.size())?"":"ne ") << "prihvaca" << endl; if (!Stack.size()) cout << "Prazan stack"; else { cout << "Na stacku je: "; ostream_iterator out(cout, " "); copy(Stack.begin(), Stack.end(), out); } cout << endl; } // void PA::Parse() // puni transliterator void PA::InputTransliterator(istream &ifs) { ifs >> TransData; } // int PA::InputTransliterator() // transliterira string PA::TransliterateString(string origString) { char *ptrC=strdup(origString.c_str()); char *ptrZ=strdup(TransData.c_str()); trans_string(ptrZ, ptrC); string tmpS(ptrC); free(ptrC); free(ptrZ); return tmpS; } // string PA::TransliterateString() // parsira datoteku, vraca broj proparsanih stringova int PA::ParseFile(istream &ifs) { cout << "Rezultat parsiranja datoteke:" << endl; int icnt=0; while (ifs.peek()!=EOF) { string biba; ifs >> biba; biba=TransliterateString(biba); ParseString(biba); ifs.ignore(255, '\n'); ++icnt; } return icnt; } // int PA::ParseFile() // ispis tablice ostream& operator<< (ostream &ofs, PA &PAOb) { ofs << "Interni zapis tablice PA:\nStanje:\tUlaz:\t" "Stog:\tNovo stanje:\tNovi vrh stoga:" << endl; for (PAData_Vector::iterator it1=PAOb.PATable.begin(); it1!=PAOb.PATable.end(); ++it1) { ofs << it1->State << "\t" << it1->InputChar << "\t" << it1->Stack << "\t" << it1->NewState << "\t\t" << it1->NewStack << endl; } return ofs; } // operator<< // ucitavanje tablice istream& operator>> (istream &ifs, PA &PAOb) { PAData tmpNode; while (1) // dok mozes citaj { ifs >> tmpNode.State >> tmpNode.InputChar >> tmpNode.Stack >> tmpNode.NewState >> tmpNode.NewStack; if (ifs) PAOb.PATable.push_back(tmpNode); else break; } return ifs; } // operator>> //blah int main(int argc, char **argv) { if (argc!=4) { cout << "Premalo parametara: ulazna_tablica" " tablica_transliteratora ulazni_niz_stringova" << endl; return EXIT_FAILURE; } ifstream if1(argv[1], ios::in); ifstream if2(argv[2], ios::in); ifstream if3(argv[3], ios::in); if (!if1 && !if2 && !if3) { cout << "Ne mogu otvoriti datoteke" << endl; return EXIT_FAILURE; } PA MojPotisni; if1 >> MojPotisni; if1.close(); // prikaz konfiguracije automata cout << MojPotisni; // napuni transliterator MojPotisni.InputTransliterator(if2); if2.close(); // parsing za liniju po liniju MojPotisni.ParseFile(if3); if3.close(); return EXIT_SUCCESS; }