├── README.md ├── demo.gif └── regex_to_min_dfa.cpp /README.md: -------------------------------------------------------------------------------- 1 | # Automata From Regular Expressions 2 | 3 | An interactive c++11 program to construct NFA, DFA, and minimized DFA from a given regular expression on the alphabet {a,b} and simulate the DFA on any possible input. 4 | 5 | ![Demo](https://github.com/swapagarwal/automata-from-regex/blob/master/demo.gif) 6 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swapagarwal/automata-from-regex/f4a02719c648adfa588df443ee3c0d595cc5ba45/demo.gif -------------------------------------------------------------------------------- /regex_to_min_dfa.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | struct nst 6 | { 7 | vector a[2], e; 8 | bool f=0; 9 | }; 10 | 11 | vector nfa; 12 | 13 | struct dst 14 | { 15 | int a[2] = {-1,-1}; 16 | bool f=0; 17 | }; 18 | 19 | vector dfa; 20 | 21 | stack st; 22 | 23 | int nfa_size, dfa_size; 24 | string dispregex; 25 | 26 | struct nst init_nfa_state; 27 | 28 | struct dst init_dfa_state; 29 | 30 | void custom_clear() { 31 | for(int i=0; i<100; i++) cout< op; 161 | char c; 162 | for(unsigned int i=0; i=priority(regexp[i])){ 182 | postfix+=op.top(); 183 | op.pop(); 184 | } 185 | else break; 186 | } 187 | op.push(regexp[i]); 188 | } 189 | //cout<&si){ 214 | for(unsigned int i=0;i state_change(int c,set&si){ 223 | set temp; 224 | if(c==1){ 225 | for (std::set::iterator it=si.begin(); it!=si.end(); ++it){ 226 | for(unsigned int j=0;j::iterator it=si.begin(); it!=si.end(); ++it){ 233 | for(unsigned int j=0;j&si,queue >&que,int start_state){ 242 | map, int> mp; 243 | mp[si]=-1; 244 | set temp1; 245 | set temp2; 246 | int ct=0; 247 | si.clear(); 248 | si.insert(0); 249 | epsilon_closure(start_state,si); 250 | if(mp.count(si)==0){ 251 | mp[si]=ct++; 252 | que.push(si); 253 | } 254 | int p=0; 255 | bool f1=false; 256 | while(que.size()!=0){ 257 | dfa.push_back(init_dfa_state); 258 | si.empty(); 259 | si=que.front(); 260 | f1=false; 261 | for (set::iterator it=si.begin(); it!=si.end(); ++it){ 262 | if(nfa[*it].f==true) 263 | f1=true; 264 | } 265 | dfa[p].f=f1; 266 | temp1=state_change(1,si); 267 | si=temp1; 268 | for (set::iterator it=si.begin(); it!=si.end(); ++it){ 269 | epsilon_closure(*it,si); 270 | } 271 | if(mp.count(si)==0){ 272 | mp[si]=ct++; 273 | que.push(si); 274 | dfa[p].a[0]=ct-1; 275 | } 276 | else{ 277 | dfa[p].a[0]=mp.find(si)->second; 278 | } 279 | temp1.clear(); 280 | 281 | si=que.front(); 282 | temp2=state_change(2,si); 283 | si=temp2; 284 | for (set::iterator it=si.begin(); it!=si.end(); ++it){ 285 | epsilon_closure(*it,si); 286 | } 287 | if(mp.count(si)==0){ 288 | mp[si]=ct++; 289 | que.push(si); 290 | dfa[p].a[1]=ct-1; 291 | } 292 | else{ 293 | dfa[p].a[1]=mp.find(si)->second; 294 | } 295 | temp2.clear(); 296 | que.pop(); 297 | p++; 298 | } 299 | for(int i=0;i > > minimize_dfa(vector dfa) { 313 | //cout< grp(dfa.size()); /// Group number for states 315 | vector > part(2, vector()); /// Partition for groups 316 | 317 | /// Initializing the groups 318 | part[0].push_back(0); 319 | for(int i=1; i<(int)grp.size(); i++) { 320 | if(dfa[i].f==dfa[0].f) { 321 | grp[i]=0; 322 | part[0].push_back(i); 323 | } else { 324 | grp[i]=1; 325 | part[1].push_back(i); 326 | } 327 | } 328 | 329 | if(!part[1].size()) part.erase(part.end()); 330 | 331 | /// Loop until no new partition is created 332 | bool chk=true; /// Check if any new partition is created 333 | int strt = 0; /// Starting State 334 | while(chk) { 335 | chk=false; 336 | 337 | /*for(int i=0; i > trans(part[i].size()); /// Transitions for the states of partitions 347 | /// Iterate over states of partitions and find transition groups 348 | for(int k=0; k= 0) 350 | trans[k] = make_pair(grp[dfa[part[i][k]].a[j]],part[i][k]); 351 | else 352 | trans[k] = make_pair(-1,part[i][k]); 353 | } 354 | sort(trans.begin(), trans.end()); 355 | 356 | /// Break partition in case of different transitions 357 | if(trans[0].first!=trans[trans.size()-1].first) { 358 | chk=true; 359 | 360 | int k, m = part.size()-1; 361 | 362 | part[i].clear(); 363 | part[i].push_back(trans[0].second); 364 | for(k=1; k ()); 371 | m++; 372 | } 373 | grp[trans[k].second] = m; 374 | part[m].push_back(trans[k].second); 375 | k++; 376 | } 377 | } 378 | } 379 | } 380 | } 381 | 382 | for(int i=0; i > ret(part.size()); 389 | //cout<(ret[i]) = (dfa[part[i][0]].a[0]>=0)?grp[dfa[part[i][0]].a[0]]:-1; 394 | get<1>(ret[i]) = (dfa[part[i][0]].a[1]>=0)?grp[dfa[part[i][0]].a[1]]:-1; 395 | get<2>(ret[i]) = dfa[part[i][0]].f; 396 | } 397 | 398 | return make_pair(strt, ret); 399 | } 400 | 401 | void print_menu(){ 402 | cout<<"\n---------------------------------------\n"; 403 | cout<<"Input Regex: "< > min_dfa) { 412 | cout<<"---------------------------------------------------------"<(min_dfa[i])<<"\t|\t"; 418 | cout<(min_dfa[i])<<"\t|\t"; 419 | if(get<2>(min_dfa[i])) cout<<"Yes\t|"; else cout<<"No\t|"; 420 | cout< >min_dfa){ 426 | print_menu(); 427 | cout<<"Enter string : "; 428 | string input; 429 | cin.ignore(); 430 | getline(cin,input); 431 | int curr_state,next_state; 432 | curr_state=start_st; 433 | custom_clear(); 434 | cout<<"-----------------------------------------"<(min_dfa[curr_state]); 440 | else 441 | next_state=get<1>(min_dfa[curr_state]); 442 | cout<=0&&get<2>(min_dfa[curr_state]))cout<<"Accepted"; else cout<<"Rejected"; 448 | 449 | cout<>regexp; 459 | dispregex=regexp; 460 | regexp=insert_concat(regexp); 461 | postfix = regexp_to_postfix(regexp); 462 | cout<<"Postfix Expression: "< si; 471 | queue > que; 472 | nfa_to_dfa(si,que,start_state); 473 | 474 | cout< > > min_dfa_tmp = minimize_dfa(dfa); 477 | 478 | vector > min_dfa= min_dfa_tmp.second; 479 | int start_st = min_dfa_tmp.first; 480 | 481 | getchar(); 482 | custom_clear(); 483 | 484 | 485 | while(1){ 486 | print_menu(); 487 | char choice; 488 | choice=getchar(); 489 | custom_clear(); 490 | 491 | switch(choice) { 492 | case '1': 493 | display_nfa(); 494 | getchar(); 495 | break; 496 | case '2': 497 | print_dfa(); 498 | getchar(); 499 | break; 500 | case '3': 501 | print(min_dfa); 502 | getchar(); 503 | break; 504 | case '4': 505 | simulate(start_st,min_dfa); 506 | break; 507 | default: 508 | exit(EXIT_SUCCESS); 509 | } 510 | } 511 | cout<=0){ 522 | if(input[i]=='a') 523 | next_state=get<0>(min_dfa[curr_state]); 524 | else 525 | next_state=get<1>(min_dfa[curr_state]); 526 | if(next_state>=0){ 527 | cout< State "< Trap State"<=0&&get<2>(min_dfa[curr_state]))cout<<"accepted"; else cout<<"rejected"; 535 | cout<