У меня есть небольшая проблема с созданием правила гибкого лексера с положительным прогнозным утверждением для определенного типа токена, и я мог бы использовать некоторую помощь. Я уверен, что мне здесь не хватает чего-то простого.
Строка токена, которую я хочу сопоставить, выглядит следующим образом:
33-abc-13/12
99-ab-33
o3sehh04/00
glu6-840d/00
vm-22hd
xyz-3
Соответствующий токен-объект представляет собой строку, содержащую letters and digits
и имеет slashes and/or hyphens
редкие случаи a dot
возможно что-то вроде xx-3006/10.00
То, что не должно совпадать (потому что другие правила охватывают эти случаи), это токены, такие как:
numeric370
hyphen-term
plainterm
00/40
То, что я пробовал до сих пор, это правило с предвкушением:
([a-z0-9/-]*)/[-/]+[0-9/-]+
С учетом вышеизложенного я получаю результаты, которые приближаются к тому, чего я хотел бы достичь. Он соответствует всем перечисленным выше строкам, но последний символ или цифра пропускаются. Соответствующие токены выглядят так:
33-abc-13/1
o3sehh04/0
...
К сожалению, правило также соответствует 00/40
(в результате чего 00/4
).
Итак, мой вопрос: что мне здесь не хватает? Было бы неплохо покрыть эти случаи одним правилом, если это возможно и достаточно быстро. Мне известен порядок обработанных правил в скрипте лексера, поэтому позиция этого правила будет одной из первых во всем наборе.
Если это невозможно, возможно, нарушение этого правила было бы другим способом.
В этом проекте я использую пакет RE-flex (https://github.com/Genivia/RE-flex) потому что он охватывает интерфейс Flex Lexer и обеспечивает Unicode (мне нужно работать с wchar_t
символьные строки).
Мой лексер — токенайзер пробелов с классификацией токенов, он был основан на пакете flex 2.5 несколько лет назад. Я переработал несколько вещей в обработке токенов и перешел на повторное сгибание, поскольку это дает мне больше возможностей. Входные строки токенизатора представляют собой короткие простые текстовые фрагменты, они не превышают длину, скажем, 250-300 символов. Пока что фон.
ПРИМЕЧАНИЕ: я использую regex101.com, чтобы проверить / поэкспериментировать при построении правил, прежде чем преобразовать их для лексера. Это немного помогает в правильном направлении, но это все.
Любая помощь с благодарностью, спасибо за ваши усилия заранее!
Обновить:
Исходя из ответа Ричи, окончательная модель теперь выглядит так:
[a-z0-9/.-]*[/.-][0-9/-]+
Это также распространяется на токены, содержащие .
, например
xx33-4.00
f/44-7.87
...
И учитывая проблему с разделителем предложений в моем комментарии ниже было просто
.
в последней группе символов шаблона. Я удалил его, и теперь он работает, как ожидалось.
Я ничего не знаю о RE-flex (хотя это выглядит круто), но если предположить, что он действительно совместим с flex, то должен сработать тот же подход: забудьте о прогнозных утверждениях вперед (поскольку строка соответствует не включите шаблон предпросмотра, и вы хотите сопоставить всю строку) и поставить правило после все остальные правила, которые могут соответствовать одному и тому же.
Гибкое правило:
Так, например, скажем, у вас есть шаблоны:
[0-9]+("/"[0-9]+)* { return SLASHED_NUMBERS; }
[a-z0-9/-]*[/-][0-9/-]+ { return GENERAL_TOKEN; }
[Примечание 1]
Оба из них будут совпадать 00/40
, так что если это токен в точке ввода, этот токен будет обнаружен как SLASHED_NUMBERS
(первое правило в файле). С другой стороны, если у вас есть 00/49-23
, это будет обнаружено как GENERAL_TOKEN
потому что это правило соответствует больше символов.
Других решений пока нет …