pd_alg_lrm.cppGo to the documentation of this file.00001 /** @file pd_alg_lrm.cpp functions related to LR machines*/ 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_lrm.h" 00011 00012 namespace faudes { 00013 00014 /* ************************* 00015 * Desc11 00016 * *************************/ 00017 std::set<Lr1Configuration> Desc11(const Grammar& gr, uint k, const Lr1Configuration& config){ 00018 00019 //config set to return 00020 std::set<Lr1Configuration> rSet; 00021 00022 //always contains the original config 00023 rSet.insert(config); 00024 00025 //check the configuration (A -> B beta . x, y) 00026 //if the first symbol B of the afterDot vector is a nonterminal 00027 if(config.AfterDot().empty()){ 00028 return rSet; 00029 } 00030 NonterminalPtr nt = std::tr1::dynamic_pointer_cast<Nonterminal>(config.AfterDot().front()); 00031 if(nt != NULL){ 00032 00033 //look for productions (B -> w) and insert a new configuration 00034 //(B -> lambda . w , firstleq1(gr, k, beta y)) for each production and lookahead 00035 std::set<GrammarProduction>::const_iterator gpit; 00036 for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){ 00037 if(gpit->Lhs() == *nt){ 00038 00039 00040 //beforeDot for the new configuration is lambda 00041 GrammarSymbolVector beforeDot; 00042 Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA)); 00043 GrammarSymbolPtr ptrtlambda(tlambda); 00044 beforeDot.push_back(ptrtlambda); 00045 00046 00047 //lookahead for the new configuration is calculated from the word beta y 00048 GrammarSymbolVector word(config.AfterDot().begin() + 1, config.AfterDot().end()); 00049 Terminal* lookahead = new Terminal(config.Lookahead()); 00050 GrammarSymbolPtr ptrlookahead(lookahead); 00051 word.push_back(ptrlookahead); 00052 00053 std::set<Terminal> firstSet = FirstLeq1(gr, k , word); 00054 std::set<Terminal>::const_iterator terminalit; 00055 //insert new production for each possible lookahead 00056 for(terminalit = firstSet.begin(); terminalit != firstSet.end(); terminalit++){ 00057 Lr1Configuration config(*nt, beforeDot, gpit->Rhs(), *terminalit); 00058 rSet.insert(config); 00059 } 00060 } 00061 } 00062 } 00063 return rSet; 00064 } 00065 00066 /* ************************* 00067 * Desc1 00068 * *************************/ 00069 std::set<Lr1Configuration> Desc1(const Grammar& gr, uint k, const std::set<Lr1Configuration>& configs){ 00070 00071 //config set to return 00072 std::set<Lr1Configuration> rSet; 00073 00074 std::set<Lr1Configuration>::const_iterator configit; 00075 //iterate over all configurations 00076 for(configit = configs.begin(); configit != configs.end(); configit++){ 00077 00078 //get descendants of current configuration and add them to the return set 00079 std::set<Lr1Configuration> descSet = Desc11(gr, k, *configit); 00080 rSet.insert(descSet.begin(), descSet.end()); 00081 } 00082 00083 return rSet; 00084 } 00085 00086 /* ************************* 00087 * Desc 00088 * *************************/ 00089 std::set<Lr1Configuration> Desc(const Grammar& gr, uint k, const std::set<Lr1Configuration>& configs){ 00090 00091 //config set to return 00092 std::set<Lr1Configuration> rSet; 00093 00094 //get immediate descendants 00095 rSet = Desc1(gr, k, configs); 00096 00097 //keep calling recursively if there were changes made 00098 //((configs.size == rSet.size && configs != rSet) || configs.size != rSet.size) 00099 if((rSet.size() == configs.size() && !std::equal(configs.begin(), configs.end(), rSet.begin())) || rSet.size() != configs.size()){ 00100 00101 //recursive call 00102 rSet = Desc(gr, k, rSet); 00103 } 00104 00105 return rSet; 00106 } 00107 00108 /* ************************* 00109 * PassesX 00110 * *************************/ 00111 std::set<Lr1Configuration> PassesX(const Lr1Configuration& config, const GrammarSymbolPtr& symbol){ 00112 00113 //config set to return 00114 std::set<Lr1Configuration> rSet; 00115 00116 //can only shift if there is at least one symbol remaining after the dot 00117 if(!config.AfterDot().empty()){ 00118 00119 //check if it is the right symbol 00120 if(*symbol == *config.AfterDot().front()){ 00121 00122 Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA)); 00123 GrammarSymbolPtr ptrtlambda(tlambda); 00124 00125 //create new configuration 00126 //(A -> a . X b, y) becomes (A -> a X . b, y) 00127 00128 //construct beforeDot 00129 GrammarSymbolVector beforeDot = config.BeforeDot(); 00130 //if beforeDot contains only lambda, clear it before adding X 00131 if(*beforeDot.front() == *ptrtlambda){ 00132 beforeDot.clear(); 00133 } 00134 beforeDot.push_back(config.AfterDot().front()); 00135 00136 //construct afterDot 00137 GrammarSymbolVector afterDot(config.AfterDot().begin() + 1, config.AfterDot().end()); 00138 00139 //if afterDot is empty, insert lambda 00140 if(afterDot.empty()){ 00141 00142 afterDot.push_back(ptrtlambda); 00143 } 00144 00145 00146 Lr1Configuration shiftedConfig(config.Lhs(), beforeDot, afterDot, config.Lookahead()); 00147 00148 //insert new configuration into set 00149 rSet.insert(shiftedConfig); 00150 } 00151 } 00152 return rSet; 00153 } 00154 00155 /* ************************* 00156 * Basis 00157 * *************************/ 00158 std::set<Lr1Configuration> Basis(const std::set<Lr1Configuration> configs, const GrammarSymbolPtr& symbol){ 00159 00160 //config set to return 00161 std::set<Lr1Configuration> rSet; 00162 00163 std::set<Lr1Configuration> shiftSet; 00164 std::set<Lr1Configuration>::const_iterator configit; 00165 //iterate over all configurations 00166 for(configit = configs.begin(); configit != configs.end(); configit++){ 00167 00168 //try to shift the dot 00169 shiftSet = PassesX(*configit,symbol); 00170 00171 //if successful, insert shifted configuration into result set 00172 if(!shiftSet.empty()){ 00173 rSet.insert(*shiftSet.begin()); 00174 } 00175 } 00176 return rSet; 00177 } 00178 00179 /* ************************* 00180 * GoTo 00181 * *************************/ 00182 std::set<Lr1Configuration> GoTo(const Grammar& gr, uint k, const std::set<Lr1Configuration> configs, const GrammarSymbolPtr& symbol){ 00183 00184 //obtain shifted configurations 00185 std::set<Lr1Configuration> shiftSet = Basis(configs, symbol); 00186 00187 //return the shifted configuration's descendants 00188 return Desc(gr, k, shiftSet); 00189 } 00190 00191 /* ************************* 00192 * Lrm1 00193 * *************************/ 00194 LrmTransitionMap Lrm1(const Grammar& gr, uint k, const Lr1ConfigurationSetSet& configSetSet){ 00195 00196 //config set map to return 00197 LrmTransitionMap rTransitions; 00198 00199 Lr1ConfigurationSetSet::const_iterator configssit; 00200 Terminal lambda(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA)); 00201 //iterate over all configuration sets 00202 for(configssit = configSetSet.begin(); configssit != configSetSet.end(); configssit++){ 00203 00204 std::set<Nonterminal>::const_iterator ntit; 00205 std::set<Terminal>::const_iterator tit; 00206 //determine the possible next configuration set for every terminal 00207 for(tit = gr.TerminalsBegin(); tit != gr.TerminalsEnd(); tit++){ 00208 00209 //dont consider lambda! 00210 if(*tit == lambda){ 00211 continue; 00212 } 00213 00214 Terminal* t = new Terminal(*tit); 00215 GrammarSymbolPtr tptr(t); 00216 //get next configuration set 00217 std::set<Lr1Configuration> nextConfigSet = GoTo(gr, k, *configssit, tptr); 00218 00219 //if the config set is not empty 00220 if(!nextConfigSet.empty()){ 00221 00222 //insert it into transition map 00223 ConfigSetGsPair configSetGsPair = std::make_pair(*configssit, tptr); 00224 rTransitions.insert(std::make_pair(configSetGsPair, nextConfigSet)); 00225 } 00226 } 00227 00228 //determine the possible next configuration set for every nonterminal 00229 for(ntit = gr.NonterminalsBegin(); ntit != gr.NonterminalsEnd(); ntit++){ 00230 00231 Nonterminal* nt = new Nonterminal(*ntit); 00232 GrammarSymbolPtr ntptr(nt); 00233 //get next configuration set 00234 std::set<Lr1Configuration> nextConfigSet = GoTo(gr, k, *configssit, ntptr); 00235 00236 //if the config set is not empty 00237 if(!nextConfigSet.empty()){ 00238 00239 //insert it into transition map 00240 ConfigSetGsPair configSetGsPair = std::make_pair(*configssit, ntptr); 00241 rTransitions.insert(std::make_pair(configSetGsPair, nextConfigSet)); 00242 } 00243 } 00244 } 00245 return rTransitions; 00246 } 00247 00248 /* ************************* 00249 * LrmLoop 00250 * *************************/ 00251 std::pair<LrmTransitionMap,Lr1ConfigurationSetSet> LrmLoop(const Grammar& gr, uint k, const LrmTransitionMap& transitions, const Lr1ConfigurationSetSet& states, Lr1ConfigurationSetSet examineStates){ 00252 00253 //save states that are already found 00254 Lr1ConfigurationSetSet foundStates(states); 00255 foundStates.insert(examineStates.begin(), examineStates.end()); 00256 00257 //pair to return if no new transition is found 00258 std::pair<LrmTransitionMap,Lr1ConfigurationSetSet> rPair; 00259 rPair = std::make_pair(transitions, foundStates); 00260 00261 //calculate new transitions 00262 LrmTransitionMap newTransitions = Lrm1(gr, k, examineStates); 00263 00264 //if new transitions were found 00265 if(!newTransitions.empty()){ 00266 00267 //determine states that need to be looked at in the next recursive iteration 00268 //(i. e., the successor states of the transitions) 00269 Lr1ConfigurationSetSet newExamineStates; 00270 LrmTransitionMap::const_iterator transit; 00271 for(transit = newTransitions.begin(); transit != newTransitions.end(); transit++){ 00272 newExamineStates.insert(transit->second); 00273 } 00274 00275 Lr1ConfigurationSetSet::const_iterator stateit; 00276 //remove states that were already visited 00277 for(stateit = foundStates.begin(); stateit != foundStates.end(); stateit++){ 00278 newExamineStates.erase(*stateit); 00279 } 00280 00281 //recursively look for new transitions and states 00282 newTransitions.insert(transitions.begin(), transitions.end()); 00283 rPair = LrmLoop(gr, k , newTransitions, foundStates, newExamineStates); 00284 } 00285 return rPair; 00286 } 00287 00288 /* ************************* 00289 * DescInitial 00290 * *************************/ 00291 std::set<Lr1Configuration> DescInitial(const Grammar& gr){ 00292 00293 //item set to return 00294 std::set<Lr1Configuration> rSet; 00295 00296 std::set<GrammarProduction>::const_iterator gpit; 00297 //look for initial grammar productions (S,w) 00298 for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){ 00299 if(gpit->Lhs() == gr.StartSymbol()){ 00300 00301 //insert configuration (S -> lambda . w, lambda) 00302 Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA)); 00303 GrammarSymbolPtr ptrtlambda(tlambda); 00304 00305 GrammarSymbolVector beforeDot; 00306 beforeDot.push_back(ptrtlambda); 00307 00308 rSet.insert(Lr1Configuration(gpit->Lhs(), beforeDot, gpit->Rhs(), *tlambda)); 00309 } 00310 } 00311 return rSet; 00312 } 00313 00314 /* ************************* 00315 * ValidEmpty 00316 * *************************/ 00317 std::set<Lr1Configuration> ValidEmpty(const Grammar& gr, uint k){ 00318 00319 //item set to return 00320 std::set<Lr1Configuration> rSet; 00321 00322 //get initial configurations 00323 rSet = DescInitial(gr); 00324 00325 //get descendants of the initial configurations 00326 rSet = Desc(gr, k, rSet); 00327 00328 return rSet; 00329 } 00330 00331 /* ************************* 00332 * Lrm 00333 * *************************/ 00334 GotoGenerator Lrm(const Grammar& gr, uint k){ 00335 00336 //generator to return 00337 GotoGenerator gotoGen; 00338 00339 //get the initial state 00340 std::set<Lr1Configuration> initState = ValidEmpty(gr, k); 00341 00342 //get the transitions and states 00343 Lr1ConfigurationSetSet initStateSet; 00344 initStateSet.insert(initState); 00345 std::pair<LrmTransitionMap,Lr1ConfigurationSetSet> transitionsStates= LrmLoop(gr, k, LrmTransitionMap(), Lr1ConfigurationSetSet(), initStateSet); 00346 00347 Lr1ConfigurationSetSet::const_iterator stateit; 00348 //insert states of the generator 00349 for(stateit = transitionsStates.second.begin(); stateit != transitionsStates.second.end(); stateit++){ 00350 Idx idx = gotoGen.InsState(); 00351 gotoGen.ConfigSet(idx, *stateit); 00352 00353 //if the current config equals the init config, set init state 00354 if(!(CompareConfigSet(*stateit, initState) || CompareConfigSet(initState, *stateit))){ 00355 gotoGen.SetInitState(idx); 00356 } 00357 } 00358 00359 //insert transitions into the generator 00360 LrmTransitionMap::const_iterator transit; 00361 for(transit = transitionsStates.first.begin(); transit != transitionsStates.first.end(); transit++){ 00362 Idx startState = gotoGen.StateIndex(transit->first.first); 00363 Idx endState = gotoGen.StateIndex(transit->second); 00364 GrammarSymbolPtr symbol = transit->first.second; 00365 00366 gotoGen.SetTransition(startState, symbol, endState); 00367 } 00368 00369 //save transitions and states the a gotoMachine 00370 // gotoMachine.InitState(initState); 00371 // gotoMachine.Transitions(transitionsStates.first); 00372 // gotoMachine.States(transitionsStates.second); 00373 00374 return gotoGen; 00375 } 00376 00377 /* ************************* 00378 * Aug 00379 * *************************/ 00380 Grammar Aug(const Grammar& gr, const Nonterminal& startSymbol, const Terminal& augSymbol){ 00381 00382 //grammar to return 00383 Grammar rGr = gr; 00384 00385 //try to set startSymbol S as the new start symbol and throw an exception 00386 //if it is already contained in the grammar's nonterminals 00387 if(!rGr.SetStartSymbol(startSymbol)){ 00388 std::stringstream errstr; 00389 errstr << "While executing Aug(): Tried to insert new startSymbol " << startSymbol.Str() << ", but it already existed in the grammar" << std::endl; 00390 throw Exception("Aug", errstr.str(), 1001); 00391 } 00392 00393 //try to insert augSymbol $ into the grammar's terminals and throw an exception if 00394 //it is already contained in the grammar's terminals 00395 if(!rGr.InsTerminal(augSymbol)){ 00396 std::stringstream errstr; 00397 errstr << "While executing Aug(): Tried to insert new augSymbol " << augSymbol.Str() << ", but it already existed in the grammar" << std::endl; 00398 throw Exception("Aug", errstr.str(), 1001); 00399 } 00400 00401 //get old startSymbol S' 00402 Nonterminal* oldStartSymbol = new Nonterminal(gr.StartSymbol()); 00403 GrammarSymbolPtr oldStartSymbolPtr(oldStartSymbol); 00404 00405 //get Pointer to augSymbol 00406 Terminal* augSymbolTemp = new Terminal(augSymbol); 00407 GrammarSymbolPtr augSymbolPtr(augSymbolTemp); 00408 00409 //construct new production's right-hand side $ S' $ 00410 GrammarSymbolVector rhs; 00411 rhs.push_back(augSymbolPtr); 00412 rhs.push_back(oldStartSymbolPtr); 00413 rhs.push_back(augSymbolPtr); 00414 00415 //construct new Production S -> $ S' $ and insert into grammar 00416 GrammarProduction gp(startSymbol,rhs); 00417 rGr.InsGrammarProduction(gp); 00418 00419 return rGr; 00420 } 00421 00422 00423 } // namespace faudes 00424 libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen |