pd_alg_lrm.cpp
Go to the documentation of this file.
1 /** @file pd_alg_lrm.cpp functions related to LR machines*/
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_lrm.h"
11 
12 namespace faudes {
13 
14 /* *************************
15  * Desc11
16  * *************************/
17 std::set<Lr1Configuration> Desc11(const Grammar& gr, uint k, const Lr1Configuration& config){
18 
19  //config set to return
20  std::set<Lr1Configuration> rSet;
21 
22  //always contains the original config
23  rSet.insert(config);
24 
25  //check the configuration (A -> B beta . x, y)
26  //if the first symbol B of the afterDot vector is a nonterminal
27  if(config.AfterDot().empty()){
28  return rSet;
29  }
30  NonterminalPtr nt = std::dynamic_pointer_cast<Nonterminal>(config.AfterDot().front());
31  if(nt){
32 
33  //look for productions (B -> w) and insert a new configuration
34  //(B -> lambda . w , firstleq1(gr, k, beta y)) for each production and lookahead
35  std::set<GrammarProduction>::const_iterator gpit;
36  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
37  if(gpit->Lhs() == *nt){
38 
39 
40  //beforeDot for the new configuration is lambda
41  GrammarSymbolVector beforeDot;
43  GrammarSymbolPtr ptrtlambda(tlambda);
44  beforeDot.push_back(ptrtlambda);
45 
46 
47  //lookahead for the new configuration is calculated from the word beta y
48  GrammarSymbolVector word(config.AfterDot().begin() + 1, config.AfterDot().end());
49  Terminal* lookahead = new Terminal(config.Lookahead());
50  GrammarSymbolPtr ptrlookahead(lookahead);
51  word.push_back(ptrlookahead);
52 
53  std::set<Terminal> firstSet = FirstLeq1(gr, k , word);
54  std::set<Terminal>::const_iterator terminalit;
55  //insert new production for each possible lookahead
56  for(terminalit = firstSet.begin(); terminalit != firstSet.end(); terminalit++){
57  Lr1Configuration config(*nt, beforeDot, gpit->Rhs(), *terminalit);
58  rSet.insert(config);
59  }
60  }
61  }
62  }
63  return rSet;
64 }
65 
66 /* *************************
67  * Desc1
68  * *************************/
69 std::set<Lr1Configuration> Desc1(const Grammar& gr, uint k, const std::set<Lr1Configuration>& configs){
70 
71  //config set to return
72  std::set<Lr1Configuration> rSet;
73 
74  std::set<Lr1Configuration>::const_iterator configit;
75  //iterate over all configurations
76  for(configit = configs.begin(); configit != configs.end(); configit++){
77 
78  //get descendants of current configuration and add them to the return set
79  std::set<Lr1Configuration> descSet = Desc11(gr, k, *configit);
80  rSet.insert(descSet.begin(), descSet.end());
81  }
82 
83  return rSet;
84 }
85 
86 /* *************************
87  * Desc
88  * *************************/
89 std::set<Lr1Configuration> Desc(const Grammar& gr, uint k, const std::set<Lr1Configuration>& configs){
90 
91  //config set to return
92  std::set<Lr1Configuration> rSet;
93 
94  //get immediate descendants
95  rSet = Desc1(gr, k, configs);
96 
97  //keep calling recursively if there were changes made
98  //((configs.size == rSet.size && configs != rSet) || configs.size != rSet.size)
99  if((rSet.size() == configs.size() && !std::equal(configs.begin(), configs.end(), rSet.begin())) || rSet.size() != configs.size()){
100 
101  //recursive call
102  rSet = Desc(gr, k, rSet);
103  }
104 
105  return rSet;
106 }
107 
108 /* *************************
109  * PassesX
110  * *************************/
111 std::set<Lr1Configuration> PassesX(const Lr1Configuration& config, const GrammarSymbolPtr& symbol){
112 
113  //config set to return
114  std::set<Lr1Configuration> rSet;
115 
116  //can only shift if there is at least one symbol remaining after the dot
117  if(!config.AfterDot().empty()){
118 
119  //check if it is the right symbol
120  if(*symbol == *config.AfterDot().front()){
121 
123  GrammarSymbolPtr ptrtlambda(tlambda);
124 
125  //create new configuration
126  //(A -> a . X b, y) becomes (A -> a X . b, y)
127 
128  //construct beforeDot
129  GrammarSymbolVector beforeDot = config.BeforeDot();
130  //if beforeDot contains only lambda, clear it before adding X
131  if(*beforeDot.front() == *ptrtlambda){
132  beforeDot.clear();
133  }
134  beforeDot.push_back(config.AfterDot().front());
135 
136  //construct afterDot
137  GrammarSymbolVector afterDot(config.AfterDot().begin() + 1, config.AfterDot().end());
138 
139  //if afterDot is empty, insert lambda
140  if(afterDot.empty()){
141 
142  afterDot.push_back(ptrtlambda);
143  }
144 
145 
146  Lr1Configuration shiftedConfig(config.Lhs(), beforeDot, afterDot, config.Lookahead());
147 
148  //insert new configuration into set
149  rSet.insert(shiftedConfig);
150  }
151  }
152  return rSet;
153 }
154 
155 /* *************************
156  * Basis
157  * *************************/
158 std::set<Lr1Configuration> Basis(const std::set<Lr1Configuration> configs, const GrammarSymbolPtr& symbol){
159 
160  //config set to return
161  std::set<Lr1Configuration> rSet;
162 
163  std::set<Lr1Configuration> shiftSet;
164  std::set<Lr1Configuration>::const_iterator configit;
165  //iterate over all configurations
166  for(configit = configs.begin(); configit != configs.end(); configit++){
167 
168  //try to shift the dot
169  shiftSet = PassesX(*configit,symbol);
170 
171  //if successful, insert shifted configuration into result set
172  if(!shiftSet.empty()){
173  rSet.insert(*shiftSet.begin());
174  }
175  }
176  return rSet;
177 }
178 
179 /* *************************
180  * GoTo
181  * *************************/
182 std::set<Lr1Configuration> GoTo(const Grammar& gr, uint k, const std::set<Lr1Configuration> configs, const GrammarSymbolPtr& symbol){
183 
184  //obtain shifted configurations
185  std::set<Lr1Configuration> shiftSet = Basis(configs, symbol);
186 
187  //return the shifted configuration's descendants
188  return Desc(gr, k, shiftSet);
189 }
190 
191 /* *************************
192  * Lrm1
193  * *************************/
194 LrmTransitionMap Lrm1(const Grammar& gr, uint k, const Lr1ConfigurationSetSet& configSetSet){
195 
196  //config set map to return
197  LrmTransitionMap rTransitions;
198 
199  Lr1ConfigurationSetSet::const_iterator configssit;
201  //iterate over all configuration sets
202  for(configssit = configSetSet.begin(); configssit != configSetSet.end(); configssit++){
203 
204  std::set<Nonterminal>::const_iterator ntit;
205  std::set<Terminal>::const_iterator tit;
206  //determine the possible next configuration set for every terminal
207  for(tit = gr.TerminalsBegin(); tit != gr.TerminalsEnd(); tit++){
208 
209  //dont consider lambda!
210  if(*tit == lambda){
211  continue;
212  }
213 
214  Terminal* t = new Terminal(*tit);
215  GrammarSymbolPtr tptr(t);
216  //get next configuration set
217  std::set<Lr1Configuration> nextConfigSet = GoTo(gr, k, *configssit, tptr);
218 
219  //if the config set is not empty
220  if(!nextConfigSet.empty()){
221 
222  //insert it into transition map
223  ConfigSetGsPair configSetGsPair = std::make_pair(*configssit, tptr);
224  rTransitions.insert(std::make_pair(configSetGsPair, nextConfigSet));
225  }
226  }
227 
228  //determine the possible next configuration set for every nonterminal
229  for(ntit = gr.NonterminalsBegin(); ntit != gr.NonterminalsEnd(); ntit++){
230 
231  Nonterminal* nt = new Nonterminal(*ntit);
232  GrammarSymbolPtr ntptr(nt);
233  //get next configuration set
234  std::set<Lr1Configuration> nextConfigSet = GoTo(gr, k, *configssit, ntptr);
235 
236  //if the config set is not empty
237  if(!nextConfigSet.empty()){
238 
239  //insert it into transition map
240  ConfigSetGsPair configSetGsPair = std::make_pair(*configssit, ntptr);
241  rTransitions.insert(std::make_pair(configSetGsPair, nextConfigSet));
242  }
243  }
244  }
245  return rTransitions;
246 }
247 
248 /* *************************
249  * LrmLoop
250  * *************************/
251 std::pair<LrmTransitionMap,Lr1ConfigurationSetSet> LrmLoop(const Grammar& gr, uint k, const LrmTransitionMap& transitions, const Lr1ConfigurationSetSet& states, Lr1ConfigurationSetSet examineStates){
252 
253  //save states that are already found
254  Lr1ConfigurationSetSet foundStates(states);
255  foundStates.insert(examineStates.begin(), examineStates.end());
256 
257  //pair to return if no new transition is found
258  std::pair<LrmTransitionMap,Lr1ConfigurationSetSet> rPair;
259  rPair = std::make_pair(transitions, foundStates);
260 
261  //calculate new transitions
262  LrmTransitionMap newTransitions = Lrm1(gr, k, examineStates);
263 
264  //if new transitions were found
265  if(!newTransitions.empty()){
266 
267  //determine states that need to be looked at in the next recursive iteration
268  //(i. e., the successor states of the transitions)
269  Lr1ConfigurationSetSet newExamineStates;
270  LrmTransitionMap::const_iterator transit;
271  for(transit = newTransitions.begin(); transit != newTransitions.end(); transit++){
272  newExamineStates.insert(transit->second);
273  }
274 
275  Lr1ConfigurationSetSet::const_iterator stateit;
276  //remove states that were already visited
277  for(stateit = foundStates.begin(); stateit != foundStates.end(); stateit++){
278  newExamineStates.erase(*stateit);
279  }
280 
281  //recursively look for new transitions and states
282  newTransitions.insert(transitions.begin(), transitions.end());
283  rPair = LrmLoop(gr, k , newTransitions, foundStates, newExamineStates);
284  }
285  return rPair;
286 }
287 
288 /* *************************
289  * DescInitial
290  * *************************/
291 std::set<Lr1Configuration> DescInitial(const Grammar& gr){
292 
293  //item set to return
294  std::set<Lr1Configuration> rSet;
295 
296  std::set<GrammarProduction>::const_iterator gpit;
297  //look for initial grammar productions (S,w)
298  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
299  if(gpit->Lhs() == gr.StartSymbol()){
300 
301  //insert configuration (S -> lambda . w, lambda)
303  GrammarSymbolPtr ptrtlambda(tlambda);
304 
305  GrammarSymbolVector beforeDot;
306  beforeDot.push_back(ptrtlambda);
307 
308  rSet.insert(Lr1Configuration(gpit->Lhs(), beforeDot, gpit->Rhs(), *tlambda));
309  }
310  }
311  return rSet;
312 }
313 
314 /* *************************
315  * ValidEmpty
316  * *************************/
317 std::set<Lr1Configuration> ValidEmpty(const Grammar& gr, uint k){
318 
319  //item set to return
320  std::set<Lr1Configuration> rSet;
321 
322  //get initial configurations
323  rSet = DescInitial(gr);
324 
325  //get descendants of the initial configurations
326  rSet = Desc(gr, k, rSet);
327 
328  return rSet;
329 }
330 
331 /* *************************
332  * Lrm
333  * *************************/
335 
336  //generator to return
337  GotoGenerator gotoGen;
338 
339  //get the initial state
340  std::set<Lr1Configuration> initState = ValidEmpty(gr, k);
341 
342  //get the transitions and states
343  Lr1ConfigurationSetSet initStateSet;
344  initStateSet.insert(initState);
345  std::pair<LrmTransitionMap,Lr1ConfigurationSetSet> transitionsStates= LrmLoop(gr, k, LrmTransitionMap(), Lr1ConfigurationSetSet(), initStateSet);
346 
347  Lr1ConfigurationSetSet::const_iterator stateit;
348  //insert states of the generator
349  for(stateit = transitionsStates.second.begin(); stateit != transitionsStates.second.end(); stateit++){
350  Idx idx = gotoGen.InsState();
351  gotoGen.ConfigSet(idx, *stateit);
352 
353  //if the current config equals the init config, set init state
354  if(!(CompareConfigSet(*stateit, initState) || CompareConfigSet(initState, *stateit))){
355  gotoGen.SetInitState(idx);
356  }
357  }
358 
359  //insert transitions into the generator
360  LrmTransitionMap::const_iterator transit;
361  for(transit = transitionsStates.first.begin(); transit != transitionsStates.first.end(); transit++){
362  Idx startState = gotoGen.StateIndex(transit->first.first);
363  Idx endState = gotoGen.StateIndex(transit->second);
364  GrammarSymbolPtr symbol = transit->first.second;
365 
366  gotoGen.SetTransition(startState, symbol, endState);
367  }
368 
369  //save transitions and states the a gotoMachine
370 // gotoMachine.InitState(initState);
371 // gotoMachine.Transitions(transitionsStates.first);
372 // gotoMachine.States(transitionsStates.second);
373 
374  gotoGen.SWrite();
375 
376  return gotoGen;
377 }
378 
379 /* *************************
380  * Aug
381  * *************************/
382 Grammar Aug(const Grammar& gr, const Nonterminal& startSymbol, const Terminal& augSymbol){
383 
384  //grammar to return
385  Grammar rGr = gr;
386 
387  //try to set startSymbol S as the new start symbol and throw an exception
388  //if it is already contained in the grammar's nonterminals
389  if(!rGr.SetStartSymbol(startSymbol)){
390  std::stringstream errstr;
391  errstr << "While executing Aug(): Tried to insert new startSymbol " << startSymbol.Str() << ", but it already existed in the grammar" << std::endl;
392  throw Exception("Aug", errstr.str(), 1001);
393  }
394 
395  //try to insert augSymbol $ into the grammar's terminals and throw an exception if
396  //it is already contained in the grammar's terminals
397  if(!rGr.InsTerminal(augSymbol)){
398  std::stringstream errstr;
399  errstr << "While executing Aug(): Tried to insert new augSymbol " << augSymbol.Str() << ", but it already existed in the grammar" << std::endl;
400  throw Exception("Aug", errstr.str(), 1001);
401  }
402 
403  //get old startSymbol S'
404  Nonterminal* oldStartSymbol = new Nonterminal(gr.StartSymbol());
405  GrammarSymbolPtr oldStartSymbolPtr(oldStartSymbol);
406 
407  //get Pointer to augSymbol
408  Terminal* augSymbolTemp = new Terminal(augSymbol);
409  GrammarSymbolPtr augSymbolPtr(augSymbolTemp);
410 
411  //construct new production's right-hand side $ S' $
413  rhs.push_back(augSymbolPtr);
414  rhs.push_back(oldStartSymbolPtr);
415  rhs.push_back(augSymbolPtr);
416 
417  //construct new Production S -> $ S' $ and insert into grammar
418  GrammarProduction gp(startSymbol,rhs);
419  rGr.InsGrammarProduction(gp);
420 
421  return rGr;
422 }
423 
424 
425 } // namespace faudes
426 

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