Nunnifsmgen-Automatic Code Generator for Finite State Machine programs
This is a good thing I know from my colleagues, nunni FSM generator. It can automatically generate the program code of the state machine according to the configuration file you entered. For detailed data, please refer to the software instructions, however, I want to focus on "automatically generated program code". Because the automatically generated code is encapsulated beautifully, I want to introduce the code.
Something that used to write state machines should not be separated from if, else, Case, switch... When these syntaxes are used together, the written code is "not easy to understand". For example, I have a state machine today. Suppose there is a table with only one bottle on it, if I take the bottle away, I cannot take it away from the table. If there is already a bottle on the table, then there will be no more bottles on the table.
If you use the IF-else syntax to write and read data, it may be as follows:
- # Include
- Int bottles = 1;
- Void getbottleapi ()
- {
- If (Bottles = 1)
- {
- Printf ("You got bottle/N ");
- Bottles --;
- }
- Else printf ("No Bootle to get/N ");
- }
- Void putbottleapi ()
- {
- If (Bottles = 0)
- {
- Printf ("You put a bottle/N ");
- Bottles ++;
- }
- Else printf ("too much bootles/N ");
- }
- Int main ()
- {
- Getbottleapi ();
- Getbottleapi ();
- Putbottleapi ();
- Putbottleapi ();
- Getbottleapi ();
- }
Int bottles is used when the global variable is used to determine whether the get or put action is valid. If this method is used in a small state machine, it is OK. If the state machine is large and complex, we can imagine that the program code will write several more judgment variables for these states.
Try the following program code. I only need to define the trigger mechanism for each State and external action, and then I can write a pretty code.
- # Include
- Struct tablestate;
- Struct tablefsm
- {
- INT (* getbottlestatus) (struct tablefsm * FSM, void * O );
- INT (* putbottlestatus) (struct tablefsm * FSM, void * O );
- Void (* changestate) (struct tablefsm * FSM, struct tablestate * nextstate );
- Struct tablestate * m_state;
- };
- Struct tablestate
- {
- INT (* getbottlestatus) (struct tablefsm * FSM, void * O );
- INT (* putbottlestatus) (struct tablefsm * FSM, void * O );
- };
- Static struct tablestate tablefull;
- Static struct tablestate tableempty;
- Void getbottle ()
- {
- Printf ("You get a bottle/N ");
- }
- Void givebottle ()
- {
- Printf ("You put bottle on the table/N ");
- }
- Void Nobottle ()
- {
- Printf ("there is no bottle on the table/N ");
- }
- Void bottlefull ()
- {
- Printf ("there is too much bottle on the table/N ");
- }
- Int fsmgetbottlestat (struct tablefsm * FSM, void * O)
- {
- Return FSM-> m_state-> getbottlestatus (FSM, O );
- }
- Int fsmputbottlestat (struct tablefsm * FSM, void * O)
- {
- Return FSM-> m_state-> putbottlestatus (FSM, O );
- }
- Void fsmchangestate (struct tablefsm * FSM, struct bottlestate * newstate)
- {
- FSM-> m_state = newstate;
- }
- Int getbottleapi (struct tablefsm * FSM, void * O)
- {
- Getbottle ();
- FSM-> changestate (FSM, & tableempty );
- }
- Int givebottleapi (struct tablefsm * FSM, void * O)
- {
- Givebottle ();
- FSM-> changestate (FSM, & tablefull );
- }
- Int toofewbottleapi (struct tablefsm * FSM, void * O)
- {
- Nobottle ();
- FSM-> changestate (FSM, & tableempty );
- }
- Int toomuchbottleapi (struct tablefsm * FSM, void * O)
- {
- Bottlefull ();
- FSM-> changestate (FSM, & tablefull );
- }
- Int main ()
- {
- Static struct tablefsm BF;
- Tablefull. getbottlestatus = getbottleapi;
- Tablefull. putbottlestatus = toomuchbottleapi;
- Tableempty. getbottlestatus = toofewbottleapi;
- Tableempty. putbottlestatus = givebottleapi;
- BF. getbottlestatus = fsmgetbottlestat;
- BF. putbottlestatus = fsmputbottlestat;
- BF. changestate = fsmchangestate;
- BF. m_state = & tablefull;
- Fsmgetbottlestat (& BF, 0 );
- Fsmgetbottlestat (& BF, 0 );
- Fsmputbottlestat (& BF, 0 );
- Fsmputbottlestat (& BF, 0 );
- }
The program code above is quite concise. When an external action triggers an internal state change, the function specified by FSM is specified to the State callback after the transfer, therefore, programmer can fully focus on the implementation of functions such as getbottleapi, without considering the complexity of the State Conversion Program.