summaryrefslogtreecommitdiff
path: root/libs/msm/doc/HTML/examples/ParsingDigits.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/msm/doc/HTML/examples/ParsingDigits.cpp')
-rw-r--r--libs/msm/doc/HTML/examples/ParsingDigits.cpp479
1 files changed, 479 insertions, 0 deletions
diff --git a/libs/msm/doc/HTML/examples/ParsingDigits.cpp b/libs/msm/doc/HTML/examples/ParsingDigits.cpp
new file mode 100644
index 0000000000..6dadb4d53e
--- /dev/null
+++ b/libs/msm/doc/HTML/examples/ParsingDigits.cpp
@@ -0,0 +1,479 @@
+// Copyright 2010 Christophe Henry
+// henry UNDERSCORE christophe AT hotmail DOT com
+// This is an extended version of the state machine available in the boost::mpl library
+// Distributed under the same license as the original.
+// Copyright for the original version:
+// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
+// under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define FUSION_MAX_VECTOR_SIZE 20
+
+#include <boost/msm/back/state_machine.hpp>
+#include "char_event_dispatcher.hpp"
+#include <boost/msm/front/state_machine_def.hpp>
+#include <boost/msm/front/functor_row.hpp>
+#include <boost/timer.hpp>
+
+namespace msm = boost::msm;
+namespace mpl = boost::mpl;
+using namespace msm::front;
+
+#include <iostream>
+#ifdef WIN32
+#include "windows.h"
+#else
+#include <sys/time.h>
+#endif
+
+// events
+struct end_sub {template <class Event> end_sub(Event const&){}};
+struct other_char {};
+struct default_char {};
+struct eos {};
+
+
+namespace test_fsm // Concrete FSM implementation
+{
+ // Concrete FSM implementation
+ struct parsing_ : public msm::front::state_machine_def<parsing_>
+ {
+ // no need for exception handling or message queue
+ typedef int no_exception_thrown;
+ typedef int no_message_queue;
+
+ struct Waiting : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Waiting" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Waiting" << std::endl;}
+ };
+ struct Digit1 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit1" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit1" << std::endl;}
+ };
+ struct Digit2 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit2" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit2" << std::endl;}
+ };
+ struct Digit3 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit3" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit3" << std::endl;}
+ };
+ struct Digit4 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit4" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit4" << std::endl;}
+ };
+ struct MinusChar1 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar1" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar1" << std::endl;}
+ };
+ struct Digit5 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit5" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit5" << std::endl;}
+ };
+ struct Digit6 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit6" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit6" << std::endl;}
+ };
+ struct Digit7 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit7" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit7" << std::endl;}
+ };
+ struct Digit8 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit8" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit8" << std::endl;}
+ };
+ struct MinusChar2 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar2" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar2" << std::endl;}
+ };
+ struct Digit9 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit9" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit9" << std::endl;}
+ };
+ struct Digit10 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit10" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit10" << std::endl;}
+ };
+ struct Digit11 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit11" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit11" << std::endl;}
+ };
+ struct Digit12 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit12" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit12" << std::endl;}
+ };
+ struct MinusChar3 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar3" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar3" << std::endl;}
+ };
+ struct Digit13 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit13" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit13" << std::endl;}
+ };
+ struct Digit14 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit14" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit14" << std::endl;}
+ };
+ struct Digit15 : public msm::front::state<>
+ {
+ // optional entry/exit methods
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit15" << std::endl;}
+ //template <class Event,class FSM>
+ //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit15" << std::endl;}
+ };
+ //struct Start : public msm::front::state<> {};
+ struct Parsed : public msm::front::state<> {};
+ //struct Failed : public msm::front::state<> {};
+
+ // the initial state of the player SM. Must be defined
+ typedef Waiting initial_state;
+ // transition actions
+ struct test_fct
+ {
+ template <class FSM,class EVT,class SourceState,class TargetState>
+ void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
+ {
+ std::cout << "Parsed!" << std::endl;
+ }
+ };
+
+ // guard conditions
+
+
+ // Transition table for parsing_
+ struct transition_table : mpl::vector<
+ // Start Event Next Action Guard
+ // +-------------+-------------------+---------+---------------------+----------------------+
+ Row < Waiting , digit , Digit1 >,
+ Row < Digit1 , digit , Digit2 >,
+ Row < Digit2 , digit , Digit3 >,
+ Row < Digit3 , digit , Digit4 >,
+ Row < Digit4 , event_char<'-'> , MinusChar1 >,
+ Row < MinusChar1 , digit , Digit5 >,
+ Row < Digit5 , digit , Digit6 >,
+ Row < Digit6 , digit , Digit7 >,
+ Row < Digit7 , digit , Digit8 >,
+ Row < Digit8 , event_char<'-'> , MinusChar2 >,
+ Row < MinusChar2 , digit , Digit9 >,
+ Row < Digit9 , digit , Digit10 >,
+ Row < Digit10 , digit , Digit11 >,
+ Row < Digit11 , digit , Digit12 >,
+ Row < Digit12 , event_char<'-'> , MinusChar3 >,
+ Row < MinusChar3 , digit , Digit13 >,
+ Row < Digit13 , digit , Digit14 >,
+ Row < Digit14 , digit , Digit15 >,
+ Row < Digit15 , eos , Parsed >,
+ Row < Parsed , eos , Waiting >
+ // +---------+-------------+---------+---------------------+----------------------+
+ > {};
+
+
+ // Replaces the default no-transition response.
+ template <class FSM,class Event>
+ void no_transition(Event const& e, FSM&,int state)
+ {
+ std::cout << "no transition from state " << state
+ << " on event " << typeid(e).name() << std::endl;
+ }
+ };
+ typedef msm::back::state_machine<parsing_> parsing;
+}
+
+#ifndef WIN32
+long mtime(struct timeval& tv1,struct timeval& tv2)
+{
+ return (tv2.tv_sec-tv1.tv_sec) *1000000 + ((tv2.tv_usec-tv1.tv_usec));
+}
+#endif
+
+// This declares the statically-initialized char_event_dispatcher instance.
+template <class Fsm>
+const msm::back::char_event_dispatcher<Fsm>
+msm::back::char_event_dispatcher<Fsm>::instance;
+
+struct Parser
+{
+ Parser():p(){p.start();}
+ void new_char(char c)
+ {
+ typedef msm::back::char_event_dispatcher<test_fsm::parsing> table;
+ table::instance.process_event(p,c);
+ }
+ void finish_string(){p.process_event(eos());}
+ void reinit(){p.process_event(eos());}
+ test_fsm::parsing p;
+};
+
+void msm_match(const char* input)
+{
+ test_fsm::parsing p;
+ p.start();
+
+ int j=0;
+ while(input[j])
+ //for (size_t j=0;j<len;++j)
+ {
+ switch (input[j])
+ {
+ case '0':
+ p.process_event(char_0());
+ break;
+ case '1':
+ p.process_event(char_1());
+ break;
+ case '2':
+ p.process_event(char_2());
+ break;
+ case '3':
+ p.process_event(char_3());
+ break;
+ case '4':
+ p.process_event(char_4());
+ break;
+ case '5':
+ p.process_event(char_5());
+ break;
+ case '6':
+ p.process_event(char_6());
+ break;
+ case '7':
+ p.process_event(char_7());
+ break;
+ case '8':
+ p.process_event(char_8());
+ break;
+ case '9':
+ p.process_event(char_9());
+ break;
+ case '-':
+ p.process_event(event_char<'-'>());
+ break;
+ default:
+ p.process_event(default_char());
+ break;
+ }
+ ++j;
+ }
+ p.process_event(eos());
+ p.process_event(eos());
+}
+
+double time_match(const char* text)
+{
+ boost::timer tim;
+ int iter = 1;
+ int counter, repeats;
+ double result = 0;
+ double run;
+ do
+ {
+ tim.restart();
+ for(counter = 0; counter < iter; ++counter)
+ {
+ msm_match( text);
+ }
+ result = tim.elapsed();
+ iter *= 2;
+ } while(result < 0.5);
+ iter /= 2;
+
+ // repeat test and report least value for consistency:
+ for(repeats = 0; repeats < 10; ++repeats)
+ {
+ tim.restart();
+ for(counter = 0; counter < iter; ++counter)
+ {
+ msm_match( text);
+ }
+ run = tim.elapsed();
+ result = (std::min)(run, result);
+ }
+ return result / iter;
+}
+int main()
+{
+ // for timing
+#ifdef WIN32
+ LARGE_INTEGER res;
+ ::QueryPerformanceFrequency(&res);
+ LARGE_INTEGER li,li2;
+#else
+ struct timeval tv1,tv2;
+ gettimeofday(&tv1,NULL);
+#endif
+
+ test_fsm::parsing p;
+ p.start();
+ const char* input = "1234-5678-1234-456";
+ size_t len = strlen(input);
+ // for timing
+#ifdef WIN32
+ ::QueryPerformanceCounter(&li);
+#else
+ gettimeofday(&tv1,NULL);
+#endif
+ for (int i=0;i<1000;++i)
+ {
+ int j=0;
+ while(input[j])
+ //for (size_t j=0;j<len;++j)
+ {
+ switch (input[j])
+ {
+ case '0':
+ p.process_event(char_0());
+ break;
+ case '1':
+ p.process_event(char_1());
+ break;
+ case '2':
+ p.process_event(char_2());
+ break;
+ case '3':
+ p.process_event(char_3());
+ break;
+ case '4':
+ p.process_event(char_4());
+ break;
+ case '5':
+ p.process_event(char_5());
+ break;
+ case '6':
+ p.process_event(char_6());
+ break;
+ case '7':
+ p.process_event(char_7());
+ break;
+ case '8':
+ p.process_event(char_8());
+ break;
+ case '9':
+ p.process_event(char_9());
+ break;
+ case '-':
+ p.process_event(event_char<'-'>());
+ break;
+ default:
+ p.process_event(default_char());
+ break;
+ }
+ ++j;
+ }
+ p.process_event(eos());
+ p.process_event(eos());
+ }
+#ifdef WIN32
+ ::QueryPerformanceCounter(&li2);
+#else
+ gettimeofday(&tv2,NULL);
+#endif
+#ifdef WIN32
+ std::cout << "msm(1) took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <<std::endl;
+#else
+ std::cout << "msm(1) took in us:" << mtime(tv1,tv2) <<"\n" <<std::endl;
+#endif
+
+ Parser parse;
+ // for timing
+#ifdef WIN32
+ ::QueryPerformanceCounter(&li);
+#else
+ gettimeofday(&tv1,NULL);
+#endif
+ for (int i=0;i<1000;++i)
+ {
+ for (size_t j=0;j<len;++j)
+ {
+ parse.new_char(input[j]);
+ }
+ parse.finish_string();
+ parse.reinit();
+ }
+#ifdef WIN32
+ ::QueryPerformanceCounter(&li2);
+#else
+ gettimeofday(&tv2,NULL);
+#endif
+#ifdef WIN32
+ std::cout << "msm(2) took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <<std::endl;
+#else
+ std::cout << "msm(2) took in us:" << mtime(tv1,tv2) <<"\n" <<std::endl;
+#endif
+ std::cout << "msm(3) took in s:" << time_match(input) <<"\n" <<std::endl;
+ return 0;
+}
+