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 backspaces
30 for(i = 0;i<line.length();i++)
32 if(!isspace(line[i])) new_line+=line[i];
38 string cut_commentary(const string line) //cut commentary 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) //return the line of code
54 for(i = 0;i<code.length();i++)
56 if(code[i]=='\n'||code[i]=='{') break;
58 ret = code.substr(0,i);
59 ret = clean_spaces(ret);
60 return cut_commentary(ret);
63 string get_return(const string code)
67 for(i = 0;i<code.length();i++)
69 if(code[i]==' ') break;
71 return code.substr(0,i);
74 string cut_namespaces(string line) //cut namespaces from the name of the state
76 int i = line.rfind("::");
77 if(i==-1) return line;
78 return line.substr(i+2);
81 bool is_derived(const string line) // return true if the struct or class is derived
84 for(i = 0;i<line.length()-1;i++)
88 if(line[i+1]!=':') return true;
95 string get_super_class(const string line) // get the super class of this declarations
98 for(i = 0;i<line.length()-1;i++)
102 if(line[i+1]!=':') break;
106 return line.substr(i+1);
109 string get_next_base(const string line) // get the super class of this declarations
113 for(i = 0;i<line.length()-1;i++)
115 if(line[i]=='<') brackets+=1;
116 if(line[i]=='>') brackets-=1;
117 if(line[i]==',' && brackets == 0) break;
119 return line.substr(i+1);
122 string get_first_base(const string line) // get the super class of this declarations
126 for(i = 0;i<line.length()-1;i++)
128 if(line[i]=='<') brackets+=1;
129 if(line[i]=='>') brackets-=1;
130 if(line[i]==',' && brackets == 0) break;
132 return line.substr(0,i);
135 bool is_state(const string line) // test if it is a state
137 if(cut_namespaces(line).compare(0,12,"simple_state")==0)
143 if(cut_namespaces(line).compare(0,5,"state")==0)
151 string cut_type(string line) // cut typedef from the beginning
154 for(i = 0;i<line.length();i++)
156 if(line[i]==' ') break;
158 return line.substr(i);
161 int count(const string line, const char c) //count all specified char in string
164 for(unsigned i = 0;i<line.length();i++)
166 if(line[i]==c) number+=1;
171 bool is_list(const string line) // is it a list?
175 for(unsigned i = 0; i<line.length();i++)
177 if(line[i]=='<') break;
178 if(line[i]==':' && line[i+1]==':') pos = i+2;
180 if(line.substr(pos).compare(0,4,"list")==0)
190 string get_inner_part(const string line) // get inner part of the list
194 for(i = 0;i<line.length();i++)
196 if(line[i]=='<') break;
198 str = line.substr(i+1);
199 for(i = 0;i<str.length();i++)
201 if(str[i]=='<') pos+=1;
208 //cout<<str.substr(0,i);
209 return str.substr(0,i);
212 bool test_model(const string line, const string model) // is it a transition
214 if(cut_namespaces(line).compare(0,model.length(),model)==0)
224 string get_params(string line) // get parameters of transition
226 int pos_front = line.find("<")+1;
227 int pos_end = line.find(">");
228 return line.substr(pos_front,pos_end-pos_front);
231 string find_states(const CXXRecordDecl *cRecDecl, string line) // test if the struct/class is he state (must be derived from simple_state)
233 string super_class = get_super_class(line), base, params;
234 if(cRecDecl->getNumBases()>1)
236 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
238 if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
239 else base = super_class;
240 if(is_state(super_class))
242 params = get_params(super_class);
246 super_class = get_next_base(super_class);
252 if(is_state(super_class))
254 //std::cout<<get_params(super_class);
255 params = get_params(super_class);
262 string find_name_of_machine(const CXXRecordDecl *cRecDecl, string line) // find name of the state machine and the start state
264 string super_class = get_super_class(line), base, params;
265 if(cRecDecl->getNumBases()>1)
267 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
269 if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
270 else base = super_class;
271 if(test_model(base,"state_machine"))
273 params = get_params(base);
277 super_class = get_next_base(super_class);
283 if(test_model(super_class,"state_machine"))
285 //std::cout<<super_class;
286 params = get_params(super_class);
293 string find_transitions (const string name_of_state, string line) // traverse all methods for finding declarations of transitions
295 string dest, params, base, trans;
296 int num = count(line,'<');
302 line = get_inner_part(line);
305 for(int j = 0;j<num;j++)
307 if(j!=num-1) base = get_first_base(line);
309 if(test_model(base,"transition"))
311 dest = name_of_state;
312 params = get_params(base);
313 //cout<<params<<"\n";
316 line = get_next_base(line);
318 if(j+1!=num) trans.append(";");
320 else if(test_model(base,"custom_reaction"))
323 dest.append(name_of_state);
324 params = get_params(base);
325 //cout<<params<<"\n";
328 line = get_next_base(line);
330 if(j+1!=num) trans.append(";");
334 line = get_next_base(line);
337 if(trans[trans.length()-1]==';') return trans.substr(0,trans.length()-1);
341 bool find_events(const CXXRecordDecl *cRecDecl, string line) // test if the decl is decl of event
343 string super_class = get_super_class(line), base, params;
344 if(cRecDecl->getNumBases()>1)
346 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
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;
353 super_class = get_next_base(super_class);
359 if(test_model(super_class,"event"))return true;