1

当执行一个动作时,我希望该动作在某些条件下触发跳转到另一个状态。为了代码可读性,我还想在机器实例化之外定义操作。

如何在机器实例化范围之外访问由 ragel 生成的状态标签?

#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;
}
4

1 回答 1

1

fgoto仅在代码块中可用,即在Ragel FSM 规范之间{和之间。}

在您的示例中,您已将 fgoto 放在代码块之外(%%{ }%%只是打开/关闭多行 FSM 规范)。

如果您的目标是将操作代码放在您的功能a()/b()当前所在的位置,您可以这样做 - 作为操作。这将至少与您当前的想法一样提高代码的可读性。

您的示例因此修改:

#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;
}

请注意,我也更改了您的init nocs声明。只有在非常特殊的情况下才需要自定义初始化 - 然后最好使用符号状态名称。

我将cs声明留在了翻译单元级别,尽管在该示例中在本地声明(和初始化)它ExecuteSM会更合适。

于 2014-05-28T20:03:44.450 回答