[ Содержание ] [ Предыдущая ] [ Следующая ]
Регулярные выражения определяют лексему. Регулярное выражение может содержать символы латинского и русского алфавитов в верхнем и нижнем регистрах, другие символы (цифры, знаки препинания и т.д.) и символы-операторы.
Операторы позволяют осуществлять различные действия над выделенной цепочкой символов. Операторы также обозначаются символами.
В выражении можно использовать любой символ. Символ можно указывать в двойных кавычках. В этом случае это всегда просто символ - его специальное значение отменяется. Например:
"abc" abc
эти последовательности символов идентичны.
. | точка означает любой символ, кроме символа новой строки "\n"; |
\XXX | указание символа его восьмеричным кодом (как в Си); |
\n | символ новой строки; |
\t | символ табуляции; |
\b | возврат курсора на один шаг назад; |
" " | любой символ пробела в выражении, если он не находится внутри квадратных скобок, необходимо заключать в двойные кавычки. Это необходимо, так как пробел и табуляция спользуются lex в качестве разделителя между определе нием и действием в правиле. |
Операторы обозначаются символами-операторами, к ним относятся:
\ ^ ? * + | $ / % [] {} () <>
Каждый из этих символов или пар скобок в регулярном выражении играет роль оператора. Если необходимо отменить специальное значение символа, обозначающего оператор, перед ним нужно поставить символ \ или указать его в двойных кавычках. Например:
abc+ - символ "+" - оператор; abc\+ - символ "+"; abc"+" - символ "+".
Квадратные скобки задают классы символов, которые в них заключены.
[abc]
означает либо символ "a", либо "b", либо символ "c";
Знак - используется для указания любого символа из лексикографически упорядоченной последовательности:
[A-z]
означает любой латинский символ;
[А-Я]
любая прописная русская буква;
[+-0-9]
все цифры и знаки "+" и "-".
Когда необходимо указать повторяемость вхождения символа в регулярном выражении, используют операторыповторители * и +.
Оператор * означает любое (в том числе и 0) число вхождений символа или класса символов. Например:
x*
любое число вхождений символа "x";
abc*
любое число вхождений цепочки "abc";
[A-z]*
любое число вхождений любой латинской буквы;
[A-ZА-Яa-zа-я_0-9]*
любое вхождение русских и латинских букв, знака подчеркивания и цифр.
Оператор + означает одно и более вхождений. Например:
x+
одно или более вхождений "x";
[0-9]+
одно или более вхождений цифр;
abc+
одно или более вхождений цепочки abc;
[A-z]+
одно или более вхождений любой латинской буквы.
Операторы
/ | ? $ ^
управляют процессом выбора символов.
ab/cd
"ab" учитывается только тогда, когда за ним следует "cd".
ab|cd
или "ab", или "cd".
x?
означает необязательный символ "x".
_?[A-Za-z]*
означает, что перед цепочкой любого количества латинских букв может быть необязательный знак подчеркивания.
-?[0-9]+
выделит любое целое число с необязательным минусом впереди.
x$
означает выбрать символ "x", если он является последним в строке. Стоит перед символом "\n"!
abc$
означает выбрать цепочку "abc", если она завершает строку.
^x
означает выбрать символ "x", если он является первым символом строки;
^abc
означает выбрать цепочку символов "abc", если она начинает строку.
[^A-Z]*
означает все символы, кроме прописных латинских букв. Когда символ ^ стоит перед выражением или внутри [], он выполняет операцию дополнение. Внутри квадратных скобок символ ^ должен обязательно стоять первым у открывающей скобки.
Оператор {} имеет два различных применения:
x{n,m}
здесь n и m натуральные, m > n. Означает от n до m вхождений x, например, x{2,7} - от 2 до 7 вхождений x.
{имя}
вместо {имя} в данное место выражения будет подставлено определение имени из области определений Lex-программы.
Пример:
БУКВА [A-ZА-Яa-zа-я_] ЦИФРА [0-9] ИДЕНТИФИКАТОР {БУКВА}({БУКВА}|{ЦИФРА})* %% {ИДЕНТИФИКАТОР} printf("\n%s",yytext);
lex построит лексический анализатор, который будет определять и выводить все "слова" из входного файла. Под словом в данном случае подразумевается идентификатор Си-программы. В этом примере {ИДЕНТИФИКАТОР} будет заменен на {БУКВА}({БУКВА}|{ЦИФРА})*, затем на [A-ZА-Яa-zа-я_]([A-ZА- Яa-zа-я_]|[0-9])*.
yytext - это внешний массив символов программы lex.yy.c, которую строит lex. yytext формируется в процессе чтения входного файла и содержит текст, для которого установлено соответствие какому-либо выражению. Этот массив доступен пользовательским разделам Lex-программы.
Оператор printf выводит каждый идентификатор на новой строке.
Правило ".|\n ;" используется для того, чтобы пропустить (не выводить) все цепочки символов, которые не соответствуют регулярному выражению {ИДЕНТИФИКАТОР}.
Раздел правил Lex-программы может содержать активные и неактивные правила. Активные правила выполняются всегда. Неактивные выполняются только в тех случаях, когда выполняется некоторое начальное условие.
Начальные условия Lex-программы помещаются в раздел определений, а неактивные правила помечаются соответствующими условиями. Оператор START позволяет указать список начальных условий Lex-программы, а оператор BEGIN позволяет активировать правила, помеченные начальными условиями.
Активные правила имеют следующий синтаксис:
РЕГУЛЯРНОЕ_ВЫРАЖЕНИЕ ДЕЙСТВИЕ
Неактивные правила имеют следующий синтаксис:
<МЕТКА_УСЛОВИЯ>РЕГ_ВЫРАЖЕНИЕ ДЕЙСТВИЕ
ВАЖНО: любое правило должно начинаться с первой позиции строки, пробелы и табуляции недопустимы - они используются как разделители между регулярным выражением и действием в правиле!
Рассмотрим пример:
%START COMMENT КОММ_НАЧАЛО "/*" КОММ_КОНЕЦ "*/" %% {КОММ_НАЧАЛО} { ECHO; BEGIN COMMENT;}; [\t\n]* ; <COMMENT>[^*]* ECHO; <COMMENT>[^/] ECHO; <COMMENT>{КОММ_КОНЕЦ} { ECHO; printf("0); BEGIN 0; };
lex построит лексический анализатор, который выделяет комментарии в Си-программе и записывает их в стандартный файл вывода. Программа начинается с ключевого слова START, которое указано после символа %. Ключевое слово START можно указать и так: Start, или S, или s . За ключевым словом START указана метка начального условия COMMENT.
Оператор "<COMMENT>x" означает - x, если анализатор находится в начальном условии COMMENT.
Oператор "BEGIN COMMENT;" переводит анализатор в начальное условие COMMENT (смотрите первое правило раздела правил этой Lex-программы). После этого анализатор уже находится в новом состоянии и теперь разбор входного потока символов будет осуществляется и теми правилами, которые начинаются оператором "<COMMENT>". Например, правило
<COMMENT>[^*]* ECHO;
выполняется только тогда, когда во входном потоке символов будет обнаружено начало комментариев ("/*"). В этом случае анализатор записывает в стандартный файл вывода любое число (в том числе и ноль) символов, отличных от символа "*". Оператор "BEGIN 0;" переводит анализатор в исходное состояние.
Lex-программа может содержать несколько помеченных начальных условий. Например, если Lex-программа начинается строкой
%START AA BB CC DD
то это означает, что она управляет четырьмя начальными состояниями анализатора. В каждое из этих начальных состояний анализатор можно перевести, используя оператор BEGIN.
Каждое правило, перед которым указан оператор типа "<МЕТКА>", мы будем называть помеченным правилом. Метка формируется так же, как и метка в Си.
Количество помеченных правил не ограничивается. Кроме того, разрешается одно правило помечать несколькими метками, например:
<МЕТКА1,МЕТКА2,МЕТКА3>x ДЕЙСТВИЕ
Запятая - обязательный разделитель списка меток!
Рассмотрим пример с несколькими начальными условиями:
%START AA BB CC БУКВА [A-ZА-Яa-zа-я_] ЦИФРА [0-9] ИДЕНТИФИКАТОР {БУКВА}({БУКВА}|{ЦИФРА})* %% ^# BEGIN AA; ^[ \t]*main BEGIN BB; ^[ \t]*{ИДЕНТИФИКАТОР} BEGIN CC; \t ; \n BEGIN 0; <AA>define { printf("Определение.\n"); } <AA>include printf("Включение.\n"); } <AA>ifdef { printf("Условная компиляция.\n"); } <BB>[^\,]*","[^\,]*")" { printf("main с аргументамии.\n"); } <BB>[^\,]*")" { printf("main без аргументов.\n"); } <CC>":"/[ \t] { printf("Метка.\n"); }
Программа содержит активные и неактивные правила. Все неактивные правила помечены, перед ними указана метка начального условия. Lex-программа управляет тремя начальными условиями, в соответствии с которыми активируются помеченные правила.
В результате работы lex мы получим лексический анализатор, который будет распознавать в Си-программе строки препроцессора Cи-компилятора, выделять функцию main, распознавая, с аргументами она или без них, распознавать метки. Лексический анализатор не выводит ничего, кроме сообщений о выделенных лексемах.
[ Содержание ] [ Предыдущая ] [ Следующая ]
c 1998-2000 SoloTony (Antonio Solo) | mailto:solotony@mail.ru |