pd_alg_lrp.cpp
Go to the documentation of this file.
1 /** @file pd_alg_lrp.cpp functions related to parsers*/
2 
3 
4 /* Pushdown plugin for FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2013/14 Stefan Jacobi, Ramon Barakat, Sven Schneider, Anne-Kathrin Hess
7 
8 */
9 
10 #include "pd_alg_lrp.h"
11 
12 namespace faudes {
13 
14 
15 /* *************************
16  * MachineGoto
17  * *************************/
18 std::set<Idx> GeneratorGoto(const GotoGenerator& gotoGen, Idx state, const GrammarSymbolPtr& symbol){
19 
20  //state set to return
21  std::set<Idx> successorStates;
22 
23  TransSet::Iterator transit;
24  //iterate over all states with state as a start state
25  for(transit = gotoGen.TransRelBegin(state); transit != gotoGen.TransRelEnd(state); transit++){
26 
27  //if the symbol is the same, insert end state of the transition as successor state
28  if(*gotoGen.Symbol(*transit) == *symbol){
29  successorStates.insert(transit->X2);
30  }
31  }
32  return successorStates;
33 }
34 
35 
36 /* *************************
37  * GeneratorGotoSeq
38  * *************************/
39 std::vector<Idx> GeneratorGotoSeq(const GotoGenerator& gotoGen, Idx startState, const GrammarSymbolVector& word){
40 
41  //state sequence to return
42  std::vector<Idx> rStateSequence;
43 
44  //for later use
46  GrammarSymbolPtr lambdaPtr(lambda);
47 
48 
49  //if the word is not empty (or does not contain lambda), it is of the form w = a.w'
50  if(!word.empty()){
51  if(*word.front() != *lambda){
52 
53  //get front symbol a and remaining word w'
54  GrammarSymbolPtr frontSymbol = word.front();
55  GrammarSymbolVector remainingWord(word.begin() + 1, word.end());
56 
57  //get next state in the sequence
58  std::set<Idx> nextStateSet = GeneratorGoto(gotoGen, startState, frontSymbol);
59  Idx nextState;
60  if(!nextStateSet.empty()){
61  nextState = *nextStateSet.begin();
62 
63  //append the next state in the sequence
64  rStateSequence.push_back(nextState);
65  }
66 
67  //get the rest of the sequence
68  std::vector<Idx> remainingSequence = GeneratorGotoSeq(gotoGen, nextState, remainingWord);
69 
70  //append the rest of the sequence
71  rStateSequence.insert(rStateSequence.end(), remainingSequence.begin(), remainingSequence.end());
72  }
73  }
74  return rStateSequence;
75 }
76 
77 /* *************************
78  * LrpShiftRules
79  * *************************/
80 std::set<Lr1ParserAction> LrpShiftRules(const Grammar& gr, const Grammar& augGr, const GotoGenerator& gotoGen, uint k){
81 
82  //parser actions to return
83  std::set<Lr1ParserAction> rActions;
84 
85  //lambda terminal for later use
87  GrammarSymbolPtr lambdaPtr(lambda);
88 
89  StateSet::Iterator stateit;
90  //iterate over all states q of the gotoGenerator
91  for(stateit = gotoGen.StatesBegin(); stateit != gotoGen.StatesEnd(); stateit++){
92 
93  std::set<Terminal>::const_iterator tit;
94  //iterate over all terminals a of the grammar
95  for(tit = gr.TerminalsBegin(); tit != gr.TerminalsEnd(); tit++){
96 
97  //do not care for lambda
98  if(tit->IsLambda()){
99  continue;
100  }
101 
102  //convert terminal into GrammarSymbolPtr
103  Terminal* a = new Terminal(*tit);
104  GrammarSymbolPtr aPtr(a);
105 
106  //get the successor state q' for this terminal
107  std::set<Idx> succStateSet = GeneratorGoto(gotoGen, *stateit, aPtr);
108 
109  //continue, if there is no successor state (there can't be too many since gotoGen
110  //is supposed to be deterministic)
111  if(succStateSet.size() != 1){
112  continue;
113  }
114 
115  //extract the successor state
116  Idx succState = *succStateSet.begin();
117 
118  std::set<Lr1Configuration>::const_iterator configit;
119  //iterate over all configurations contained in the successor state
120  for(configit = gotoGen.ConfigSet(*stateit).begin(); configit != gotoGen.ConfigSet(*stateit).end(); configit++){
121 
122  //only consider this configuration (A -> w1 . a w2, z) if the
123  //production (A -> w1 a w2) is in the grammar.
124 
125  GrammarSymbolVector beforeDot, afterDot;
126  //construct right-hand side of the production, but need to make sure to delete
127  //unnecessary lambdas
128  beforeDot = configit->BeforeDot();
129  if(**beforeDot.begin() == *lambda){
130  beforeDot.clear();
131  }
132  afterDot = configit->AfterDot();
133  if(**afterDot.begin() == *lambda){
134  afterDot.clear();
135  }
136 
137  //create w1 a w2 from afterDot and beforeDot
138  GrammarSymbolVector rhs(beforeDot);
139  rhs.insert(rhs.end(), afterDot.begin(), afterDot.end());
140  if(rhs.empty()){
141  rhs.push_back(lambdaPtr);
142  }
143 
144  //construct production
145  GrammarProduction gp(configit->Lhs(), rhs);
146 
147  //test if the configuration is not in the grammar and if so, continue
148  if(gr.GrammarProductions().find(gp) == gr.GrammarProductionsEnd()){
149  continue;
150  }
151 
152  //construct the word w2 z
153  //w2 can't be lambda
154  GrammarSymbolVector w2z(configit->AfterDot().begin() + 1, configit->AfterDot().end());
155 
156  //append z if it's not lambda
157  if(!configit->Lookahead().IsLambda()){
158  Terminal* lookahead = new Terminal(configit->Lookahead());
159  GrammarSymbolPtr lookaheadPtr(lookahead);
160  w2z.push_back(lookaheadPtr);
161  }
162 
163  //get first terminals after w2z (will be either nothing or lambda)
164  std::set<Terminal> firstTerminals = FirstLeq1(augGr, k - 1, w2z);
165 
166  std::set<Terminal>::const_iterator firsttit;
167  //iterate over first terminals and add a parser action for each terminal y
168  for(firsttit = firstTerminals.begin(); firsttit != firstTerminals.end(); firsttit++){
169 
170  //just to make sure that the terminal must be lambda
171  if(!firsttit->IsLambda()){
172  std::stringstream errstr;
173  errstr << "While executing LrpRules(): Constructing shift actions and the terminal " << firsttit->Str() << ", which was expected to be lambda" << std::endl;
174  throw Exception("LrpRules", errstr.str(), 1001);
175  }
176 
177  //construct left-hand side of the rule (q | a y) (which is (q | a),
178  //because y is lambda)
179  std::vector<Idx> stateStack;
180  stateStack.push_back(*stateit);
181  Lr1ParserActionElement actionLhs(stateStack, *a);
182 
183  //construct right-hand side of the rule (q q' | y)
184  stateStack.push_back(succState);
185  Lr1ParserActionElement actionRhs(stateStack, *lambda);
186 
187  //construct shift action (q | a) -> (q q' | lambda) and insert into
188  //set of actions
189  Lr1ParserAction action(actionLhs, actionRhs);
190  rActions.insert(action);
191  }
192  }
193  }
194  }
195  return rActions;
196 }
197 
198 /* *************************
199  * LrpReduceRules
200  * *************************/
201 std::set<Lr1ParserAction> LrpReduceRules(const Grammar& gr, const Grammar& augGr, const GotoGenerator& gotoGen, uint k){
202 
203  //parser actions to return
204  std::set<Lr1ParserAction> rActions;
205 
206  //lambda terminal for later use
208 
209  StateSet::Iterator stateit;
210  //iterate over all states q of the gotoGenerator
211  for(stateit = gotoGen.StatesBegin(); stateit != gotoGen.StatesEnd(); stateit++){
212 
213  std::set<Lr1Configuration>::const_iterator configit;
214  //iterate over all configurations contained in the state q
215  for(configit = gotoGen.ConfigSet(*stateit).begin(); configit != gotoGen.ConfigSet(*stateit).end(); configit++){
216 
217  //only consider this configuration if it is of the form (A -> lambda . w, z),
218  //i. e. if beforeDot is lambda
219  if(**configit->BeforeDot().begin() != *lambda){
220  continue;
221  }
222 
223  //only consider this configuration if the production (A -> w) is in the grammar
224  GrammarProduction gp(configit->Lhs(), configit->AfterDot());
225  if(gr.GrammarProductions().find(gp) == gr.GrammarProductionsEnd()){
226  continue;
227  }
228 
229  //convert A into GrammarSymbolPtr and get successor state qa of q with the symbol A
230  Nonterminal* a = new Nonterminal(configit->Lhs());
231  GrammarSymbolPtr aPtr(a);
232  std::set<Idx> succStateSet = GeneratorGoto(gotoGen, *stateit, aPtr);
233 
234  //if there is no successor state, continue
235  if(succStateSet.size() != 1){
236  continue;
237  }
238  Idx succState = *succStateSet.begin();
239 
240  //get successor state sequence qs of q with the word w
241  std::vector<Idx> succStateSequence = GeneratorGotoSeq(gotoGen, *stateit, configit->AfterDot());
242 
243  //join state q and state sequence qs
244  std::vector<Idx> qQs;
245  qQs.push_back(*stateit);
246  qQs.insert(qQs.end(), succStateSequence.begin(), succStateSequence.end());
247 
248  //get last state of qQs state sequence
249  Idx lastState = qQs.back();
250 
251  std::set<Lr1Configuration>::const_iterator lsconfigit;
252  //iterate over configurations in the last state
253  for(lsconfigit = gotoGen.ConfigSet(lastState).begin(); lsconfigit != gotoGen.ConfigSet(lastState).end(); lsconfigit++){
254 
255  //only consider this configuration if it is of the form (A -> w . lambda, y),
256  if(lsconfigit->Lhs() != configit->Lhs()){
257  continue;
258  }
259  if(!EqualsGsVector(lsconfigit->BeforeDot(), configit->AfterDot())){
260  continue;
261  }
262  if(**lsconfigit->AfterDot().begin() != *lambda){
263  continue;
264  }
265 
266  //get the lookahead terminal
267  Terminal lookahead(lsconfigit->Lookahead());
268 
269  //add parser action for each configuration
270  //construct left-hand side (q qs | y)
271  Lr1ParserActionElement lhs(qQs, lookahead);
272 
273  //construct right-hand side (q qa | y)
274  std::vector<Idx> stateStack;
275  stateStack.push_back(*stateit);
276  stateStack.push_back(succState);
277  Lr1ParserActionElement rhs(stateStack, lookahead);
278 
279  //construct reduce action (q qs | y) -> (q qa | y) and insert it into set
280  //of actions
281  Lr1ParserAction action(lhs, rhs, gp);
282  rActions.insert(action);
283  }
284  }
285  }
286  return rActions;
287 }
288 
289 /* *************************
290  * LrpRules
291  * *************************/
292 std::set<Lr1ParserAction> LrpRules(const Grammar& gr, const Grammar& augGr, const GotoGenerator& gotoGen, uint k){
293 
294  //parser actions to return
295  std::set<Lr1ParserAction> rActions;
296 
297  //get shift actions
298  rActions = LrpShiftRules(gr, augGr, gotoGen, k);
299 
300  //get reduce actions
301  std::set<Lr1ParserAction> reduceActions = LrpReduceRules(gr, augGr, gotoGen, k);
302  rActions.insert(reduceActions.begin(), reduceActions.end());
303 
304  return rActions;
305 }
306 
307 /* *************************
308  * Lrp
309  * *************************/
310 Lr1Parser Lrp(const Grammar& gr, const Grammar& augGr, const GotoGenerator& gotoGen, uint k, const Terminal& augSymbol){
311 
312  //parser to return
313  Lr1Parser rParser;
314 
315  //convert augSymbol $ into GrammarSymbolPtr
316  Terminal* augSymbolTemp = new Terminal(augSymbol);
317  GrammarSymbolPtr augSymbolPtr(augSymbolTemp);
318 
319  //convert the grammar's start symbol q0 into GrammarSymbolPtr
320  Nonterminal* q0 = new Nonterminal(gr.StartSymbol());
321  GrammarSymbolPtr q0Ptr(q0);
322 
323  //get successor state of the initial goto generator state and $
324  std::set<Idx> succStateSetAug = GeneratorGoto(gotoGen, gotoGen.InitState(), augSymbolPtr);
325 
326  //get successor state sequence of the initial goto generator state and $ q0
327  GrammarSymbolVector word;
328  word.push_back(augSymbolPtr);
329  word.push_back(q0Ptr);
330  std::vector<Idx> succStateSeqAugQ0 = GeneratorGotoSeq(gotoGen, gotoGen.InitState(), word);
331 
332  //get successor state sequence of the initial goto generator state and $ q0 $
333  word.push_back(augSymbolPtr);
334  std::vector<Idx> succStateSeqAugQ0Aug = GeneratorGotoSeq(gotoGen, gotoGen.InitState(), word);
335 
336  //if the successor states for $, $ q0 and $ q0 $ exist (i. e. they are not empty)
337  if(!succStateSetAug.empty() && !succStateSeqAugQ0.empty() && !succStateSeqAugQ0Aug.empty()){
338 
339  //get the successor state for $
340  Idx succStateAug = *succStateSetAug.begin();
341 
342  //get the last state of the $ q0 sequence
343  Idx lastStateAugQ0 = succStateSeqAugQ0.back();
344 
345  //get the last state of the $ q0 $ sequence
346  Idx lastStateAugQ0Aug = succStateSeqAugQ0Aug.back();
347 
348  StateSet::Iterator stateit;
349  //insert all states of the gotoGen as nonterminals of the parser, but exclude
350  //the start state and the end state
351  for(stateit = gotoGen.StatesBegin(); stateit != gotoGen.StatesEnd(); stateit++){
352  if(*stateit != gotoGen.InitState() && *stateit != lastStateAugQ0Aug){
353  rParser.InsNonterminal(*stateit);
354  }
355  }
356 
357  std::set<Terminal>::const_iterator tit;
358  //insert all the augmented grammar's terminals as the parser's terminals
359  for(tit = augGr.TerminalsBegin(); tit != augGr.TerminalsEnd(); tit++){
360  rParser.InsTerminal(*tit);
361  }
362 
363  //set the parser's start state
364  rParser.SetStartState(succStateAug);
365 
366  //set the parser's final state
367  rParser.InsFinalState(lastStateAugQ0);
368 
369  //get the parsing actions
370  std::set<Lr1ParserAction> actions = LrpRules(gr, augGr, gotoGen, k);
371 
372  std::set<Lr1ParserAction>::const_iterator actit;
373  //insert the parsing actions into the parser
374  for(actit = actions.begin(); actit != actions.end(); actit++){
375  rParser.InsAction(*actit);
376  }
377 
378  //save $ for later reference in the parser
379  rParser.SetAugSymbol(augSymbol);
380  }
381 
382  return rParser;
383 }
384 
385 
386 //************************
387 // detach augment symbol
388 //************************
389 void DetachAugSymbol(Lr1Parser& parser) {
390  std::set<Lr1ParserAction> tmp;
391  std::set<Lr1ParserAction>::iterator it;
392 
393  //set each nonterminal before augment symbol as final state
394  //and remove those actions
395  parser.ClrFinalStates();
396  for (it = parser.Actions().begin(); it != parser.Actions().end(); ++it) {
397  if (it->Rhs().NextTerminal() != parser.AugSymbol()) {
398  tmp.insert(*it);
399  } else {
400  parser.InsFinalState(it->Lhs().StateStack().back());
401  }
402  }
403 
404  parser.mActions = tmp;
405 }
406 
407 
408 /*
409  * Get state stack by creating or get new nonterms.
410  * Each state from given state stack(except last one) will be converted to a pair of state an lambda.
411  * The last state will be converted to a pair of state and given terminal.
412  * ( e.g. given state stack [s1,s2,s3] and terminal t will get
413  * [z1,z2,z3] with z1 = (s1,lambda), z2 = (s2,lambda) and z3 =(s3,t) )
414  *
415  * @param rVec
416  * reference to statestack
417  * @param term
418  * terminal symbol
419  * @param indexMap
420  * map to remember new indices of new nonterminal representing (nonterminal, terminal) pairs.
421  * New nonterminals will add to this map.
422  *
423  * @result
424  * statestack with indices of the new nonterminals
425  */
426 std::vector<Idx> CreateNonterms(const std::vector<Idx>& rVec,Terminal term, std::map<std::pair<Idx,Terminal>,Idx >& indexMap){
427 
428  // result vector
429  std::vector<Idx> res;
430 
431  //lambda terminal
433 
434  std::map<std::pair<Idx,Terminal>,Idx >::iterator mapit;
435  std::vector<Idx>::const_iterator it;
436 
437 
438  //find or create(q,lambda)
439  for(it = rVec.begin(); it != rVec.end(); ++it ){
440  std::pair<Idx,Terminal> p = std::make_pair(*it,lambda);
441 
442 
443  if(std::distance(it,rVec.end()) == 1)
444  p = std::make_pair(*it,term);
445 
446  mapit = indexMap.find(p);
447 
448  // if p already exists, get index of p
449  if(mapit != indexMap.end()){
450  res.push_back(mapit->second);
451  }else{
452  //if p doesn't exists, get new index
453  Idx i = indexMap.size()+1;
454  indexMap.insert(std::make_pair(p,i));
455  res.push_back(i);
456  }
457  }
458 
459  return res;
460 
461 }
462 
463 // Transform following actions of given parser
464 // (q,a,p,a) => ((q,lambda),a,(p,a),lambda) , ((q,a),lambda,(p,a),lambda)
465 // (q,a,p,lambda) => ((q,lambda),a,(p,lambda),lambda) , ((q,a),lambda,(p,lambda),lambda)
467  Lr1Parser rParser;
468 
469  // map to remember new indices of new nonterminal representing (nonterminal, terminal) pairs
470  std::map<std::pair<Idx,Terminal>,Idx > indexMap;
471  std::map<std::pair<Idx,Terminal>,Idx >::iterator mapit;
472  std::set<Idx> nonterms;
473  std::set<Lr1ParserAction>::iterator actionsit;
474 
475  //lambda terminal
478 
479  //set start state
480  std::pair<Idx,Terminal> start = std::make_pair(parser.StartState(),lambda);
481  indexMap[start] = 1;
482  rParser.SetStartState(1);
483 
484  //for each action
485  for (actionsit = parser.Actions().begin(); actionsit != parser.Actions().end();
486  ++actionsit) {
487  Lr1ParserAction action = *actionsit;
488 
489  //(q,a,p,a)
490  if (action.Lhs().NextTerminal() == action.Rhs().NextTerminal()) {
491  //get Terminal a
492  Terminal terminal = action.Lhs().NextTerminal();
493 
494  //lhs = (q,lambda),a
496  CreateNonterms(action.Lhs().StateStack(), lambda, indexMap),terminal);
497 
498  //rhs = (p,a),lambda
500  CreateNonterms(action.Rhs().StateStack(), terminal,indexMap), lambda);
501 
502  //(q,a,p,a) => ((q,lambda),a,(p,a),lambda)
503  rParser.InsAction(Lr1ParserAction(lhs1, rhs1));
504 
505 
506  //lhs = (q,a),lambda
508  CreateNonterms(action.Lhs().StateStack(), terminal, indexMap), lambda);
509 
510  //rhs = (p,a),lambda
511  Lr1ParserActionElement rhs2 = rhs1;
512 
513  //(q,a,p,a) => ((q,a),lambda,(p,a),lambda)
514  rParser.InsAction(Lr1ParserAction(lhs2, rhs2));
515 
516  }
517  //(q,a,p,lambda)
518  else if (action.Rhs().NextTerminal().IsLambda()) {
519  Terminal terminal = action.Lhs().NextTerminal();
520 
521  //lhs = (q,lambda),a
523  CreateNonterms(action.Lhs().StateStack(), lambda, indexMap), terminal);
524  //rhs = (p,lambda),lambda
526  CreateNonterms(action.Rhs().StateStack(), lambda, indexMap), lambda);
527 
528  //(q,a,p,lambda) => ((q,lambda),a,(p,lambda),lambda)
529  rParser.InsAction(Lr1ParserAction(lhs1, rhs1));
530 
531  //lhs = (q,a),lambda
533  CreateNonterms(action.Lhs().StateStack(), terminal, indexMap), lambda);
534  //rhs = (p,lambda),lambda
535  Lr1ParserActionElement rhs2 = rhs1;
536 
537  //(q,a,p,lambda) => ((q,a),lambda,(p,lambda),lambda)
538  rParser.InsAction(Lr1ParserAction(lhs2, rhs2));
539  }
540  }
541 
542  //set final states (p,lambda)
543  std::set<Idx>::iterator fit;
544  for (fit = parser.FinalStates().begin(); fit != parser.FinalStates().end(); fit++) {
545  mapit = indexMap.find(std::make_pair(*fit,lambda));
546  if(mapit != indexMap.end())
547  rParser.InsFinalState(mapit->second);
548  }
549 
550  //get all nonterminals = values of indexMap
551  for(mapit = indexMap.begin(); mapit != indexMap.end(); ++mapit){
552  nonterms.insert(mapit->second);
553  }
554 
555  //set nonterminals, terminals and augment symbol
556  rParser.mNonterminals = nonterms;
557  rParser.mTerminals = parser.mTerminals;
558  rParser.mAugSymbol = parser.mAugSymbol;
559 
560  return rParser;
561 }
562 
563 
564 /* *************************
565  * LrParser2EPDA
566  * *************************/
568  FUNCTION(__FUNCTION__); //scop log
569  bool debug = false; //debug?
570 
571  std::string statepre = "q";
572  std::string stacksympre = "x";
573 
574  //generator to return
575  PushdownGenerator rPd;
576 
577  std::set<Idx>::iterator it;
578  std::set<Terminal>::iterator termit;
579  std::set<Lr1ParserAction>::iterator actionit;
580 
581  // the parser's nonterminals are the generator's ...
582  for (it = parser.Nonterminals().begin(); it != parser.Nonterminals().end();
583  ++it) {
584  // ... states
585  rPd.InsState(*it);
586  rPd.StateName(*it,statepre + ToStringInteger(*it));
587 
588  // ... and stack symbols
590  }
591  DEBUG_PRINTF(debug,"LrParser2EPDA: Set states and stack symbols","");
592  FD_DF("LrParser2EPDA: Set states and stack symbols");
593 
594  //set init state
595  rPd.SetInitState(parser.StartState());
596 
597  //set final states
598  for (it = parser.FinalStates().begin(); it != parser.FinalStates().end(); ++it) {
599  rPd.SetMarkedState(*it);
600  }
601  DEBUG_PRINTF(debug,"LrParser2EPDA: Set final states","");
602  FD_DF("LrParser2EPDA: Set final states");
603 
604  //set events
605  for (termit = parser.Terminals().begin(); termit != parser.Terminals().end(); ++termit){
606  if ((*termit) != parser.AugSymbol())
607  rPd.InsEvent(termit->Str());
608  }
609  DEBUG_PRINTF(debug,"LrParser2EPDA: Set events","");
610  FD_DF("LrParser2EPDA: Set events");
611 
612 
613  //set stack bottom
614  std::string bottom = rPd.UniqueStackSymbolName("sb");
615  rPd.InsStackSymbol(bottom);
616  rPd.SetStackBottom(bottom);
617  DEBUG_PRINTF(debug,"LrParser2EPDA: Set stack bottom: "+bottom,"");
618  FD_DF("LrParser2EPDA: Set stack bottom: "+bottom);
619 
620  //lambda is always a stack symbol
621  Idx lambda = rPd.InsStackSymbol(FAUDES_PD_LAMBDA);
622 
623  //create transitions for each action
624  for (actionit = parser.Actions().begin(); actionit != parser.Actions().end(); ++actionit) {
625  Lr1ParserAction ac = *actionit;
626  Idx src = ac.Lhs().StateStack().back();
627  Idx trg = ac.Rhs().StateStack().back();
628  Idx ev = rPd.EventIndex(ac.Lhs().NextTerminal().Str());
629 
630  std::vector<Idx> pop = ac.Lhs().StateStack();
631  pop.pop_back();
632 
633  std::vector<Idx> push = ac.Rhs().StateStack();
634  push.pop_back();
635 
636  std::vector<std::string> popTrans(pop.size());
637  std::vector<std::string> pushTrans(push.size());
638 
639  //need transformation because stack symbol idx
640  //don't have to be the same as former added ones
641  //but stack symbol names should be equal
642  std::transform(pop.rbegin(), pop.rend(), popTrans.begin(), ToStringInteger);
643  std::transform(push.rbegin(), push.rend(), pushTrans.begin(), ToStringInteger);
644 
645  if (popTrans.empty())
646  popTrans.push_back(rPd.StackSymbolName(lambda));
647  if (pushTrans.empty())
648  pushTrans.push_back(rPd.StackSymbolName(lambda));
649 
650  rPd.SetTransition(src, ev, trg, popTrans, pushTrans);
651  }
652 
653  DEBUG_PRINTF(debug,"LrParser2EPDA: Set transitions","");
654  FD_DF("LrParser2EPDA: Set transitions");
655 
656  return rPd;
657 }
658 
659 } // namespace faudes
660 

libFAUDES 2.26g --- 2015.08.17 --- c++ api documentaion by doxygen