]> rtime.felk.cvut.cz Git - boost-statechart-viewer.git/blob - src/stringoper.h
Correct error when printing multiple transitions in the state.
[boost-statechart-viewer.git] / src / stringoper.h
1 /** @file */ 
2 ////////////////////////////////////////////////////////////////////////////////////////  
3 //    
4 //    This file is part of Boost Statechart Viewer.
5 //
6 //    Boost Statechart Viewer is free software: you can redistribute it and/or modify
7 //    it under the terms of the GNU General Public License as published by
8 //    the Free Software Foundation, either version 3 of the License, or
9 //    (at your option) any later version.
10 //
11 //    Boost Statechart Viewer is distributed in the hope that it will be useful,
12 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //    GNU General Public License for more details.
15 //
16 //    You should have received a copy of the GNU General Public License
17 //    along with Boost Statechart Viewer.  If not, see <http://www.gnu.org/licenses/>.
18 //
19 ////////////////////////////////////////////////////////////////////////////////////////
20
21 #include <string>
22
23 using namespace std;
24 using namespace clang;
25         
26 string clean_spaces(const string line) /** Remove gaps from string.*/
27 {
28         unsigned i;
29         string new_line = "";
30         for(i = 0;i<line.length();i++)
31         {
32                 if(!isspace(line[i])) new_line+=line[i];
33         }
34         //cout<<new_line;
35         return new_line;
36 }
37
38 string cut_commentary(const string line) /** This function cuts commentaries at the end of line. */
39 {
40         unsigned i = 0;
41         for(i = 0;i<line.length()-1;i++)
42         {
43                 if(line[i]=='/' && line[i+1]=='/') return line.substr(0,i);
44                 if(line[i]=='/' && line[i+1]=='*') return line.substr(0,i);
45         }
46         return line;
47 }
48
49 string get_line_of_code(const string code) /** Thie function return the line of code that belongs to a declaration. The output string line doesn't have gaps and commentaries.*/
50 {
51         string ret;     
52         unsigned i;     
53         for(i = 0;i<code.length();i++)
54         {
55                 if(code[i]=='\n'||code[i]=='{') break;
56         }
57         ret = code.substr(0,i);
58         ret = clean_spaces(ret);
59         return cut_commentary(ret);
60
61
62 string get_return(const string code) /** Return return statement. */
63 {
64         string ret;     
65         unsigned i;
66         for(i = 0;i<code.length();i++)
67         {
68                 if(code[i]==' ') break;
69         }
70         return code.substr(0,i);
71 }
72
73 string cut_namespaces(string line) /** Cut namespaces from the declarations. */
74 {
75         int i;
76         int brackets = 0;
77         for(i = line.length()-1;i>0;i--)
78         {
79                 if(line[i]=='<') brackets+=1;
80                 if(line[i]=='>') brackets-=1;
81                 if(line[i]==':' && line[i-1]==':')
82                 {
83                         if(brackets == 0) break;
84                         else i--;
85                 }
86         }
87         if(i==0) return line;
88         return line.substr(i+1);
89 }
90
91 string cut_namespaces(string line, int ortho) /** Cut namespaces ORTHOGONAL STATES. */
92 {
93         int i;
94         int brackets = 0;
95         for(i = line.length()-1;i>0;i--)
96         {
97                 if(line[i]=='<') brackets+=1;
98                 if(line[i]=='>') brackets-=1;
99                 if(line[i]==':' && line[i-1]==':')
100                 {
101                         if(brackets == 0) break;
102                         else i--;
103                 }
104         }
105         if(i==0) return line;
106         return line.substr(0,i-1);
107 }
108
109 bool is_derived(const string line) /** Test whether this struct or class is derived */
110 {
111         unsigned i;
112         for(i = 0;i<line.length()-2;i++)
113         {
114                 if(line[i]==':')
115                 {
116                         if(line[i+1]!=':') return true;
117                         else i+=1;
118                 }
119         }
120         return false;
121 }
122
123 string get_super_class(const string line) /** Get the super classes of this declarations. */
124 {
125         unsigned i;
126         for(i = 0;i<line.length()-1;i++)
127         {
128                 if(line[i]==':')
129                 {
130                         if(line[i+1]!=':') break;
131                         else i+=1;
132                 }
133         }
134         return line.substr(i+1);
135 }
136
137 string get_next_base(const string line) /** Get next super classes of this declarations Do the first super class is ommitted. */
138 {
139         unsigned i;
140         int brackets = 0;
141         for(i = 0;i<line.length()-1;i++)
142         {
143                 if(line[i]=='<') brackets+=1;
144                 if(line[i]=='>') brackets-=1;
145                 if(line[i]==',' && brackets == 0) break;
146         }
147         return line.substr(i+1);
148 }  
149
150 string get_first_base(const string line) /** Get the first super class of this declarations. */
151 {
152         unsigned i;
153         int brackets = 0;
154         for(i = 0;i<line.length()-1;i++)
155         {
156                 if(line[i]=='<') brackets+=1;
157                 if(line[i]=='>') brackets-=1;
158                 if(line[i]==',' && brackets == 0) break;
159         }
160         return line.substr(0,i);
161 }  
162
163 bool is_state(const string line) /** Test if this declaration is a state. It is used to test the base classes. */
164 {
165         if(cut_namespaces(line).compare(0,12,"simple_state")==0)
166         {
167                 return true;    
168         }
169         else
170         {
171                 if(cut_namespaces(line).compare(0,5,"state")==0)
172                 {
173                         return true;    
174                 }
175                 return false;
176         }
177 }
178
179 string cut_type(string line) /** This function cuts type of the declaration from the string. */
180 {
181         unsigned i;
182         for(i = 0;i<line.length();i++)
183         {
184                 if(line[i]==' ') break;
185         }
186         return line.substr(i);
187 }
188
189 int count(const string line, const char c) /** Count all specified char in string. So it returns the number of specified characters. */
190 {
191         int number = 0;
192         for(unsigned i = 0;i<line.length();i++)
193         {
194                 if(line[i]==c) number+=1;
195         }
196         return number;
197 }
198
199 bool is_list(const string line) /** Test if this decl is mpl::list. */
200 {
201         //cout<<line<<"\n";
202         int pos = 0;
203         for(unsigned i = 0; i<line.length();i++)
204         {
205                 if(line[i]=='<') break;
206                 if(line[i]==':' && line[i+1]==':') pos = i+2;
207         }       
208         if(line.substr(pos).compare(0,4,"list")==0)
209         {
210                 return true;    
211         }
212         else
213         {
214                 return false;
215         }
216 }
217
218 string get_inner_part(const string line) /** Get inner part of the list. */
219 {
220         string str;
221         unsigned i, pos = 0;
222         for(i = 0;i<line.length();i++)
223         {
224                 if(line[i]=='<') break;
225         }
226         str = line.substr(i+1);
227         for(i = 0;i<str.length();i++)
228         {
229                 if(str[i]=='<') pos+=1;
230                 if(str[i]=='>')
231                 { 
232                         if(pos==0) break;
233                         else pos-=1;
234                 }
235         }
236         return str.substr(0,i);
237 }
238
239 int get_model(const string line) /** Test the string to has a specified model. */
240 {
241         string str = cut_namespaces(line);
242         if(str.find("<")<str.length()) str = str.substr(0,str.find("<"));
243         switch(str.length())
244         {
245                 case 5 : if(str.compare(0,5,"event")==0) return 1;
246                                         break;
247                 case 6 : if(str.compare(0,6,"result")==0) return 5;
248                                    break;
249                 case 7 : if(str.compare(0,7,"transit")==0) return 6;
250                                    break;
251                 case 8 : if(str.compare(0,8,"deferral")==0) return 13;
252                                    break;               
253                 case 10 : if(str.compare(0,10,"transition")==0) return 11;
254                                          break;
255                 case 11 : if(str.compare(0,11,"defer_event")==0) return 7;
256                                          break; 
257                 case 13 : if(str.compare(0,13,"state_machine")==0) return 3;
258                                          break;
259                 case 15 : if(str.compare(0,15,"custom_reaction")==0) return 12;
260                                          break;
261                 default : return -1;
262         }
263 }
264
265 string get_params(string line) /** Return parameters of the specified transition */
266 {
267         int pos_front = line.find("<")+1;
268         int pos_end = line.rfind(">");
269         return line.substr(pos_front,pos_end-pos_front);
270 }
271         
272 string find_states(const CXXRecordDecl *cRecDecl, string line) /** test if the struct/class is he state (must be derived from simple_state or state). */
273 {       
274         string super_class = get_super_class(line), base, params;
275         if(cRecDecl->getNumBases()>1)
276         {
277                 
278                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
279                 {
280                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
281                         else base = super_class;
282                         if(is_state(super_class)) 
283                         {
284                                 params = get_params(super_class);
285                         }
286                         else
287                         {
288                                 super_class = get_next_base(super_class);
289                         }
290                 }
291         }
292         else
293         {               
294                 if(is_state(super_class)) 
295                 {                       
296                         params = get_params(super_class);
297                 }
298                 else params = "";
299         }
300         return params;
301 }
302                 
303 string find_name_of_machine(const CXXRecordDecl *cRecDecl, string line) /** Find name of the state machine and the start state. */
304 {       
305         string super_class = get_super_class(line), base, params;
306         if(cRecDecl->getNumBases()>1)
307         {
308                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
309                 {
310                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
311                         else base = super_class;
312                         if(get_model(base)==3)
313                         {
314                                 params = get_params(base);
315                         }
316                         else
317                         {
318                                 super_class = get_next_base(super_class);
319                         }
320                 }
321         }
322         else
323         { 
324                 if(get_model(super_class)==3)
325                 {
326                         params = get_params(super_class);
327                 }
328         }
329         return params;
330 }
331
332 string find_transitions (const string name_of_state, string line) /** Traverse all methods for finding declarations of transitions. */
333 {       
334         string dest, params, base, trans;
335         int num = count(line,'<');      
336         if(num>1)
337         {
338                 num-=1;
339                 if(is_list(line))
340                 {
341                         line = get_inner_part(line);
342                 }
343         }
344         for(int j = 0;j<num;j++)
345         {
346                 if(j!=num-1) base = get_first_base(line);                       
347                 else base = line;
348                 if(get_model(base)>10)
349                 {
350                         if(get_model(base)==12) dest = ";";
351                         else if (get_model(base) == 13) dest = ",";
352                         else dest = "";
353                         dest.append(name_of_state);
354                         params = get_params(base);
355                         dest.append(",");                                                       
356                         dest.append(params);
357                         trans.append(dest);             
358                         if(j!=num-1) trans.append(";");
359                 }
360                 line = get_next_base(line);
361         }
362         if(trans[trans.length()-1]==';') return trans.substr(0,trans.length()-1);
363         else return trans;      
364 }
365
366 bool find_events(const CXXRecordDecl *cRecDecl, string line) /** This function provides testing if the decl is decl of event*/
367 {       
368         string super_class = get_super_class(line), base, params;
369         if(cRecDecl->getNumBases()>1)
370         {
371                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
372                 {
373                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
374                         else base = super_class;
375                         if(get_model(base)==1) return true;
376                         else
377                         {
378                                 super_class = get_next_base(super_class);
379                         }
380                 }
381         }
382         else
383         { 
384                 if(get_model(super_class)==1)return true;
385         }
386         return false;
387 }
388