2 ////////////////////////////////////////////////////////////////////////////////////////
4 // This file is part of Boost Statechart Viewer.
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.
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.
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/>.
19 ////////////////////////////////////////////////////////////////////////////////////////
24 using namespace clang;
26 string clean_spaces(const string line) /** Remove gaps from string.*/
30 for(i = 0;i<line.length();i++)
32 if(!isspace(line[i])) new_line+=line[i];
38 string cut_commentary(const string line) /** This function cuts commentaries at the end of line. */
41 for(i = 0;i<line.length()-1;i++)
43 if(line[i]=='/' && line[i+1]=='/') return line.substr(0,i);
44 if(line[i]=='/' && line[i+1]=='*') return line.substr(0,i);
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.*/
53 for(i = 0;i<code.length();i++)
55 if(code[i]=='\n'||code[i]=='{') break;
57 ret = code.substr(0,i);
58 ret = clean_spaces(ret);
59 return cut_commentary(ret);
62 string get_return(const string code) /** Return return statement. */
66 for(i = 0;i<code.length();i++)
68 if(code[i]==' ') break;
70 return code.substr(0,i);
73 string cut_namespaces(string line) /** Cut namespaces from the declarations. */
77 for(i = line.length()-1;i>0;i--)
79 if(line[i]=='<') brackets+=1;
80 if(line[i]=='>') brackets-=1;
81 if(line[i]==':' && line[i-1]==':')
83 if(brackets == 0) break;
88 return line.substr(i+1);
91 string cut_namespaces(string line, int ortho) /** Cut namespaces ORTHOGONAL STATES. */
95 for(i = line.length()-1;i>0;i--)
97 if(line[i]=='<') brackets+=1;
98 if(line[i]=='>') brackets-=1;
99 if(line[i]==':' && line[i-1]==':')
101 if(brackets == 0) break;
105 if(i==0) return line;
106 return line.substr(0,i-1);
109 bool is_derived(const string line) /** Test whether this struct or class is derived */
112 for(i = 0;i<line.length()-2;i++)
116 if(line[i+1]!=':') return true;
123 string get_super_class(const string line) /** Get the super classes of this declarations. */
126 for(i = 0;i<line.length()-1;i++)
130 if(line[i+1]!=':') break;
134 return line.substr(i+1);
137 string get_next_base(const string line) /** Get next super classes of this declarations Do the first super class is ommitted. */
141 for(i = 0;i<line.length()-1;i++)
143 if(line[i]=='<') brackets+=1;
144 if(line[i]=='>') brackets-=1;
145 if(line[i]==',' && brackets == 0) break;
147 return line.substr(i+1);
150 string get_first_base(const string line) /** Get the first super class of this declarations. */
154 for(i = 0;i<line.length()-1;i++)
156 if(line[i]=='<') brackets+=1;
157 if(line[i]=='>') brackets-=1;
158 if(line[i]==',' && brackets == 0) break;
160 return line.substr(0,i);
163 bool is_state(const string line) /** Test if this declaration is a state. It is used to test the base classes. */
165 if(cut_namespaces(line).compare(0,12,"simple_state")==0)
171 if(cut_namespaces(line).compare(0,5,"state")==0)
179 string cut_type(string line) /** This function cuts type of the declaration from the string. */
182 for(i = 0;i<line.length();i++)
184 if(line[i]==' ') break;
186 return line.substr(i);
189 int count(const string line, const char c) /** Count all specified char in string. So it returns the number of specified characters. */
192 for(unsigned i = 0;i<line.length();i++)
194 if(line[i]==c) number+=1;
199 bool is_list(const string line) /** Test if this decl is mpl::list. */
203 for(unsigned i = 0; i<line.length();i++)
205 if(line[i]=='<') break;
206 if(line[i]==':' && line[i+1]==':') pos = i+2;
208 if(line.substr(pos).compare(0,4,"list")==0)
218 string get_inner_part(const string line) /** Get inner part of the list. */
222 for(i = 0;i<line.length();i++)
224 if(line[i]=='<') break;
226 str = line.substr(i+1);
227 for(i = 0;i<str.length();i++)
229 if(str[i]=='<') pos+=1;
236 return str.substr(0,i);
239 int get_model(const string line) /** Test the string to has a specified model. */
241 string str = cut_namespaces(line);
242 if(str.find("<")<str.length()) str = str.substr(0,str.find("<"));
245 case 5 : if(str.compare(0,5,"event")==0) return 1;
247 case 6 : if(str.compare(0,6,"result")==0) return 5;
249 case 7 : if(str.compare(0,7,"transit")==0) return 6;
251 case 8 : if(str.compare(0,8,"deferral")==0) return 13;
253 case 10 : if(str.compare(0,10,"transition")==0) return 11;
255 case 13 : if(str.compare(0,13,"state_machine")==0) return 3;
257 case 15 : if(str.compare(0,15,"custom_reaction")==0) return 12;
263 string get_params(string line) /** Return parameters of the specified transition */
265 int pos_front = line.find("<")+1;
266 int pos_end = line.rfind(">");
267 return line.substr(pos_front,pos_end-pos_front);
270 string find_states(const CXXRecordDecl *cRecDecl, string line) /** test if the struct/class is he state (must be derived from simple_state or state). */
272 string super_class = get_super_class(line), base, params;
273 if(cRecDecl->getNumBases()>1)
276 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
278 if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
279 else base = super_class;
280 if(is_state(super_class))
282 params = get_params(super_class);
286 super_class = get_next_base(super_class);
292 if(is_state(super_class))
294 params = get_params(super_class);
301 string find_name_of_machine(const CXXRecordDecl *cRecDecl, string line) /** Find name of the state machine and the start state. */
303 string super_class = get_super_class(line), base, params;
304 if(cRecDecl->getNumBases()>1)
306 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
308 if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
309 else base = super_class;
310 if(get_model(base)==3)
312 params = get_params(base);
316 super_class = get_next_base(super_class);
322 if(get_model(super_class)==3)
324 params = get_params(super_class);
330 string find_transitions (const string name_of_state, string line) /** Traverse all methods for finding declarations of transitions. */
332 string dest, params, base, trans;
333 int num = count(line,'<');
339 line = get_inner_part(line);
342 for(int j = 0;j<num;j++)
344 if(j!=num-1) base = get_first_base(line);
346 if(get_model(base)>10)
348 if(get_model(base)==12) dest = ";";
349 else if (get_model(base) == 13) dest = ",";
350 dest.append(name_of_state);
351 params = get_params(base);
355 if(j+1!=num) trans.append(";");
357 line = get_next_base(line);
359 if(trans[trans.length()-1]==';') return trans.substr(0,trans.length()-1);
363 bool find_events(const CXXRecordDecl *cRecDecl, string line) /** This function provides testing if the decl is decl of event*/
365 string super_class = get_super_class(line), base, params;
366 if(cRecDecl->getNumBases()>1)
368 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
370 if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
371 else base = super_class;
372 if(get_model(base)==1) return true;
375 super_class = get_next_base(super_class);
381 if(get_model(super_class)==1)return true;