pd_alg_lrp.cpp

Go 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