pd_alg_lrp.cppGo to the documentation of this file.00001 /** @file pd_alg_lrp.cpp functions related to parsers*/ 00002 00003 00004 /* Pushdown plugin for FAU Discrete Event Systems Library (libfaudes) 00005 00006 Copyright (C) 2013 Stefan Jacobi, Sven Schneider, Anne-Kathrin Hess 00007 00008 */ 00009 00010 #include "pd_alg_lrp.h" 00011 00012 namespace faudes { 00013 00014 00015 /* ************************* 00016 * MachineGoto 00017 * *************************/ 00018 std::set<Idx> GeneratorGoto(const GotoGenerator& gotoGen, Idx state, const GrammarSymbolPtr& symbol){ 00019 00020 //state set to return 00021 std::set<Idx> successorStates; 00022 00023 TransSet::Iterator transit; 00024 //iterate over all states with state as a start state 00025 for(transit = gotoGen.TransRelBegin(state); transit != gotoGen.TransRelEnd(state); transit++){ 00026 00027 //if the symbol is the same, insert end state of the transition as successor state 00028 if(*gotoGen.Symbol(*transit) == *symbol){ 00029 successorStates.insert(transit->X2); 00030 } 00031 } 00032 return successorStates; 00033 } 00034 00035 00036 /* ************************* 00037 * GeneratorGotoSeq 00038 * *************************/ 00039 std::vector<Idx> GeneratorGotoSeq(const GotoGenerator& gotoGen, Idx startState, const GrammarSymbolVector& word){ 00040 00041 //state sequence to return 00042 std::vector<Idx> rStateSequence; 00043 00044 //for later use 00045 Terminal* lambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA)); 00046 GrammarSymbolPtr lambdaPtr(lambda); 00047 00048 00049 //if the word is not empty (or does not contain lambda), it is of the form w = a.w' 00050 if(!word.empty()){ 00051 if(*word.front() != *lambda){ 00052 00053 //get front symbol a and remaining word w' 00054 GrammarSymbolPtr frontSymbol = word.front(); 00055 GrammarSymbolVector remainingWord(word.begin() + 1, word.end()); 00056 00057 //get next state in the sequence 00058 std::set<Idx> nextStateSet = GeneratorGoto(gotoGen, startState, frontSymbol); 00059 Idx nextState; 00060 if(!nextStateSet.empty()){ 00061 nextState = *nextStateSet.begin(); 00062 00063 //append the next state in the sequence 00064 rStateSequence.push_back(nextState); 00065 } 00066 00067 //get the rest of the sequence 00068 std::vector<Idx> remainingSequence = GeneratorGotoSeq(gotoGen, nextState, remainingWord); 00069 00070 //append the rest of the sequence 00071 rStateSequence.insert(rStateSequence.end(), remainingSequence.begin(), remainingSequence.end()); 00072 } 00073 } 00074 return rStateSequence; 00075 } 00076 00077 /* ************************* 00078 * LrpShiftRules 00079 * *************************/ 00080 std::set<Lr1ParserAction> LrpShiftRules(const Grammar& gr, const Grammar& augGr, const GotoGenerator& gotoGen, uint k){ 00081 00082 //parser actions to return 00083 std::set<Lr1ParserAction> rActions; 00084 00085 //lambda terminal for later use 00086 Terminal* lambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA)); 00087 GrammarSymbolPtr lambdaPtr(lambda); 00088 00089 StateSet::Iterator stateit; 00090 //iterate over all states q of the gotoGenerator 00091 for(stateit = gotoGen.StatesBegin(); stateit != gotoGen.StatesEnd(); stateit++){ 00092 00093 std::set<Terminal>::const_iterator tit; 00094 //iterate over all terminals a of the grammar 00095 for(tit = gr.TerminalsBegin(); tit != gr.TerminalsEnd(); tit++){ 00096 00097 //do not care for lambda 00098 if(tit->IsLambda()){ 00099 continue; 00100 } 00101 00102 //convert terminal into GrammarSymbolPtr 00103 Terminal* a = new Terminal(*tit); 00104 GrammarSymbolPtr aPtr(a); 00105 00106 //get the successor state q' for this terminal 00107 std::set<Idx> succStateSet = GeneratorGoto(gotoGen, *stateit, aPtr); 00108 00109 //continue, if there is no successor state (there can't be too many since gotoGen 00110 //is supposed to be deterministic) 00111 if(succStateSet.size() != 1){ 00112 continue; 00113 } 00114 00115 //extract the successor state 00116 Idx succState = *succStateSet.begin(); 00117 00118 std::set<Lr1Configuration>::const_iterator configit; 00119 //iterate over all configurations contained in the successor state 00120 for(configit = gotoGen.ConfigSet(*stateit).begin(); configit != gotoGen.ConfigSet(*stateit).end(); configit++){ 00121 00122 //only consider this configuration (A -> w1 . a w2, z) if the 00123 //production (A -> w1 a w2) is in the grammar. 00124 00125 GrammarSymbolVector beforeDot, afterDot; 00126 //construct right-hand side of the production, but need to make sure to delete 00127 //unnecessary lambdas 00128 beforeDot = configit->BeforeDot(); 00129 if(**beforeDot.begin() == *lambda){ 00130 beforeDot.clear(); 00131 } 00132 afterDot = configit->AfterDot(); 00133 if(**afterDot.begin() == *lambda){ 00134 afterDot.clear(); 00135 } 00136 00137 //create w1 a w2 from afterDot and beforeDot 00138 GrammarSymbolVector rhs(beforeDot); 00139 rhs.insert(rhs.end(), afterDot.begin(), afterDot.end()); 00140 if(rhs.empty()){ 00141 rhs.push_back(lambdaPtr); 00142 } 00143 00144 //construct production 00145 GrammarProduction gp(configit->Lhs(), rhs); 00146 00147 //test if the configuration is not in the grammar and if so, continue 00148 if(gr.GrammarProductions().find(gp) == gr.GrammarProductionsEnd()){ 00149 continue; 00150 } 00151 00152 //construct the word w2 z 00153 //w2 can't be lambda 00154 GrammarSymbolVector w2z(configit->AfterDot().begin() + 1, configit->AfterDot().end()); 00155 00156 //append z if it's not lambda 00157 if(!configit->Lookahead().IsLambda()){ 00158 Terminal* lookahead = new Terminal(configit->Lookahead()); 00159 GrammarSymbolPtr lookaheadPtr(lookahead); 00160 w2z.push_back(lookaheadPtr); 00161 } 00162 00163 //get first terminals after w2z (will be either nothing or lambda) 00164 std::set<Terminal> firstTerminals = FirstLeq1(augGr, k - 1, w2z); 00165 00166 std::set<Terminal>::const_iterator firsttit; 00167 //iterate over first terminals and add a parser action for each terminal y 00168 for(firsttit = firstTerminals.begin(); firsttit != firstTerminals.end(); firsttit++){ 00169 00170 //just to make sure that the terminal must be lambda 00171 if(!firsttit->IsLambda()){ 00172 std::stringstream errstr; 00173 errstr << "While executing LrpRules(): Constructing shift actions and the terminal " << firsttit->Str() << ", which was expected to be lambda" << std::endl; 00174 throw Exception("LrpRules", errstr.str(), 1001); 00175 } 00176 00177 //construct left-hand side of the rule (q | a y) (which is (q | a), 00178 //because y is lambda) 00179 std::vector<Idx> stateStack; 00180 stateStack.push_back(*stateit); 00181 Lr1ParserActionElement actionLhs(stateStack, *a); 00182 00183 //construct right-hand side of the rule (q q' | y) 00184 stateStack.push_back(succState); 00185 Lr1ParserActionElement actionRhs(stateStack, *lambda); 00186 00187 //construct shift action (q | a) -> (q q' | lambda) and insert into 00188 //set of actions 00189 Lr1ParserAction action(actionLhs, actionRhs); 00190 rActions.insert(action); 00191 } 00192 } 00193 } 00194 } 00195 return rActions; 00196 } 00197 00198 /* ************************* 00199 * LrpReduceRules 00200 * *************************/ 00201 std::set<Lr1ParserAction> LrpReduceRules(const Grammar& gr, const Grammar& augGr, const GotoGenerator& gotoGen, uint k){ 00202 00203 //parser actions to return 00204 std::set<Lr1ParserAction> rActions; 00205 00206 //lambda terminal for later use 00207 Terminal* lambda = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index(FAUDES_PD_LAMBDA)); 00208 00209 StateSet::Iterator stateit; 00210 //iterate over all states q of the gotoGenerator 00211 for(stateit = gotoGen.StatesBegin(); stateit != gotoGen.StatesEnd(); stateit++){ 00212 00213 std::set<Lr1Configuration>::const_iterator configit; 00214 //iterate over all configurations contained in the state q 00215 for(configit = gotoGen.ConfigSet(*stateit).begin(); configit != gotoGen.ConfigSet(*stateit).end(); configit++){ 00216 00217 //only consider this configuration if it is of the form (A -> lambda . w, z), 00218 //i. e. if beforeDot is lambda 00219 if(**configit->BeforeDot().begin() != *lambda){ 00220 continue; 00221 } 00222 00223 //only consider this configuration if the production (A -> w) is in the grammar 00224 GrammarProduction gp(configit->Lhs(), configit->AfterDot()); 00225 if(gr.GrammarProductions().find(gp) == gr.GrammarProductionsEnd()){ 00226 continue; 00227 } 00228 00229 //convert A into GrammarSymbolPtr and get successor state qa of q with the symbol A 00230 Nonterminal* a = new Nonterminal(configit->Lhs()); 00231 GrammarSymbolPtr aPtr(a); 00232 std::set<Idx> succStateSet = GeneratorGoto(gotoGen, *stateit, aPtr); 00233 00234 //if there is no successor state, continue 00235 if(succStateSet.size() != 1){ 00236 continue; 00237 } 00238 Idx succState = *succStateSet.begin(); 00239 00240 //get successor state sequence qs of q with the word w 00241 std::vector<Idx> succStateSequence = GeneratorGotoSeq(gotoGen, *stateit, configit->AfterDot()); 00242 00243 //join state q and state sequence qs 00244 std::vector<Idx> qQs; 00245 qQs.push_back(*stateit); 00246 qQs.insert(qQs.end(), succStateSequence.begin(), succStateSequence.end()); 00247 00248 //get last state of qQs state sequence 00249 Idx lastState = qQs.back(); 00250 00251 std::set<Lr1Configuration>::const_iterator lsconfigit; 00252 //iterate over configurations in the last state 00253 for(lsconfigit = gotoGen.ConfigSet(lastState).begin(); lsconfigit != gotoGen.ConfigSet(lastState).end(); lsconfigit++){ 00254 00255 //only consider this configuration if it is of the form (A -> w . lambda, y), 00256 if(lsconfigit->Lhs() != configit->Lhs()){ 00257 continue; 00258 } 00259 if(!EqualsGsVector(lsconfigit->BeforeDot(), configit->AfterDot())){ 00260 continue; 00261 } 00262 if(**lsconfigit->AfterDot().begin() != *lambda){ 00263 continue; 00264 } 00265 00266 //get the lookahead terminal 00267 Terminal lookahead(lsconfigit->Lookahead()); 00268 00269 //add parser action for each configuration 00270 //construct left-hand side (q qs | y) 00271 Lr1ParserActionElement lhs(qQs, lookahead); 00272 00273 //construct right-hand side (q qa | y) 00274 std::vector<Idx> stateStack; 00275 stateStack.push_back(*stateit); 00276 stateStack.push_back(succState); 00277 Lr1ParserActionElement rhs(stateStack, lookahead); 00278 00279 //construct reduce action (q qs | y) -> (q qa | y) and insert it into set 00280 //of actions 00281 Lr1ParserAction action(lhs, rhs, gp); 00282 rActions.insert(action); 00283 } 00284 } 00285 } 00286 return rActions; 00287 } 00288 00289 /* ************************* 00290 * LrpRules 00291 * *************************/ 00292 std::set<Lr1ParserAction> LrpRules(const Grammar& gr, const Grammar& augGr, const GotoGenerator& gotoGen, uint k){ 00293 00294 //parser actions to return 00295 std::set<Lr1ParserAction> rActions; 00296 00297 //get shift actions 00298 rActions = LrpShiftRules(gr, augGr, gotoGen, k); 00299 00300 //get reduce actions 00301 std::set<Lr1ParserAction> reduceActions = LrpReduceRules(gr, augGr, gotoGen, k); 00302 rActions.insert(reduceActions.begin(), reduceActions.end()); 00303 00304 return rActions; 00305 } 00306 00307 /* ************************* 00308 * Lrp 00309 * *************************/ 00310 Lr1Parser Lrp(const Grammar& gr, const Grammar& augGr, const GotoGenerator& gotoGen, uint k, const Terminal& augSymbol){ 00311 00312 //parser to return 00313 Lr1Parser rParser; 00314 00315 //convert augSymbol $ into GrammarSymbolPtr 00316 Terminal* augSymbolTemp = new Terminal(augSymbol); 00317 GrammarSymbolPtr augSymbolPtr(augSymbolTemp); 00318 00319 //convert the grammar's start symbol q0 into GrammarSymbolPtr 00320 Nonterminal* q0 = new Nonterminal(gr.StartSymbol()); 00321 GrammarSymbolPtr q0Ptr(q0); 00322 00323 //get successor state of the initial goto generator state and $ 00324 std::set<Idx> succStateSetAug = GeneratorGoto(gotoGen, gotoGen.InitState(), augSymbolPtr); 00325 00326 //get successor state sequence of the initial goto generator state and $ q0 00327 GrammarSymbolVector word; 00328 word.push_back(augSymbolPtr); 00329 word.push_back(q0Ptr); 00330 std::vector<Idx> succStateSeqAugQ0 = GeneratorGotoSeq(gotoGen, gotoGen.InitState(), word); 00331 00332 //get successor state sequence of the initial goto generator state and $ q0 $ 00333 word.push_back(augSymbolPtr); 00334 std::vector<Idx> succStateSeqAugQ0Aug = GeneratorGotoSeq(gotoGen, gotoGen.InitState(), word); 00335 00336 //if the successor states for $, $ q0 and $ q0 $ exist (i. e. they are not empty) 00337 if(!succStateSetAug.empty() && !succStateSeqAugQ0.empty() && !succStateSeqAugQ0Aug.empty()){ 00338 00339 //get the successor state for $ 00340 Idx succStateAug = *succStateSetAug.begin(); 00341 00342 //get the last state of the $ q0 sequence 00343 Idx lastStateAugQ0 = succStateSeqAugQ0.back(); 00344 00345 //get the last state of the $ q0 $ sequence 00346 Idx lastStateAugQ0Aug = succStateSeqAugQ0Aug.back(); 00347 00348 StateSet::Iterator stateit; 00349 //insert all states of the gotoGen as nonterminals of the parser, but exclude 00350 //the start state and the end state 00351 for(stateit = gotoGen.StatesBegin(); stateit != gotoGen.StatesEnd(); stateit++){ 00352 if(*stateit != gotoGen.InitState() && *stateit != lastStateAugQ0Aug){ 00353 rParser.InsNonterminal(*stateit); 00354 } 00355 } 00356 00357 std::set<Terminal>::const_iterator tit; 00358 //insert all the augmented grammar's terminals as the parser's terminals 00359 for(tit = augGr.TerminalsBegin(); tit != augGr.TerminalsEnd(); tit++){ 00360 rParser.InsTerminal(*tit); 00361 } 00362 00363 //set the parser's start state 00364 rParser.SetStartState(succStateAug); 00365 00366 //set the parser's final state 00367 rParser.SetFinalState(lastStateAugQ0); 00368 00369 //get the parsing actions 00370 std::set<Lr1ParserAction> actions = LrpRules(gr, augGr, gotoGen, k); 00371 00372 std::set<Lr1ParserAction>::const_iterator actit; 00373 //insert the parsing actions into the parser 00374 for(actit = actions.begin(); actit != actions.end(); actit++){ 00375 rParser.InsAction(*actit); 00376 } 00377 00378 //save $ for later reference in the parser 00379 rParser.SetAugSymbol(augSymbol); 00380 } 00381 00382 return rParser; 00383 } 00384 00385 /* ************************* 00386 * Gp2Pp 00387 * *************************/ 00388 PushdownGenerator Gp2Pp(const GotoGenerator& gotoGen, const Lr1Parser& parser){ 00389 00390 //generator to return 00391 PushdownGenerator rPd; 00392 00393 std::set<Idx>::const_iterator ntit; 00394 std::set<Terminal>::const_iterator tit; 00395 std::map<std::pair<Idx,Idx>, Idx> stateMap; 00396 std::map<std::pair<Idx,Idx>, Idx>::const_iterator statemapit; 00397 00398 //iterate over the parser's nonterminals 00399 for(ntit = parser.Nonterminals().begin(); ntit != parser.Nonterminals().end();ntit++){ 00400 00401 //insert states for each pair of nonterminal and terminal of the parser 00402 for(tit = parser.Terminals().begin(); tit != parser.Terminals().end(); tit++){ 00403 00404 //insert new states. start/final states can be inserted if the current terminal 00405 //is lambda 00406 Idx newState; 00407 //start state 00408 if(parser.StartState() == *ntit && tit->IsLambda()){ 00409 newState = rPd.InsInitState(); 00410 } 00411 //final state 00412 else if(parser.FinalState() == *ntit && tit->IsLambda()){ 00413 newState = rPd.InsMarkedState(); 00414 } 00415 //normal state 00416 else{ 00417 newState = rPd.InsState(); 00418 } 00419 00420 //set MergeStateEvent of that new state 00421 MergeStateEvent mse(*ntit, tit->Event()); 00422 rPd.SetMerge(newState, mse); 00423 00424 //save information on how the new states were created for later reference 00425 std::pair<Idx,Idx> key = std::make_pair(*ntit, tit->Event()); 00426 stateMap.insert(std::make_pair(key, newState)); 00427 } 00428 00429 //the parser's nonterminals are the generator's stack symbols (needs conversion to 00430 //string) 00431 std::stringstream s; 00432 s << *ntit; 00433 rPd.InsStackSymbol(s.str()); 00434 } 00435 00436 //lambda is always a stack symbol 00437 rPd.InsStackSymbol(FAUDES_PD_LAMBDA); 00438 00439 //add "0" as stack bottom 00440 rPd.SetStackBottom("0"); 00441 00442 //the parser's terminals are the generator's events 00443 for(tit = parser.Terminals().begin(); tit != parser.Terminals().end(); tit++){ 00444 00445 //insert event 00446 rPd.InsEvent(tit->Str()); 00447 } 00448 00449 //insert final state of the pushdown generator. the final state is a tuple of 00450 //the goto generator's final state and lambda. first check if that state already 00451 //has been added 00452 std::pair<Idx, Idx> finalState = std::make_pair(*gotoGen.MarkedStatesBegin(), rPd.EventIndex(FAUDES_PD_LAMBDA)); 00453 statemapit = stateMap.find(finalState); 00454 00455 std::set<Lr1ParserAction>::const_iterator actit; 00456 //iterate over parser actions to create transitions 00457 for(actit = parser.Actions().begin(); actit != parser.Actions().end(); actit++){ 00458 00459 //get left-hand side and right-hand side of the action 00460 Lr1ParserActionElement lhs = actit->Lhs(); 00461 Lr1ParserActionElement rhs = actit->Rhs(); 00462 00463 //if the actions left-hand side next terminal is lambda, it is an unexpected rule, 00464 //so throw an error 00465 if(lhs.NextTerminal().IsLambda()){ 00466 std::stringstream errstr; 00467 errstr << "While executing Gp2Pp(): Tried to create transition from parser action " << actit->Str() << ", but no rule exists for converting transitions with lambda in the left-hand side's next terminal. " << std::endl; 00468 throw Exception("Gp2Pp", errstr.str(), 1001); 00469 } 00470 00471 //for each shift action (A | a) -> (AB | lambda) 00472 else if(lhs.StateStack().size() == 1 && 00473 rhs.StateStack().size() == 2 && 00474 rhs.NextTerminal().IsLambda() && 00475 lhs.StateStack().front() == rhs.StateStack().front()) 00476 { 00477 //extract A, B, a and lambda 00478 Idx stateA = rhs.StateStack().front(); 00479 Idx stateB = rhs.StateStack().back(); 00480 Idx eventA = lhs.NextTerminal().Event(); 00481 Idx eventLambda = rhs.NextTerminal().Event(); 00482 00483 //get state (A, lambda) 00484 statemapit = stateMap.find(std::make_pair(stateA,eventLambda)); 00485 if(statemapit == stateMap.end()){ 00486 std::stringstream errstr; 00487 errstr << "While executing Gp2Pp(): Tried to find a pushdown generator state for the pair of goto generator state " << stateA << " and parser terminal " << eventLambda << " (" << rhs.NextTerminal().Str() << "), but could not be found." << std::endl; 00488 throw Exception("Gp2Pp", errstr.str(), 1001); 00489 } 00490 Idx aLambda = statemapit->second; 00491 00492 //get state (B, lambda) 00493 statemapit = stateMap.find(std::make_pair(stateB,eventLambda)); 00494 if(statemapit == stateMap.end()){ 00495 std::stringstream errstr; 00496 errstr << "While executing Gp2Pp(): Tried to find a pushdown generator state for the pair of goto generator state " << stateB << " and parser terminal " << eventLambda << " (" << rhs.NextTerminal().Str() << "), but could not be found." << std::endl; 00497 throw Exception("Gp2Pp", errstr.str(), 1001); 00498 } 00499 Idx bLambda = statemapit->second; 00500 00501 //get state (A, a) 00502 statemapit = stateMap.find(std::make_pair(stateA,eventA)); 00503 if(statemapit == stateMap.end()){ 00504 std::stringstream errstr; 00505 errstr << "While executing Gp2Pp(): Tried to find a pushdown generator state for the pair of goto generator state " << stateA << " and parser terminal " << eventA << " (" << lhs.NextTerminal().Str() << "), but could not be found." << std::endl; 00506 throw Exception("Gp2Pp", errstr.str(), 1001); 00507 } 00508 Idx aA = statemapit->second; 00509 00510 //create stack symbol vectors lambda and A 00511 std::vector<StackSymbol> popLambda, pushA; 00512 popLambda.push_back(StackSymbol(FAUDES_PD_LAMBDA)); 00513 std::stringstream s; 00514 s << stateA; 00515 pushA.push_back(StackSymbol(s.str())); 00516 00517 //insert transition ((A, lambda), a, lambda, A, (B, lambda)) 00518 rPd.SetTransition(aLambda, eventA, bLambda, popLambda, pushA); 00519 00520 //insert transition ((A, a), lambda, lambda, A, (B, lambda)) 00521 rPd.SetTransition(aA, eventLambda, bLambda, popLambda, pushA); 00522 00523 00524 } 00525 00526 //for each reduce action (AwB | y) -> (AC | y) 00527 else if(//lhs.StateStack().size() >= 2 && 00528 rhs.StateStack().size() == 2 && 00529 lhs.StateStack().front() == rhs.StateStack().front() && 00530 lhs.NextTerminal() == rhs.NextTerminal()) 00531 { 00532 00533 //extract A, B, C, w and y 00534 Idx stateA = rhs.StateStack().front(); 00535 Idx stateB = lhs.StateStack().back(); 00536 Idx stateC = rhs.StateStack().back(); 00537 Idx eventY = lhs.NextTerminal().Event(); 00538 std::vector<Idx> statesW; 00539 if(lhs.StateStack().size() > 2){ 00540 statesW = std::vector<Idx>(lhs.StateStack().begin() + 1, lhs.StateStack().end() - 1); 00541 } 00542 00543 //get state (B, lambda) 00544 Idx eventLambda = rPd.EventIndex(FAUDES_PD_LAMBDA); 00545 statemapit = stateMap.find(std::make_pair(stateB,eventLambda)); 00546 if(statemapit == stateMap.end()){ 00547 std::stringstream errstr; 00548 errstr << "While executing Gp2Pp(): Tried to find a pushdown generator state for the pair of goto generator state " << stateB << " and parser terminal " << eventLambda << " (" << FAUDES_PD_LAMBDA << "), but could not be found." << std::endl; 00549 throw Exception("Gp2Pp", errstr.str(), 1001); 00550 } 00551 Idx bLambda = statemapit->second; 00552 00553 //get state (C, y) 00554 statemapit = stateMap.find(std::make_pair(stateC,eventY)); 00555 if(statemapit == stateMap.end()){ 00556 std::stringstream errstr; 00557 errstr << "While executing Gp2Pp(): Tried to find a pushdown generator state for the pair of goto generator state " << stateC << " and parser terminal " << eventY << " (" << lhs.NextTerminal().Str() << "), but could not be found." << std::endl; 00558 throw Exception("Gp2Pp", errstr.str(), 1001); 00559 } 00560 Idx cY = statemapit->second; 00561 00562 //get state (B, y) 00563 statemapit = stateMap.find(std::make_pair(stateB,eventY)); 00564 if(statemapit == stateMap.end()){ 00565 std::stringstream errstr; 00566 errstr << "While executing Gp2Pp(): Tried to find a pushdown generator state for the pair of goto generator state " << stateB << " and parser terminal " << eventY << " (" << lhs.NextTerminal().Str() << "), but could not be found." << std::endl; 00567 throw Exception("Gp2Pp", errstr.str(), 1001); 00568 } 00569 Idx bY = statemapit->second; 00570 00571 //create stack symbol vectors w^-1 A and A 00572 std::vector<StackSymbol> popWA, pushA; 00573 std::vector<Idx>::const_reverse_iterator idxit; 00574 for(idxit = statesW.rbegin(); idxit != statesW.rend(); idxit++){ 00575 std::stringstream s; 00576 s << *idxit; 00577 popWA.push_back(StackSymbol(s.str())); 00578 } 00579 std::stringstream s; 00580 s << stateA; 00581 //only pop A if AwB has a size greater than 1 00582 if(lhs.StateStack().size() > 1){ 00583 popWA.push_back(StackSymbol(s.str())); 00584 } 00585 else{ 00586 popWA.push_back(StackSymbol(FAUDES_PD_LAMBDA)); 00587 } 00588 pushA.push_back(StackSymbol(s.str())); 00589 00590 //insert transition ((B, lambda), eventY, w^-1 A, A, (C, y)) 00591 rPd.SetTransition(bLambda, eventY, cY, popWA, pushA); 00592 00593 //insert transition ((B, y), lambda, w^-1 A, A, (C, y)) 00594 rPd.SetTransition(bY, eventLambda, cY, popWA, pushA); 00595 00596 } 00597 00598 //every other action must be an error 00599 else{ 00600 std::stringstream errstr; 00601 errstr << "While executing Gp2Pp(): Tried to create transition from parser action " << actit->Str() << ", but no rule exists for converting it. It seems to be neither a shift nor a reduce action. " << std::endl; 00602 throw Exception("Aug", errstr.str(), 1001); 00603 } 00604 } 00605 00606 00607 return rPd; 00608 } 00609 00610 /* ************************* 00611 * Dim 00612 * *************************/ 00613 PushdownGenerator Dim(const PushdownGenerator& pd, const Terminal& augSymbol){ 00614 00615 //generator to return 00616 PushdownGenerator rPd = pd; 00617 00618 TransSet::Iterator transit; 00619 PopPushSet::const_iterator ppit; 00620 //look at every transition 00621 for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){ 00622 00623 //if the event is the same as augSymbol 00624 if(transit->Ev == augSymbol.Event()){ 00625 00626 //set that transition's start state as final 00627 rPd.InsMarkedState(transit->X1); 00628 00629 //delete that transition from the generator for every pop push set 00630 for(ppit = pd.PopPushBegin(*transit); ppit != pd.PopPushEnd(*transit); ppit++){ 00631 rPd.ClrTransition(*transit, ppit->first, ppit->second); 00632 } 00633 } 00634 } 00635 00636 //remove the event 00637 rPd.DelEvent(augSymbol.Event()); 00638 00639 return rPd; 00640 } 00641 00642 } // namespace faudes 00643 libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen |