拉吉尔过渡行动与国家行动之间的区别

时间:2019-08-13 16:55:50

标签: go state-machine ragel

状态机,术语和工具对我来说都是新的,尽管最近我一直在尝试通过各种在线资源来解决这些问题。当我想在Ragel和Go中构建比正则表达式更快的解析器时,就开始了。我对Ragel docs的第3章感到困惑,该章讨论了动作。

我不清楚与状态转换相关的动作与状态本身之间的区别是什么。这些示例仅针对状态嵌入操作具有错误,因此我不确定何时使用tofrom运算符。我举了一个简单的例子:

package main

import (
    "fmt"
)

%% machine scanner;

%%{
    action fooStart { fmt.Println("foo start")}
    action fooEnd   { fmt.Println("foo end")}
    action barStart { fmt.Println("bar start")}
    action barEnd   { fmt.Println("bar end")}
    action bazStart { fmt.Println("baz start")}
    action bazEnd   { fmt.Println("baz end")}

    main := "foo" >fooStart @fooEnd "bar" >barStart @barEnd "baz" >bazStart @bazEnd;
}%%

%% write data;

func main() {
    ParseEmbedding([]byte("foobarbaz"))
}

func ParseEmbedding(data []byte) {


    cs, p, pe := 0, 0, len(data)
    %%{
    write init;
    write exec;
    }%%
}

我期望的输出如下:

foo start
foo end
bar start
bar end
baz start
baz end

但是,如果我使用相同的周围代码将其替换为状态嵌入动作:

main := "foo" >~fooStart %*fooEnd "bar" >~barStart %*barEnd "baz" >~bazStart %*bazEnd;

我得到以下输出,其中的顺序和缺少的行对我来说没有意义:

bar start
foo end
baz start
bar end

我的最初印象是,当您只想在整个状态机中的特定点而不是更精细的过渡上运行动作时,将使用状态嵌入动作。这仍然让我对它们的执行顺序以及为什么不执行“ foo”的启动“ to-state”动作感到困惑。

所以我的问题是,使用状态动作而不是过渡动作的一些实际原因或示例是什么?在外行看来,它们的工作方式有何不同?

这里是状​​态嵌入动作的图形。 state embedded actions

1 个答案:

答案 0 :(得分:1)

通常,您要使用过渡动作。实际上,我很少使用基于状态的操作。通常只在我想初始化某些东西并希望在看角色之前执行它时才可以。例如,在执行条件之前。当前,基于状态的操作是实现这一目标的唯一方法。

有一段时间,我梦想着有一个解决方案,其中您可以嵌入在测试条件之前运行的基于过渡的操作,因此您不需要基于状态的操作进行初始化。使用基于状态的操作总感觉有点像黑客。