pd_alg_lrp_test.cppGo 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 |