Regex Beginner;Написание регулярных выражений, совместимых с Lex / Flex (специально для определения четных целых) - PullRequest
0 голосов
/ 21 сентября 2018

Итак, я собираюсь написать простую программу flex, в которой я хотел бы использовать выражение Regex для определения целых чисел (и отделения их от любого «пробела»).Затем я использую блоки кода C, в которых я буду увеличивать integerCount и evenCount (инициализированные в 0) соответственно.Я совершенно новичок как в Flex, так и в написании регулярных выражений.Я использую книгу Flex / Bison от O'Reilly Media в качестве справочника для написания программ Flex.Поскольку я незнаком с регулярными выражениями в целом, я обратился к Google для ознакомления, которое привело меня к следующим веб-сайтам:

  • Regexr.com помог мнелучше понимать регулярные выражения, так как я смог поиграть с ними и увидеть в реальном времени изменения, которые я на самом деле делаюПроблема в том, что мне удалось успешно написать нужное регулярное выражение на веб-сайте (я собираюсь поместить его в внизу страницы , чтобы оно лучше отформатировалось), однако оно не работает должным образом внутрипрогибается.Это привело меня к пониманию, что flex не использует те же обозначения / правила для регулярных выражений, к которым я привык.

  • Этот сайт сравнивает правила регулярных выражений в Perl,Grep и Lex. Как видите, многие функции, которые я использовал для создания своих регулярных выражений, несовместимы с Lex.Насколько я понимаю, я не работаю с пробелами , скажем так, но с ASCII-пробелом, возвратом кода и т. Д.

Ниже приведено выражение Regex, которое я создал на Regexr..com для определения случайных целых чисел.

    \d+[02468]+((\n)|(\s)|($)){1}

Поскольку это совместимо, мне пришлось внести некоторые изменения.Я могу понять, как поменять \ d с [0-9], однако замена \ n с возвратом каретки на \ x0D и \ s с пробелом \ x0 кажется неправильным подходом.

IЯ использую flex для компиляции программы в lex.yy.c и вызываю "cc lex.yy.c -lfl", чтобы скомпилировать ее в исполняемую программу a.out.Это работает только в Linux, а не в OSX.

Вот ссылка на мою программу Solution.l на данный момент.

Если у вас есть какие-либо советы для меня, ябыл бы очень признателен за ваше руководство.В любом случае, спасибо за чтение.

1 Ответ

0 голосов
/ 21 сентября 2018

Для сопоставления целых чисел вам просто необходимо:

[[:digit:]]+               { /* handle a number */ }

Если вы хотите сопоставить четные целые числа, вы можете использовать

[[:digit:]]*[02468]        { /* handle an even number */ }

Если вы хотите сопоставить четные и нечетные целые числаделая что-то другое для каждого паритета, вы бы использовали два правила:

[[:digit:]]*[02468]        { /* handle an even number */ }
[[:digit:]]*[13579]        { /* handle an odd number */ }

Или вы можете сделать это с первыми двумя шаблонами, если вы поместите их в правильном порядке:

[[:digit:]]*[02468]        { /* handle an even number */ }
[[:digit:]]+               { /* handle any other number */ }

Это работает, потому что (f) lex всегда использует первое правило, если два шаблона одинаково хороши.

Нет смысла пытаться сопоставить пробел или символы новой строки как часть числа.Они не являются частью числа, и идея flex заключается в том, что вы разбиваете входные данные на осмысленные части («токены»).Возможно, вам нет дела до других частей ввода, но вам все равно нужно их распознать, хотя бы для того, чтобы явно их игнорировать.Например, чтобы игнорировать все, что не является цифрой, вы можете добавить следующее правило:

[^[:digit:]]               ; /* Do nothing*/

Точка с запятой требуется, поскольку (f) lex не допускает пустых действий.

Теперь, возможно, вы намеревались не считать числа в середине слова, например F29 или 23skidoo.В этом случае вы захотите добавить другой шаблон, который распознает те строки, которые могут содержать числа.Тогда вам, вероятно, придется явно распознавать пробелы, а не смешивать их с «не цифрой».Удивительно, но это довольно просто:

[[:digit:]]*[02468]        { /* handle an even number */ }
[[:digit:]]+               { /* handle any other number */ }
[[:space:]]+               ; /* Ignore whitespace */
[^[:space:]]+               ; /* Ignore everything else */

Последний шаблон может нуждаться в некотором объяснении, поскольку число также является последовательностью непробельных символов.Но это работает по той же причине, что нам не нужно явное совпадение для нечетных чисел;Правило «максимального мунка» гласит, что (f) lex всегда использует шаблон с самым длинным соответствием, а если для самого длинного соответствия связано более одного шаблона, он использует первый.Другими словами, если последовательность символов, разделенных пробелами, оказывается числом, будет выбрано одно из правил нумерации, а не последнее правило.С другой стороны, если за номером сразу следует мусор, будет использовано последнее правило, поскольку оно имеет более длинное совпадение.

...