pd_alg_lrp_test.cpp

Go to the documentation of this file.
00001 /** @file pd_alg_lrp_test.cpp  Unit Tests */
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 #include "pd_alg_lrp_test.h"
00010 
00011 namespace faudes {
00012 
00013   
00014 /* *****************
00015  * TestGeneratorGotoOneSuccessor
00016  * *****************/
00017 void TestGeneratorGotoOneSuccessor(){
00018   std::string name = "GeneratorGoto One Successor";
00019   TestStart(name);
00020   
00021   Grammar gr = TestGrammar7();
00022   
00023   //create terminals
00024   Terminal* ta = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("a"));
00025   GrammarSymbolPtr ptrta(ta);
00026   Terminal* tb = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("b"));
00027   GrammarSymbolPtr ptrtb(tb);
00028   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00029   GrammarSymbolPtr ptrtdollar(tdollar);
00030   Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA));
00031   GrammarSymbolPtr ptrtlambda(tlambda);
00032   
00033   //create nonterminals
00034   std::vector<Idx> v;
00035   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00036   Nonterminal* nt1dot = new Nonterminal(1,v);
00037   GrammarSymbolPtr ptrnt1dot(nt1dot);
00038   
00039   v.clear();
00040   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
00041   Nonterminal* nt1square = new Nonterminal(1,v);
00042   GrammarSymbolPtr ptrnt1square(nt1square);
00043   
00044   //test with state ((1, [dot]) -> $(1, [square]) . $, lambda) and symbol $
00045   //    ((1, [dot]) -> $(1, [square])$ . lambda, lambda)
00046   GrammarSymbolVector beforeDot, afterDot;
00047   beforeDot.push_back(ptrtdollar);
00048   beforeDot.push_back(ptrnt1square);
00049   afterDot.push_back(ptrtdollar);
00050   Lr1Configuration config(*nt1dot, beforeDot, afterDot, *tlambda);
00051   
00052   std::set<Lr1Configuration> startState;
00053   startState.insert(config);
00054 
00055   beforeDot.clear();
00056   afterDot.clear();
00057   beforeDot.push_back(ptrtdollar);
00058   beforeDot.push_back(ptrnt1square);
00059   beforeDot.push_back(ptrtdollar);
00060   afterDot.push_back(ptrtlambda);
00061   Lr1Configuration expectedConfig(*nt1dot, beforeDot, afterDot, *tlambda);
00062   
00063   GotoGenerator gotoGen = Lrm(gr,1);
00064   std::set<Idx> successorStates = GeneratorGoto(gotoGen, gotoGen.StateIndex(startState), ptrtdollar);
00065   try{
00066     
00067     //size of successorStates must be one
00068     if(successorStates.size() != 1){
00069       std::stringstream errstr;
00070       errstr << "number of successor states was expected to be 1, but was " << successorStates.size() << "." << std::endl;
00071       throw Exception(name, errstr.str(), 1003);
00072     }
00073     
00074     //number of contained configurations must be one
00075     if(gotoGen.ConfigSet(*successorStates.begin()).size() != 1){
00076       std::stringstream errstr;
00077       errstr << "number of configurations in successor state " << *successorStates.begin() << " was expected to be 1, but was " << gotoGen.ConfigSet(*successorStates.begin()).size() << "." << std::endl;
00078       throw Exception(name, errstr.str(), 1003);
00079     }
00080     
00081     //the contained configuration must be expectedConfig
00082     if(*gotoGen.ConfigSet(*successorStates.begin()).begin() != expectedConfig){
00083       std::stringstream errstr;
00084       errstr << "configuration contained in successor state " << *successorStates.begin() << " was expected to be (" << expectedConfig.Str() << "), but was (" << gotoGen.ConfigSet(*successorStates.begin()).begin()->Str() << ")." << std::endl;
00085       throw Exception(name, errstr.str(), 1003);
00086     }  
00087   }
00088   catch (Exception e){ 
00089   }
00090   TestEnd(name);
00091 }
00092 
00093 /* *****************
00094  * TestGeneratorGotoNoSuccessor
00095  * *****************/
00096 void TestGeneratorGotoNoSuccessor(){
00097   std::string name = "GeneratorGoto No Successor";
00098   TestStart(name);
00099   
00100   Grammar gr = TestGrammar7();
00101   
00102   //create terminals
00103   Terminal* ta = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("a"));
00104   GrammarSymbolPtr ptrta(ta);
00105   Terminal* tb = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("b"));
00106   GrammarSymbolPtr ptrtb(tb);
00107   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00108   GrammarSymbolPtr ptrtdollar(tdollar);
00109   Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA));
00110   GrammarSymbolPtr ptrtlambda(tlambda);
00111   
00112   //create nonterminals
00113   std::vector<Idx> v;
00114   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00115   Nonterminal* nt1dot = new Nonterminal(1,v);
00116   GrammarSymbolPtr ptrnt1dot(nt1dot);
00117   
00118   v.clear();
00119   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
00120   Nonterminal* nt1square = new Nonterminal(1,v);
00121   GrammarSymbolPtr ptrnt1square(nt1square);
00122   
00123   //test with state ((1, [dot]) -> $(1, [square]) . $, $) and symbol $
00124   //    empty
00125   GrammarSymbolVector beforeDot, afterDot;
00126   beforeDot.push_back(ptrtdollar);
00127   beforeDot.push_back(ptrnt1square);
00128   afterDot.push_back(ptrtdollar);
00129   Lr1Configuration config(*nt1dot, beforeDot, afterDot, *tdollar);
00130   
00131   std::set<Lr1Configuration> startState;
00132   startState.insert(config);
00133   
00134   GotoGenerator gotoGen = Lrm(gr,1);
00135   
00136   std::set<Idx> successorStates = GeneratorGoto(gotoGen, gotoGen.StateIndex(startState), ptrtdollar);
00137   
00138   try{
00139     
00140     //size of successorStates must be zero
00141     if(successorStates.size() != 0){
00142       std::stringstream errstr;
00143       errstr << "number of successor states was expected to be 0, because state with configuration (" << config.Str() << ") does not exist , but was " << successorStates.size() << "." << std::endl;
00144       throw Exception(name, errstr.str(), 1003);
00145     }
00146   }
00147   catch (Exception e){ 
00148   }
00149   
00150   //test with state ((1, [dot]) -> $(1, [square]) . $, lambda) and symbol a
00151   //    empty
00152   beforeDot.clear();
00153   afterDot.clear();
00154   beforeDot.push_back(ptrtdollar);
00155   beforeDot.push_back(ptrnt1square);
00156   afterDot.push_back(ptrtdollar);
00157   Lr1Configuration config2(*nt1dot, beforeDot, afterDot, *tlambda);
00158   
00159   startState.clear();
00160   startState.insert(config2);
00161   
00162   successorStates = GeneratorGoto(gotoGen, gotoGen.StateIndex(startState), ptrta);
00163   
00164   try{
00165     
00166     //size of successorStates must be zero
00167     if(successorStates.size() != 0){
00168       std::stringstream errstr;
00169       errstr << "number of successor states was expected to be 0, because state with configuration (" << config2.Str() << ") and symbol a does not exist, but was " << successorStates.size() << "." << std::endl;
00170       throw Exception(name, errstr.str(), 1003);
00171     }
00172   }
00173   catch (Exception e){ 
00174   }
00175   TestEnd(name);
00176 }
00177 
00178 /* *****************
00179  * TestGeneratorGotoSeqFull
00180  * *****************/
00181 void TestGeneratorGotoSeqFull(){
00182   std::string name = "GeneratorGotoSeq Full";
00183   TestStart(name);
00184   
00185   Grammar gr = TestGrammar7();
00186   
00187   //create terminals
00188   Terminal* ta = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("a"));
00189   GrammarSymbolPtr ptrta(ta);
00190   Terminal* tb = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("b"));
00191   GrammarSymbolPtr ptrtb(tb);
00192   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00193   GrammarSymbolPtr ptrtdollar(tdollar);
00194   Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA));
00195   GrammarSymbolPtr ptrtlambda(tlambda);
00196   
00197   //create nonterminals
00198   std::vector<Idx> v;
00199   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00200   Nonterminal* nt1dot = new Nonterminal(1,v);
00201   GrammarSymbolPtr ptrnt1dot(nt1dot);
00202   
00203   v.clear();
00204   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
00205   Nonterminal* nt1square = new Nonterminal(1,v);
00206   GrammarSymbolPtr ptrnt1square(nt1square);
00207   
00208   //test with state ((1, [dot]) -> lambda . $(1, [square])$, lambda) and
00209   //word $a(1, [square])
00210   GrammarSymbolVector beforeDot, afterDot;
00211   beforeDot.push_back(ptrtlambda);
00212   afterDot.push_back(ptrtdollar);
00213   afterDot.push_back(ptrnt1square);
00214   afterDot.push_back(ptrtdollar);
00215   Lr1Configuration config(*nt1dot, beforeDot, afterDot, *tlambda);
00216   
00217   std::set<Lr1Configuration> startState;
00218   startState.insert(config);
00219   
00220   GrammarSymbolVector word;
00221   
00222   word.push_back(ptrtdollar);
00223   word.push_back(ptrta);
00224   word.push_back(ptrnt1square);
00225   
00226   //create expected last state of the sequence
00227   beforeDot.clear();
00228   afterDot.clear();
00229   beforeDot.push_back(ptrta);
00230   beforeDot.push_back(ptrnt1square);
00231   afterDot.push_back(ptrtlambda);
00232   Lr1Configuration expectedEndConfig(*nt1square, beforeDot, afterDot, *tdollar);
00233   
00234   GotoGenerator gotoGen = Lrm(gr,1);
00235   std::vector<Idx> stateSequence = GeneratorGotoSeq(gotoGen, gotoGen.StateIndex(startState), word);
00236 
00237   try{
00238     
00239     //size of stateSequence must be 3
00240     if(stateSequence.size() != 3){
00241       std::stringstream errstr;
00242       errstr << "number of successor states was expected to be 3, but was " << stateSequence.size() << "." << std::endl;
00243       throw Exception(name, errstr.str(), 1003);
00244     }
00245     
00246     //number of contained configurations in the last state must be 1
00247     if(gotoGen.ConfigSet(stateSequence.back()).size() != 1){
00248       std::stringstream errstr;
00249       errstr << "number of configurations in the last state of the sequence was expected to be 1, but was " << gotoGen.ConfigSet(stateSequence.back()).size() << "." << std::endl;
00250       throw Exception(name, errstr.str(), 1003);
00251     }
00252     
00253     //the last configuration in the sequence must be expectedEndConfig
00254     if(*gotoGen.ConfigSet(stateSequence.back()).begin() != expectedEndConfig){
00255       std::stringstream errstr;
00256       errstr << "state at the end of the sequence was expected to contain the configuration (" << expectedEndConfig.Str() << "), but was (" << gotoGen.ConfigSet(stateSequence.back()).begin()->Str() << ")." << std::endl;
00257       throw Exception(name, errstr.str(), 1003);
00258     }  
00259   }
00260   catch (Exception e){ 
00261   }
00262   TestEnd(name);
00263 }
00264 
00265 /* *****************
00266  * TestGeneratorGotoSeqPartial
00267  * *****************/
00268 void TestGeneratorGotoSeqPartial(){
00269   std::string name = "GeneratorGotoSeq Partial";
00270   TestStart(name);
00271   
00272   Grammar gr = TestGrammar7();
00273   
00274   //create terminals
00275   Terminal* ta = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("a"));
00276   GrammarSymbolPtr ptrta(ta);
00277   Terminal* tb = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("b"));
00278   GrammarSymbolPtr ptrtb(tb);
00279   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00280   GrammarSymbolPtr ptrtdollar(tdollar);
00281   Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA));
00282   GrammarSymbolPtr ptrtlambda(tlambda);
00283   
00284   //create nonterminals
00285   std::vector<Idx> v;
00286   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00287   Nonterminal* nt1dot = new Nonterminal(1,v);
00288   GrammarSymbolPtr ptrnt1dot(nt1dot);
00289   
00290   v.clear();
00291   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
00292   Nonterminal* nt1square = new Nonterminal(1,v);
00293   GrammarSymbolPtr ptrnt1square(nt1square);
00294   
00295   //test with state ((1, [dot]) -> lambda . $(1, [square])$, lambda) and
00296   //word $b$
00297   GrammarSymbolVector beforeDot, afterDot;
00298   beforeDot.push_back(ptrtlambda);
00299   afterDot.push_back(ptrtdollar);
00300   afterDot.push_back(ptrnt1square);
00301   afterDot.push_back(ptrtdollar);
00302   Lr1Configuration config(*nt1dot, beforeDot, afterDot, *tlambda);
00303   
00304   std::set<Lr1Configuration> startState;
00305   startState.insert(config);
00306   
00307   GrammarSymbolVector word;
00308   
00309   word.push_back(ptrtdollar);
00310   word.push_back(ptrtb);
00311   word.push_back(ptrtdollar);
00312   
00313   //create expected last state of the sequence
00314   beforeDot.clear();
00315   afterDot.clear();
00316   beforeDot.push_back(ptrtb);
00317   afterDot.push_back(ptrtlambda);
00318   Lr1Configuration expectedEndConfig(*nt1square, beforeDot, afterDot, *tdollar);
00319   
00320   GotoGenerator gotoGen = Lrm(gr,1);
00321   std::vector<Idx> stateSequence = GeneratorGotoSeq(gotoGen, gotoGen.StateIndex(startState), word);
00322 
00323   try{
00324     
00325     //size of stateSequence must be 2
00326     if(stateSequence.size() != 2){
00327       std::stringstream errstr;
00328       errstr << "number of successor states was expected to be 2, but was " << stateSequence.size() << "." << std::endl;
00329       throw Exception(name, errstr.str(), 1003);
00330     }
00331     
00332     //number of contained configurations in the last state must be 1
00333     if(gotoGen.ConfigSet(stateSequence.back()).size() != 1){
00334       std::stringstream errstr;
00335       errstr << "number of configurations in the last state of the sequence was expected to be 1, but was " << gotoGen.ConfigSet(stateSequence.back()).size() << "." << std::endl;
00336       throw Exception(name, errstr.str(), 1003);
00337     }
00338     
00339     //the last configuration in the sequence must be expectedEndConfig
00340     if(*gotoGen.ConfigSet(stateSequence.back()).begin() != expectedEndConfig){
00341       std::stringstream errstr;
00342       errstr << "state at the end of the sequence was expected to contain the configuration (" << expectedEndConfig.Str() << "), but was (" << gotoGen.ConfigSet(stateSequence.back()).begin()->Str() << ")." << std::endl;
00343       throw Exception(name, errstr.str(), 1003);
00344     }  
00345   }
00346   catch (Exception e){ 
00347   }
00348   TestEnd(name);
00349 }
00350 
00351 /* *****************
00352  * TestLrpShiftRulesNumberAndTerminals
00353  * *****************/
00354 void TestLrpShiftRulesNumberAndTerminals(){
00355   std::string name = "LrpShiftRules Number And Terminals";
00356   TestStart(name);
00357   
00358   Grammar gr = TestGrammar9();
00359   
00360   //create terminals
00361   Terminal* ta = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("a"));
00362   GrammarSymbolPtr ptrta(ta);
00363   Terminal* tb = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("b"));
00364   GrammarSymbolPtr ptrtb(tb);
00365   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00366   GrammarSymbolPtr ptrtdollar(tdollar);
00367   Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA));
00368   GrammarSymbolPtr ptrtlambda(tlambda);
00369   
00370   //create nonterminals
00371   std::vector<Idx> v;
00372   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00373   Nonterminal* nt1dot = new Nonterminal(1,v);
00374   GrammarSymbolPtr ptrnt1dot(nt1dot);
00375   
00376   v.clear();
00377   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
00378   Nonterminal* nt1square = new Nonterminal(1,v);
00379   GrammarSymbolPtr ptrnt1square(nt1square);
00380   
00381   Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
00382   
00383   GotoGenerator gotoGen = Lrm(augGr, 1);
00384   std::set<Lr1ParserAction> actions = LrpShiftRules(gr, augGr, gotoGen, 1);
00385 
00386   try{
00387     
00388     //number of found actions must be 4
00389     if(actions.size() != 4){
00390       std::stringstream errstr;
00391       errstr << "number of shift actions was expected to be 4, but was " << actions.size() << "." << std::endl;
00392       throw Exception(name, errstr.str(), 1003);
00393     } 
00394     //there must be 2 actions that reduce with terminal a
00395     int i = 0;
00396     std::set<Lr1ParserAction>::const_iterator pait;
00397     for(pait = actions.begin(); pait != actions.end(); pait++){
00398       if(pait->Lhs().NextTerminal() == *ta){
00399         i++;
00400       }
00401     }
00402     if(i != 2){
00403       std::stringstream errstr;
00404       errstr << "number of shift actions for symbol a of the form (x | a) -> (xy | lambda) was expected to be 2, but was " << i << "." << std::endl;
00405       throw Exception(name, errstr.str(), 1003);
00406     }
00407     
00408     //there must be 2 actions that reduce with terminal b
00409     i = 0;
00410     for(pait = actions.begin(); pait != actions.end(); pait++){
00411       if(pait->Lhs().NextTerminal() == *tb){
00412         i++;
00413       }
00414     }
00415     if(i != 2){
00416       std::stringstream errstr;
00417       errstr << "number of shift actions for symbol b of the form (x | b) -> (xy | lambda) was expected to be 2, but was " << i << "." << std::endl;
00418       throw Exception(name, errstr.str(), 1003);
00419     }
00420   }
00421   catch (Exception e){ 
00422   }
00423   TestEnd(name);
00424 }
00425 
00426 /* *****************
00427  * TestLrpReduceRulesNumberAndTerminals
00428  * *****************/
00429 void TestLrpReduceRulesNumberAndTerminals(){
00430   std::string name = "LrpReduceRules Number And Terminals";
00431   TestStart(name);
00432   
00433   Grammar gr = TestGrammar9();
00434   
00435   //create terminals
00436   Terminal* ta = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("a"));
00437   GrammarSymbolPtr ptrta(ta);
00438   Terminal* tb = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("b"));
00439   GrammarSymbolPtr ptrtb(tb);
00440   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00441   GrammarSymbolPtr ptrtdollar(tdollar);
00442   Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA));
00443   GrammarSymbolPtr ptrtlambda(tlambda);
00444   
00445   //create nonterminals
00446   std::vector<Idx> v;
00447   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00448   Nonterminal* nt1dot = new Nonterminal(1,v);
00449   GrammarSymbolPtr ptrnt1dot(nt1dot);
00450   
00451   v.clear();
00452   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
00453   Nonterminal* nt1square = new Nonterminal(1,v);
00454   GrammarSymbolPtr ptrnt1square(nt1square);
00455   
00456   Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
00457   
00458   GotoGenerator gotoGen = Lrm(augGr, 1);
00459   std::set<Lr1ParserAction> actions = LrpReduceRules(gr, augGr, gotoGen, 1);
00460 
00461   try{
00462     
00463     //number of found actions must be 4
00464     if(actions.size() != 4){
00465       std::stringstream errstr;
00466       errstr << "number of shift actions was expected to be 4, but was " << actions.size() << "." << std::endl;
00467       throw Exception(name, errstr.str(), 1003);
00468     } 
00469     //there must be 4 actions that shift with terminal $
00470     int i = 0;
00471     std::set<Lr1ParserAction>::const_iterator pait;
00472     for(pait = actions.begin(); pait != actions.end(); pait++){
00473       if(pait->Lhs().NextTerminal() == *tdollar && pait->Rhs().NextTerminal() == *tdollar){
00474         i++;
00475       }
00476     }
00477     if(i != 4){
00478       std::stringstream errstr;
00479       errstr << "number of shift actions for symbol a of the form (x | $) -> (xy | $) was expected to be 4, but was " << i << "." << std::endl;
00480       throw Exception(name, errstr.str(), 1003);
00481     }
00482   }
00483   catch (Exception e){ 
00484   }
00485   TestEnd(name);
00486 }
00487 
00488 /* *****************
00489  * TestLrpActions
00490  * *****************/
00491 void TestLrpActions(){
00492   std::string name = "Lrp Actions";
00493   TestStart(name);
00494   
00495   Grammar gr = TestGrammar9();
00496   
00497   //create terminals
00498   Terminal* ta = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("a"));
00499   GrammarSymbolPtr ptrta(ta);
00500   Terminal* tb = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("b"));
00501   GrammarSymbolPtr ptrtb(tb);
00502   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00503   GrammarSymbolPtr ptrtdollar(tdollar);
00504   Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA));
00505   GrammarSymbolPtr ptrtlambda(tlambda);
00506   
00507   //create nonterminals
00508   std::vector<Idx> v;
00509   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00510   Nonterminal* nt1dot = new Nonterminal(1,v);
00511   GrammarSymbolPtr ptrnt1dot(nt1dot);
00512   
00513   v.clear();
00514   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
00515   Nonterminal* nt1square = new Nonterminal(1,v);
00516   GrammarSymbolPtr ptrnt1square(nt1square);
00517   
00518   Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
00519   
00520   GotoGenerator gotoGen = Lrm(augGr, 1);
00521   Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
00522   
00523   try{
00524     
00525     //number of found actions must be 8
00526     std::set<Lr1ParserAction> actions = parser.Actions();
00527     if(actions.size() != 8){
00528       std::stringstream errstr;
00529       errstr << "number of actions was expected to be 8, but was " << actions.size() << "." << std::endl;
00530       throw Exception(name, errstr.str(), 1003);
00531     } 
00532     //there must be 4 actions with terminal $ and $on the left-hand and right-hand side,
00533     //2 with a and lambda, and 2 with b and lambda
00534     int dollarCount = 0;
00535     int aCount = 0;
00536     int bCount = 0;
00537     std::set<Lr1ParserAction>::const_iterator pait;
00538     for(pait = actions.begin(); pait != actions.end(); pait++){
00539       if(pait->Lhs().NextTerminal() == *tdollar && pait->Rhs().NextTerminal() == *tdollar){
00540         dollarCount++;
00541       }
00542       if(pait->Lhs().NextTerminal() == *ta && pait->Rhs().NextTerminal() == *tlambda){
00543         aCount++;
00544       }
00545       if(pait->Lhs().NextTerminal() == *tb && pait->Rhs().NextTerminal() == *tlambda){
00546         bCount++;
00547       }
00548     }
00549     if(dollarCount != 4){
00550       std::stringstream errstr;
00551       errstr << "number of actions for symbol $ of the form (x | $) -> (xy | $) was expected to be 4, but was " << dollarCount << "." << std::endl;
00552       throw Exception(name, errstr.str(), 1003);
00553     }
00554     if(aCount != 2){
00555       std::stringstream errstr;
00556       errstr << "number of actions for symbol a of the form (x | a) -> (xy | lambda) was expected to be 2, but was " << aCount << "." << std::endl;
00557       throw Exception(name, errstr.str(), 1003);
00558     }
00559     if(bCount != 2){
00560       std::stringstream errstr;
00561       errstr << "number of actions for symbol b of the form (x | b) -> (xy | $) was expected to be 2, but was " << bCount << "." << std::endl;
00562       throw Exception(name, errstr.str(), 1003);
00563     }
00564   }
00565   catch (Exception e){ 
00566   }
00567   TestEnd(name);
00568 }
00569 
00570 /* *****************
00571  * TestLrpNonterminalsTerminals
00572  * *****************/
00573 void TestLrpNonterminalsTerminals(){
00574   std::string name = "Lrp Nonterminals Terminals";
00575   TestStart(name);
00576   
00577   Grammar gr = TestGrammar9();
00578   
00579   //create terminals
00580   Terminal* ta = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("a"));
00581   GrammarSymbolPtr ptrta(ta);
00582   Terminal* tb = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("b"));
00583   GrammarSymbolPtr ptrtb(tb);
00584   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00585   GrammarSymbolPtr ptrtdollar(tdollar);
00586   Terminal* tlambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA));
00587   GrammarSymbolPtr ptrtlambda(tlambda);
00588   
00589   //create nonterminals
00590   std::vector<Idx> v;
00591   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00592   Nonterminal* nt1dot = new Nonterminal(1,v);
00593   GrammarSymbolPtr ptrnt1dot(nt1dot);
00594   
00595   v.clear();
00596   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
00597   Nonterminal* nt1square = new Nonterminal(1,v);
00598   GrammarSymbolPtr ptrnt1square(nt1square);
00599   
00600   Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
00601   
00602   GotoGenerator gotoGen = Lrm(augGr, 1);
00603   Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
00604   
00605   try{
00606     
00607     //number of Nonterminals must be 5
00608     std::set<Idx> nonterminals = parser.Nonterminals();
00609     if(nonterminals.size() != 5){
00610       std::stringstream errstr;
00611       errstr << "number of nonterminals was expected to be 5, but was " << nonterminals.size() << "." << std::endl;
00612       throw Exception(name, errstr.str(), 1003);
00613     }
00614     
00615     //number of Terminals must be 4
00616     std::set<Terminal> terminals = parser.Terminals();
00617     if(terminals.size() != 4){
00618       std::stringstream errstr;
00619       errstr << "number of terminals was expected to be 4, but was " << terminals.size() << "." << std::endl;
00620       throw Exception(name, errstr.str(), 1003);
00621     }
00622     
00623     //the augment symbol must be $
00624     if(parser.AugSymbol() != *tdollar){
00625       std::stringstream errstr;
00626       errstr << "the parser's augment symbol was expected to be " << tdollar->Str() << ", but was " << parser.AugSymbol().Str() << "." << std::endl;
00627       throw Exception(name, errstr.str(), 1003);
00628     }
00629   }
00630   catch (Exception e){ 
00631   }
00632   TestEnd(name);
00633 }
00634 
00635 /* *****************
00636  * TestGp2PpStates
00637  * *****************/
00638 void TestGp2PpStates(){
00639   std::string name = "Gp2Pp States";
00640   TestStart(name);
00641   
00642   Grammar gr = TestGrammar9();
00643   
00644   //create terminals
00645   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00646   GrammarSymbolPtr ptrtdollar(tdollar);
00647 
00648   //get event indices
00649   Idx aIdx = PushdownGenerator::GlobalEventSymbolTablep()->Index("a");
00650   Idx bIdx = PushdownGenerator::GlobalEventSymbolTablep()->Index("b");
00651   Idx lambdaIdx = PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA);
00652   Idx dollarIdx = PushdownGenerator::GlobalEventSymbolTablep()->Index("$");
00653   
00654   //create state event pairs that are expected to be used in the generator
00655   std::vector<MergeStateEvent> sePairs;
00656   std::vector<MergeStateEvent>::iterator sePairsit;
00657   sePairs.push_back(MergeStateEvent(6,lambdaIdx));
00658   sePairs.push_back(MergeStateEvent(6,aIdx));
00659   sePairs.push_back(MergeStateEvent(6,bIdx));
00660   sePairs.push_back(MergeStateEvent(7,lambdaIdx));
00661   sePairs.push_back(MergeStateEvent(7,aIdx));
00662   sePairs.push_back(MergeStateEvent(7,bIdx));
00663   sePairs.push_back(MergeStateEvent(4,lambdaIdx));
00664   sePairs.push_back(MergeStateEvent(5,lambdaIdx));
00665   sePairs.push_back(MergeStateEvent(2,dollarIdx));
00666   sePairs.push_back(MergeStateEvent(4,dollarIdx));
00667   sePairs.push_back(MergeStateEvent(5,dollarIdx));
00668   
00669   //create nonterminals
00670   std::vector<Idx> v;
00671   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00672   Nonterminal* nt1dot = new Nonterminal(1,v);
00673   GrammarSymbolPtr ptrnt1dot(nt1dot);
00674   
00675   //create pushdown generator
00676   Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
00677   
00678   GotoGenerator gotoGen = Lrm(augGr, 1);
00679   Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
00680 
00681   PushdownGenerator pd = Gp2Pp(gotoGen, parser);
00682 
00683   try{
00684     
00685     //number of states must be 20
00686     if(pd.Size() != 20){
00687       std::stringstream errstr;
00688       errstr << "number of states was expected to be 20, but was " << pd.Size() << "." << std::endl;
00689       throw Exception(name, errstr.str(), 1003);
00690     }
00691     
00692     //get the states that are actually used
00693     StateSet states;
00694     TransSet::Iterator transit;
00695     for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
00696       states.Insert(transit->X1);
00697       states.Insert(transit->X2);
00698     }
00699     //number of used states must be 11
00700     if(states.Size() != 11){
00701       std::stringstream errstr;
00702       errstr << "number of used states was expected to be 11, but was " << states.Size() << "." << std::endl;
00703       throw Exception(name, errstr.str(), 1003);
00704     }
00705     //test whether the used states are the expected ones
00706     StateSet::Iterator stateit;
00707     for(stateit = states.Begin(); stateit != states.End(); stateit++){
00708       
00709       //get MergeStateEvent
00710       const MergeStateEvent* mse = dynamic_cast<const MergeStateEvent*>(pd.StateAttribute(*stateit).Merge());
00711       if(mse == NULL){
00712         throw Exception(name, "MergeStateEvent not set.", 1003);
00713       }
00714       
00715       //test for existence in expected merge state events
00716       bool found = false;
00717       for(sePairsit = sePairs.begin(); sePairsit != sePairs.end(); sePairsit++){
00718         if(sePairsit->State() == mse->State() && sePairsit->Event() == mse->Event()){
00719           found = true;
00720           break;
00721         }
00722       }
00723       
00724       if(!found){
00725         std::stringstream errstr;
00726         errstr << "state with MergeStateEvent (" << mse->State() << ", " << PushdownGenerator::GlobalEventSymbolTablep()->Symbol(mse->Event()) << ") was not expected to be in the set of used states." << std::endl;
00727         throw Exception(name, errstr.str(), 1003);
00728       }
00729     }
00730     
00731   }
00732   catch (Exception e){ 
00733   }
00734   TestEnd(name);
00735 }
00736 
00737 /* *****************
00738  * TestGp2PpTransitions
00739  * *****************/
00740 void TestGp2PpTransitions(){
00741   std::string name = "Gp2Pp Transitions";
00742   TestStart(name);
00743   
00744   Grammar gr = TestGrammar9();
00745   
00746   //create terminals
00747   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00748   GrammarSymbolPtr ptrtdollar(tdollar);
00749 
00750   //get event indices
00751   Idx aIdx = PushdownGenerator::GlobalEventSymbolTablep()->Index("a");
00752   Idx bIdx = PushdownGenerator::GlobalEventSymbolTablep()->Index("b");
00753   Idx lambdaIdx = PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA);
00754   Idx dollarIdx = PushdownGenerator::GlobalEventSymbolTablep()->Index("$");
00755   
00756   //create nonterminals
00757   std::vector<Idx> v;
00758   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00759   Nonterminal* nt1dot = new Nonterminal(1,v);
00760   GrammarSymbolPtr ptrnt1dot(nt1dot);
00761   
00762   //create pushdown generator
00763   Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
00764   
00765   GotoGenerator gotoGen = Lrm(augGr, 1);
00766   Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
00767 
00768   PushdownGenerator pd = Gp2Pp(gotoGen, parser);
00769 
00770   try{
00771     
00772     
00773     
00774     int transCount = 0;
00775     int aCount = 0;
00776     int bCount = 0;
00777     int dollarCount = 0;
00778     int lambdaCount = 0;
00779     int push6Count = 0;
00780     int push7Count = 0;
00781     int popLambdaCount = 0;
00782     int popSize1 = 0;
00783     int popSize2 = 0;
00784     TransSet::Iterator transit;
00785     for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
00786       
00787       //count events
00788       if(transit->Ev == aIdx)
00789         aCount++;
00790       else if(transit->Ev == bIdx)
00791         bCount++;
00792       else if(transit->Ev == lambdaIdx)
00793         lambdaCount++;
00794       else if(transit->Ev == dollarIdx)
00795         dollarCount++;
00796       
00797       
00798       PopPushSet popPush = pd.PopPush(*transit);
00799       PopPushSet::const_iterator ppit;
00800       for(ppit = popPush.begin(); ppit != popPush.end(); ppit++){
00801         //count transitions
00802         transCount++;
00803         
00804         //count pops
00805         if(ppit->first.size() == 2)
00806           popSize2++;
00807         else if(ppit->first.size() == 1){
00808           popSize1++;
00809           if(ppit->first.front() == pd.StackSymbolIndex(FAUDES_PD_LAMBDA))
00810             popLambdaCount++;
00811         }
00812         
00813         //count pushes
00814         if(ppit->second.size() == 1){
00815           if(ppit->second.front() == pd.StackSymbolIndex("6"))
00816             push6Count++;
00817           else if(ppit->second.front() == pd.StackSymbolIndex("7"))
00818             push7Count++;
00819         }
00820         
00821       }
00822     }
00823     
00824     //number of transitions must be 16
00825     if(transCount != 16){
00826       std::stringstream errstr;
00827       errstr << "number of transitions was expected to be 16, but was " << transCount << "." << std::endl;
00828       throw Exception(name, errstr.str(), 1003);
00829     }
00830     //number of a events must be 2
00831     if(aCount != 2){
00832       std::stringstream errstr;
00833       errstr << "number of transitions with the event a was expected to be 2, but was " << aCount << "." << std::endl;
00834       throw Exception(name, errstr.str(), 1003);
00835     }
00836     //number of b events must be 2
00837     if(bCount != 2){
00838       std::stringstream errstr;
00839       errstr << "number of transitions with the event b was expected to be 2, but was " << bCount << "." << std::endl;
00840       throw Exception(name, errstr.str(), 1003);
00841     }
00842     //number of $ events must be 4
00843     if(dollarCount != 4){
00844       std::stringstream errstr;
00845       errstr << "number of transitions with the event $ was expected to be 4, but was " << dollarCount << "." << std::endl;
00846       throw Exception(name, errstr.str(), 1003);
00847     }
00848     //number of lambda events must be 8
00849     if(lambdaCount != 8){
00850       std::stringstream errstr;
00851       errstr << "number of transitions with the event lambda was expected to be 8, but was " << lambdaCount << "." << std::endl;
00852       throw Exception(name, errstr.str(), 1003);
00853     }
00854     //number of 6 pushes must be 8
00855     if(push6Count != 8){
00856       std::stringstream errstr;
00857       errstr << "number of transitions that push 6 was expected to be 8, but was " << push6Count << "." << std::endl;
00858       throw Exception(name, errstr.str(), 1003);
00859     }
00860     //number of 7 pushes must be 8
00861     if(push7Count != 8){
00862       std::stringstream errstr;
00863       errstr << "number of transitions that push 7 was expected to be 8, but was " << push7Count << "." << std::endl;
00864       throw Exception(name, errstr.str(), 1003);
00865     }
00866     //number of transitions that pop 2 stack symbols must be 4
00867     if(popSize2 != 4){
00868       std::stringstream errstr;
00869       errstr << "number of transitions that pop 2 stack symbols was expected to be 4, but was " << popSize2 << "." << std::endl;
00870       throw Exception(name, errstr.str(), 1003);
00871     }
00872     //number of transitions that pop 1 stack symbol must be 12
00873     if(popSize1 != 12){
00874       std::stringstream errstr;
00875       errstr << "number of transitions that pop 1 stack symbol was expected to be 12, but was " << popSize1 << "." << std::endl;
00876       throw Exception(name, errstr.str(), 1003);
00877     }
00878     //number of transitions that pop lambda must be 8
00879     if(popLambdaCount != 8){
00880       std::stringstream errstr;
00881       errstr << "number of transitions that pop lambda was expected to be 8, but was " << popLambdaCount << "." << std::endl;
00882       throw Exception(name, errstr.str(), 1003);
00883     }
00884   }
00885   catch (Exception e){ 
00886   }
00887   TestEnd(name);
00888 }
00889 
00890 /* *****************
00891  * TestDimNoAugment
00892  * *****************/
00893 void TestDimNoAugment(){
00894   std::string name = "Dim No Augment";
00895   TestStart(name);
00896   
00897   Grammar gr = TestGrammar9();
00898   
00899   //create terminals
00900   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00901   GrammarSymbolPtr ptrtdollar(tdollar);
00902 
00903   //get event indices
00904   Idx dollarIdx = PushdownGenerator::GlobalEventSymbolTablep()->Index("$");
00905   
00906   //create nonterminals
00907   std::vector<Idx> v;
00908   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00909   Nonterminal* nt1dot = new Nonterminal(1,v);
00910   GrammarSymbolPtr ptrnt1dot(nt1dot);
00911   
00912   //create pushdown generator and diminish it
00913   Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
00914   
00915   GotoGenerator gotoGen = Lrm(augGr, 1);
00916   Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
00917 
00918   PushdownGenerator pdtemp = Gp2Pp(gotoGen, parser);
00919   PushdownGenerator pd = Dim(pdtemp,*tdollar);
00920   
00921   try{
00922     
00923     int transCount = 0;
00924     Transition trans;
00925     bool dollarFound = false;
00926     TransSet::Iterator transit;
00927     for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){  
00928       PopPushSet popPush = pd.PopPush(*transit);
00929       PopPushSet::const_iterator ppit;
00930       
00931       //count transitions
00932       for(ppit = popPush.begin(); ppit != popPush.end(); ppit++){
00933         transCount++;
00934       }
00935       
00936       //look for transitions with $
00937       if(transit->Ev == dollarIdx){
00938         dollarFound = true;
00939         trans = *transit;
00940       }
00941     }
00942     
00943     //number of transitions must be 12
00944     if(transCount != 12){
00945       std::stringstream errstr;
00946       errstr << "number of transitions was expected to be 12, but was " << transCount << "." << std::endl;
00947       throw Exception(name, errstr.str(), 1003);
00948     }
00949     
00950     //no $ event must be found
00951     if(dollarFound){
00952       std::stringstream errstr;
00953       errstr << "transition "<< trans.Str() << " with event $ was found, but not expected." << std::endl;
00954       throw Exception(name, errstr.str(), 1003);
00955     }
00956 
00957   }
00958   catch (Exception e){ 
00959   }
00960   TestEnd(name);
00961 }
00962 
00963 /* *****************
00964  * TestDimNewFinalStates
00965  * *****************/
00966 void TestDimNewFinalStates(){
00967   std::string name = "Dim Final States";
00968   TestStart(name);
00969   
00970   Grammar gr = TestGrammar9();
00971   
00972   //create terminals
00973   Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
00974   GrammarSymbolPtr ptrtdollar(tdollar);
00975 
00976   //get event indices
00977   Idx dollarIdx = PushdownGenerator::GlobalEventSymbolTablep()->Index("$");
00978   
00979   //create nonterminals
00980   std::vector<Idx> v;
00981   v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
00982   Nonterminal* nt1dot = new Nonterminal(1,v);
00983   GrammarSymbolPtr ptrnt1dot(nt1dot);
00984   
00985   //create pushdown generator
00986   Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
00987   
00988   GotoGenerator gotoGen = Lrm(augGr, 1);
00989   Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
00990 
00991   PushdownGenerator pdtemp = Gp2Pp(gotoGen, parser);
00992   
00993   //get indices of states that must be made final after diminishing
00994   TransSet::Iterator transit;
00995   StateSet expectedFinalStates;
00996   for(transit = pdtemp.TransRelBegin(); transit != pdtemp.TransRelEnd(); transit++){
00997     if(transit->Ev == dollarIdx){
00998       expectedFinalStates.Insert(transit->X1);
00999     }
01000   }
01001   
01002   //diminish pushdown generator
01003   PushdownGenerator pd = Dim(pdtemp,*tdollar);
01004   
01005   try{
01006     
01007     StateSet::Iterator stateit;
01008     //test for final states
01009     for(stateit = expectedFinalStates.Begin(); stateit != expectedFinalStates.End(); stateit++){
01010       if(!pd.ExistsMarkedState(*stateit)){
01011         std::stringstream errstr;
01012         errstr << "state " << *stateit << " was expected to be a final state, but was not." << std::endl;
01013         throw Exception(name, errstr.str(), 1003);
01014       }
01015     }
01016   }
01017   catch (Exception e){ 
01018   }
01019   TestEnd(name);
01020 }
01021 
01022 /* *****************
01023  * TestGeneratorGoto
01024  * *****************/
01025 void TestGeneratorGoto(){
01026   TestGeneratorGotoNoSuccessor();
01027   TestGeneratorGotoOneSuccessor();
01028 }
01029 
01030 /* *****************
01031  * TestGeneratorGotoSeq
01032  * *****************/
01033 void TestGeneratorGotoSeq(){
01034   TestGeneratorGotoSeqFull();
01035   TestGeneratorGotoSeqPartial();
01036 }
01037 
01038 /* *****************
01039  * TestLrpShiftRules
01040  * *****************/
01041 void TestLrpShiftRules(){
01042   TestLrpShiftRulesNumberAndTerminals();
01043 }
01044 
01045 /* *****************
01046  * TestLrpReduceRules
01047  * *****************/
01048 void TestLrpReduceRules(){
01049   TestLrpReduceRulesNumberAndTerminals();
01050 }
01051 
01052 /* *****************
01053  * TestLrp
01054  * *****************/
01055 void TestLrp(){
01056   TestLrpActions();
01057   TestLrpNonterminalsTerminals();
01058 }
01059 
01060 /* *****************
01061  * TestGp2Pp
01062  * *****************/
01063 void TestGp2Pp(){
01064   
01065   TestGp2PpTransitions();
01066   TestGp2PpStates();
01067 }
01068 
01069 /* *****************
01070  * TestDim
01071  * *****************/
01072 void TestDim(){
01073   TestDimNoAugment(); 
01074   TestDimNewFinalStates();
01075 }
01076   
01077 } // namespace faudes
01078 

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