Как реализовать Lookahead в Ragel
У меня есть два состояния; один является конкретным случаем другого, более общего состояния. Я считаю, что правильный способ избежать одновременного входа в оба состояния - это реализовать упреждающий просмотр с 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
Msgstr "Это означает, что мне нужно 7 байтов упреждения при определении сегментов приложения.
1 ответ
Я хочу маркировать заголовок 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
Это похоже на поведение, которого вы пытаетесь достичь.