Parsers_FSM.cpp
Go to the documentation of this file.
00001 // http://www.compileonline.com/compile_cpp0x_online.php
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         //============= TOKENAZER ===============================
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         //============= LEXEM PARSER =================================
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("&amp;");       break;
00259                     case '\"': buffer.append("&quot;");      break;
00260                     case '\'': buffer.append("&apos;");      break;
00261                     case '<':  buffer.append("&lt;");        break;
00262                     case '>':  buffer.append("&gt;");        break;
00263                     default:   buffer.append(&data[pos], 1); break;
00264                 }
00265             }
00266             //data.swap(buffer);
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                         //PRINT(constructor);
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


decision_making_parser
Author(s):
autogenerated on Wed Aug 26 2015 11:16:57