我有两种状态,一种是另一种更一般的状态的具体实例。
我认为避免同时进入这两个状态的正确方法是实现k>1的lookahead,但是我找不到任何这样做的例子。
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字节的前瞻性。 最佳答案
我想标记一个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
时才会发生,这似乎是您试图实现的行为。