如何在机器实例化范围之外使用ragel标签

时间:2014-05-26 17:04:06

标签: ragel

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

如何在机器实例化范围之外访问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;
}

1 个答案:

答案 0 :(得分: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中本地声明(并初始化)更合适。