pd_alg_lrm.cpp

Go 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