我有两种状态;一个是另一个更一般的状态的特定实例。我相信避免同时进入两种状态的正确方法是使用 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 标记后跟一个 2 字节长度和字符串“ JFIF\0
”。这意味着在识别应用程序段时我需要 7 个字节的前瞻。