pd_alg_first.cpp
Go to the documentation of this file.
1 /** @file pd_alg_first.cpp functions related to the first function*/
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 
10 #include "pd_alg_first.h"
11 
12 namespace faudes {
13 
14 
15 /* *************************
16  * PostCl
17  * *************************/
19 
21  GrammarSymbolVector postfix;
22  GrammarSymbolVector::const_reverse_iterator vit;
23  //iterate backwards over the word, thus building all postfixes
24  for(vit = word.rbegin(); vit != word.rend(); vit++){
25 
26  postfix.insert(postfix.begin(),*vit);
27  rSet.insert(postfix);
28  }
29 
30  //lambda always belongs in the set
31  GrammarSymbolVector lambda;
33  GrammarSymbolPtr ptr(tlambda);
34  lambda.push_back(ptr);
35  rSet.insert(lambda);
36 
37  return rSet;
38 }
39 
40 /* *************************
41  * Fds
42  * *************************/
44 
45  GrammarSymbolWordSet rSet, postfixSet;
46  GrammarSymbolVector gsVector;
47  std::set<GrammarProduction>::const_iterator gpit;
48 
49  //iterate over all grammar productions
50  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
51 
52  gsVector.clear();
53 
54  //add lefthand side
55  Nonterminal* nt = new Nonterminal(gpit->Lhs());
56  NonterminalPtr ntPtr(nt);
57  gsVector.push_back(ntPtr);
58  rSet.insert(gsVector);
59 
60  //add postfixes of righthand side
61  postfixSet = PostCl(gpit->Rhs());
62  rSet.insert(postfixSet.begin(), postfixSet.end());
63 
64  }
65  return rSet;
66 }
67 
68 /* *************************
69  * First1
70  * *************************/
71 GrammarSymbolWordMap First1(const Grammar& gr, const GrammarSymbolWordMap& f, bool* madeChanges){
72 
73  //take a copy rf of the old first function f for extending and returning
74  GrammarSymbolWordMap rf = f;
75 
76  //helper variable to determine if changes were made from f to rf
77  bool changed = false;
78  *madeChanges = false;
79 
80  //get all postfixes and lefthand sides of the grammar
81  GrammarSymbolWordSet words = Fds(gr);
82 
83  GrammarSymbolWordSet::const_iterator wordit;
84  std::set<Terminal>::const_iterator insertWordit;
85 
86  std::set<GrammarProduction>::const_iterator gpit;
87  //for every word w in Fds(gr)
88  for(wordit = words.begin(); wordit != words.end(); wordit++){
89 
90  //get the first symbol of the word w = a.w'
91  GrammarSymbolPtr firstSymbol = wordit->front();
92 
93  //if the first symbol is a terminal
94  TerminalPtr terminalA = std::tr1::dynamic_pointer_cast<Terminal>(firstSymbol);
95  if(terminalA != NULL){
96 
97  std::set<Terminal> rfw;
98  //add the terminal to the first function rf
99  //if w does not already exist in rf, create it
100  if(rf.find(*wordit) == rf.end()){
101  rf.insert(std::make_pair(*wordit, std::set<Terminal>()));
102  }
103 
104  //add rf(w) = a to the first function rf
105  changed = rf.find(*wordit)->second.insert(*terminalA).second;
106  if(changed) *madeChanges = true;
107  }
108 
109  //if the first symbol is a nonterminal
110  NonterminalPtr nonterminalA = std::tr1::dynamic_pointer_cast<Nonterminal>(firstSymbol);
111  if(nonterminalA != NULL){
112 
113  std::set<Terminal> directDependencies;
114 
115  //get the first symbols f(x) for every production (a-->x)
116  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
117 
118  //check if the production has the nonterminal a on its lefthand side and if the
119  //righthand side x exists in f
120  if(gpit->Lhs() == *nonterminalA){
121  if(f.find(gpit->Rhs()) != f.end()){
122 
123  //get f(x) and add it to directDependencies
124  std::set<Terminal> fx = f.find(gpit->Rhs())->second;
125  directDependencies.insert(fx.begin(),fx.end());
126  }
127  }
128  }
129 
130  //construct the symbol a ...
132  a.push_back(nonterminalA);
133  //... and get the first symbols of a (f(a))
134  std::set<Terminal> fa;
135  if(f.find(a) != f.end()){
136  fa = f.find(a)->second;
137  }
138 
139  //get w' (the second part of the current word w = a.w'),
140  GrammarSymbolVector wBack(wordit->begin() + 1, wordit->end());//can never go out of bounds because of outermost for loop
141 
142  //if w' is not empty, remove lambda from f(a) and the direct dependencies,
143  //because eliminability of a does not imply eliminability of w'
144  GrammarSymbolVector lambdaWord;
146 
147  //remove lambda and remember for later if lambda was in f(a)
148  bool faContainsLambda = false;
149  if(!wBack.empty()){
150  if(fa.erase(tlambda) == 1){
151  faContainsLambda = true;
152  }
153  directDependencies.erase(tlambda);
154  }
155 
156  //add new items to rf(w)
157  std::set<Terminal> rfw;
158  //if w does not already exist in rf, create it
159  if(rf.find(*wordit) == rf.end()){
160  rf.insert(std::make_pair(*wordit, std::set<Terminal>()));
161  }
162 
163  //add f(a)
164  for(insertWordit = fa.begin(); insertWordit != fa.end(); insertWordit++){
165  changed = rf.find(*wordit)->second.insert(*insertWordit).second;
166  if(changed) *madeChanges = true;
167  }
168 
169  //add direct dependencies
170  for(insertWordit = directDependencies.begin(); insertWordit != directDependencies.end(); insertWordit++){
171  changed = rf.find(*wordit)->second.insert(*insertWordit).second;
172  if(changed) *madeChanges = true;
173  }
174 
175  //if a is eliminable, add f(w') to f(w)
176  if(faContainsLambda){
177  std::set<Terminal> fwBack;
178  //get f(w')
179  if(f.find(wBack) != f.end()){
180  fwBack = f.find(wBack)->second;
181  }
182 
183  //add f(w')
184  for(insertWordit = fwBack.begin(); insertWordit != fwBack.end(); insertWordit++){
185  changed = rf.find(*wordit)->second.insert(*insertWordit).second;
186  if(changed) *madeChanges = true;
187  }
188  }
189  }
190  }
191  return rf;
192 }
193 
194 /* *************************
195  * FirstL
196  * *************************/
198 
199  //calculate first function
200  bool changed;
201  GrammarSymbolWordMap fNew = First1(gr,f,&changed);
202 
203  //repeat until no changes are made
204  if(changed){
205  fNew = FirstL(gr,fNew);
206  }
207 
208  return fNew;
209 }
210 
211 /* *************************
212  * FirstA
213  * *************************/
214 std::set<Terminal> FirstA(const Grammar& gr, const GrammarSymbolVector& word){
215 
216  //calculate first function
217  GrammarSymbolWordMap f = FirstL(gr,f);
218 
219  GrammarSymbolWordMap::const_iterator fit = f.find(word);
220  if(fit == f.end()){
221  GrammarSymbolVector::const_iterator vit;
222  std::stringstream errstr;
223  errstr << "word " << std::endl;
224  for(vit = word.begin(); vit != word.end(); vit++){
225  errstr << (*vit)->Str();
226  }
227  errstr << " was not found in the first function";
228  throw Exception("FirstA", errstr.str(), 1001);
229  }
230 
231  return fit->second;
232 }
233 
234 /* *************************
235  * First
236  * *************************/
237 std::set<Terminal> First(const Grammar& gr, const GrammarSymbolVector& word){
238 
239  //"empty" words must still contain lambda!
240  if(word.empty()){
241  std::stringstream errstr;
242  errstr << "word parameter was empty. try calling it with lambda instead of an empty vector.";
243  throw Exception("First", errstr.str(), 1001);
244  }
245 
246  //set of nonterminals to return
247  std::set<Terminal> rSet;
248 
249  //if the first symbol of the word is a terminal (or lambda)
250  TerminalPtr t = std::tr1::dynamic_pointer_cast<Terminal>(word.front());
251  if(t != NULL) {
252 
253  //insert the terminal (can be lambda)
254  rSet.insert(*t);
255  }
256 
257  //if the first symbol of the word is a nonterminal
258  NonterminalPtr nt = std::tr1::dynamic_pointer_cast<Nonterminal>(word.front());
259  if(nt != NULL){
260 
261  //get first set of the nonterminal
263  v.push_back(nt);
264  rSet = FirstA(gr,v);
265 
266  //if the word contains more symbols and the set contains, it needs to erased
267  //be removed from the set
268  if(word.size() > 1){
269 
271  //the set contains lambda (the nonterminal is eliminable). the remaining word
272  //needs to be examined
273  if(rSet.erase(tlambda) == 1){
274 
275  //recursive call of first
276  std::set<Terminal> recSet = First(gr, GrammarSymbolVector(word.begin() + 1, word.end()));
277  rSet.insert(recSet.begin(), recSet.end());
278  }
279  }
280  }
281  return rSet;
282 }
283 
284 /* *************************
285  * FirstRed
286  * *************************/
287 std::set<Terminal> FirstRed(const Grammar& gr, const GrammarSymbolVector& word){
288 
289  //set to return
290  std::set<Terminal> rSet;
291 
292  //if every symbol of the word is a symbol of the grammar, the word is consistent
293  bool consistent = true;
294  GrammarSymbolVector::const_iterator wordit;
295  std::set<Terminal>::const_iterator tit;
296  std::set<Nonterminal>::const_iterator ntit;
297 
298  //check every symbol of the word
299  for(wordit = word.begin(); wordit != word.end(); wordit++){
300 
301  //if it's a terminal
302  TerminalPtr t = std::tr1::dynamic_pointer_cast<Terminal>(*wordit);
303  if(t != NULL) {
304  //if it's not in the grammar's terminals
305  if(gr.Terminals().find(*t) == gr.TerminalsEnd()){
306  consistent = false;
307  break;
308  }
309  }
310 
311  //if it's a nonterminal
312  NonterminalPtr nt = std::tr1::dynamic_pointer_cast<Nonterminal>(*wordit);
313  if(nt != NULL) {
314  //if it's not in the grammar's nonterminals
315  if(gr.Nonterminals().find(*nt) == gr.NonterminalsEnd()){
316  consistent = false;
317  break;
318  }
319  }
320  }
321 
322  //call first only if it's consistent
323  if(consistent){
324  rSet = First(gr, word);
325  }
326  //else return empty set
327  return rSet;
328 }
329 
330 /* *************************
331  * Filter1
332  * *************************/
333 NonterminalPtr Filter1(const std::set<Nonterminal>& symbolSet, const GrammarSymbolVector& w){
334 
335  GrammarSymbolVector::const_iterator wit;
336  std::set<Nonterminal>::const_iterator ntit;
337  //iterate over all symbols of the word
338  for(wit = w.begin(); wit != w.end(); wit++){
339  //test if current symbol is a nonterminal
340  ConstNonterminalPtr nt = std::tr1::dynamic_pointer_cast<const Nonterminal>(*wit);
341  if(nt != NULL){
342 
343  //look for the symbol in the nonterminal set
344  ntit = symbolSet.find(*nt);
345 
346  //if the symbol was found, return it
347  if(ntit != symbolSet.end()){
348  Nonterminal* rNt = new Nonterminal(*nt);
349  return NonterminalPtr(rNt);
350  }
351  }
352  }
353  //else return NULL
354  return NonterminalPtr();
355 }
356 
357 /* *************************
358  * FirstAll
359  * *************************/
360 std::set<Terminal> FirstAll(const Grammar& gr, const GrammarSymbolVector& word){
361 
362  //set to return
363  std::set<Terminal> rSet;
364 
365  //get nonterminals contained in the word
366  std::set<Nonterminal> filterSet = Filter(gr.Nonterminals(), word);
367 
368  //if no nonterminals were found, call First
369  if(filterSet.empty()){
370  rSet = First(gr, word);
371  }
372  //if nonterminals were found
373  else{
374 
375  //create temporary grammar with the first nonterminal as a start symbol
376  Grammar tempGr = gr;
377  NonterminalPtr firstNt = Filter1(gr.Nonterminals(), word);
378  tempGr.SetStartSymbol(*firstNt);
379  //remove nonproducte productions from this grammar
380  Grammar optGr = Rnpp(tempGr);
381  //if the grammar is not empty, call FirstRed
382  if(!optGr.GrammarProductions().empty()){
383  rSet = FirstRed(optGr, word);
384  }
385  }
386 
387  return rSet;
388 }
389 
390 /* *************************
391  * FirstLeq1
392  * *************************/
393 std::set<Terminal> FirstLeq1(const Grammar& gr, uint k, const GrammarSymbolVector& word){
394 
395  //set to return
396  std::set<Terminal> rSet;
397 
398  //if k > 1, return empty set
399  if(k > 1){
400  return rSet;
401  }
402 
403  //else determine first set
404  rSet = FirstAll(gr, word);
405 
406  //if k == 0 and the first set is not empty, return lambda as first set
407  if(k == 0 && !rSet.empty()){
409 
410  rSet.clear();
411  rSet.insert(tlambda);
412  }
413 
414  return rSet;
415 }
416 
417 /* *****************
418  * WriteMap
419  * *****************/
420 void WriteMap(GrammarSymbolWordMap f, bool changed){
421 
422  GrammarSymbolWordMap::const_iterator fit;
423  std::set<Terminal>::const_iterator setit;
424  GrammarSymbolVector::const_iterator wordit;
425  std::stringstream mapstr;
426  mapstr << "************************************************" << std::endl;
427  mapstr << "changes made:";
428  if(changed) mapstr << "yes" << std::endl;
429  else mapstr << "no" << std::endl;
430  mapstr << std::endl;
431  for(fit = f.begin(); fit != f.end(); fit++){
432 
433  for(wordit = fit->first.begin(); wordit != fit->first.end(); wordit++){
434  mapstr << (*wordit)->Str();
435  }
436 
437  mapstr << ": ";
438  mapstr << std::endl << " ";
439  for(setit = fit->second.begin(); setit != fit->second.end(); setit++){
440  if(setit != fit->second.begin()){
441  mapstr << ", ";
442  }
443  mapstr << (*wordit)->Str();
444  }
445  mapstr << std::endl;
446  }
447 
448  std::cout << mapstr.str() << std::endl;
449 }
450 
451 } // namespace faudes
452 

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