00001
00002 #ifndef _AUTOMAT_H_
00003 #define _AUTOMAT_H_
00004
00005 #include <string>
00006 #include <set>
00007 #include <map>
00008 #include <list>
00009
00010 using namespace std;
00011
00012
00013 template <class T> class automat
00014 {
00015 public:
00016 typedef void (T:: *action)(char c);
00017
00018 struct state;
00019 struct transition
00020 {
00021 transition(state *dest, const string &input, action act) :
00022 input(input.begin(), input.end()),
00023 dest(dest),
00024 act(act)
00025 {}
00026
00027 set<char> input;
00028 state *dest;
00029 action act;
00030 };
00031 struct state
00032 {
00033 void add_transition(state *dest, const string &input, action act)
00034 {
00035
00036 transitions.push_back(transition(dest, input, act));
00037 }
00038 transition *get_transition(char c)
00039 {
00040
00041 for (typename list<transition>::iterator I = transitions.begin() ; I!=transitions.end() ; I++)
00042 {
00043 if ((*I).input.find(c) != (*I).input.end())
00044 return &(*I);
00045 }
00046 return NULL;
00047 }
00048
00049 list<transition> transitions;
00050 };
00051
00052 public:
00053
00054 automat(T *output) :
00055 output(output)
00056 {
00057 begin = &(states["begin"]);
00058 end = &(states["end"]);
00059 error = &(states["error"]);
00060 eof = &(states["eof"]);
00061 reset();
00062 }
00063
00064 void add_transition(const char *src, const char *dest, const string in, action act = 0)
00065 {
00066 states[src].add_transition(&(states[dest]),in,act);
00067 }
00068
00069
00070 void reset() {current = begin;}
00071 void process(char c)
00072 {
00073 if ((current == end) || (current == error))
00074 current = error;
00075 else
00076 {
00077 transition *transit = current->get_transition(c);
00078 if (transit==NULL)
00079 current = error;
00080 else
00081 {
00082 if (transit->act != 0)
00083 (output->*(transit->act))(c);
00084 current = transit->dest;
00085 }
00086 }
00087 }
00088 bool is_end() {return current == end;}
00089 bool is_error() {return current == error;}
00090 bool is_eof() {return current == eof;}
00091 void read_from(istream &in)
00092 {
00093 reset();
00094 char c;
00095 while (!is_end() && !is_error() && !in.eof())
00096 {
00097 in.read(&c,1);
00098 process(c);
00099 }
00100 if (in.eof())
00101 {
00102 if (current == begin)
00103 current = eof;
00104 else
00105 current = error;
00106 }
00107 }
00108
00109 private:
00110 T *output;
00111 map<string,state> states;
00112 state *begin;
00113 state *end;
00114 state *error;
00115 state *eof;
00116 state *current;
00117 };
00118
00119 #endif //_AUTOMAT_H_