00001
00002 #include <iostream>
00003 #include <fstream>
00004
00005 #include "Tokenizer.h"
00006 #include "FSMConstructor.h"
00007 #include "ParserExceptions.h"
00008
00009 using fsm_constructor::FSMConstructor;
00010
00011 #define PRINT(X) //cout<<"parser: "<<X<<endl
00012
00013 class FSMParser {
00014 public:
00015 enum TokenType{
00016 tkn_null=0,
00017 tkn_text=1,
00018 tkn_fsm,
00019 tkn_fsm_start,
00020 tkn_fsm_bgn,
00021 tkn_fsm_end,
00022 tkn_state,
00023 tkn_call_task,
00024 tkn_call_fsm,
00025 tkn_call_bt,
00026 tkn_transitions,
00027 tkn_on_event,
00028 tkn_on_condition,
00029 tkn_raise,
00030 tkn_states,
00031 tkn_next,
00032
00033 tkn_bopen,
00034 tkn_bclose,
00035 tkn_fopen,
00036 tkn_fclose,
00037 tkn_semicol,
00038 tkn_col,
00039 tkn_slesh,
00040 };
00041
00042
00043
00044
00045
00046 struct TokenizerInit{
00047 void init(Parser::TokenizerData<TokenType>& tkn){
00048 tkn.string_token["FSM"]=tkn_fsm;
00049 tkn.string_token["FSM_START"]=tkn_fsm_start;
00050 tkn.string_token["FSM_BGN"]=tkn_fsm_bgn;
00051 tkn.string_token["FSM_END"]=tkn_fsm_end;
00052 tkn.string_token["FSM_STATE"]=tkn_state;
00053 tkn.string_token["FSM_NEXT"]=tkn_next;
00054 tkn.string_token["FSM_CALL_FSM"]=tkn_call_fsm;
00055 tkn.string_token["FSM_CALL_TASK"]=tkn_call_task;
00056 tkn.string_token["FSM_CALL_BT"]=tkn_call_bt;
00057 tkn.string_token["FSM_TRANSITIONS"]=tkn_transitions;
00058 tkn.string_token["FSM_ON_EVENT"]=tkn_on_event;
00059 tkn.string_token["FSM_ON_CONDITION"]=tkn_on_condition;
00060 tkn.string_token["FSM_RAISE"]=tkn_raise;
00061 tkn.string_token["FSM_RISE"]=tkn_raise;
00062 tkn.string_token["FSM_STATES"]=tkn_states;
00063
00064 tkn.spec_token['(']=tkn_bopen;
00065 tkn.spec_token[')']=tkn_bclose;
00066 tkn.spec_token['{']=tkn_fopen;
00067 tkn.spec_token['}']=tkn_fclose;
00068 tkn.spec_token[',']=tkn_col;
00069 tkn.spec_token[';']=tkn_semicol;
00070 tkn.spec_token['/']=tkn_slesh;
00071 }
00072 bool isTokenSumbol(char c){
00073 return
00074 ('0'<=c and c<='9') or
00075 ('a'<=c and c<='z') or
00076 ('A'<=c and c<='Z') or
00077 (c=='_')
00078 ;
00079 }
00080 bool isDelimiter(char c){
00081 return not isTokenSumbol(c);
00082 }
00083 bool isFlowControl(char c){
00084 return c==10 or c==13;
00085 }
00086 };
00087
00088
00089
00090 typedef Parser::TokenStream<TokenType> tstream;
00091 typedef Parser::Token<TokenType> Token;
00092
00093 bool fsm(tstream& stream, Token& tkn){
00094 PRINT("start search from "<<stream.first());
00095 while(not stream.eof()){
00096 stream >> tkn;
00097 if( tkn.type == tkn_fsm ){
00098 PRINT("fsm found");
00099 return true;
00100 }
00101 }
00102 return false;
00103 }
00104
00105 bool name(tstream& stream, string txt, string& output, int& line, int& pos){
00106 Token tkn;
00107 TKN_NEXT( tkn_bopen )
00108 TKN_NEXT( tkn_text )
00109 PRINT(txt<<" name is "<<tkn.text);
00110 output = tkn.text;
00111 searchLineInfo(tkn.start, line, pos);
00112 TKN_NEXT( tkn_bclose )
00113 return true;
00114 }
00115 bool name(tstream& stream, string txt, string& output){
00116 int line, pos;
00117 return name(stream,txt, output, line, pos);
00118 }
00119 bool name(tstream& stream, string txt){ string t; return name(stream,txt,t); }
00120
00121
00122 bool fsm_start(tstream& stream){
00123 Token tkn;
00124 while(not stream.eof()){
00125 stream >> tkn;
00126 if( tkn.type == tkn_fsm_start ){
00127 string start_state;
00128 TKN_SEARCH( name(stream, "fsm start", start_state) )
00129 constructor.fsm().start = start_state;
00130 return true;
00131 }
00132 }
00133 ADD_ERROR(_curr_fsm, "Cann't find FSM_START for FSM("+_curr_fsm_name+")")
00134 return false;
00135 }
00136 bool fsm_bgn(tstream& stream){
00137 Token tkn;
00138 while(not stream.eof()){
00139 stream >> tkn;
00140 if( tkn.type == tkn_fsm_bgn ){
00141 PRINT("fsm_bgn found");
00142 return true;
00143 }
00144 }
00145 ADD_ERROR(_curr_fsm, "Cann't find FSM_BGN for FSM("+_curr_fsm_name+")")
00146 return false;
00147 }
00148
00149 bool transition_name(tstream& stream){
00150 Token tkn;
00151 TKN_NEXT( tkn_bopen )
00152 TKN_NEXT( tkn_text )
00153 PRINT("on event "<<tkn.text;
00154 TKN_NEXT( tkn_col )
00155 TKN_NEXT( tkn_text )
00156 cout<<" go to "<<tkn.text);
00157 TKN_NEXT( tkn_bclose )
00158 return true;
00159 }
00160 bool textUpTo(tstream& stream, TokenType endTkn, string& output){
00161 Token tkn;
00162 bool r=false;
00163 int s(-1),e(-1);
00164 while(not stream.eof() and tkn.type!=endTkn){
00165 stream >> tkn;
00166 r=true;
00167 if( tkn.type==endTkn ) continue;
00168 if(s<0)s=tkn.start;
00169 e=tkn.end;
00170 }
00171 if(s>=0 and e>s) output = fullText.substr(s, e-s);
00172 return r;
00173 }
00174
00175 bool search_calls_in_state(tstream& stream, Token& tkn){
00176 if( tkn.type == tkn_call_fsm ){
00177 PRINT("call fsm");
00178 fsm_constructor::Call call; call.type = "fsm"; call.file=filename; call.id=constructor.fsm().state().getId();
00179 TKN_SEARCH( name(stream, "called fsm", call.text, call.line, call.pos) )
00180 constructor.fsm().state().calls.push_back(call);
00181 }
00182 if( tkn.type == tkn_call_bt ){
00183 PRINT("call bt");
00184 fsm_constructor::Call call; call.type = "bt"; call.file=filename; call.id=constructor.fsm().state().getId();
00185 TKN_SEARCH( name(stream, "called bt", call.text, call.line, call.pos) )
00186 constructor.fsm().state().calls.push_back(call);
00187 }
00188 if( tkn.type == tkn_call_task ){
00189 PRINT("call task");
00190 fsm_constructor::Call call; call.type = "task"; call.file=filename; call.id=constructor.fsm().state().getId();
00191 TKN_SEARCH( name(stream, "called task", call.text, call.line, call.pos) )
00192 constructor.fsm().state().calls.push_back(call);
00193 }
00194 return true;
00195 }
00196 bool search_raises_in_state(tstream& stream, Token& tkn){
00197 if( tkn.type == tkn_raise ){
00198 TKN_NEXT(tkn_bopen)
00199 string text="";
00200 TKN_SEARCH( textUpTo(stream, tkn_bclose, text));
00201 PRINT("raise event: "<<text);
00202 fsm_constructor::Raise raise; raise.text=text;
00203 constructor.fsm().state().raises.push_back(raise);
00204 }
00205 return true;
00206 }
00207 bool search_next_in_events(tstream& stream, Token& tkn, bool& found){
00208 if( tkn.type == tkn_next ){
00209 string text;
00210 TKN_SEARCH( name(stream, "transition", text) )
00211 found=true;
00212 fsm_constructor::EventAction ac; ac.type="next";
00213 ac.text=text;
00214 constructor.fsm().state().event().actions.push_back(ac);
00215 }
00216 return true;
00217 }
00218 bool search_raise_in_events(tstream& stream, Token& tkn, bool& found){
00219 if( tkn.type == tkn_raise ){
00220 TKN_NEXT(tkn_bopen)
00221 string text="";
00222 TKN_SEARCH( textUpTo(stream, tkn_bclose, text));
00223 PRINT("raise event: "<<text);
00224 found = true;
00225 fsm_constructor::EventAction ac; ac.type="raise";
00226 ac.text=text;
00227 constructor.fsm().state().event().actions.push_back(ac);
00228 }
00229 return true;
00230 }
00231 bool search_on_events_in_transition(tstream& stream, Token& tkn){
00232 if( tkn.type == tkn_on_event ){
00233 TKN_NEXT( tkn_bopen)
00234 string text="";
00235 TKN_SEARCH( textUpTo(stream, tkn_col, text));
00236 PRINT("on event : "<<text);
00237 constructor.fsm().state().create_event();
00238 constructor.fsm().state().event().type="event";
00239 constructor.fsm().state().event().text=text;
00240 bool found_next = false, found_raise = false;
00241 stream >> tkn;
00242 TKN_SEARCH( search_next_in_events(stream, tkn, found_next) )
00243 TKN_SEARCH( search_raise_in_events(stream, tkn, found_raise) )
00244 if(found_next==false and found_raise==false){
00245 constructor.fsm().state().drop_event();
00246 return false;
00247 }
00248 TKN_NEXT( tkn_bclose)
00249 constructor.fsm().state().add_event();
00250 }
00251 return true;
00252 }
00253 string encode(const std::string& data) {
00254 std::string buffer;
00255 buffer.reserve(data.size()*1.1);
00256 for(size_t pos = 0; pos != data.size(); ++pos) {
00257 switch(data[pos]) {
00258 case '&': buffer.append("&"); break;
00259 case '\"': buffer.append("""); break;
00260 case '\'': buffer.append("'"); break;
00261 case '<': buffer.append("<"); break;
00262 case '>': buffer.append(">"); break;
00263 default: buffer.append(&data[pos], 1); break;
00264 }
00265 }
00266
00267 return buffer;
00268 }
00269 bool search_on_conditions_in_transition(tstream& stream, Token& tkn){
00270 if( tkn.type == tkn_on_condition ){
00271 TKN_NEXT( tkn_bopen)
00272 string text="";
00273 TKN_SEARCH( textUpTo(stream, tkn_col, text));
00274 PRINT("on condition : "<<text);
00275 constructor.fsm().state().create_event();
00276 constructor.fsm().state().event().type="condition";
00277 constructor.fsm().state().event().text=encode(text);
00278 bool found_next = false, found_raise = false;
00279 stream >> tkn;
00280 TKN_SEARCH( search_next_in_events(stream, tkn, found_next) )
00281 TKN_SEARCH( search_raise_in_events(stream, tkn, found_raise) )
00282 if(found_next==false and found_raise==false){
00283 constructor.fsm().state().drop_event();
00284 return false;
00285 }
00286 TKN_NEXT( tkn_bclose)
00287 constructor.fsm().state().add_event();
00288 }
00289 return true;
00290 }
00291
00292 bool transitions(tstream& stream){
00293 Token tkn;
00294 size_t current_end = stream.getEnd();
00295 bool transitions=false;
00296 while(not stream.eof()){
00297 stream >> tkn;
00298 TKN_SEARCH( search_calls_in_state(stream , tkn) )
00299 TKN_SEARCH( search_raises_in_state(stream , tkn) )
00300 if( tkn.type == tkn_transitions ){
00301 PRINT("transition");
00302 TKN_NEXT_OPTIONAL(tkn_fopen, return true)
00303 size_t end_of_tran = TKN_SEARCH_CLOSE_PARENT(end_of_tran, stream, tkn_fopen, tkn_fclose, "FSM Transitions definition")
00304 stream.setEnd(end_of_tran);
00305 transitions = true;
00306 }
00307 if(transitions){
00308 TKN_SEARCH_OPTIONAL( search_on_events_in_transition(stream , tkn) , {})
00309 TKN_SEARCH_OPTIONAL( search_on_conditions_in_transition(stream , tkn) , {})
00310 }
00311 }
00312 stream.setEnd(current_end);
00313 return true;
00314 }
00315
00316 bool fsm_state_body(tstream& stream, size_t end_of_fsm){
00317 Token tkn;
00318 TKN_NEXT( tkn_fopen )
00319 size_t end_of_state = TKN_SEARCH_CLOSE_PARENT(end_of_state, stream, tkn_fopen, tkn_fclose, "FSM State definition")
00320 stream.setEnd(end_of_state);
00321 TKN_SEARCH( transitions(stream) )
00322 stream.setEnd(end_of_fsm);
00323 return true;
00324 }
00325
00326 bool fsm_states(tstream& stream, size_t end_of_fsm){
00327 Token tkn;
00328 while(not stream.eof()){
00329 stream >> tkn;
00330 if( tkn.type == tkn_fsm_end ){
00331 PRINT("fsm_end found");
00332 return true;
00333 }
00334 if( tkn.type == tkn_state ){
00335 PRINT("state found");
00336 _curr_state = tkn;
00337 string state_name;
00338 TKN_SEARCH( name(stream, "state", state_name) )
00339 _curr_state_name = state_name;
00340 constructor.fsm().create();
00341 constructor.fsm().state().name=state_name;
00342 if( fsm_state_body(stream, end_of_fsm) ){
00343 constructor.fsm().add();
00344 }else{
00345 constructor.fsm().drop();
00346 ADD_ERROR(_curr_state, "Error in state "+_curr_state_name+" definition")
00347 return false;
00348 }
00349 }
00350 }
00351 ADD_ERROR(_curr_fsm, "Cann't find FSM_END for FSM("+_curr_fsm_name+")")
00352 return false;
00353 }
00354
00355 bool parse_fsm_body(tstream& stream){
00356 Token tkn;
00357 TKN_NEXT( tkn_fopen )
00358 size_t end_of_fsm = TKN_SEARCH_CLOSE_PARENT(end_of_fsm, stream, tkn_fopen, tkn_fclose, "FSM definition")
00359 stream.setEnd(end_of_fsm);
00360 TKN_SEARCH( fsm_start(stream) )
00361 TKN_SEARCH( fsm_bgn(stream) )
00362 TKN_SEARCH( fsm_states(stream, end_of_fsm) )
00363 stream.setEnd();
00364 return true;
00365 }
00366 bool parse_fsm(tstream& stream){
00367 Token tkn;
00368 TKN_SEARCH( fsm(stream, tkn) )
00369 _curr_fsm = tkn;
00370 string fsm_name;
00371 TKN_SEARCH( name(stream, "fsm", fsm_name) )
00372 _curr_fsm_name = fsm_name;
00373 constructor.create();
00374 constructor.fsm().name = fsm_name;
00375 if( parse_fsm_body(stream) ){
00376 constructor.add();
00377 }else{
00378 constructor.drop();
00379 return false;
00380 }
00381 return true;
00382 }
00383
00384 struct TokenizerContext{
00385 Parser::Tokenizer<TokenType, TokenizerInit> tokenizer;
00386 std::stringstream ss_fullText;
00387 stringstream buffer;
00388 size_t start_index, index;
00389 ifstream& file;
00390 char c;
00391 TokenizerContext(ifstream& file):
00392 start_index(0),index(0),
00393 file(file), c(0)
00394 {}
00395 };
00396
00397 void searchLineInfo(int i, int& line, int& pos){
00398 line=0;
00399 for(size_t n=0;n<lines.size();n++){
00400 if(i<lines[n]){
00401 pos = i-lines[line-2];
00402 return;
00403 }
00404 line = n+2;
00405 }
00406 }
00407
00408 void saveReadedChar(TokenizerContext& ctx , char c){
00409 ctx.ss_fullText<<c;
00410 if(c=='\n') lines.push_back(ctx.index);
00411 }
00412
00413 bool skipComments( TokenizerContext& ctx )
00414 {
00415 if(ctx.c=='/' and ctx.file.eof()==false){
00416 char cc;
00417 ctx.file.read(&cc, 1); ctx.ss_fullText<<cc;
00418 if(cc=='/'){
00419 ctx.index++;
00420 while(cc!='\n' and ctx.file.eof()==false){
00421 ctx.file.read(&cc, 1); saveReadedChar(ctx, cc); ctx.index++;
00422 }
00423 ctx.index++;
00424 return true;
00425 }
00426 else{
00427 ctx.tokenizer.searchToken(ctx.index++, ctx.buffer, ctx.start_index, ctx.c, tokens);
00428 ctx.c=cc;
00429 }
00430 }
00431 return false;
00432 }
00433
00434 FSMParser(string file):filename(file), constructor(errors, file){}
00435
00436 string filename;
00437 std::string fullText;
00438 tstream tokens;
00439 FSMConstructor constructor;
00440 std::stringstream errors;
00441 std::vector<int> lines;
00442 Token _curr_fsm;
00443 std::string _curr_fsm_name;
00444 Token _curr_state;
00445 std::string _curr_state_name;
00446
00447 FSMConstructor& main()
00448 {
00449 PRINT(__TIME__);
00450 if(true){
00451 PRINT("Read input file");
00452 ifstream file(filename.c_str());
00453 TokenizerContext ctx(file);
00454 if(ctx.file.is_open()){
00455 PRINT("File ("<<filename<<") is open");
00456 while(ctx.file.eof()==false){
00457 ctx.file.read(&ctx.c, 1); saveReadedChar(ctx, ctx.c);
00458 if(skipComments(ctx)) continue;
00459 ctx.tokenizer.searchToken(ctx.index++, ctx.buffer, ctx.start_index, ctx.c, tokens);
00460 }
00461 PRINT("End of file");
00462 fullText = ctx.ss_fullText.str();
00463 file.close();
00464 }else{
00465 throw PEFileNotFound(filename);
00466 }
00467 }
00468 if(false){
00469 PRINT("Result: ");
00470 while(not tokens.eof()){
00471 Token t; tokens>>t;
00472 PRINT(t);
00473 }
00474 }
00475 if(true){
00476 while(not tokens.eof()){
00477 parse_fsm(tokens);
00478 }
00479
00480
00481 }
00482 return constructor;
00483 }
00484 };
00485
00486 ostream& operator<<(ostream& out, FSMParser::TokenType t){
00487 #define PRINTTKN(x) case FSMParser::tkn_##x: return out<<#x;
00488 switch(t){
00489 PRINTTKN(null)
00490 PRINTTKN(fsm)
00491 PRINTTKN(fsm_start)
00492 PRINTTKN(fsm_bgn)
00493 PRINTTKN(fsm_end)
00494 PRINTTKN(state)
00495 PRINTTKN(call_task)
00496 PRINTTKN(call_fsm)
00497 PRINTTKN(next)
00498 PRINTTKN(call_bt)
00499 PRINTTKN(transitions)
00500 PRINTTKN(on_event)
00501 PRINTTKN(on_condition)
00502 PRINTTKN(raise)
00503 PRINTTKN(states)
00504
00505 PRINTTKN(bopen)
00506 PRINTTKN(bclose)
00507 PRINTTKN(fopen)
00508 PRINTTKN(fclose)
00509 PRINTTKN(semicol)
00510 PRINTTKN(col)
00511 PRINTTKN(text)
00512 PRINTTKN(slesh)
00513 }
00514 return out<<"???";
00515 #undef PRINTTKN
00516 }
00517
00518 FSMConstructor& parseFSM(FSMParser* p){
00519 return p->main();
00520 }
00521
00522 FSMParser* createFSM(std::string filename){
00523 return new FSMParser(filename);
00524 }
00525
00526 void del(FSMParser* p){ delete p; }
00527
00528 #undef PRINT