pd_grammar.cpp

Go to the documentation of this file.
00001 /** @file pd_merge.cpp  grammar data structure */
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_grammar.h"
00011 
00012 namespace faudes {
00013 
00014 /*******************************
00015 * 
00016 * Implementation of GrammarSymbol
00017 *
00018 */ 
00019 bool GrammarSymbol::operator==(const GrammarSymbol& other) const{
00020   if (!(*this < other) && !(other < *this)) return true;
00021   return false;
00022 }
00023 
00024 bool GrammarSymbol::operator!=(const GrammarSymbol& other) const{
00025   if (!(*this < other) && !(other < *this)) return false;
00026   return true;
00027 }
00028 
00029 /*******************************
00030 * 
00031 * Implementation of Terminal
00032 *
00033 */  
00034 
00035 std::string Terminal::Str() const{
00036   return PushdownGenerator::GlobalEventSymbolTablep()->Symbol(mEvent);
00037 }
00038 
00039 bool Terminal::IsLambda() const{
00040   if (PushdownGenerator::GlobalEventSymbolTablep()->Symbol(mEvent).compare(FAUDES_PD_LAMBDA) == 0)
00041     return true;
00042   return false;
00043 }
00044 
00045 bool Terminal::operator<(const GrammarSymbol& other) const{
00046   if(typeid(*this) != typeid(other)) return false; //other is a nonterminal
00047   const Terminal& t = dynamic_cast<const Terminal&>(other); //other is a terminal
00048   return mEvent < t.Event(); 
00049 }
00050 
00051 Terminal* Terminal::Clone() const{
00052   
00053   Terminal* t = NULL;
00054   try{
00055     t = new Terminal(*this);
00056   }
00057   catch (std::bad_alloc& ba){
00058     std::cerr << "bad_alloc caught in Terminal::Clone new Clone(*this): " << ba.what() << std::endl;
00059   }
00060   return t;
00061 }
00062   
00063 /*******************************
00064 * 
00065 * Implementation of Nonterminal
00066 *
00067 */ 
00068 std::string Nonterminal::Str() const{
00069   std::stringstream s;
00070   std::vector<Idx>::const_iterator it;
00071   s << "(" <<  mStartState << ", [";
00072   for(it = mOnStack.begin(); it != mOnStack.end(); it++){
00073     if(it == mOnStack.begin()){
00074       s << PushdownGenerator::GlobalStackSymbolTablep()->Symbol(*it);
00075     }
00076     else{
00077       s << ", " << PushdownGenerator::GlobalStackSymbolTablep()->Symbol(*it);
00078     }
00079   }
00080   s << "]";
00081   if(mEndState != 0){
00082     s << ", " << mEndState; 
00083   }
00084   s << ")";
00085   return s.str();
00086 }
00087 
00088 bool Nonterminal::operator<(const GrammarSymbol& other) const{
00089   if(typeid(*this) != typeid(other)) return true; //other is a terminal
00090   const Nonterminal& nt = dynamic_cast<const Nonterminal&>(other); //other is a nonterminal
00091   if (mStartState < nt.StartState()) return true;
00092   if (mStartState > nt.StartState()) return false;
00093   
00094   if (mOnStack.size() < nt.OnStack().size()) return true; //also makes sure that it2 will not go out of bounds
00095   if (nt.OnStack().size() < mOnStack.size()) return false;
00096   
00097   std::vector<Idx>::const_iterator it1, it2;
00098   it2 = nt.OnStack().begin();
00099   for(it1 = mOnStack.begin(); it1 != mOnStack.end(); it1++){
00100     if(*it1 < *it2) return true;
00101     if(*it2 < *it1) return false;
00102     it2++;
00103   }
00104   
00105   if (mEndState < nt.EndState()) return true;
00106   return false;    
00107 }
00108 
00109 Nonterminal* Nonterminal::Clone() const{
00110   Nonterminal* nt = NULL;
00111   try{
00112     nt = new Nonterminal(*this);
00113   }
00114   catch (std::bad_alloc& ba){
00115     std::cerr << "bad_alloc caught in Nonterminal::Clone new Clone(*this): " << ba.what() << std::endl;
00116   }
00117   return nt;
00118 }
00119 
00120 /*******************************
00121 * 
00122 * Implementation of CompareGsVector
00123 *
00124 */
00125 
00126 bool CompareGsVector(const GrammarSymbolVector& lhs, const GrammarSymbolVector& rhs){
00127   if (lhs.size() < rhs.size()) return true; //also makes sure that it2 will not go out of bounds
00128   if (rhs.size() < lhs.size()) return false;
00129   
00130   GrammarSymbolVector::const_iterator it1, it2;
00131   it2 = rhs.begin();
00132   for(it1 = lhs.begin(); it1 != lhs.end(); it1++){
00133     if(**it1 < **it2) return true;
00134     if(**it2 < **it1) return false;
00135     it2++;
00136   }
00137   return false;
00138 }
00139 
00140 /*******************************
00141 * 
00142 * Implementation of EqualsGsVector
00143 *
00144 */
00145 bool EqualsGsVector(const GrammarSymbolVector& lhs, const GrammarSymbolVector& rhs){
00146   return(!CompareGsVector(lhs,rhs) && !CompareGsVector(rhs,lhs));
00147 }
00148 
00149 /*******************************
00150 * 
00151 * Implementation of CompareGs
00152 *
00153 */
00154 
00155 bool CompareGs(const GrammarSymbolPtr& lhs, const GrammarSymbolPtr& rhs){
00156   return *lhs < *rhs;
00157 }
00158 
00159 /* *************************
00160  * ContainsWord
00161  * *************************/
00162 bool ContainsWord(const GrammarSymbolWordSet& set, const GrammarSymbolVector& word){
00163   
00164   GrammarSymbolWordSet::const_iterator setit;
00165   GrammarSymbolVector::const_iterator gsit1, gsit2;
00166   bool found = false;
00167   
00168   //iterate over the word set and look for the word
00169   for(setit = set.begin(); setit != set.end(); setit++){
00170     
00171     //sizes are the same so this word is a candidate
00172     if(setit->size() == word.size()){
00173       
00174       found = true;
00175       
00176       //compare the words' symbols
00177       gsit2 = word.begin();
00178       for(gsit1 = setit->begin(); gsit1 != setit->end(); gsit1++){
00179         
00180         //symbols were not the same, this is not the word we are looking for
00181         if(**gsit1 != **gsit2){
00182           found = false;
00183           break;
00184         }
00185         gsit2++;
00186       }
00187       //the word was found and no further search is necessary
00188       if(found){
00189         break;
00190       }
00191     }
00192   }
00193   return found;
00194 }
00195 /*******************************
00196 * 
00197 * Implementation of GrammarProduction
00198 *
00199 */
00200 
00201 std::string GrammarProduction::Str() const{
00202   std::stringstream s;
00203   s << mLhs.Str() << " --> ";
00204   GrammarSymbolVector::const_iterator it;
00205   for(it = mRhs.begin(); it < mRhs.end(); it++){
00206     s << (*it)->Str();
00207   }
00208   return s.str();;
00209 }
00210 
00211 bool GrammarProduction::operator<(const GrammarProduction& other) const{
00212   if (mLhs < other.Lhs()) return true;
00213   if (other.Lhs() < mLhs) return false;
00214   if(CompareGsVector(mRhs,other.Rhs())) return true;
00215 //   if (mRhs.size() < other.Rhs().size()) return true; //also makes sure that it2 will not go out of bounds
00216 //   if (other.Rhs().size() < mRhs.size()) return false;
00217 //   
00218 //   std::vector<GrammarSymbol*>::const_iterator it1, it2;
00219 //   it2 = other.Rhs().begin();
00220 //   for(it1 = mRhs.begin(); it1 != mRhs.end(); it1++){
00221 //     if(**it1 < **it2) return true;
00222 //     if(**it2 < **it1) return false;
00223 //     it2++;
00224 //   }
00225   return false;    
00226 }
00227 
00228 
00229 /*******************************
00230 * 
00231 * Implementation of Grammar
00232 *
00233 */ 
00234 
00235 bool Grammar::SetStartSymbol(const Nonterminal& s){
00236   mStartSymbol = s;
00237   return mNonterminals.insert(s).second;
00238 }
00239 
00240 bool Grammar::InsTerminal(const Terminal& t){
00241   return mTerminals.insert(t).second;
00242 }
00243 
00244 void Grammar::InsTerminals(const std::set<Terminal>& t){
00245   mTerminals.insert(t.begin(),t.end());
00246 }
00247 
00248 bool Grammar::InsNonterminal(const Nonterminal& nt){
00249   return mNonterminals.insert(nt).second;
00250 }
00251 
00252 void Grammar::InsNonterminals(const std::set<Nonterminal>& nt){
00253   mNonterminals.insert(nt.begin(),nt.end());
00254 }
00255 
00256 bool Grammar::InsGrammarProduction(const GrammarProduction& gp){
00257   
00258   //check lefthand side for validity
00259   if(mNonterminals.find(gp.Lhs()) == mNonterminals.end()) {
00260     std::stringstream errstr;
00261     errstr << "Grammar symbol mismatch: Lefthand-side nonterminal " << gp.Lhs().Str() << " does not exist in grammar." <<std::endl;
00262     throw Exception("Grammar::InsGrammarProduction", errstr.str(), 1001);
00263   }
00264   
00265   //check righthand side for validity
00266   GrammarSymbolVector::const_iterator gsit;
00267   for(gsit = gp.Rhs().begin(); gsit != gp.Rhs().end(); gsit ++){
00268     
00269     //check nonterminals
00270     ConstNonterminalPtr nt = std::tr1::dynamic_pointer_cast<const Nonterminal>(*gsit);
00271     if(nt != NULL){
00272       if(mNonterminals.find(*nt) == mNonterminals.end()) {
00273         std::stringstream errstr;
00274         errstr << "Grammar symbol mismatch: Righthand-side nonterminal " << nt->Str() << " does not exist in grammar." <<std::endl;
00275         throw Exception("Grammar::InsGrammarProduction", errstr.str(), 1001);
00276       }
00277     }
00278     //check terminals
00279     ConstTerminalPtr t = std::tr1::dynamic_pointer_cast<const Terminal>(*gsit);
00280     if(t != NULL){
00281       if(mTerminals.find(*t) == mTerminals.end()) {
00282         std::stringstream errstr;
00283         errstr << "Grammar symbol mismatch: Righthand-side terminal " << t->Str() << " does not exist in grammar." <<std::endl;
00284         throw Exception("Grammar::InsGrammarProduction", errstr.str(), 1001);
00285       }
00286     }
00287   }
00288   
00289   return mGrammarProductions.insert(gp).second;
00290 }
00291 
00292 void Grammar::InsGrammarProductions(const std::set<GrammarProduction>& gp){
00293   std::set<GrammarProduction>::const_iterator gpit;
00294   for(gpit = gp.begin(); gpit != gp.end(); gpit++){
00295     InsGrammarProduction(*gpit);
00296   }
00297 }
00298 
00299 std::set<Terminal>::const_iterator Grammar::TerminalsBegin() const{
00300   return mTerminals.begin();
00301 }
00302 
00303 std::set<Terminal>::const_iterator Grammar::TerminalsEnd() const{
00304   return mTerminals.end();
00305 }
00306 
00307 std::set<Nonterminal>::const_iterator Grammar::NonterminalsBegin() const{
00308   return mNonterminals.begin();
00309 }
00310 
00311 std::set<Nonterminal>::const_iterator Grammar::NonterminalsEnd() const{
00312   return mNonterminals.end();
00313 }
00314 
00315 std::set<GrammarProduction>::const_iterator Grammar::GrammarProductionsBegin() const{
00316   return mGrammarProductions.begin();
00317 }
00318 
00319 std::set<GrammarProduction>::const_iterator Grammar::GrammarProductionsEnd() const{
00320   return mGrammarProductions.end();
00321 }
00322 
00323 std::string Grammar::StrTerminals() const{
00324   std::string s;
00325   std::set<Terminal>::const_iterator it;
00326   it = mTerminals.end();
00327   for(it = mTerminals.begin(); it != mTerminals.end(); it++){
00328     if(it == mTerminals.begin()) s+= it->Str();
00329     else s+= ", " + it->Str();
00330   }
00331   return s;
00332 }
00333 
00334 std::string Grammar::StrNonterminals() const{
00335   std::string s;
00336   std::set<Nonterminal>::const_iterator it;
00337   it = mNonterminals.end();
00338   for(it = mNonterminals.begin(); it != mNonterminals.end(); it++){
00339     if(it == mNonterminals.begin()) s+= it->Str();
00340     else s+= ", " + it->Str();
00341   }
00342   return s;
00343 }
00344 
00345 std::string Grammar::StrStartSymbol() const{
00346   return mStartSymbol.Str();
00347 }
00348 
00349 std::string Grammar::StrGrammarProductions() const{
00350   std::string s;
00351   std::set<GrammarProduction>::const_iterator it;
00352   it = mGrammarProductions.end();
00353   for(it = mGrammarProductions.begin(); it != mGrammarProductions.end(); it++){
00354     s+= "\n     " + it->Str();
00355   }
00356   return s;
00357 }
00358 
00359 std::string Grammar::Str() const{
00360   std::string s;
00361   
00362   s += "start symbol: " + StrStartSymbol() + "\n";
00363   s += "nonterminals: " + StrNonterminals() + "\n";
00364   s += "terminals: " + StrTerminals() + "\n";
00365   s += "grammar productions: " + StrGrammarProductions() + "\n";
00366   
00367   return s;
00368   
00369 }
00370 
00371 } // namespace faudes
00372 

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen