1

When an action is executed I want the action to trigger a jump to another state under certain conditions. For code readability I'd also like to define the action outside of the machine instantiation.

How can I access the state labels generated by ragel outside the scope of the machine instantiation?

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

static int cs=1;

%%{
    machine simpleMachine;  
    write data;
}%%

//The code for ActionA and ActionB is defined outside the scope 
//of the instatiation for readability

void a(void)
{   //Called for ActionA
}

void b(void)
{   //Called for ActionB
    int var2=0;
    if (var2==0)
    {
        %%{
            fgoto STATE_A; 
            #This fgoto generates a ragel parse error
            #how to use the STATE_A label outside 
            #of the machine definition?
        }%%
    }
}
void ExecuteSM(const char *p)
{   const char *pe = p + strlen( p );
    int var1=0; 
    %%{
        EVENT1 = 'a';
        EVENT2 = 'b';
        EVENT3=  'c';

        action ActionA
        {   a();
            if (var1==0)
            {
                fgoto STATE_B; //This fgoto compiles OK
            }
        }
        action ActionB
        {
            b();//I'd like to execute an fgoto in the function b() but I get a 
               //parse error
        }
        myfsm := (
                #STATE          EVENT               ACTION              NEXT_STATE
            start:(             EVENT1              >ActionA            ->STATE_A), 
            STATE_A:(           EVENT2              >ActionB            ->STATE_B),
            STATE_B:(           EVENT3)             
        );
    write init nocs;
    write exec;
    }%%
}
int main()
{
    ExecuteSM("abc");
    return 0;
}
monzie
  • 665
  • 1
  • 6
  • 12

1 Answers1

1

fgoto is only available in code blocks, i.e. between { and } in a Ragel FSM specification.

In your example, you have put the fgoto outside of a code block (the %%{ }%% just opens/closes a multi-line FSM specification).

If your objective is to put the action-code where your functions a()/b() currently are, you can just do that - as actions. This would improve code-readability at least as much as your current idea.

Your example thus modified:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

static int cs=0;

%%{
  machine simpleMachine;  
  write data;

  action ActionA
  {
    if (var1 == 0)
      fgoto STATE_B; //This fgoto compiles OK
  }
  action ActionB
  {
    int var2 = 0;
    if (var2 == 0)
      fgoto STATE_A; 
  }
}%%

void ExecuteSM(const char *p)
{
    const char *pe = p + strlen(p);
    int var1 = 0; 
    %%{
        EVENT1 = 'a';
        EVENT2 = 'b';
        EVENT3 = 'c';

        myfsm := (
            #STATE       EVENT       ACTION       NEXT_STATE
            start:  (    EVENT1      >ActionA     ->STATE_A), 
            STATE_A:(    EVENT2      >ActionB     ->STATE_B),
            STATE_B:(    EVENT3)             
        );
        write exec;
    }%%
}
int main()
{
    %% write init;
    ExecuteSM("abc");
    return 0;
}

Note that I've also changed your init nocs statement. Custom initialization should only be necessary in very special circumstances - and then it is preferably to use symbolic state names.

I've left the cs declaration at translation unit level, although in that example declaring (and initializing) it locally in ExecuteSM would be more appropriate.

maxschlepzig
  • 35,645
  • 14
  • 145
  • 182
  • If I want to generate an event within an action (for example generate EVENT3 within ActionA) what is a good way to do this? Currently I am doing this: { fexec "a";pe=p+2;//Generate EVENT1} Is this the recommended way of generating an event within an action? – monzie May 29 '14 at 16:58