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

libFAUDES 2.28c --- 2016.09.30 --- c++ api documentaion by doxygen