├── Automata ├── Automata.cpp ├── Automata.h ├── FA.cpp └── FA.h ├── CMakeLists.txt ├── ERE.cpp ├── ERE.filters ├── ERE.vcxproj ├── ERE.vcxproj.filters ├── ERE.vcxproj.user ├── LICENSE ├── Parser ├── BREParser.cpp └── BREParser.h ├── README.md ├── doc ├── 1.png ├── DFA.dot.png ├── NFA.dot.png └── min_DFA.dot.png ├── third_part └── ATMPL │ ├── LICENSE │ ├── README.md │ ├── any │ ├── any.hpp │ ├── readme.md │ └── test.cpp │ ├── functinal_helper │ ├── bind.hpp │ ├── func_traits.hpp │ ├── readme.md │ └── test.cpp │ └── optional │ ├── optional.hpp │ ├── optional_test.cpp │ └── readme.md └── util ├── Set.cpp └── Set.h /Automata/Automata.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yufengzjj/ERE/5c62b344472754dc67b75038de7193e653e1e37d/Automata/Automata.cpp -------------------------------------------------------------------------------- /Automata/Automata.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "../third_part/ATMPL/optional/optional.hpp" 16 | #include "../util/Set.h" 17 | template 18 | class Automata 19 | { 20 | public: 21 | enum { epsilon = 1 }; 22 | enum { invalid_state = -1 }; 23 | //the set must impl unique insert(). 24 | using state_set = Set<_State>; 25 | Automata(_Sigma sigma); 26 | explicit Automata(const _Driver& d, _Sigma sigma); 27 | Automata(const Automata& ato_); 28 | Automata& operator=(const Automata& ato_); 29 | Automata& operator=(Automata&& ato_); 30 | Automata(Automata&& ato_); 31 | Automata clone() const; 32 | ~Automata() {} 33 | 34 | _State gen_state(); 35 | void add_edge(_State src, _State dest, _Driver d); 36 | void remove_edge(_State src, _State dest, _Driver d); 37 | void set_start(_State s); 38 | void set_accept(_State s); 39 | void set_accept(state_set s); 40 | void cancle_accept(_State s); 41 | void cancle_accept(state_set s); 42 | state_set get_accepts(); 43 | _State get_start(); 44 | state_set get_states(); 45 | _State direct_to(_State src, _Driver d); 46 | state_set direct_to(state_set src, _Driver d); 47 | state_set e_closure(_State s); 48 | state_set e_closure(state_set s); 49 | 50 | //operations 51 | Automata operator|(Automata& ato_); 52 | Automata operator+(Automata& ato_); 53 | Automata closure(); 54 | void determinate(); 55 | void minimize(); 56 | bool consume(_Driver d); 57 | _State cur_state(); 58 | 59 | //port to third 60 | void print(std::string name); 61 | 62 | class AutomataException :public std::exception 63 | { 64 | public: 65 | AutomataException(std::string msg) :msg_(msg) {} 66 | virtual const char* what() const noexcept 67 | { 68 | return msg_.c_str(); 69 | } 70 | private: 71 | std::string msg_; 72 | }; 73 | private: 74 | struct State :public std::enable_shared_from_this 75 | { 76 | using direc_list = std::forward_list< 77 | std::pair<_Driver, State>>; 78 | using direc_ptr = std::shared_ptr; 79 | State(_State s, direc_ptr dptr) 80 | { 81 | state_ = s; 82 | directed_ = dptr; 83 | } 84 | friend bool operator==(const State& lhs, const State& rhs) 85 | { 86 | return lhs.state_ == rhs.state_; 87 | } 88 | friend bool operator<(const State& lhs, const State& rhs) 89 | { 90 | return lhs.state_ < rhs.state_; 91 | } 92 | 93 | _State state_; 94 | direc_ptr directed_; 95 | }; 96 | typename Automata<_State, _Driver, _Sigma>::State add_state(_State s); 97 | ATMPL::optional::State> find_state(_State s); 98 | typename Automata<_State, _Driver, _Sigma>::State::direc_ptr alloc_drc_ptr(); 99 | private: 100 | state_set accept_; 101 | _State start_; 102 | _State cur_state_; 103 | static _State seed_; 104 | _Sigma sigma_; 105 | 106 | std::forward_list graph_; 107 | }; 108 | 109 | template 110 | _State Automata<_State, _Driver, _Sigma>::cur_state() 111 | { 112 | return cur_state_; 113 | } 114 | 115 | template 116 | bool Automata<_State, _Driver, _Sigma>::consume(_Driver d) 117 | { 118 | auto st = direct_to(cur_state_, d); 119 | if (st != invalid_state) 120 | { 121 | cur_state_ = st; 122 | return true; 123 | } 124 | return false; 125 | 126 | } 127 | 128 | template 129 | void Automata<_State, _Driver, _Sigma>::minimize() 130 | { 131 | state_set origin; 132 | for (auto s : graph_) 133 | { 134 | origin.insert(s.state_); 135 | } 136 | std::forward_list equivalence; 137 | using index = typename std::forward_list::iterator::difference_type; 138 | auto eq_drt = [&](_State s, _Driver d)->index 139 | { 140 | _State s_ = direct_to(s, d); 141 | if (s_ == invalid_state) 142 | { 143 | s_ = s; 144 | } 145 | for (auto i = equivalence.begin(); i != equivalence.end(); ++i) 146 | { 147 | if (i->find(s_) != i->end()) 148 | { 149 | return std::distance(equivalence.begin(), i); 150 | } 151 | } 152 | throw AutomataException("unexpected state" + std::to_string(s_)); 153 | }; 154 | if (!accept_.empty()) 155 | { 156 | equivalence.push_front(accept_); 157 | 158 | } 159 | if (!(origin - accept_).empty()) 160 | { 161 | equivalence.push_front(origin - accept_); 162 | } 163 | else 164 | { 165 | //in this consequence it should not use minimizing algorithm 166 | return; 167 | } 168 | 169 | bool done = false; 170 | while (!done)//calculate equivalence state set 171 | { 172 | done = true; 173 | for (auto states = equivalence.begin(); states != equivalence.end(); ++states) 174 | { 175 | if (states->size() <= 1) 176 | { 177 | continue; 178 | } 179 | state_set apart_states; 180 | for (auto d : sigma_) 181 | { 182 | index first = eq_drt(*states->begin(), d); 183 | for (auto c = ++states->begin(); c != states->end(); ++c) 184 | { 185 | index cur = eq_drt(*c, d); 186 | if (cur != first) 187 | { 188 | apart_states.insert(*c); 189 | } 190 | } 191 | if (!apart_states.empty()) 192 | { 193 | break; 194 | } 195 | } 196 | if (!apart_states.empty()) 197 | { 198 | done = false; 199 | equivalence.push_front(apart_states); 200 | *states = *states - apart_states; 201 | break; 202 | } 203 | } 204 | } 205 | 206 | Automata<_State, _Driver, _Sigma> ato(sigma_); 207 | std::forward_list<_State> equivalence_state; 208 | auto eq_drive = [&](_State s, _Driver d)->ATMPL::optional 209 | { 210 | _State s_ = direct_to(s, d); 211 | if (s_ == invalid_state) 212 | { 213 | return ATMPL::optional(); 214 | } 215 | for (auto i = equivalence.begin(); i != equivalence.end(); ++i) 216 | { 217 | if (i->find(s_) != i->end()) 218 | { 219 | return std::distance(equivalence.begin(), i); 220 | } 221 | } 222 | throw AutomataException("unexpected state" + std::to_string(s_)); 223 | }; 224 | for (auto i = equivalence.begin(); i != equivalence.end(); ++i) 225 | { 226 | equivalence_state.push_front(gen_state()); 227 | } 228 | //generate new automata from equivalence state set. 229 | for (auto eq = equivalence.begin(); eq != equivalence.end(); ++eq) 230 | { 231 | for (auto d : sigma_) 232 | { 233 | auto index_ = eq_drive(*eq->begin(), d); 234 | if (index_) 235 | { 236 | auto eq_state_src = equivalence_state.begin(); 237 | auto eq_state_dst = equivalence_state.begin(); 238 | std::advance(eq_state_src, std::distance(equivalence.begin(), eq)); 239 | std::advance(eq_state_dst, *index_); 240 | ato.add_edge(*eq_state_src, *eq_state_dst, d); 241 | } 242 | } 243 | auto eq_state_i = equivalence_state.begin(); 244 | std::advance(eq_state_i, std::distance(equivalence.begin(), eq)); 245 | if (!(*eq & accept_).empty()) 246 | { 247 | ato.set_accept(*eq_state_i); 248 | } 249 | if (eq->find(start_) != eq->end()) 250 | { 251 | ato.set_start(*eq_state_i); 252 | } 253 | 254 | 255 | } 256 | *this = ato; 257 | } 258 | 259 | template 260 | void Automata<_State, _Driver, _Sigma>::determinate() 261 | { 262 | std::forward_list walker; 263 | std::forward_list> state_set2state; 264 | auto state_find = [&](state_set s)->ATMPL::optional<_State> { 265 | for (auto m : state_set2state) 266 | { 267 | if (m.second == s) 268 | { 269 | return m.first; 270 | } 271 | } 272 | return ATMPL::optional<_State>(); 273 | }; 274 | std::forward_list traverse; 275 | Automata<_State, _Driver, _Sigma> ato(sigma_); 276 | //init 277 | state_set2state.push_front(std::make_pair(gen_state(), e_closure({ start_ }))); 278 | walker.push_front(state_set2state.front().second); 279 | ato.set_start(state_set2state.front().first); 280 | traverse.push_front(state_set2state.front().second); 281 | //stop until no new sets. 282 | while (!walker.empty()) 283 | { 284 | auto s = walker.front(); 285 | walker.pop_front(); 286 | 287 | for (auto d : sigma_) 288 | { 289 | auto st = direct_to(s, d); 290 | if (!st.empty()) 291 | { 292 | st = e_closure(st); 293 | if (std::find(traverse.begin(), traverse.end(), st) == traverse.end()) 294 | { 295 | traverse.push_front(st); 296 | walker.push_front(st); 297 | } 298 | 299 | auto start = state_find(s); 300 | if (start) 301 | { 302 | auto end = state_find(st); 303 | if (end) 304 | { 305 | ato.add_edge(*start, *end, d); 306 | } 307 | else 308 | { 309 | state_set2state.push_front(std::make_pair(gen_state(), st)); 310 | ato.add_edge(*start, state_set2state.front().first, d); 311 | } 312 | 313 | } 314 | } 315 | 316 | } 317 | 318 | } 319 | 320 | //mark accept states 321 | state_set accept; 322 | for (auto a : state_set2state) 323 | { 324 | for (auto acp : accept_) 325 | { 326 | if (a.second.find(acp) != a.second.end()) 327 | { 328 | accept.insert(a.first); 329 | } 330 | } 331 | 332 | } 333 | ato.set_accept(accept); 334 | *this = ato; 335 | } 336 | 337 | template 338 | Automata<_State, _Driver, _Sigma> Automata<_State, _Driver, _Sigma>::closure() 339 | { 340 | auto ato = clone(); 341 | auto start = gen_state(); 342 | auto accept = gen_state(); 343 | for (auto acp : ato.accept_) 344 | { 345 | ato.add_edge(acp, ato.start_, epsilon); 346 | ato.add_edge(acp, accept, epsilon); 347 | } 348 | ato.add_edge(start, ato.start_, epsilon); 349 | ato.add_edge(start, accept, epsilon); 350 | ato.set_start(start); 351 | ato.accept_.clear(); 352 | ato.set_accept(accept); 353 | return ato; 354 | } 355 | 356 | template 357 | Automata<_State, _Driver, _Sigma> 358 | Automata<_State, _Driver, _Sigma>::operator+(Automata& ato_) 359 | { 360 | auto ato = clone(); 361 | ato.graph_.sort(); 362 | ato_.graph_.sort(); 363 | ato.graph_.merge(ato_.graph_); 364 | ato.graph_.unique(); 365 | for (auto accept : ato.accept_) 366 | { 367 | ato.add_edge(accept, ato_.start_, epsilon); 368 | } 369 | ato.accept_.clear(); 370 | ato.set_accept(ato_.accept_); 371 | return ato; 372 | } 373 | 374 | template 375 | Automata<_State, _Driver, _Sigma>::Automata(_Sigma sigma) 376 | :start_(invalid_state), 377 | sigma_(sigma) 378 | { 379 | //std::cout << "Default constructor" << std::endl; 380 | } 381 | 382 | template 383 | Automata<_State, _Driver, _Sigma>& Automata<_State, _Driver, _Sigma>::operator=(Automata&& ato_) 384 | { 385 | //std::cout << "Move assignment operator" << std::endl; 386 | set_start(ato_.get_start()); 387 | accept_.clear(); 388 | set_accept(ato_.get_accepts()); 389 | graph_ = ato_.graph_; 390 | sigma_ = ato_.sigma_; 391 | return *this; 392 | } 393 | 394 | template 395 | void Automata<_State, _Driver, _Sigma>::print(std::string name) 396 | { 397 | std::ofstream out(name); 398 | out << "digraph{" << std::endl; 399 | out << R"(rankdir="LR";)" << std::endl; 400 | out << R"(fontname = "Microsoft YaHei";)" << std::endl; 401 | out << R"(node [shape = circle, fontname = "Microsoft YaHei"];)" << std::endl; 402 | out << R"(edge [fontname = "Microsoft YaHei"];)" << std::endl; 403 | out << R"(-1[style=invis];)" << std::endl; 404 | for (auto acp : accept_) 405 | { 406 | out << acp << R"( [ shape = doublecircle ];)" << std::endl; 407 | } 408 | out << "-1 -> " << get_start() << ";" << std::endl; 409 | for (auto state : graph_) 410 | { 411 | for (auto drct : *state.directed_) 412 | { 413 | if (drct.first == epsilon) 414 | { 415 | out << state.state_ << " -> " << drct.second.state_ << R"([ label = )" << "<ε>" << R"( ];)" << std::endl; 416 | } 417 | else 418 | { 419 | out << state.state_ << " -> " << drct.second.state_ << R"([ label = ")" << drct.first << R"(" ];)" << std::endl; 420 | } 421 | 422 | } 423 | } 424 | out << "}"; 425 | out.flush(); 426 | out.close(); 427 | } 428 | 429 | template 430 | typename Automata<_State, _Driver, _Sigma>::State::direc_ptr 431 | Automata<_State, _Driver, _Sigma>::alloc_drc_ptr() 432 | { 433 | return typename Automata<_State, _Driver, _Sigma>::State::direc_ptr 434 | (new typename Automata<_State, _Driver, _Sigma>::State::direc_list); 435 | } 436 | 437 | template 438 | typename Automata<_State, _Driver, _Sigma>::State 439 | Automata<_State, _Driver, _Sigma>::add_state(_State s) 440 | { 441 | auto state = find_state(s); 442 | if (!state) 443 | { 444 | graph_.push_front(State(s, alloc_drc_ptr())); 445 | return graph_.front(); 446 | } 447 | return *state; 448 | } 449 | 450 | template 451 | inline typename Automata<_State, _Driver, _Sigma>::state_set 452 | Automata<_State, _Driver, _Sigma>::get_accepts() 453 | { 454 | return accept_; 455 | } 456 | 457 | template 458 | inline _State Automata<_State, _Driver, _Sigma>::get_start() 459 | { 460 | return start_; 461 | } 462 | 463 | template 464 | inline typename Automata<_State, _Driver, _Sigma>::state_set 465 | Automata<_State, _Driver, _Sigma>::get_states() 466 | { 467 | state_set st; 468 | for (auto s : graph_) 469 | { 470 | st.insert(s.state_); 471 | } 472 | return st; 473 | } 474 | 475 | template 476 | inline _State Automata<_State, _Driver, _Sigma>::direct_to(_State src, _Driver d) 477 | { 478 | auto s = find_state(src); 479 | if (s) 480 | { 481 | for (auto edge : (*(*s).directed_)) 482 | { 483 | if (edge.first == d) 484 | { 485 | return edge.second.state_; 486 | } 487 | } 488 | 489 | } 490 | return _State(invalid_state); 491 | } 492 | 493 | template 494 | inline typename Automata<_State, _Driver, _Sigma>::state_set 495 | Automata<_State, _Driver, _Sigma>::direct_to(state_set src, _Driver d) 496 | { 497 | state_set st; 498 | for (auto s : src) 499 | { 500 | st.insert(direct_to(s, d)); 501 | } 502 | st.erase(invalid_state); 503 | return st; 504 | } 505 | 506 | template 507 | inline typename Automata<_State, _Driver, _Sigma>::state_set 508 | Automata<_State, _Driver, _Sigma>::e_closure(_State s) 509 | { 510 | state_set st; 511 | std::stack<_State> walker; 512 | walker.push(s); 513 | while (!walker.empty()) 514 | { 515 | auto state = walker.top(); 516 | walker.pop(); 517 | auto node = find_state(state); 518 | if (node) 519 | { 520 | for (auto s_ : *((*node).directed_)) 521 | { 522 | if (s_.first == epsilon && st.find(s_.second.state_) == st.end()) 523 | { 524 | walker.push(s_.second.state_); 525 | } 526 | } 527 | } 528 | st.insert(state); 529 | } 530 | return st; 531 | } 532 | 533 | template 534 | inline typename Automata<_State, _Driver, _Sigma>::state_set 535 | Automata<_State, _Driver, _Sigma>::e_closure(state_set s) 536 | { 537 | state_set st; 538 | for (auto s_ : s) 539 | { 540 | auto st_ = e_closure(s_); 541 | st.insert(st_.begin(), st_.end()); 542 | } 543 | return st; 544 | } 545 | 546 | template 547 | inline Automata<_State, _Driver, _Sigma> 548 | Automata<_State, _Driver, _Sigma>::operator|(Automata & ato_) 549 | { 550 | auto ato = clone(); 551 | ato.graph_.sort(); 552 | ato_.graph_.sort(); 553 | ato.graph_.merge(ato_.graph_); 554 | ato.graph_.unique(); 555 | auto start = gen_state(); 556 | auto end = gen_state(); 557 | ato.add_edge(start, ato.start_, epsilon); 558 | ato.add_edge(start, ato_.start_, epsilon); 559 | ato.set_start(start); 560 | for (auto s : ato.accept_) 561 | { 562 | ato.add_edge(s, end, epsilon); 563 | } 564 | for (auto s : ato_.accept_) 565 | { 566 | ato.add_edge(s, end, epsilon); 567 | } 568 | ato.accept_.clear(); 569 | ato.set_accept(end); 570 | return ato; 571 | } 572 | 573 | template 574 | ATMPL::optional::State> 575 | Automata<_State, _Driver, _Sigma>::find_state(_State s) 576 | { 577 | for (auto g : graph_) 578 | { 579 | if (g.state_ == s) 580 | { 581 | return g; 582 | } 583 | } 584 | return ATMPL::optional::State>(); 585 | } 586 | 587 | template 588 | void Automata<_State, _Driver, _Sigma>::add_edge(_State src, _State dest, _Driver d) 589 | { 590 | State src_state = add_state(src); 591 | State dest_state = add_state(dest); 592 | std::pair<_Driver, State> edge = std::pair<_Driver, State>(d, dest_state); 593 | src_state.directed_->push_front(edge); 594 | src_state.directed_->unique(); 595 | } 596 | 597 | template 598 | inline void Automata<_State, _Driver, _Sigma>::remove_edge(_State src, _State dest, _Driver d) 599 | { 600 | auto src_state = find_state(src); 601 | auto dest_state = find_state(dest); 602 | if (src_state&&dest_state) 603 | { 604 | std::pair<_Driver, State> edge = std::pair<_Driver, State>(d, dest_state); 605 | (*src_state).directed_->remove(edge); 606 | } 607 | } 608 | 609 | template 610 | inline void Automata<_State, _Driver, _Sigma>::set_start(_State s) 611 | { 612 | if (!find_state(s)) 613 | { 614 | add_state(s); 615 | } 616 | start_ = s; 617 | cur_state_ = start_; 618 | } 619 | 620 | template 621 | inline void Automata<_State, _Driver, _Sigma>::set_accept(_State s) 622 | { 623 | accept_.insert(s); 624 | } 625 | 626 | template 627 | inline void Automata<_State, _Driver, _Sigma>::set_accept(typename Automata<_State, _Driver, _Sigma>::state_set s) 628 | { 629 | accept_.insert(s.begin(), s.end()); 630 | } 631 | 632 | template 633 | inline void Automata<_State, _Driver, _Sigma>::cancle_accept(_State s) 634 | { 635 | if (accept_.find() != accept_.end()) 636 | { 637 | accept_.erase(s); 638 | } 639 | 640 | } 641 | 642 | template 643 | inline void Automata<_State, _Driver, _Sigma>:: 644 | cancle_accept(typename Automata<_State, _Driver, _Sigma>::state_set s) 645 | { 646 | for (auto state : s) 647 | { 648 | cancle_accept(s); 649 | } 650 | } 651 | 652 | template 653 | inline Automata<_State, _Driver, _Sigma>::Automata(Automata && ato_) 654 | { 655 | //std::cout << "Move constructors" << std::endl; 656 | set_start(ato_.get_start()); 657 | set_accept(ato_.get_accepts()); 658 | graph_ = ato_.graph_; 659 | sigma_ = ato_.sigma_; 660 | } 661 | 662 | template 663 | Automata<_State, _Driver, _Sigma> Automata<_State, _Driver, _Sigma>::clone() const 664 | { 665 | //std::cout << "clone" << std::endl; 666 | Automata<_State, _Driver, _Sigma> ato(sigma_); 667 | ato.graph_.clear(); 668 | for (auto g : graph_) 669 | { 670 | for (auto drc : (*g.directed_)) 671 | { 672 | ato.add_edge(g.state_, drc.second.state_, drc.first); 673 | } 674 | } 675 | ato.set_start(const_cast*>(this)->get_start()); 676 | ato.set_accept(const_cast*>(this)->get_accepts()); 677 | return ato; 678 | } 679 | 680 | template 681 | _State Automata<_State, _Driver, _Sigma>::gen_state() 682 | { 683 | auto state = seed_++; 684 | if (state == invalid_state) 685 | { 686 | seed_ = invalid_state + 1; 687 | state = seed_; 688 | } 689 | return state; 690 | } 691 | 692 | template 693 | _State Automata<_State, _Driver, _Sigma>::seed_ = Automata<_State, _Driver, _Sigma>::invalid_state + 1; 694 | 695 | template 696 | Automata<_State, _Driver, _Sigma>::Automata(const _Driver& d, _Sigma sigma) 697 | :sigma_(sigma) 698 | { 699 | //std::cout << "Converting constructor" << std::endl; 700 | auto start = gen_state(); 701 | auto accept = gen_state(); 702 | set_start(start); 703 | set_accept(accept); 704 | add_edge(start, accept, d); 705 | } 706 | 707 | template 708 | inline Automata<_State, _Driver, _Sigma>::Automata(const Automata & ato_) 709 | { 710 | //std::cout << "Copy constructors" << std::endl; 711 | *this = ato_; 712 | } 713 | 714 | template 715 | inline Automata<_State, _Driver, _Sigma> & Automata<_State, _Driver, _Sigma>::operator=(const Automata & ato_) 716 | { 717 | //std::cout << "Copy assignment operator" << std::endl; 718 | auto ato = ato_.clone(); 719 | graph_ = ato.graph_; 720 | sigma_ = ato_.sigma_; 721 | accept_.clear(); 722 | set_start(const_cast&>(ato).get_start()); 723 | set_accept(const_cast&>(ato).get_accepts()); 724 | return *this; 725 | } 726 | -------------------------------------------------------------------------------- /Automata/FA.cpp: -------------------------------------------------------------------------------- 1 | #include "FA.h" 2 | #include 3 | 4 | std::string FA::alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 5 | 6 | FA::FA(const alphabet_type& d) 7 | :ato_(d, alphabet) 8 | { 9 | 10 | } 11 | 12 | 13 | FA::~FA() 14 | { 15 | } 16 | 17 | 18 | void FA::print(std::string name) 19 | { 20 | ato_.print(name); 21 | } 22 | 23 | bool FA::check(under_type str) 24 | { 25 | auto acp = ato_.get_accepts(); 26 | for (auto i = str.begin(); i != str.end(); ++i) 27 | { 28 | if (ato_.consume(*i)) 29 | { 30 | if (acp.find(ato_.cur_state()) != acp.end() 31 | && std::distance(i, str.begin()) == std::distance(--str.end(), str.begin())) 32 | { 33 | return true; 34 | } 35 | } 36 | else 37 | { 38 | return false; 39 | } 40 | } 41 | return false; 42 | } 43 | 44 | void FA::set_alphabet(under_type _alphabet) 45 | { 46 | alphabet = _alphabet; 47 | } 48 | 49 | void FA::alternate_FA(FA _FA) 50 | { 51 | ato_ = ato_ | _FA.ato_; 52 | } 53 | 54 | void FA::concat_FA(FA _FA) 55 | { 56 | ato_ = ato_ + _FA.ato_; 57 | } 58 | 59 | void FA::closure() 60 | { 61 | ato_ = ato_.closure(); 62 | } 63 | 64 | void FA::to_mini_DFA() 65 | { 66 | determinate(); 67 | minimize(); 68 | } 69 | 70 | 71 | void FA::determinate() 72 | { 73 | ato_.determinate(); 74 | } 75 | 76 | void FA::minimize() 77 | { 78 | ato_.minimize(); 79 | } 80 | -------------------------------------------------------------------------------- /Automata/FA.h: -------------------------------------------------------------------------------- 1 | #ifndef FA_h__ 2 | #define FA_h__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "Automata.h" 10 | #pragma once 11 | class FA 12 | { 13 | public: 14 | using state = int; 15 | static std::string alphabet; 16 | using under_type = decltype(alphabet); 17 | using alphabet_type = under_type::value_type; 18 | using automata_type = Automata; 19 | 20 | explicit FA(const alphabet_type& d); 21 | ~FA(); 22 | 23 | void print(std::string name); 24 | bool check(under_type str); 25 | static void set_alphabet(under_type _alphabet); 26 | 27 | //construct NFA 28 | void alternate_FA(FA _FA); 29 | void concat_FA(FA _FA); 30 | void closure(); 31 | 32 | void to_mini_DFA(); 33 | void determinate(); 34 | void minimize(); 35 | 36 | private: 37 | automata_type ato_; 38 | }; 39 | 40 | #endif // FA_h__ 41 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.6) 2 | project(ERE) 3 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 5 | set(SOURCE_FILES Automata/FA.cpp Automata/Automata.cpp Parser/BREParser.cpp util/Set.cpp ERE.cpp) 6 | add_executable(ERE ${SOURCE_FILES}) 7 | target_link_libraries(ERE libboost_program_options-mt.a) -------------------------------------------------------------------------------- /ERE.cpp: -------------------------------------------------------------------------------- 1 | #include "util/Set.h" 2 | #include "Automata//Automata.h" 3 | #include "Parser/BREParser.h" 4 | #include "boost/program_options/options_description.hpp" 5 | #include "boost/program_options/parsers.hpp" 6 | #include "boost/program_options/variables_map.hpp" 7 | #include 8 | #include 9 | #include 10 | namespace po = boost::program_options; 11 | void event_handler(BREParser::event e_, ATMPL::any msg_) 12 | { 13 | switch (e_) 14 | { 15 | case BREParser::event::NFA_complete: 16 | ATMPL::any::cast(msg_).print("NFA.dot"); 17 | break; 18 | case BREParser::event::NFA_determinated: 19 | ATMPL::any::cast(msg_).print("DFA.dot"); 20 | break; 21 | case BREParser::event::DFA_minimized: 22 | ATMPL::any::cast(msg_).print("min_DFA.dot"); 23 | break; 24 | } 25 | } 26 | 27 | int main(int argc, char* argv[]) 28 | { 29 | po::options_description desc("Allowed options"); 30 | desc.add_options() 31 | ("help,h", "produce help message") 32 | ("expr,e", po::value(), "set regular expression") 33 | ("string,s", po::value(), "string to check by regular expression") 34 | ("alphabet,a", po::value()->default_value(FA::alphabet.data()), "set regular expression alphabet"); 35 | po::variables_map vm; 36 | po::store(po::parse_command_line(argc, argv, desc), vm); 37 | po::notify(vm); 38 | if (vm.count("expr") && vm.count("string")) 39 | { 40 | try 41 | { 42 | FA::set_alphabet(vm["alphabet"].as().c_str()); 43 | BREParser bre_parser; 44 | bre_parser.register_event(BREParser::event::NFA_complete, event_handler); 45 | bre_parser.register_event(BREParser::event::NFA_determinated, event_handler); 46 | bre_parser.register_event(BREParser::event::DFA_minimized, event_handler); 47 | auto fa = bre_parser.parse(vm["expr"].as()); 48 | if (fa.check(vm["string"].as())) 49 | { 50 | std::cout << "matching!" << std::endl; 51 | } 52 | else 53 | { 54 | std::cout << "not matching!" << std::endl; 55 | } 56 | } 57 | catch (std::exception &e) 58 | { 59 | std::cout << e.what() << std::endl; 60 | } 61 | } 62 | else 63 | { 64 | std::cout << desc; 65 | } 66 | 67 | } 68 | 69 | -------------------------------------------------------------------------------- /ERE.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 头文件 20 | 21 | 22 | 头文件 23 | 24 | 25 | 头文件 26 | 27 | 28 | 头文件 29 | 30 | 31 | 32 | 33 | 源文件 34 | 35 | 36 | 源文件 37 | 38 | 39 | 源文件 40 | 41 | 42 | -------------------------------------------------------------------------------- /ERE.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {86C0F19F-12CE-44A0-BD82-A7221563BFEE} 15 | Win32Proj 16 | RE_Engine 17 | 8.1 18 | ERE 19 | 20 | 21 | 22 | Application 23 | true 24 | v140 25 | Unicode 26 | 27 | 28 | Application 29 | false 30 | v140 31 | true 32 | Unicode 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | true 46 | $(VC_IncludePath);$(WindowsSDK_IncludePath);G:\opensource libs\boost_1_62_0; 47 | $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);G:\opensource libs\boost_1_62_0\lib32-msvc-14.0; 48 | $(WindowsSDK_MetadataPath);G:\opensource libs\boost_1_62_0\lib32-msvc-14.0; 49 | 50 | 51 | false 52 | $(VC_IncludePath);$(WindowsSDK_IncludePath);G:\opensource libs\boost_1_62_0; 53 | $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);G:\opensource libs\boost_1_62_0\lib32-msvc-14.0; 54 | $(WindowsSDK_MetadataPath);G:\opensource libs\boost_1_62_0\lib32-msvc-14.0; 55 | 56 | 57 | 58 | 59 | 60 | Level3 61 | Disabled 62 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 63 | 64 | 65 | Console 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 78 | 79 | 80 | None 81 | true 82 | 83 | 84 | Console 85 | true 86 | true 87 | true 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /ERE.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Parser 7 | 8 | 9 | util 10 | 11 | 12 | Automata 13 | 14 | 15 | Automata 16 | 17 | 18 | 19 | 20 | {86ed5819-5bb7-496c-a427-cb4a0c39ad6e} 21 | 22 | 23 | {9515bada-3a17-4266-99ae-2299b657bff1} 24 | 25 | 26 | {9425ca9f-6075-4a9f-9c79-ec244024ac86} 27 | 28 | 29 | 30 | 31 | Parser 32 | 33 | 34 | util 35 | 36 | 37 | Automata 38 | 39 | 40 | Automata 41 | 42 | 43 | -------------------------------------------------------------------------------- /ERE.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -e "a*|(b|c)*" -s aaaa -a abc 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 yufeng Z 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Parser/BREParser.cpp: -------------------------------------------------------------------------------- 1 | #include "BREParser.h" 2 | #include 3 | BREParser::BREParser() 4 | :m_pos(-1) 5 | { 6 | } 7 | 8 | 9 | BREParser::~BREParser() 10 | { 11 | } 12 | 13 | FA BREParser::parse(std::string _src) 14 | { 15 | m_rexpr = _src; 16 | auto fa = RE(); 17 | if (m_pos < _src.length()-1) 18 | { 19 | throw BREParserException("abort unexpected at offset:" + std::to_string(m_pos + 1)); 20 | } 21 | dispatch(event::NFA_complete, fa); 22 | fa.determinate(); 23 | dispatch(event::NFA_determinated, fa); 24 | fa.minimize(); 25 | dispatch(event::DFA_minimized, fa); 26 | return fa; 27 | 28 | } 29 | 30 | void BREParser::register_event(event e_, event_handler h_) 31 | { 32 | event_center_.push_front(std::make_pair(e_, h_)); 33 | } 34 | 35 | void BREParser::dispatch(event e_, ATMPL::any msg_) 36 | { 37 | for (auto ev : event_center_) 38 | { 39 | if (ev.first == e_) 40 | { 41 | ev.second(e_, msg_); 42 | } 43 | } 44 | } 45 | 46 | FA BREParser::RE() 47 | { 48 | return expr(); 49 | } 50 | 51 | FA BREParser::expr() 52 | { 53 | FA _fa = term(); 54 | if (peek_next() == '|') 55 | { 56 | next(); 57 | _fa.alternate_FA(expr()); 58 | } 59 | return _fa; 60 | } 61 | 62 | FA BREParser::term() 63 | { 64 | FA _fa = factor(); 65 | while (peek_next() != '|' && peek_next() != ')' && has_next()) 66 | { 67 | _fa.concat_FA(factor()); 68 | } 69 | return _fa; 70 | } 71 | 72 | FA BREParser::factor() 73 | { 74 | FA _fa = item(); 75 | while (peek_next() == '*') 76 | { 77 | next(); 78 | _fa.closure(); 79 | } 80 | return _fa; 81 | } 82 | 83 | FA BREParser::item() 84 | { 85 | if (peek_next() == '(') 86 | { 87 | next(); 88 | auto _fa = expr(); 89 | if (peek_next() != ')') 90 | { 91 | //missing ')' 92 | throw BREParserException(("missing ')' at offset:" + std::to_string(m_pos + 1)).c_str()); 93 | } 94 | next(); 95 | return _fa; 96 | } 97 | else if (std::find(FA::alphabet.begin(), FA::alphabet.end(),peek_next()) != FA::alphabet.end()) 98 | { 99 | return sym(); 100 | } 101 | throw BREParserException(("unknown letter found at offset:" + std::to_string(m_pos + 1)).c_str()); 102 | } 103 | 104 | FA BREParser::sym() 105 | { 106 | FA _fa(peek_next()); 107 | next(); 108 | return _fa; 109 | } 110 | 111 | char BREParser::next() 112 | { 113 | char _next_char = peek_next(); 114 | if (_next_char != eof) 115 | { 116 | ++m_pos; 117 | } 118 | return _next_char; 119 | } 120 | 121 | char BREParser::peek_next() 122 | { 123 | pos next_pos = m_pos + 1; 124 | if (next_pos < m_rexpr.length()) 125 | { 126 | return m_rexpr.at(next_pos); 127 | } 128 | return eof; 129 | } 130 | 131 | bool BREParser::has_next() 132 | { 133 | if (peek_next() != eof) 134 | { 135 | return true; 136 | } 137 | return false; 138 | } 139 | 140 | -------------------------------------------------------------------------------- /Parser/BREParser.h: -------------------------------------------------------------------------------- 1 | #ifndef BREParser_h__ 2 | #define BREParser_h__ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "../third_part/ATMPL/any/any.hpp" 9 | #include "../Automata/FA.h" 10 | #pragma once 11 | class BREParser 12 | { 13 | public: 14 | BREParser(); 15 | ~BREParser(); 16 | FA parse(std::string _src); 17 | class BREParserException :public std::exception 18 | { 19 | public: 20 | BREParserException(std::string msg):msg_(msg){} 21 | virtual const char* what() const noexcept 22 | { 23 | return msg_.c_str(); 24 | } 25 | private: 26 | std::string msg_; 27 | }; 28 | enum event 29 | { 30 | NFA_complete, 31 | NFA_determinated, 32 | DFA_minimized 33 | }; 34 | using event_handler = std::function; 35 | void register_event(event e_, event_handler h_); 36 | private: 37 | void dispatch(event e_, ATMPL::any msg_); 38 | private: 39 | //note: the current letter view as processed. 40 | FA RE(); 41 | FA expr(); 42 | FA term(); 43 | FA factor(); 44 | FA item(); 45 | FA sym(); 46 | 47 | //move one step forward. 48 | //return eof = '\0' if no next letter. 49 | char next(); 50 | 51 | //get next letter but not move forward. 52 | //return eof = '\0' if no next letter. 53 | char peek_next(); 54 | 55 | bool has_next(); 56 | 57 | using pos = unsigned int; 58 | char eof = '\0'; 59 | 60 | std::string m_rexpr; 61 | pos m_pos; 62 | 63 | std::forward_list> event_center_; 64 | 65 | }; 66 | #endif // BREParser_h__ 67 | 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ERE 2 | **Educational Regular expression Engine--purpose for education of automata theory.** 3 | 4 | all base on C++11 standard library and a tiny C++11 template library [ATMPL](https://github.com/yufengzjj/ATMPL) . 5 | 6 | this regular expression engine only support core operations:alternate,concat and closure. 7 | 8 | it uses recursive descent parsing to parse regular expression and then generate finite state automata.it can generate DOT(Graphviz) file of NFA/DFA/miniDFA of the regular expression automata. 9 | 10 | examples: 11 | 12 | > ERE.exe --help 13 | > 14 | > -h [ --help ] produce help message 15 | > 16 | > -e [ --expr ] arg set regular expression 17 | > 18 | > -s [ --string ] arg string to check by regular expression 19 | > 20 | > -a [ --alphabet ] arg set regular expression alphabet 21 | 22 | ERE.exe -e "a(b|cd)*e" -s abbbcdcde 23 | 24 | ![](doc/1.png) 25 | 26 | dot -T png -O NFA.dot DFA.dot min_DFA.dot 27 | 28 | 29 | 30 | ![](doc/NFA.dot.png) 31 | 32 | ![](doc/DFA.dot.png) 33 | 34 | ![](doc/min_DFA.dot.png) -------------------------------------------------------------------------------- /doc/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yufengzjj/ERE/5c62b344472754dc67b75038de7193e653e1e37d/doc/1.png -------------------------------------------------------------------------------- /doc/DFA.dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yufengzjj/ERE/5c62b344472754dc67b75038de7193e653e1e37d/doc/DFA.dot.png -------------------------------------------------------------------------------- /doc/NFA.dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yufengzjj/ERE/5c62b344472754dc67b75038de7193e653e1e37d/doc/NFA.dot.png -------------------------------------------------------------------------------- /doc/min_DFA.dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yufengzjj/ERE/5c62b344472754dc67b75038de7193e653e1e37d/doc/min_DFA.dot.png -------------------------------------------------------------------------------- /third_part/ATMPL/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 yufeng Z 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /third_part/ATMPL/README.md: -------------------------------------------------------------------------------- 1 | # ATMPL 2 | 3 | **all library components write in c++11 without any other dependency.** 4 | 5 | at present, this ATMPL--Another Template Meta Programming Library has a little supported 6 | 7 | features as follow: 8 | 9 | ### functional_helper 10 | include function traits and a enhanced bind template class. 11 | 12 | ### Any 13 | 14 | Safe, generic container for single values of different value types. **similar to [boost.Any](http://www.boost.org/doc/libs/1_60_0/doc/html/any.html)** but c++11 version. 15 | 16 | ### Optional 17 | 18 | A value-semantic, type-safe wrapper for representing 'optional' (or 'nullable') objects of a given type. An optional object may or may not contain a value of the underlying type. [boost.Optional](http://www.boost.org/doc/libs/1_61_0/libs/optional/doc/html/index.html) C++11 version 19 | 20 | **all test on VS2015/GCC 5.3.0/Clang 3.8.0** 21 | 22 | -------------------------------------------------------------------------------- /third_part/ATMPL/any/any.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by bhzyf on 2016/5/2. 3 | // 4 | 5 | #ifndef CLIONSCIENCE_ANY_HPP 6 | #define CLIONSCIENCE_ANY_HPP 7 | #include 8 | #include 9 | 10 | namespace ATMPL 11 | { 12 | class any 13 | { 14 | private: 15 | class placeholder 16 | { 17 | public: // structors 18 | 19 | virtual ~placeholder() 20 | { 21 | } 22 | 23 | public: // queries 24 | 25 | virtual placeholder *clone() const = 0; 26 | 27 | }; 28 | 29 | template 30 | class holder : public placeholder 31 | { 32 | public: 33 | holder(const _ValueType &v) 34 | : _hold(v) 35 | { 36 | } 37 | 38 | placeholder *clone() const override 39 | { 40 | return new holder(_hold); 41 | } 42 | 43 | public: 44 | _ValueType _hold; 45 | }; 46 | 47 | public: 48 | any() : _holder(nullptr) 49 | { 50 | } 51 | 52 | template 53 | any(const _ValueType &v) 54 | : _holder(new holder::type>::type>(v)) 55 | { 56 | } 57 | 58 | // Perfect forwarding of _ValueType 59 | template 60 | any(_ValueType &&v 61 | , typename std::enable_if::type>::value, _ValueType>::type* = nullptr 62 | , typename std::enable_if::value>::type* = nullptr) 63 | :_holder(new holder< typename std::decay<_ValueType>::type >(std::forward<_ValueType>(v))) 64 | { 65 | } 66 | 67 | //copy constructor 68 | any(const any &other) 69 | : _holder(other._holder != nullptr ? other._holder->clone() : nullptr) 70 | { 71 | } 72 | 73 | //move constructor 74 | any(any && other) 75 | :_holder(other._holder) 76 | { 77 | other._holder = nullptr; 78 | } 79 | 80 | //assignment constructor 81 | any & operator=(const any& other_any) 82 | { 83 | _holder = other_any._holder->clone(); 84 | return *this; 85 | } 86 | 87 | //move assignment constructor 88 | any & operator=(any&& other_any) 89 | { 90 | _holder = other_any._holder; 91 | other_any._holder = nullptr; 92 | return *this; 93 | } 94 | 95 | ~any() 96 | { 97 | delete _holder; 98 | _holder = nullptr; 99 | } 100 | 101 | template 102 | static _ValueType cast(any &operand) 103 | { 104 | typedef typename std::remove_reference<_ValueType>::type nonref; 105 | nonref * op = cast(&operand); 106 | typedef typename std::conditional::value, _ValueType, 107 | typename std::add_lvalue_reference<_ValueType>::type>::type ref_type; 108 | return static_cast(*op); 109 | } 110 | 111 | private: 112 | template 113 | static _ValueType *cast(any *operand) 114 | { 115 | auto _holder = dynamic_cast *>(operand->_holder); 116 | if (_holder == nullptr) 117 | throw std::bad_cast(); 118 | return &_holder->_hold; 119 | } 120 | 121 | template 122 | static const _ValueType *cast(const any *operand) 123 | { 124 | return cast<_ValueType>(const_cast(operand)); 125 | } 126 | 127 | 128 | public: 129 | placeholder *_holder; 130 | }; 131 | 132 | 133 | } 134 | #endif //CLIONSCIENCE_ANY_HPP 135 | -------------------------------------------------------------------------------- /third_part/ATMPL/any/readme.md: -------------------------------------------------------------------------------- 1 | examples: 2 | 3 | ```c++ 4 | #include 5 | #include 6 | #include "any.hpp" 7 | #include 8 | using namespace ATMPL; 9 | 10 | template 11 | void pod_test(any &v) 12 | { 13 | std::cout << "any cast to " << typeid(_T).name() << " : " << any::cast<_T>(v) << std::endl; 14 | } 15 | 16 | any ret() 17 | { 18 | int i = 1; 19 | return any(i); 20 | } 21 | 22 | int main() 23 | { 24 | 25 | 26 | try 27 | { 28 | any v(short(1)); 29 | pod_test(v); 30 | 31 | any v_int(int(2)); 32 | pod_test(v_int); 33 | 34 | any v_long(long(3)); 35 | pod_test(v_long); 36 | 37 | any v_longlong((long long)(4)); 38 | pod_test(v_longlong); 39 | 40 | any v_char(char('5')); 41 | pod_test(v_char); 42 | 43 | char str[] = "hello world"; 44 | any v_cptr(str); 45 | pod_test(v_cptr); 46 | 47 | any v_string(std::string("HI! string any cast")); 48 | pod_test(v_string); 49 | 50 | any any_0; 51 | any any_1(ret()); 52 | pod_test(any_1); 53 | 54 | any any_2(any_1); 55 | pod_test(any_2); 56 | 57 | any any_3 = ret(); 58 | pod_test(any_3); 59 | 60 | any any_4 = any_1; 61 | pod_test(any_4); 62 | 63 | any any_5 = any(int(5)); 64 | pod_test(any_5); 65 | 66 | std::vector any_vec; 67 | any_vec.push_back('A'); 68 | any_vec.push_back(short(1)); 69 | any_vec.push_back(int(2)); 70 | any_vec.push_back(str); 71 | any_vec.push_back(std::string("hello any,world")); 72 | pod_test(any_vec[0]); 73 | pod_test(any_vec[1]); 74 | pod_test(any_vec[2]); 75 | pod_test(any_vec[3]); 76 | pod_test(any_vec[4]); 77 | 78 | printf("test passed\n"); 79 | } 80 | catch (std::bad_cast&e) 81 | { 82 | std::cout << e.what()<<" occured when use any\n"; 83 | } 84 | 85 | 86 | } 87 | ``` -------------------------------------------------------------------------------- /third_part/ATMPL/any/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "any.hpp" 4 | #include 5 | using namespace ATMPL; 6 | 7 | template 8 | void pod_test(any &v) 9 | { 10 | std::cout << "any cast to " << typeid(_T).name() << " : " << any::cast<_T>(v) << std::endl; 11 | } 12 | 13 | any ret() 14 | { 15 | int i = 1; 16 | return any(i); 17 | } 18 | 19 | int main() 20 | { 21 | 22 | 23 | try 24 | { 25 | any v(short(1)); 26 | pod_test(v); 27 | 28 | any v_int(int(2)); 29 | pod_test(v_int); 30 | 31 | any v_long(long(3)); 32 | pod_test(v_long); 33 | 34 | any v_longlong((long long)(4)); 35 | pod_test(v_longlong); 36 | 37 | any v_char(char('5')); 38 | pod_test(v_char); 39 | 40 | char str[] = "hello world"; 41 | any v_cptr(str); 42 | pod_test(v_cptr); 43 | 44 | any v_string(std::string("HI! string any cast")); 45 | pod_test(v_string); 46 | 47 | any any_0; 48 | any any_1(ret()); 49 | pod_test(any_1); 50 | 51 | any any_2(any_1); 52 | pod_test(any_2); 53 | 54 | any any_3 = ret(); 55 | pod_test(any_3); 56 | 57 | any any_4 = any_1; 58 | pod_test(any_4); 59 | 60 | any any_5 = any(int(5)); 61 | pod_test(any_5); 62 | 63 | std::vector any_vec; 64 | any_vec.push_back('A'); 65 | any_vec.push_back(short(1)); 66 | any_vec.push_back(int(2)); 67 | any_vec.push_back(str); 68 | any_vec.push_back(std::string("hello any,world")); 69 | pod_test(any_vec[0]); 70 | pod_test(any_vec[1]); 71 | pod_test(any_vec[2]); 72 | pod_test(any_vec[3]); 73 | pod_test(any_vec[4]); 74 | 75 | printf("test passed\n"); 76 | } 77 | catch (std::bad_cast&e) 78 | { 79 | std::cout << e.what()<<" occured when use any\n"; 80 | } 81 | 82 | 83 | } -------------------------------------------------------------------------------- /third_part/ATMPL/functinal_helper/bind.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "func_traits.hpp" 5 | namespace ATMPL 6 | { 7 | 8 | 9 | namespace functional_helper 10 | { 11 | template 12 | struct bind_holder; 13 | 14 | template 15 | struct is_bind_holder 16 | :public std::false_type 17 | {}; 18 | template 19 | struct is_bind_holder> 20 | :public std::true_type 21 | {}; 22 | 23 | template 24 | struct is_bind_holder> 25 | :public std::true_type 26 | {}; 27 | 28 | template 29 | struct is_bind_holder> 30 | :public std::true_type 31 | {}; 32 | 33 | template 34 | struct is_bind_holder> 35 | :public std::true_type 36 | {}; 37 | 38 | 39 | 40 | template 41 | struct bind_holder_stripper_helper; 42 | 43 | template 44 | struct bind_holder_stripper_helper 45 | : public func_traits 46 | {}; 47 | 48 | template 49 | struct bind_holder_stripper_helper 50 | :public bind_holder_stripper_helper::value> 51 | {}; 52 | 53 | template 54 | struct bind_holder_stripper 55 | :public bind_holder_stripper_helper::value> 56 | {}; 57 | 58 | template 59 | struct bind_holder 60 | { 61 | private: 62 | BindExpr _bind_expr; 63 | public: 64 | 65 | typedef F bind_type; 66 | typedef bind_holder_stripper underlying_type; 67 | typedef std::integral_constant bind_arity; 68 | explicit bind_holder(BindExpr&& _functor) 69 | :_bind_expr(std::move(std::forward(_functor))) 70 | { 71 | } 72 | 73 | template 74 | struct bind_arg 75 | { 76 | static_assert(N < bind_arity::value, "error: invalid parameter index."); 77 | using type = typename std::tuple_element>::type; 78 | }; 79 | 80 | template 81 | auto operator()(_Args&&...params) 82 | ->decltype(this->_bind_expr(std::forward<_Args>(params)...)) 83 | { 84 | return this->_bind_expr(std::forward<_Args>(params)...); 85 | } 86 | }; 87 | 88 | template 89 | struct remove_cvr 90 | { 91 | using type = typename std::remove_cv::type>::type; 92 | }; 93 | 94 | template 95 | auto bind(F&& f, Args&&... args) 96 | ->decltype((bind_holder(f), std::forward(args)...)), 97 | typename remove_cvr::type, Args...> 98 | (std::bind(std::forward(f), std::forward(args)...)))) 99 | { 100 | return (bind_holder(f), std::forward(args)...)), 101 | typename remove_cvr::type, Args...> 102 | (std::bind(std::forward(f), std::forward(args)...))); 103 | } 104 | } 105 | 106 | } -------------------------------------------------------------------------------- /third_part/ATMPL/functinal_helper/func_traits.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace ATMPL 6 | { 7 | 8 | namespace functional_helper 9 | { 10 | template 11 | struct func_traits; 12 | 13 | //function 14 | template 15 | struct func_traits<_Ret(_Args...)> 16 | { 17 | typedef _Ret ret; 18 | typedef std::integral_constant arity; 19 | template 20 | struct arg 21 | { 22 | static_assert(N < arity::value, "invalid parameter index"); 23 | using type = typename std::tuple_element>::type; 24 | }; 25 | }; 26 | 27 | //function pointer 28 | template 29 | struct func_traits<_Ret(*)(_Args...)> :public func_traits<_Ret(_Args...)> 30 | { 31 | }; 32 | 33 | //member function pointer 34 | template 35 | struct func_traits<_Ret(_Class::*)(_Args...)> :public func_traits<_Ret(_Class&, _Args...)> 36 | { 37 | }; 38 | 39 | template 40 | struct func_traits<_Ret(_Class::*)(_Args...) const> :public func_traits<_Ret(_Class&, _Args...)> 41 | { 42 | }; 43 | 44 | 45 | //functor and lambda 46 | template 47 | struct func_traits : public func_traits 48 | { 49 | }; 50 | 51 | } 52 | 53 | 54 | } -------------------------------------------------------------------------------- /third_part/ATMPL/functinal_helper/readme.md: -------------------------------------------------------------------------------- 1 | ### functional_helper 2 | 3 | include function traits and a enhanced bind template class. 4 | 5 | ##### function_traits 6 | 7 | it provide a template class named function_traits