pd_alg_first.cppGo to the documentation of this file.00001 /** @file pd_alg_first.cpp functions related to the first function*/ 00002 00003 00004 /* Pushdown plugin for FAU Discrete Event Systems Library (libfaudes) 00005 00006 Copyright (C) 2013 Stefan Jacobi, Sven Schneider, Anne-Kathrin Hess 00007 00008 */ 00009 00010 #include "pd_alg_first.h" 00011 00012 namespace faudes { 00013 00014 00015 /* ************************* 00016 * PostCl 00017 * *************************/ 00018 GrammarSymbolWordSet PostCl(const GrammarSymbolVector& word){ 00019 00020 GrammarSymbolWordSet rSet; 00021 GrammarSymbolVector postfix; 00022 GrammarSymbolVector::const_reverse_iterator vit; 00023 //iterate backwards over the word, thus building all postfixes 00024 for(vit = word.rbegin(); vit != word.rend(); vit++){ 00025 00026 postfix.insert(postfix.begin(),*vit); 00027 rSet.insert(postfix); 00028 } 00029 00030 //lambda always belongs in the set 00031 GrammarSymbolVector lambda; 00032 Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA)); 00033 GrammarSymbolPtr ptr(tlambda); 00034 lambda.push_back(ptr); 00035 rSet.insert(lambda); 00036 00037 return rSet; 00038 } 00039 00040 /* ************************* 00041 * Fds 00042 * *************************/ 00043 GrammarSymbolWordSet Fds(const Grammar& gr){ 00044 GrammarSymbolWordSet rSet, postfixSet; 00045 GrammarSymbolVector gsVector; 00046 std::set<GrammarProduction>::const_iterator gpit; 00047 00048 //iterate over all grammar productions 00049 for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){ 00050 00051 gsVector.clear(); 00052 00053 //add lefthand side 00054 Nonterminal* nt = new Nonterminal(gpit->Lhs()); 00055 NonterminalPtr ntPtr(nt); 00056 gsVector.push_back(ntPtr); 00057 rSet.insert(gsVector); 00058 00059 //add postfixes of righthand side 00060 postfixSet = PostCl(gpit->Rhs()); 00061 rSet.insert(postfixSet.begin(), postfixSet.end()); 00062 00063 } 00064 return rSet; 00065 } 00066 00067 /* ************************* 00068 * First1 00069 * *************************/ 00070 GrammarSymbolWordMap First1(const Grammar& gr, const GrammarSymbolWordMap& f, bool* madeChanges){ 00071 00072 //take a copy rf of the old first function f for extending and returning 00073 GrammarSymbolWordMap rf = f; 00074 00075 //helper variable to determine if changes were made from f to rf 00076 bool changed = false; 00077 *madeChanges = false; 00078 00079 //get all postfixes and lefthand sides of the grammar 00080 GrammarSymbolWordSet words = Fds(gr); 00081 00082 GrammarSymbolWordSet::const_iterator wordit; 00083 std::set<Terminal>::const_iterator insertWordit; 00084 00085 std::set<GrammarProduction>::const_iterator gpit; 00086 //for every word w in Fds(gr) 00087 for(wordit = words.begin(); wordit != words.end(); wordit++){ 00088 00089 //get the first symbol of the word w = a.w' 00090 GrammarSymbolPtr firstSymbol = wordit->front(); 00091 00092 //if the first symbol is a terminal 00093 TerminalPtr terminalA = std::tr1::dynamic_pointer_cast<Terminal>(firstSymbol); 00094 if(terminalA != NULL){ 00095 00096 std::set<Terminal> rfw; 00097 //add the terminal to the first function rf 00098 //if w does not already exist in rf, create it 00099 if(rf.find(*wordit) == rf.end()){ 00100 rf.insert(std::make_pair(*wordit, std::set<Terminal>())); 00101 } 00102 00103 //add rf(w) = a to the first function rf 00104 changed = rf.find(*wordit)->second.insert(*terminalA).second; 00105 if(changed) *madeChanges = true; 00106 } 00107 00108 //if the first symbol is a nonterminal 00109 NonterminalPtr nonterminalA = std::tr1::dynamic_pointer_cast<Nonterminal>(firstSymbol); 00110 if(nonterminalA != NULL){ 00111 00112 std::set<Terminal> directDependencies; 00113 00114 //get the first symbols f(x) for every production (a-->x) 00115 for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){ 00116 00117 //check if the production has the nonterminal a on its lefthand side and if the 00118 //righthand side x exists in f 00119 if(gpit->Lhs() == *nonterminalA){ 00120 if(f.find(gpit->Rhs()) != f.end()){ 00121 00122 //get f(x) and add it to directDependencies 00123 std::set<Terminal> fx = f.find(gpit->Rhs())->second; 00124 directDependencies.insert(fx.begin(),fx.end()); 00125 } 00126 } 00127 } 00128 00129 //construct the symbol a ... 00130 GrammarSymbolVector a; 00131 a.push_back(nonterminalA); 00132 //... and get the first symbols of a (f(a)) 00133 std::set<Terminal> fa; 00134 if(f.find(a) != f.end()){ 00135 fa = f.find(a)->second; 00136 } 00137 00138 //get w' (the second part of the current word w = a.w'), 00139 GrammarSymbolVector wBack(wordit->begin() + 1, wordit->end());//can never go out of bounds because of outermost for loop 00140 00141 //if w' is not empty, remove lambda from f(a) and the direct dependencies, 00142 //because eliminability of a does not imply eliminability of w' 00143 GrammarSymbolVector lambdaWord; 00144 Terminal tlambda(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA)); 00145 00146 //remove lambda and remember for later if lambda was in f(a) 00147 bool faContainsLambda = false; 00148 if(!wBack.empty()){ 00149 if(fa.erase(tlambda) == 1){ 00150 faContainsLambda = true; 00151 } 00152 directDependencies.erase(tlambda); 00153 } 00154 00155 //add new items to rf(w) 00156 std::set<Terminal> rfw; 00157 //if w does not already exist in rf, create it 00158 if(rf.find(*wordit) == rf.end()){ 00159 rf.insert(std::make_pair(*wordit, std::set<Terminal>())); 00160 } 00161 00162 //add f(a) 00163 for(insertWordit = fa.begin(); insertWordit != fa.end(); insertWordit++){ 00164 changed = rf.find(*wordit)->second.insert(*insertWordit).second; 00165 if(changed) *madeChanges = true; 00166 } 00167 00168 //add direct dependencies 00169 for(insertWordit = directDependencies.begin(); insertWordit != directDependencies.end(); insertWordit++){ 00170 changed = rf.find(*wordit)->second.insert(*insertWordit).second; 00171 if(changed) *madeChanges = true; 00172 } 00173 00174 //if a is eliminable, add f(w') to f(w) 00175 if(faContainsLambda){ 00176 std::set<Terminal> fwBack; 00177 //get f(w') 00178 if(f.find(wBack) != f.end()){ 00179 fwBack = f.find(wBack)->second; 00180 } 00181 00182 //add f(w') 00183 for(insertWordit = fwBack.begin(); insertWordit != fwBack.end(); insertWordit++){ 00184 changed = rf.find(*wordit)->second.insert(*insertWordit).second; 00185 if(changed) *madeChanges = true; 00186 } 00187 } 00188 } 00189 } 00190 return rf; 00191 } 00192 00193 /* ************************* 00194 * FirstL 00195 * *************************/ 00196 GrammarSymbolWordMap FirstL(const Grammar& gr, const GrammarSymbolWordMap& f){ 00197 00198 //calculate first function 00199 bool changed; 00200 GrammarSymbolWordMap fNew = First1(gr,f,&changed); 00201 00202 //repeat until no changes are made 00203 if(changed){ 00204 fNew = FirstL(gr,fNew); 00205 } 00206 00207 return fNew; 00208 } 00209 00210 /* ************************* 00211 * FirstA 00212 * *************************/ 00213 std::set<Terminal> FirstA(const Grammar& gr, const GrammarSymbolVector& word){ 00214 00215 //calculate first function 00216 GrammarSymbolWordMap f = FirstL(gr,f); 00217 00218 GrammarSymbolWordMap::const_iterator fit = f.find(word); 00219 if(fit == f.end()){ 00220 GrammarSymbolVector::const_iterator vit; 00221 std::stringstream errstr; 00222 errstr << "word " << std::endl; 00223 for(vit = word.begin(); vit != word.end(); vit++){ 00224 errstr << (*vit)->Str(); 00225 } 00226 errstr << " was not found in the first function"; 00227 throw Exception("FirstA", errstr.str(), 1001); 00228 } 00229 00230 return fit->second; 00231 } 00232 00233 /* ************************* 00234 * First 00235 * *************************/ 00236 std::set<Terminal> First(const Grammar& gr, const GrammarSymbolVector& word){ 00237 00238 //"empty" words must still contain lambda! 00239 if(word.empty()){ 00240 std::stringstream errstr; 00241 errstr << "word parameter was empty. try calling it with lambda instead of an empty vector."; 00242 throw Exception("First", errstr.str(), 1001); 00243 } 00244 00245 //set of nonterminals to return 00246 std::set<Terminal> rSet; 00247 00248 //if the first symbol of the word is a terminal (or lambda) 00249 TerminalPtr t = std::tr1::dynamic_pointer_cast<Terminal>(word.front()); 00250 if(t != NULL) { 00251 00252 //insert the terminal (can be lambda) 00253 rSet.insert(*t); 00254 } 00255 00256 //if the first symbol of the word is a nonterminal 00257 NonterminalPtr nt = std::tr1::dynamic_pointer_cast<Nonterminal>(word.front()); 00258 if(nt != NULL){ 00259 00260 //get first set of the nonterminal 00261 GrammarSymbolVector v; 00262 v.push_back(nt); 00263 rSet = FirstA(gr,v); 00264 00265 //if the word contains more symbols and the set contains, it needs to erased 00266 //be removed from the set 00267 if(word.size() > 1){ 00268 00269 Terminal tlambda(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA)); 00270 //the set contains lambda (the nonterminal is eliminable). the remaining word 00271 //needs to be examined 00272 if(rSet.erase(tlambda) == 1){ 00273 00274 //recursive call of first 00275 std::set<Terminal> recSet = First(gr, GrammarSymbolVector(word.begin() + 1, word.end())); 00276 rSet.insert(recSet.begin(), recSet.end()); 00277 } 00278 } 00279 } 00280 return rSet; 00281 } 00282 00283 /* ************************* 00284 * FirstRed 00285 * *************************/ 00286 std::set<Terminal> FirstRed(const Grammar& gr, const GrammarSymbolVector& word){ 00287 00288 //set to return 00289 std::set<Terminal> rSet; 00290 00291 //if every symbol of the word is a symbol of the grammar, the word is consistent 00292 bool consistent = true; 00293 GrammarSymbolVector::const_iterator wordit; 00294 std::set<Terminal>::const_iterator tit; 00295 std::set<Nonterminal>::const_iterator ntit; 00296 00297 //check every symbol of the word 00298 for(wordit = word.begin(); wordit != word.end(); wordit++){ 00299 00300 //if it's a terminal 00301 TerminalPtr t = std::tr1::dynamic_pointer_cast<Terminal>(*wordit); 00302 if(t != NULL) { 00303 //if it's not in the grammar's terminals 00304 if(gr.Terminals().find(*t) == gr.TerminalsEnd()){ 00305 consistent = false; 00306 break; 00307 } 00308 } 00309 00310 //if it's a nonterminal 00311 NonterminalPtr nt = std::tr1::dynamic_pointer_cast<Nonterminal>(*wordit); 00312 if(nt != NULL) { 00313 //if it's not in the grammar's nonterminals 00314 if(gr.Nonterminals().find(*nt) == gr.NonterminalsEnd()){ 00315 consistent = false; 00316 break; 00317 } 00318 } 00319 } 00320 00321 //call first only if it's consistent 00322 if(consistent){ 00323 rSet = First(gr, word); 00324 } 00325 //else return empty set 00326 return rSet; 00327 } 00328 00329 /* ************************* 00330 * Filter1 00331 * *************************/ 00332 NonterminalPtr Filter1(const std::set<Nonterminal>& symbolSet, const GrammarSymbolVector& w){ 00333 00334 GrammarSymbolVector::const_iterator wit; 00335 std::set<Nonterminal>::const_iterator ntit; 00336 //iterate over all symbols of the word 00337 for(wit = w.begin(); wit != w.end(); wit++){ 00338 //test if current symbol is a nonterminal 00339 ConstNonterminalPtr nt = std::tr1::dynamic_pointer_cast<const Nonterminal>(*wit); 00340 if(nt != NULL){ 00341 00342 //look for the symbol in the nonterminal set 00343 ntit = symbolSet.find(*nt); 00344 00345 //if the symbol was found, return it 00346 if(ntit != symbolSet.end()){ 00347 Nonterminal* rNt = new Nonterminal(*nt); 00348 return NonterminalPtr(rNt); 00349 } 00350 } 00351 } 00352 //else return NULL 00353 return NonterminalPtr(); 00354 } 00355 00356 /* ************************* 00357 * FirstAll 00358 * *************************/ 00359 std::set<Terminal> FirstAll(const Grammar& gr, const GrammarSymbolVector& word){ 00360 00361 //set to return 00362 std::set<Terminal> rSet; 00363 00364 //get nonterminals contained in the word 00365 std::set<Nonterminal> filterSet = Filter(gr.Nonterminals(), word); 00366 00367 //if no nonterminals were found, call First 00368 if(filterSet.empty()){ 00369 rSet = First(gr, word); 00370 } 00371 //if nonterminals were found 00372 else{ 00373 00374 //create temporary grammar with the first nonterminal as a start symbol 00375 Grammar tempGr = gr; 00376 NonterminalPtr firstNt = Filter1(gr.Nonterminals(), word); 00377 tempGr.SetStartSymbol(*firstNt); 00378 //remove nonproducte productions from this grammar 00379 Grammar optGr = Rnpp(tempGr); 00380 //if the grammar is not empty, call FirstRed 00381 if(!optGr.GrammarProductions().empty()){ 00382 rSet = FirstRed(optGr, word); 00383 } 00384 } 00385 00386 return rSet; 00387 } 00388 00389 /* ************************* 00390 * FirstLeq1 00391 * *************************/ 00392 std::set<Terminal> FirstLeq1(const Grammar& gr, uint k, const GrammarSymbolVector& word){ 00393 00394 //set to return 00395 std::set<Terminal> rSet; 00396 00397 //if k > 1, return empty set 00398 if(k > 1){ 00399 return rSet; 00400 } 00401 00402 //else determine first set 00403 rSet = FirstAll(gr, word); 00404 00405 //if k == 0 and the first set is not empty, return lambda as first set 00406 if(k == 0 && !rSet.empty()){ 00407 Terminal tlambda(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA)); 00408 00409 rSet.clear(); 00410 rSet.insert(tlambda); 00411 } 00412 00413 return rSet; 00414 } 00415 00416 /* ***************** 00417 * WriteMap 00418 * *****************/ 00419 void WriteMap(GrammarSymbolWordMap f, bool changed){ 00420 GrammarSymbolWordMap::const_iterator fit; 00421 std::set<Terminal>::const_iterator setit; 00422 GrammarSymbolVector::const_iterator wordit; 00423 std::stringstream mapstr; 00424 mapstr << "************************************************" << std::endl; 00425 mapstr << "changes made:"; 00426 if(changed) mapstr << "yes" << std::endl; 00427 else mapstr << "no" << std::endl; 00428 mapstr << std::endl; 00429 for(fit = f.begin(); fit != f.end(); fit++){ 00430 00431 for(wordit = fit->first.begin(); wordit != fit->first.end(); wordit++){ 00432 mapstr << (*wordit)->Str(); 00433 } 00434 00435 mapstr << ": "; 00436 mapstr << std::endl << " "; 00437 for(setit = fit->second.begin(); setit != fit->second.end(); setit++){ 00438 if(setit != fit->second.begin()){ 00439 mapstr << ", "; 00440 } 00441 mapstr << (*wordit)->Str(); 00442 } 00443 mapstr << std::endl; 00444 } 00445 00446 std::cout << mapstr.str() << std::endl; 00447 } 00448 00449 } // namespace faudes 00450 libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen |