pd_alg_lrp_test.cpp
Go to the documentation of this file.
1 /** @file pd_alg_lrp_test.cpp Unit Tests */
2 
3 
4 /* Pushdown plugin for FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2013 Stefan Jacobi, Sven Schneider, Anne-Kathrin Hess
7 
8 */
9 #include "pd_alg_lrp_test.h"
10 
11 namespace faudes {
12 
13 
14 /* *****************
15  * TestGeneratorGotoOneSuccessor
16  * *****************/
18  std::string name = "GeneratorGoto One Successor";
19  TestStart(name);
20 
21  Grammar gr = TestGrammar7();
22 
23  //create terminals
25  GrammarSymbolPtr ptrta(ta);
27  GrammarSymbolPtr ptrtb(tb);
28  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
29  GrammarSymbolPtr ptrtdollar(tdollar);
31  GrammarSymbolPtr ptrtlambda(tlambda);
32 
33  //create nonterminals
34  std::vector<Idx> v;
35  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
36  Nonterminal* nt1dot = new Nonterminal(1,v);
37  GrammarSymbolPtr ptrnt1dot(nt1dot);
38 
39  v.clear();
40  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
41  Nonterminal* nt1square = new Nonterminal(1,v);
42  GrammarSymbolPtr ptrnt1square(nt1square);
43 
44  //test with state ((1, [dot]) -> $(1, [square]) . $, lambda) and symbol $
45  // ((1, [dot]) -> $(1, [square])$ . lambda, lambda)
46  GrammarSymbolVector beforeDot, afterDot;
47  beforeDot.push_back(ptrtdollar);
48  beforeDot.push_back(ptrnt1square);
49  afterDot.push_back(ptrtdollar);
50  Lr1Configuration config(*nt1dot, beforeDot, afterDot, *tlambda);
51 
52  std::set<Lr1Configuration> startState;
53  startState.insert(config);
54 
55  beforeDot.clear();
56  afterDot.clear();
57  beforeDot.push_back(ptrtdollar);
58  beforeDot.push_back(ptrnt1square);
59  beforeDot.push_back(ptrtdollar);
60  afterDot.push_back(ptrtlambda);
61  Lr1Configuration expectedConfig(*nt1dot, beforeDot, afterDot, *tlambda);
62 
63  GotoGenerator gotoGen = Lrm(gr,1);
64  std::set<Idx> successorStates = GeneratorGoto(gotoGen, gotoGen.StateIndex(startState), ptrtdollar);
65  try{
66 
67  //size of successorStates must be one
68  if(successorStates.size() != 1){
69  std::stringstream errstr;
70  errstr << "number of successor states was expected to be 1, but was " << successorStates.size() << "." << std::endl;
71  throw Exception(name, errstr.str(), 1003);
72  }
73 
74  //number of contained configurations must be one
75  if(gotoGen.ConfigSet(*successorStates.begin()).size() != 1){
76  std::stringstream errstr;
77  errstr << "number of configurations in successor state " << *successorStates.begin() << " was expected to be 1, but was " << gotoGen.ConfigSet(*successorStates.begin()).size() << "." << std::endl;
78  throw Exception(name, errstr.str(), 1003);
79  }
80 
81  //the contained configuration must be expectedConfig
82  if(*gotoGen.ConfigSet(*successorStates.begin()).begin() != expectedConfig){
83  std::stringstream errstr;
84  errstr << "configuration contained in successor state " << *successorStates.begin() << " was expected to be (" << expectedConfig.Str() << "), but was (" << gotoGen.ConfigSet(*successorStates.begin()).begin()->Str() << ")." << std::endl;
85  throw Exception(name, errstr.str(), 1003);
86  }
87  }
88  catch (Exception e){
89  }
90  TestEnd(name);
91 }
92 
93 /* *****************
94  * TestGeneratorGotoNoSuccessor
95  * *****************/
97  std::string name = "GeneratorGoto No Successor";
98  TestStart(name);
99 
100  Grammar gr = TestGrammar7();
101 
102  //create terminals
104  GrammarSymbolPtr ptrta(ta);
106  GrammarSymbolPtr ptrtb(tb);
107  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
108  GrammarSymbolPtr ptrtdollar(tdollar);
110  GrammarSymbolPtr ptrtlambda(tlambda);
111 
112  //create nonterminals
113  std::vector<Idx> v;
114  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
115  Nonterminal* nt1dot = new Nonterminal(1,v);
116  GrammarSymbolPtr ptrnt1dot(nt1dot);
117 
118  v.clear();
119  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
120  Nonterminal* nt1square = new Nonterminal(1,v);
121  GrammarSymbolPtr ptrnt1square(nt1square);
122 
123  //test with state ((1, [dot]) -> $(1, [square]) . $, $) and symbol $
124  // empty
125  GrammarSymbolVector beforeDot, afterDot;
126  beforeDot.push_back(ptrtdollar);
127  beforeDot.push_back(ptrnt1square);
128  afterDot.push_back(ptrtdollar);
129  Lr1Configuration config(*nt1dot, beforeDot, afterDot, *tdollar);
130 
131  std::set<Lr1Configuration> startState;
132  startState.insert(config);
133 
134  GotoGenerator gotoGen = Lrm(gr,1);
135 
136  std::set<Idx> successorStates = GeneratorGoto(gotoGen, gotoGen.StateIndex(startState), ptrtdollar);
137 
138  try{
139 
140  //size of successorStates must be zero
141  if(successorStates.size() != 0){
142  std::stringstream errstr;
143  errstr << "number of successor states was expected to be 0, because state with configuration (" << config.Str() << ") does not exist , but was " << successorStates.size() << "." << std::endl;
144  throw Exception(name, errstr.str(), 1003);
145  }
146  }
147  catch (Exception e){
148  }
149 
150  //test with state ((1, [dot]) -> $(1, [square]) . $, lambda) and symbol a
151  // empty
152  beforeDot.clear();
153  afterDot.clear();
154  beforeDot.push_back(ptrtdollar);
155  beforeDot.push_back(ptrnt1square);
156  afterDot.push_back(ptrtdollar);
157  Lr1Configuration config2(*nt1dot, beforeDot, afterDot, *tlambda);
158 
159  startState.clear();
160  startState.insert(config2);
161 
162  successorStates = GeneratorGoto(gotoGen, gotoGen.StateIndex(startState), ptrta);
163 
164  try{
165 
166  //size of successorStates must be zero
167  if(successorStates.size() != 0){
168  std::stringstream errstr;
169  errstr << "number of successor states was expected to be 0, because state with configuration (" << config2.Str() << ") and symbol a does not exist, but was " << successorStates.size() << "." << std::endl;
170  throw Exception(name, errstr.str(), 1003);
171  }
172  }
173  catch (Exception e){
174  }
175  TestEnd(name);
176 }
177 
178 /* *****************
179  * TestGeneratorGotoSeqFull
180  * *****************/
182  std::string name = "GeneratorGotoSeq Full";
183  TestStart(name);
184 
185  Grammar gr = TestGrammar7();
186 
187  //create terminals
189  GrammarSymbolPtr ptrta(ta);
191  GrammarSymbolPtr ptrtb(tb);
192  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
193  GrammarSymbolPtr ptrtdollar(tdollar);
195  GrammarSymbolPtr ptrtlambda(tlambda);
196 
197  //create nonterminals
198  std::vector<Idx> v;
199  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
200  Nonterminal* nt1dot = new Nonterminal(1,v);
201  GrammarSymbolPtr ptrnt1dot(nt1dot);
202 
203  v.clear();
204  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
205  Nonterminal* nt1square = new Nonterminal(1,v);
206  GrammarSymbolPtr ptrnt1square(nt1square);
207 
208  //test with state ((1, [dot]) -> lambda . $(1, [square])$, lambda) and
209  //word $a(1, [square])
210  GrammarSymbolVector beforeDot, afterDot;
211  beforeDot.push_back(ptrtlambda);
212  afterDot.push_back(ptrtdollar);
213  afterDot.push_back(ptrnt1square);
214  afterDot.push_back(ptrtdollar);
215  Lr1Configuration config(*nt1dot, beforeDot, afterDot, *tlambda);
216 
217  std::set<Lr1Configuration> startState;
218  startState.insert(config);
219 
220  GrammarSymbolVector word;
221 
222  word.push_back(ptrtdollar);
223  word.push_back(ptrta);
224  word.push_back(ptrnt1square);
225 
226  //create expected last state of the sequence
227  beforeDot.clear();
228  afterDot.clear();
229  beforeDot.push_back(ptrta);
230  beforeDot.push_back(ptrnt1square);
231  afterDot.push_back(ptrtlambda);
232  Lr1Configuration expectedEndConfig(*nt1square, beforeDot, afterDot, *tdollar);
233 
234  GotoGenerator gotoGen = Lrm(gr,1);
235  std::vector<Idx> stateSequence = GeneratorGotoSeq(gotoGen, gotoGen.StateIndex(startState), word);
236 
237  try{
238 
239  //size of stateSequence must be 3
240  if(stateSequence.size() != 3){
241  std::stringstream errstr;
242  errstr << "number of successor states was expected to be 3, but was " << stateSequence.size() << "." << std::endl;
243  throw Exception(name, errstr.str(), 1003);
244  }
245 
246  //number of contained configurations in the last state must be 1
247  if(gotoGen.ConfigSet(stateSequence.back()).size() != 1){
248  std::stringstream errstr;
249  errstr << "number of configurations in the last state of the sequence was expected to be 1, but was " << gotoGen.ConfigSet(stateSequence.back()).size() << "." << std::endl;
250  throw Exception(name, errstr.str(), 1003);
251  }
252 
253  //the last configuration in the sequence must be expectedEndConfig
254  if(*gotoGen.ConfigSet(stateSequence.back()).begin() != expectedEndConfig){
255  std::stringstream errstr;
256  errstr << "state at the end of the sequence was expected to contain the configuration (" << expectedEndConfig.Str() << "), but was (" << gotoGen.ConfigSet(stateSequence.back()).begin()->Str() << ")." << std::endl;
257  throw Exception(name, errstr.str(), 1003);
258  }
259  }
260  catch (Exception e){
261  }
262  TestEnd(name);
263 }
264 
265 /* *****************
266  * TestGeneratorGotoSeqPartial
267  * *****************/
269  std::string name = "GeneratorGotoSeq Partial";
270  TestStart(name);
271 
272  Grammar gr = TestGrammar7();
273 
274  //create terminals
276  GrammarSymbolPtr ptrta(ta);
278  GrammarSymbolPtr ptrtb(tb);
279  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
280  GrammarSymbolPtr ptrtdollar(tdollar);
282  GrammarSymbolPtr ptrtlambda(tlambda);
283 
284  //create nonterminals
285  std::vector<Idx> v;
286  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
287  Nonterminal* nt1dot = new Nonterminal(1,v);
288  GrammarSymbolPtr ptrnt1dot(nt1dot);
289 
290  v.clear();
291  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
292  Nonterminal* nt1square = new Nonterminal(1,v);
293  GrammarSymbolPtr ptrnt1square(nt1square);
294 
295  //test with state ((1, [dot]) -> lambda . $(1, [square])$, lambda) and
296  //word $b$
297  GrammarSymbolVector beforeDot, afterDot;
298  beforeDot.push_back(ptrtlambda);
299  afterDot.push_back(ptrtdollar);
300  afterDot.push_back(ptrnt1square);
301  afterDot.push_back(ptrtdollar);
302  Lr1Configuration config(*nt1dot, beforeDot, afterDot, *tlambda);
303 
304  std::set<Lr1Configuration> startState;
305  startState.insert(config);
306 
307  GrammarSymbolVector word;
308 
309  word.push_back(ptrtdollar);
310  word.push_back(ptrtb);
311  word.push_back(ptrtdollar);
312 
313  //create expected last state of the sequence
314  beforeDot.clear();
315  afterDot.clear();
316  beforeDot.push_back(ptrtb);
317  afterDot.push_back(ptrtlambda);
318  Lr1Configuration expectedEndConfig(*nt1square, beforeDot, afterDot, *tdollar);
319 
320  GotoGenerator gotoGen = Lrm(gr,1);
321  std::vector<Idx> stateSequence = GeneratorGotoSeq(gotoGen, gotoGen.StateIndex(startState), word);
322 
323  try{
324 
325  //size of stateSequence must be 2
326  if(stateSequence.size() != 2){
327  std::stringstream errstr;
328  errstr << "number of successor states was expected to be 2, but was " << stateSequence.size() << "." << std::endl;
329  throw Exception(name, errstr.str(), 1003);
330  }
331 
332  //number of contained configurations in the last state must be 1
333  if(gotoGen.ConfigSet(stateSequence.back()).size() != 1){
334  std::stringstream errstr;
335  errstr << "number of configurations in the last state of the sequence was expected to be 1, but was " << gotoGen.ConfigSet(stateSequence.back()).size() << "." << std::endl;
336  throw Exception(name, errstr.str(), 1003);
337  }
338 
339  //the last configuration in the sequence must be expectedEndConfig
340  if(*gotoGen.ConfigSet(stateSequence.back()).begin() != expectedEndConfig){
341  std::stringstream errstr;
342  errstr << "state at the end of the sequence was expected to contain the configuration (" << expectedEndConfig.Str() << "), but was (" << gotoGen.ConfigSet(stateSequence.back()).begin()->Str() << ")." << std::endl;
343  throw Exception(name, errstr.str(), 1003);
344  }
345  }
346  catch (Exception e){
347  }
348  TestEnd(name);
349 }
350 
351 /* *****************
352  * TestLrpShiftRulesNumberAndTerminals
353  * *****************/
355  std::string name = "LrpShiftRules Number And Terminals";
356  TestStart(name);
357 
358  Grammar gr = TestGrammar9();
359 
360  //create terminals
362  GrammarSymbolPtr ptrta(ta);
364  GrammarSymbolPtr ptrtb(tb);
365  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
366  GrammarSymbolPtr ptrtdollar(tdollar);
368  GrammarSymbolPtr ptrtlambda(tlambda);
369 
370  //create nonterminals
371  std::vector<Idx> v;
372  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
373  Nonterminal* nt1dot = new Nonterminal(1,v);
374  GrammarSymbolPtr ptrnt1dot(nt1dot);
375 
376  v.clear();
377  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
378  Nonterminal* nt1square = new Nonterminal(1,v);
379  GrammarSymbolPtr ptrnt1square(nt1square);
380 
381  Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
382 
383  GotoGenerator gotoGen = Lrm(augGr, 1);
384  std::set<Lr1ParserAction> actions = LrpShiftRules(gr, augGr, gotoGen, 1);
385 
386  try{
387 
388  //number of found actions must be 4
389  if(actions.size() != 4){
390  std::stringstream errstr;
391  errstr << "number of shift actions was expected to be 4, but was " << actions.size() << "." << std::endl;
392  throw Exception(name, errstr.str(), 1003);
393  }
394  //there must be 2 actions that reduce with terminal a
395  int i = 0;
396  std::set<Lr1ParserAction>::const_iterator pait;
397  for(pait = actions.begin(); pait != actions.end(); pait++){
398  if(pait->Lhs().NextTerminal() == *ta){
399  i++;
400  }
401  }
402  if(i != 2){
403  std::stringstream errstr;
404  errstr << "number of shift actions for symbol a of the form (x | a) -> (xy | lambda) was expected to be 2, but was " << i << "." << std::endl;
405  throw Exception(name, errstr.str(), 1003);
406  }
407 
408  //there must be 2 actions that reduce with terminal b
409  i = 0;
410  for(pait = actions.begin(); pait != actions.end(); pait++){
411  if(pait->Lhs().NextTerminal() == *tb){
412  i++;
413  }
414  }
415  if(i != 2){
416  std::stringstream errstr;
417  errstr << "number of shift actions for symbol b of the form (x | b) -> (xy | lambda) was expected to be 2, but was " << i << "." << std::endl;
418  throw Exception(name, errstr.str(), 1003);
419  }
420  }
421  catch (Exception e){
422  }
423  TestEnd(name);
424 }
425 
426 /* *****************
427  * TestLrpReduceRulesNumberAndTerminals
428  * *****************/
430  std::string name = "LrpReduceRules Number And Terminals";
431  TestStart(name);
432 
433  Grammar gr = TestGrammar9();
434 
435  //create terminals
437  GrammarSymbolPtr ptrta(ta);
439  GrammarSymbolPtr ptrtb(tb);
440  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
441  GrammarSymbolPtr ptrtdollar(tdollar);
443  GrammarSymbolPtr ptrtlambda(tlambda);
444 
445  //create nonterminals
446  std::vector<Idx> v;
447  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
448  Nonterminal* nt1dot = new Nonterminal(1,v);
449  GrammarSymbolPtr ptrnt1dot(nt1dot);
450 
451  v.clear();
452  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
453  Nonterminal* nt1square = new Nonterminal(1,v);
454  GrammarSymbolPtr ptrnt1square(nt1square);
455 
456  Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
457 
458  GotoGenerator gotoGen = Lrm(augGr, 1);
459  std::set<Lr1ParserAction> actions = LrpReduceRules(gr, augGr, gotoGen, 1);
460 
461  try{
462 
463  //number of found actions must be 4
464  if(actions.size() != 4){
465  std::stringstream errstr;
466  errstr << "number of shift actions was expected to be 4, but was " << actions.size() << "." << std::endl;
467  throw Exception(name, errstr.str(), 1003);
468  }
469  //there must be 4 actions that shift with terminal $
470  int i = 0;
471  std::set<Lr1ParserAction>::const_iterator pait;
472  for(pait = actions.begin(); pait != actions.end(); pait++){
473  if(pait->Lhs().NextTerminal() == *tdollar && pait->Rhs().NextTerminal() == *tdollar){
474  i++;
475  }
476  }
477  if(i != 4){
478  std::stringstream errstr;
479  errstr << "number of shift actions for symbol a of the form (x | $) -> (xy | $) was expected to be 4, but was " << i << "." << std::endl;
480  throw Exception(name, errstr.str(), 1003);
481  }
482  }
483  catch (Exception e){
484  }
485  TestEnd(name);
486 }
487 
488 /* *****************
489  * TestLrpActions
490  * *****************/
492  std::string name = "Lrp Actions";
493  TestStart(name);
494 
495  Grammar gr = TestGrammar9();
496 
497  //create terminals
499  GrammarSymbolPtr ptrta(ta);
501  GrammarSymbolPtr ptrtb(tb);
502  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
503  GrammarSymbolPtr ptrtdollar(tdollar);
505  GrammarSymbolPtr ptrtlambda(tlambda);
506 
507  //create nonterminals
508  std::vector<Idx> v;
509  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
510  Nonterminal* nt1dot = new Nonterminal(1,v);
511  GrammarSymbolPtr ptrnt1dot(nt1dot);
512 
513  v.clear();
514  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
515  Nonterminal* nt1square = new Nonterminal(1,v);
516  GrammarSymbolPtr ptrnt1square(nt1square);
517 
518  Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
519 
520  GotoGenerator gotoGen = Lrm(augGr, 1);
521  Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
522 
523  try{
524 
525  //number of found actions must be 8
526  std::set<Lr1ParserAction> actions = parser.Actions();
527  if(actions.size() != 8){
528  std::stringstream errstr;
529  errstr << "number of actions was expected to be 8, but was " << actions.size() << "." << std::endl;
530  throw Exception(name, errstr.str(), 1003);
531  }
532  //there must be 4 actions with terminal $ and $on the left-hand and right-hand side,
533  //2 with a and lambda, and 2 with b and lambda
534  int dollarCount = 0;
535  int aCount = 0;
536  int bCount = 0;
537  std::set<Lr1ParserAction>::const_iterator pait;
538  for(pait = actions.begin(); pait != actions.end(); pait++){
539  if(pait->Lhs().NextTerminal() == *tdollar && pait->Rhs().NextTerminal() == *tdollar){
540  dollarCount++;
541  }
542  if(pait->Lhs().NextTerminal() == *ta && pait->Rhs().NextTerminal() == *tlambda){
543  aCount++;
544  }
545  if(pait->Lhs().NextTerminal() == *tb && pait->Rhs().NextTerminal() == *tlambda){
546  bCount++;
547  }
548  }
549  if(dollarCount != 4){
550  std::stringstream errstr;
551  errstr << "number of actions for symbol $ of the form (x | $) -> (xy | $) was expected to be 4, but was " << dollarCount << "." << std::endl;
552  throw Exception(name, errstr.str(), 1003);
553  }
554  if(aCount != 2){
555  std::stringstream errstr;
556  errstr << "number of actions for symbol a of the form (x | a) -> (xy | lambda) was expected to be 2, but was " << aCount << "." << std::endl;
557  throw Exception(name, errstr.str(), 1003);
558  }
559  if(bCount != 2){
560  std::stringstream errstr;
561  errstr << "number of actions for symbol b of the form (x | b) -> (xy | $) was expected to be 2, but was " << bCount << "." << std::endl;
562  throw Exception(name, errstr.str(), 1003);
563  }
564  }
565  catch (Exception e){
566  }
567  TestEnd(name);
568 }
569 
570 /* *****************
571  * TestLrpNonterminalsTerminals
572  * *****************/
574  std::string name = "Lrp Nonterminals Terminals";
575  TestStart(name);
576 
577  Grammar gr = TestGrammar9();
578 
579  //create terminals
581  GrammarSymbolPtr ptrta(ta);
583  GrammarSymbolPtr ptrtb(tb);
584  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
585  GrammarSymbolPtr ptrtdollar(tdollar);
587  GrammarSymbolPtr ptrtlambda(tlambda);
588 
589  //create nonterminals
590  std::vector<Idx> v;
591  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
592  Nonterminal* nt1dot = new Nonterminal(1,v);
593  GrammarSymbolPtr ptrnt1dot(nt1dot);
594 
595  v.clear();
596  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("square"));
597  Nonterminal* nt1square = new Nonterminal(1,v);
598  GrammarSymbolPtr ptrnt1square(nt1square);
599 
600  Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
601 
602  GotoGenerator gotoGen = Lrm(augGr, 1);
603  Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
604 
605  try{
606 
607  //number of Nonterminals must be 5
608  std::set<Idx> nonterminals = parser.Nonterminals();
609  if(nonterminals.size() != 5){
610  std::stringstream errstr;
611  errstr << "number of nonterminals was expected to be 5, but was " << nonterminals.size() << "." << std::endl;
612  throw Exception(name, errstr.str(), 1003);
613  }
614 
615  //number of Terminals must be 4
616  std::set<Terminal> terminals = parser.Terminals();
617  if(terminals.size() != 4){
618  std::stringstream errstr;
619  errstr << "number of terminals was expected to be 4, but was " << terminals.size() << "." << std::endl;
620  throw Exception(name, errstr.str(), 1003);
621  }
622 
623  //the augment symbol must be $
624  if(parser.AugSymbol() != *tdollar){
625  std::stringstream errstr;
626  errstr << "the parser's augment symbol was expected to be " << tdollar->Str() << ", but was " << parser.AugSymbol().Str() << "." << std::endl;
627  throw Exception(name, errstr.str(), 1003);
628  }
629  }
630  catch (Exception e){
631  }
632  TestEnd(name);
633 }
634 
635 /* *****************
636  * TestLrParser2EPDAStates
637  * *****************/
639  std::string name = "LrParser2EPDA States";
640  TestStart(name);
641 
642  Grammar gr = TestGrammar9();
643 
644  //create terminals
645  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
646  GrammarSymbolPtr ptrtdollar(tdollar);
647 
648  //get event indices
653 
654  //create state event pairs that are expected to be used in the generator
655  std::vector<MergeStateEvent> sePairs;
656  std::vector<MergeStateEvent>::iterator sePairsit;
657  sePairs.push_back(MergeStateEvent(6,lambdaIdx));
658  sePairs.push_back(MergeStateEvent(6,aIdx));
659  sePairs.push_back(MergeStateEvent(6,bIdx));
660  sePairs.push_back(MergeStateEvent(7,lambdaIdx));
661  sePairs.push_back(MergeStateEvent(7,aIdx));
662  sePairs.push_back(MergeStateEvent(7,bIdx));
663  sePairs.push_back(MergeStateEvent(4,lambdaIdx));
664  sePairs.push_back(MergeStateEvent(5,lambdaIdx));
665  sePairs.push_back(MergeStateEvent(2,dollarIdx));
666  sePairs.push_back(MergeStateEvent(4,dollarIdx));
667  sePairs.push_back(MergeStateEvent(5,dollarIdx));
668 
669  //create nonterminals
670  std::vector<Idx> v;
671  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
672  Nonterminal* nt1dot = new Nonterminal(1,v);
673  GrammarSymbolPtr ptrnt1dot(nt1dot);
674 
675  //create pushdown generator
676  Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
677 
678  GotoGenerator gotoGen = Lrm(augGr, 1);
679  Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
680 
681  //detach augment symbol
682  DetachAugSymbol(parser);
683 
684  // Transform following actions
685  parser = TransformParserAction(parser);
686 
687  PushdownGenerator pd = LrParser2EPDA(parser);
688 
689  try{
690 
691  //number of states must be 7
692  if(pd.Size() != 7){
693  std::stringstream errstr;
694  errstr << "number of states was expected to be 7, but was " << pd.Size() << "." << std::endl;
695  throw Exception(name, errstr.str(), 1003);
696  }
697 
698  //get the states that are actually used
699  StateSet states;
700  TransSet::Iterator transit;
701 
702  //test whether the used states are the expected ones
703  StateSet::Iterator stateit;
704  for(stateit = states.Begin(); stateit != states.End(); stateit++){
705 
706  //get MergeStateEvent
707  const MergeStateEvent* mse = dynamic_cast<const MergeStateEvent*>(pd.StateAttribute(*stateit).Merge());
708  if(mse == NULL){
709  throw Exception(name, "MergeStateEvent not set.", 1003);
710  }
711 
712  //test for existence in expected merge state events
713  bool found = false;
714  for(sePairsit = sePairs.begin(); sePairsit != sePairs.end(); sePairsit++){
715  if(sePairsit->State() == mse->State() && sePairsit->Event() == mse->Event()){
716  found = true;
717  break;
718  }
719  }
720 
721  if(!found){
722  std::stringstream errstr;
723  errstr << "state with MergeStateEvent (" << mse->State() << ", " << PushdownGenerator::GlobalEventSymbolTablep()->Symbol(mse->Event()) << ") was not expected to be in the set of used states." << std::endl;
724  throw Exception(name, errstr.str(), 1003);
725  }
726  }
727 
728  }
729  catch (Exception e){
730  }
731  TestEnd(name);
732 }
733 
734 /* *****************
735  * TestLrParser2EPDATransitions
736  * *****************/
738  std::string name = "LrParser2EPDA Transitions";
739  TestStart(name);
740 
741  Grammar gr = TestGrammar9();
742 
743  //create terminals
744  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
745  GrammarSymbolPtr ptrtdollar(tdollar);
746 
747  //get event indices
752 
753  //create nonterminals
754  std::vector<Idx> v;
755  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
756  Nonterminal* nt1dot = new Nonterminal(1,v);
757  GrammarSymbolPtr ptrnt1dot(nt1dot);
758 
759  //create pushdown generator
760  Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
761 
762  GotoGenerator gotoGen = Lrm(augGr, 1);
763  Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
764 
765  //detach augment symbol
766  DetachAugSymbol(parser);
767 
768  // Transform following actions
769  parser = TransformParserAction(parser);
770  PushdownGenerator pd = LrParser2EPDA(parser);
771 
772  try{
773 
774 
775 
776  int transCount = 0;
777  int aCount = 0;
778  int bCount = 0;
779  int dollarCount = 0;
780  int lambdaCount = 0;
781  int push6Count = 0;
782  int push7Count = 0;
783  int popLambdaCount = 0;
784  int popSize1 = 0;
785  int popSize2 = 0;
786  TransSet::Iterator transit;
787  for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
788 
789  //count events
790  if(transit->Ev == aIdx)
791  aCount++;
792  else if(transit->Ev == bIdx)
793  bCount++;
794  else if(transit->Ev == lambdaIdx)
795  lambdaCount++;
796  else if(transit->Ev == dollarIdx)
797  dollarCount++;
798 
799 
800  PopPushSet popPush = pd.PopPush(*transit);
801  PopPushSet::const_iterator ppit;
802  for(ppit = popPush.begin(); ppit != popPush.end(); ppit++){
803  //count transitions
804  transCount++;
805 
806  //count pops
807  if(ppit->first.size() == 2)
808  popSize2++;
809  else if(ppit->first.size() == 1){
810  popSize1++;
811  if(ppit->first.front() == pd.StackSymbolIndex(FAUDES_PD_LAMBDA))
812  popLambdaCount++;
813  }
814 
815  //count pushes
816  if(ppit->second.size() == 1){
817  if(ppit->second.front() == pd.StackSymbolIndex("6"))
818  push6Count++;
819  else if(ppit->second.front() == pd.StackSymbolIndex("7"))
820  push7Count++;
821  }
822 
823  }
824  }
825 
826  //number of transitions must be 8
827  if(transCount != 8){
828  std::stringstream errstr;
829  errstr << "number of transitions was expected to be 8, but was " << transCount << "." << std::endl;
830  throw Exception(name, errstr.str(), 1003);
831  }
832  //number of a events must be 2
833  if(aCount != 2){
834  std::stringstream errstr;
835  errstr << "number of transitions with the event a was expected to be 2, but was " << aCount << "." << std::endl;
836  throw Exception(name, errstr.str(), 1003);
837  }
838  //number of b events must be 2
839  if(bCount != 2){
840  std::stringstream errstr;
841  errstr << "number of transitions with the event b was expected to be 2, but was " << bCount << "." << std::endl;
842  throw Exception(name, errstr.str(), 1003);
843  }
844  //number of $ events must be 0
845  if(dollarCount != 0){
846  std::stringstream errstr;
847  errstr << "number of transitions with the event $ was expected to be 0, but was " << dollarCount << "." << std::endl;
848  throw Exception(name, errstr.str(), 1003);
849  }
850  //number of lambda events must be 8
851  if(lambdaCount != 4){
852  std::stringstream errstr;
853  errstr << "number of transitions with the event lambda was expected to be 4, but was " << lambdaCount << "." << std::endl;
854  throw Exception(name, errstr.str(), 1003);
855  }
856  //number of 6 pushes must be 0
857  if(push6Count != 0){
858  std::stringstream errstr;
859  errstr << "number of transitions that push 6 was expected to be 0, but was " << push6Count << "." << std::endl;
860  throw Exception(name, errstr.str(), 1003);
861  }
862  //number of 7 pushes must be 0
863  if(push7Count != 0){
864  std::stringstream errstr;
865  errstr << "number of transitions that push 7 was expected to be 0, but was " << push7Count << "." << std::endl;
866  throw Exception(name, errstr.str(), 1003);
867  }
868  //number of transitions that pop 2 stack symbols must be 0
869  if(popSize2 != 0){
870  std::stringstream errstr;
871  errstr << "number of transitions that pop 2 stack symbols was expected to be 0, but was " << popSize2 << "." << std::endl;
872  throw Exception(name, errstr.str(), 1003);
873  }
874  //number of transitions that pop 1 stack symbol must be 8
875  if(popSize1 != 8){
876  std::stringstream errstr;
877  errstr << "number of transitions that pop 1 stack symbol was expected to be 8, but was " << popSize1 << "." << std::endl;
878  throw Exception(name, errstr.str(), 1003);
879  }
880  //number of transitions that pop lambda must be 8
881  if(popLambdaCount != 8){
882  std::stringstream errstr;
883  errstr << "number of transitions that pop lambda was expected to be 8, but was " << popLambdaCount << "." << std::endl;
884  throw Exception(name, errstr.str(), 1003);
885  }
886  }
887  catch (Exception e){
888  }
889  TestEnd(name);
890 }
891 
892 /* *****************
893  * TestDimNoAugment
894  * *****************/
896  std::string name = "Dim No Augment";
897  TestStart(name);
898 
899  Grammar gr = TestGrammar9();
900 
901  //create terminals
902  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
903  GrammarSymbolPtr ptrtdollar(tdollar);
904 
905  //get event indices
907 
908  //create nonterminals
909  std::vector<Idx> v;
910  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
911  Nonterminal* nt1dot = new Nonterminal(1,v);
912  GrammarSymbolPtr ptrnt1dot(nt1dot);
913 
914  //create pushdown generator and diminish it
915  Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
916 
917  GotoGenerator gotoGen = Lrm(augGr, 1);
918  Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
919 
920 
921  //detach augment symbol
922  DetachAugSymbol(parser);
923 
924  // Transform following actions
925  parser = TransformParserAction(parser);
926 
927  PushdownGenerator pdtemp = LrParser2EPDA(parser);
928  PushdownGenerator pd = Dim(pdtemp,*tdollar);
929 
930  try{
931 
932  int transCount = 0;
933  Transition trans;
934  bool dollarFound = false;
935  TransSet::Iterator transit;
936  for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
937  PopPushSet popPush = pd.PopPush(*transit);
938  PopPushSet::const_iterator ppit;
939 
940  //count transitions
941  for(ppit = popPush.begin(); ppit != popPush.end(); ppit++){
942  transCount++;
943  }
944 
945  //look for transitions with $
946  if(transit->Ev == dollarIdx){
947  dollarFound = true;
948  trans = *transit;
949  }
950  }
951 
952  //number of transitions must be 8
953  if(transCount != 8){
954  std::stringstream errstr;
955  errstr << "number of transitions was expected to be 8, but was " << transCount << "." << std::endl;
956  throw Exception(name, errstr.str(), 1003);
957  }
958 
959  //no $ event must be found
960  if(dollarFound){
961  std::stringstream errstr;
962  errstr << "transition "<< trans.Str() << " with event $ was found, but not expected." << std::endl;
963  throw Exception(name, errstr.str(), 1003);
964  }
965 
966  }
967  catch (Exception e){
968  }
969  TestEnd(name);
970 }
971 
972 /* *****************
973  * TestDimNewFinalStates
974  * *****************/
976  std::string name = "Dim Final States";
977  TestStart(name);
978 
979  Grammar gr = TestGrammar9();
980 
981  //create terminals
982  Terminal* tdollar = new Terminal(PushdownGenerator::GlobalEventSymbolTablep()->Index("$"));
983  GrammarSymbolPtr ptrtdollar(tdollar);
984 
985  //get event indices
987 
988  //create nonterminals
989  std::vector<Idx> v;
990  v.push_back(PushdownGenerator::GlobalStackSymbolTablep()->Index("dot"));
991  Nonterminal* nt1dot = new Nonterminal(1,v);
992  GrammarSymbolPtr ptrnt1dot(nt1dot);
993 
994  //create pushdown generator
995  Grammar augGr = Aug(gr, *nt1dot ,*tdollar);
996 
997  GotoGenerator gotoGen = Lrm(augGr, 1);
998  Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, *tdollar);
999 
1000  //detach augment symbol
1001  DetachAugSymbol(parser);
1002 
1003  // Transform following actions
1004  parser = TransformParserAction(parser);
1005 
1006  PushdownGenerator pdtemp = LrParser2EPDA(parser);
1007 
1008  //get indices of states that must be made final after diminishing
1009  TransSet::Iterator transit;
1010  StateSet expectedFinalStates;
1011  for(transit = pdtemp.TransRelBegin(); transit != pdtemp.TransRelEnd(); transit++){
1012  if(transit->Ev == dollarIdx){
1013  expectedFinalStates.Insert(transit->X1);
1014  }
1015  }
1016 
1017  //diminish pushdown generator
1018  PushdownGenerator pd = Dim(pdtemp,*tdollar);
1019 
1020  try{
1021 
1022  StateSet::Iterator stateit;
1023  //test for final states
1024  for(stateit = expectedFinalStates.Begin(); stateit != expectedFinalStates.End(); stateit++){
1025  if(!pd.ExistsMarkedState(*stateit)){
1026  std::stringstream errstr;
1027  errstr << "state " << *stateit << " was expected to be a final state, but was not." << std::endl;
1028  throw Exception(name, errstr.str(), 1003);
1029  }
1030  }
1031  }
1032  catch (Exception e){
1033  }
1034  TestEnd(name);
1035 }
1036 
1037 /* *****************
1038  * TestGeneratorGoto
1039  * *****************/
1043 }
1044 
1045 /* *****************
1046  * TestGeneratorGotoSeq
1047  * *****************/
1051 }
1052 
1053 /* *****************
1054  * TestLrpShiftRules
1055  * *****************/
1058 }
1059 
1060 /* *****************
1061  * TestLrpReduceRules
1062  * *****************/
1065 }
1066 
1067 /* *****************
1068  * TestLrp
1069  * *****************/
1070 void TestLrp(){
1071  TestLrpActions();
1073 }
1074 
1075 /* *****************
1076  * TestLrParser2EPDA
1077  * *****************/
1079 
1082 }
1083 
1084 /* *****************
1085  * TestDim
1086  * *****************/
1087 void TestDim(){
1088  TestDimNoAugment();
1090 }
1091 
1092 } // namespace faudes
1093 

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