Как реализовать 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\0Msgstr "Это означает, что мне нужно 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Это похоже на поведение, которого вы пытаетесь достичь.

Другие вопросы по тегам