当执行某个动作时,我希望动作在某些条件下触发跳转到另一个状态。 为了代码可读性,我还想在机器实例化之外定义动作。
如何在机器实例化范围之外访问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;
}
答案 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
中本地声明(并初始化)更合适。