]> rtime.felk.cvut.cz Git - boost-statechart-viewer.git/blob - src/stringoper.h
6a039063a083886685a3f7aeed1a4bab09303578
[boost-statechart-viewer.git] / src / stringoper.h
1
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 backspaces
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) //cut commentary 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) //return the line of code
50 {
51         string ret;     
52         unsigned i;     
53         //cout<<code<<"\n\n";
54         for(i = 0;i<code.length();i++)
55         {
56                 if(code[i]=='\n'||code[i]=='{') break;
57         }
58         ret = code.substr(0,i);
59         ret = clean_spaces(ret);
60         return cut_commentary(ret);
61
62
63 string get_return(const string code)
64 {
65         string ret;     
66         unsigned i;
67         for(i = 0;i<code.length();i++)
68         {
69                 if(code[i]==' ') break;
70         }
71         return code.substr(0,i);
72 }
73
74 string cut_namespaces(string line) //cut namespaces from the name of the state
75 {
76         int i = line.rfind("::");
77         if(i==-1) return line;
78         return line.substr(i+2);
79 }
80
81 bool is_derived(const string line) // return true if the struct or class is derived
82 {
83         unsigned i;
84         for(i = 0;i<line.length()-1;i++)
85         {
86                 if(line[i]==':')
87                 {
88                         if(line[i+1]!=':') return true;
89                         else i+=1;
90                 }
91         }
92         return false;
93 }
94
95 string get_super_class(const string line) // get the super class of this declarations
96 {
97         unsigned i;
98         for(i = 0;i<line.length()-1;i++)
99         {
100                 if(line[i]==':')
101                 {
102                         if(line[i+1]!=':') break;
103                         else i+=1;
104                 }
105         }
106         return line.substr(i+1);
107 }
108
109 string get_next_base(const string line) // get the super class of this declarations
110 {
111         unsigned i;
112         int brackets = 0;
113         for(i = 0;i<line.length()-1;i++)
114         {
115                 if(line[i]=='<') brackets+=1;
116                 if(line[i]=='>') brackets-=1;
117                 if(line[i]==',' && brackets == 0) break;
118         }
119         return line.substr(i+1);
120 }  
121
122 string get_first_base(const string line) // get the super class of this declarations
123 {
124         unsigned i;
125         int brackets = 0;
126         for(i = 0;i<line.length()-1;i++)
127         {
128                 if(line[i]=='<') brackets+=1;
129                 if(line[i]=='>') brackets-=1;
130                 if(line[i]==',' && brackets == 0) break;
131         }
132         return line.substr(0,i);
133 }  
134
135 bool is_state(const string line) // test if it is a state
136 {
137         if(cut_namespaces(line).compare(0,12,"simple_state")==0)
138         {
139                 return true;    
140         }
141         else
142         {
143                 if(cut_namespaces(line).compare(0,5,"state")==0)
144                 {
145                         return true;    
146                 }
147                 return false;
148         }
149 }
150
151 string cut_type(string line) // cut typedef from the beginning
152 {
153         unsigned i;
154         for(i = 0;i<line.length();i++)
155         {
156                 if(line[i]==' ') break;
157         }
158         return line.substr(i);
159 }
160
161 int count(const string line, const char c) //count all specified char in string
162 {
163         int number = 0;
164         for(unsigned i = 0;i<line.length();i++)
165         {
166                 if(line[i]==c) number+=1;
167         }
168         return number;
169 }
170
171 bool is_list(const string line) // is it a list?
172 {
173         //cout<<line<<"\n";
174         int pos = 0;
175         for(unsigned i = 0; i<line.length();i++)
176         {
177                 if(line[i]=='<') break;
178                 if(line[i]==':' && line[i+1]==':') pos = i+2;
179         }       
180         if(line.substr(pos).compare(0,4,"list")==0)
181         {
182                 return true;    
183         }
184         else
185         {
186                 return false;
187         }
188 }
189
190 string get_inner_part(const string line) // get inner part of the list
191 {
192         string str;
193         unsigned i, pos = 0;
194         for(i = 0;i<line.length();i++)
195         {
196                 if(line[i]=='<') break;
197         }
198         str = line.substr(i+1);
199         for(i = 0;i<str.length();i++)
200         {
201                 if(str[i]=='<') pos+=1;
202                 if(str[i]=='>')
203                 { 
204                         if(pos==0) break;
205                         else pos-=1;
206                 }
207         }
208         //cout<<str.substr(0,i);
209         return str.substr(0,i);
210 }
211
212 bool test_model(const string line, const string model) // is it a transition
213 {
214         if(cut_namespaces(line).compare(0,model.length(),model)==0)
215         {
216                 return true;    
217         }
218         else
219         {
220                 return false;
221         }
222 }
223
224 string get_params(string line) // get parameters of transition
225 {
226         int pos_front = line.find("<")+1;
227         int pos_end = line.find(">");
228         return line.substr(pos_front,pos_end-pos_front);
229 }
230         
231 string find_states(const CXXRecordDecl *cRecDecl, string line) // test if the struct/class is he state (must be derived from simple_state)
232 {       
233         string super_class = get_super_class(line), base, params;               
234         if(cRecDecl->getNumBases()>1)
235         {
236                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
237                 {
238                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
239                         else base = super_class;
240                         if(is_state(super_class)) 
241                         {
242                                 params = get_params(super_class);
243                         }
244                         else
245                         {
246                                 super_class = get_next_base(super_class);
247                         }
248                 }
249         }
250         else
251         { 
252                 if(is_state(super_class)) 
253                 {
254                         //std::cout<<get_params(super_class);
255                         params = get_params(super_class);
256                 }
257                 else params = "";
258         }
259         return params;
260 }
261                 
262 string find_name_of_machine(const CXXRecordDecl *cRecDecl, string line) // find name of the state machine and the start state
263 {       
264         string super_class = get_super_class(line), base, params;
265         if(cRecDecl->getNumBases()>1)
266         {
267                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
268                 {
269                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
270                         else base = super_class;
271                         if(test_model(base,"state_machine"))
272                         {
273                                 params = get_params(base);
274                         }
275                         else
276                         {
277                                 super_class = get_next_base(super_class);
278                         }
279                 }
280         }
281         else
282         { 
283                 if(test_model(super_class,"state_machine"))
284                 {
285                         //std::cout<<super_class;
286                         params = get_params(super_class);
287                         //std::cout<<params;
288                 }
289         }
290         return params;
291 }
292
293 string find_transitions (const string name_of_state, string line) // traverse all methods for finding declarations of transitions
294 {       
295         string dest, params, base, trans;
296         int num = count(line,'<');      
297         if(num>1)
298         {
299                 num-=1;
300                 if(is_list(line))
301                 {
302                         line = get_inner_part(line);
303                 }
304         }
305         for(int j = 0;j<num;j++)
306         {
307                 if(j!=num-1) base = get_first_base(line);                       
308                 else base = line;
309                 if(test_model(base,"transition"))
310                 {
311                         dest = name_of_state;
312                         params = get_params(base);
313                         //cout<<params<<"\n";
314                         dest.append(",");                                                       
315                         dest.append(params);
316                         line = get_next_base(line);
317                         trans.append(dest);
318                         if(j+1!=num) trans.append(";");
319                 }
320                 else if(test_model(base,"custom_reaction"))
321                 {
322                         dest = ";";
323                         dest.append(name_of_state);
324                         params = get_params(base);
325                         //cout<<params<<"\n";
326                         dest.append(",");                                                       
327                         dest.append(params);
328                         line = get_next_base(line);
329                         trans.append(dest);
330                         if(j+1!=num) trans.append(";");
331                 }
332                 else
333                 {
334                         line = get_next_base(line);
335                 }
336         }
337         if(trans[trans.length()-1]==';') return trans.substr(0,trans.length()-1);
338         else return trans;      
339 }
340
341 bool find_events(const CXXRecordDecl *cRecDecl, string line) // test if the decl is decl of event
342 {       
343         string super_class = get_super_class(line), base, params;
344         if(cRecDecl->getNumBases()>1)
345         {
346                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
347                 {
348                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
349                         else base = super_class;
350                         if(test_model(base,"event")) return true;
351                         else
352                         {
353                                 super_class = get_next_base(super_class);
354                         }
355                 }
356         }
357         else
358         { 
359                 if(test_model(super_class,"event"))return true;
360         }
361         return false;
362 }
363