Anon Objects as a Byte-Compiler

A self-compiling Finite State Machine in C++

Actions of the FSM


Generating a chain of actions in an arc of the FSM

class ActionGen
{
  ActionBody * body;
  ActionBody * last_in_chain;
protected:
  ActionGen(ActionBody * born_body)
  	: body(born_body), last_in_chain(born_body) {}
public:
  operator ActionBody * (void) const 		{ return body; }
  			// Grow a chain further by a next_body
  			// (and whatever hangs from it)
  ActionGen& operator + (const ActionGen& next_body)
    { last_in_chain->next = next_body;
      last_in_chain = next_body.last_in_chain;
      assert( last_in_chain->next == 0 );
      return *this;
    }
};


An action maker: it's a byte-compiler!

template <class T> class MA : public ActionGen
{
public:
  MA(void) : ActionGen(new T) {}
};


The finite automaton itself

The automaton is ridiculously simple, just to prove the concept. It merely replaces every stretch of white spaces with a single blank
struct Arc;
typedef Arc Node;		// Node is just a bunch of arcs

struct Arc			// Arc of a FSM
{
  int activator;		// character-activator or ANY
  ActionBody * const actions;	// byte-compiled actions
  Node * next_node;		// Node to follow
};
#define ANY	0xf00	// Matches any symbol

extern Arc N_space[];
	// Read characters and fill the current paragraph
Arc N_filling [] =
{
 {' ',MA<CallOutputSpace>(),N_space},
 {'\t',MA<CallOutputSpace>(),N_space},
 {'\n',MA<CallOutputSpace>(),N_space},
 {ANY,MA<FormatCurrChar>() + MA<NoAction>() + MA<NoAction>(),N_filling}
};

	// Got white spaces: ignore more than one
Arc N_space [] =
{
  {' ',  MA<NoAction>(),N_space}, // ignore the second wspace etc
  {'\t', MA<NoAction>(),N_space},
  {'\n', MA<NoAction>(),N_space},
  {ANY,  MA<FormatCurrChar>(),N_filling}
};

static const Node * const Start_node = N_filling;

Note how several actions can be put together with a + sign


The main module

void main(void)
{
  const char * sample_string = "abc a\t \nb";

  const Node * Current_node = Start_node;

					/* Drive the automaton	 */
  for(register const char * cp = sample_string; *cp != '\0'; cp++)
  {
    register const Arc * curr_arc;
    for( curr_arc=Current_node; ; curr_arc++)
      if( curr_arc->activator == ANY || curr_arc->activator == *cp )
      {
	curr_arc->actions->execute_all(*cp);
	Current_node = curr_arc->next_node;
	break;
      }
  }
 cerr << "Done" << endl;
}



Next | Table of contents