Нет, он соответствует спецификации.
Правило ( man 1p lex )
Во время сопоставления с шаблоном, lex должен искать набор шаблонов для максимально длинного совпадения. Из правил, которые соответствуют одинаковому количеству символов, должно быть выбрано первое правило.
так что он всегда будет жадно искать самый длинный AAAA
первым. Это правило распространено в лексических соглашениях многих языков. Например. C ++:
void f(void*=0);
не сможет выполнить синтаксический анализ, потому что символы *=
интерпретируются как оператор присваивания-умножения (который является самым длинным соответствием), а не *
, а затем =
.
Причина этого правила в том, что оно может быть эффективно реализовано. Сканеру с этим правилом требуется только пространство O (1) (включая ввод, т. Е. Вход не должен помещаться в память) и время O (N). Если бы он проверил, что остальная часть входных данных также может быть размечена, ему потребуется O (N) пространство и столько же O (N ^ 2) времени. В частности, потребление памяти имело решающее значение в средние века вычислительной техники, когда вся компиляция выполнялась линейными проходами. И я уверен, что вы не оценили бы время выполнения O (N ^ 2) при анализе сегодняшних нескольких сотен тысяч строк исходных файлов (например, файлов C, включая заголовки). Во-вторых, генерируемые таким образом сканеры очень быстрые и очень помогают при разборе.
И последнее, но не менее важное: правило простое для понимания. В качестве примера обратного рассмотрим правило ANTLR для токенизации, которое иногда может не совпадать, даже если префикс текущего токена является токеном, а входной минус, что префикс является токенизируемым. Например:
TOK1 : 12
TOK2 : (13)+
не будет соответствовать '12131312'. С lex таких сюрпризов не бывает; поэтому я предлагаю принять правило как есть.