我有两个州;一个是另一个更一般的状态的特定实例。 我认为避免同时进入两个状态的正确方法是实现k> 1的前瞻,但我找不到任何如何做到这一点的例子。
Ragle用户指南说:
在使用fhold和fexec时,用户必须小心将所得到的机器与另一台机器相结合,使得调整当前位置的过渡不会与来自另一台机器的过渡相结合。
我不完全确定这意味着什么,除了“不要试图读过当前表达的结尾”。
我的机器看起来像这样:
seglen16 = any{2} >{ swab(p, &len, 2); len = len - 2; };
action check {len--}
buffer = (any when check)* %when !check @{ printf("[%d]:%d\n", len, *p); };
# JPEG Markers
mk_app0 = 0xFF 0xE0;
mk_appx = 0xFF (0xE0..0xEF);
marker = 0xFF ^0x00;
nonmarker = !marker - zlen;
# JPEG APP Segments
seg_app0_jfif = mk_app0 seglen16 "JFIF" 0x00 buffer @{ printf("jfif app0\n"); };
seg_appx_unk = mk_appx nonmarker* @{ printf("unknown app content\n"); };
seg_app = (seg_app0_jfif | seg_app1_exif | seg_appx_unk);
# Main Machine
expr = (mk_soi @lerr(bad) nonmarker* seg_app* nonmarker* mk_eoi);
我想标记JPEG标题,跳过未知段并处理像JFIF这样的知名段。 JPEG应用程序段app0以0xFFE0
开头。如果app0包含JFIF数据,则app0标记后面将跟着两个字节的长度和字符串“JFIF\0
”。这意味着在识别应用程序段时我需要7个字节的前瞻。
答案 0 :(得分:2)
我想标记JPEG标题,跳过未知段并处理像JFIF这样的知名段。 JPEG应用程序段app0以0xFFE0开头。如果app0包含JFIF数据,则app0标记后面跟着两个字节的长度和字符串“JFIF \ 0”。
好的。
这意味着在识别应用程序段时我需要7个字节的前瞻。
为什么呢?您可以将“未知”模式应用于除使用常规模式已知的之外的所有段
seg_app0_jfif = mk_app0 seglen16 "JFIF" 0x00 buffer @{ printf("jfif app0\n"); };
known_segment = (seg_app0_jfif | seg_app1_exif);
unknown_segment = ((mk_appx nonmarker*) - known_segment) @{ printf("unknown app content\n"); };
seg_app = (known_segment | unknown_segment);
这样做不需要前瞻。 Ragel生成适当的状态和转换,同时处理两个模式,直到处理了足够的输入以消除它们的歧义。 unknown_segment
上的完成操作只有在不是known_segment
的情况下才会发生,这似乎是您尝试实现的行为。