Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lex.docx
Скачиваний:
12
Добавлен:
20.03.2016
Размер:
133.64 Кб
Скачать

3.2. Раздел правил

Все, что указано после первой пары %% и до конца Lex-

программы или до второй пары %%, если она указана, относится

к разделу правил. Раздел правил может содержать правила и

фрагменты программ. Фрагменты программ, содержащиеся в раз-

деле правил, становятся частью функции yylex файла lex.yy.c,

в которой осуществляется выполнение действий активных пра-

вил. Фрагмент программы указывается следующим образом:

%{

строки

фрагмента

программы

%}

Например:

%%

%{

#include file.h

%}

.

.

.

18

Здесь строка "#include file.h" станет строкой функции

yylex().

Раздел правил может включать список активных и неактив-

ных (помеченных) правил. Активные и неактивные правила

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

мешанными" в списке. Активные правила выполняются всегда,

неактивные только по ссылке на них оператором BEGIN.

Активное правило имеет вид:

ВЫРАЖЕНИЕ ДЕЙСТВИЕ

Неактивное правило имеет вид:

<МЕТКА>ВЫРАЖЕНИЕ ДЕЙСТВИЕ

или

<СПИСОК_МЕТОК>ВЫРАЖЕНИЕ ДЕЙСТВИЕ

где СПИСОК_МЕТОК имеет вид:

метка1,метка2,...

В качестве первого правила раздела правил может быть правило

вида:

BEGIN МЕТКА;

В этом правиле отсутствует ВЫРАЖЕНИЕ, и первым действием в

разделе правил будет активизация помеченных правил. Для

возвращения автомата в исходное состояние можно использовать

действие:

BEGIN 0;

Важно отметить следующее. Если Lex-программа содержит актив-

ные и неактивные правила, то активные правила работают

всегда. Оператор "BEGIN МЕТКА;" просто расширяет список

активных правил, активируя помеченные меткой МЕТКА. А опера-

тор "BEGIN 0;" удаляет из списка активных правил все поме-

ченные правила, которые до этого были активированы. Кроме

того, если из помеченного и активного в данный момент вре-

мени правила осуществляется действие BEGIN МЕТКА, то из

помеченных правил активными останутся только те, которые

помечены меткой МЕТКА.

3.2.1. Действия в правилах Lex-программы

Действие можно представлять либо как оператор lex, нап-

ример, "BEGIN МЕТКА;", либо как оператор Си. Если имеется

необходимость выполнить достаточно большой набор преобразо-

ваний, то действие оформляют как блок Си-программы (он

19

начинается открывающей фигурной скобкой и завершается закры-

вающей фигурной скобкой), содержащий необходимые фрагменты.

Действие в правиле указывается через не менее, чем один

пробел или табуляцию после выражения (обязательно в той же

строке, где и выражение), а его продолжение может быть ука-

зано в следующих строках только в том случае, если действие

оформлено как блок Си-программы.

Область действия переменных, объявленных внутри блока,

распространяется только на этот блок. Внешними переменными

для всех действий будут являться только те переменные, кото-

рые объявлены в разделе определений Lex-программы.

Действия в правилах Lex-программы выполняются, если

правило активно, и если автомат распознает цепочку символов

из входного потока как соответствующую регулярному выражению

данного правила. Однако, одно действие выполняется всегда -

оно заключается в копировании входного потока символов в

выходной. Это копирование осуществляется для всех входных

строк, которые не соответствуют правилам, преобразующим эти

строки. Комбинация символов, не учтенная в правилах и поя-

вившаяся на входе, будет напечатана на выходе. Можно ска-

зать, что действие - это то, что делается вместо копирования

входного потока символов на выход. Часто бывает необходимо

не копировать на выход некоторую цепочку символов, которая

удовлетворяет некоторому регулярному выражению. Для этой

цели используется пустой оператор Си, например:

[ 0 ;

Это правило игнорирует (запрещает) вывод пробелов, табуляций

и символа новая строка. Запрет выражается в том, что на

указанныe символы во входном потоке осуществляется действие

";" - пустой оператор Си, и эти символы не копируются в

выводной поток символов.

Существует возможность для нескольких регулярных выра-

жений указывать одно действие. Для этого используется символ

"|", который указывает, что действие данного правила совпа-

дает с действием для следующего, например:

" " |

|

;

Результат будет тот же, что и в примере, указанном выше.

Когда необходимо вывести или преобразовать текст, соот-

ветствующий некоторому регулярному выражению, используется

внешний массив символов, который формирует lex. Называется

он yytext и доступен в действиях правил. Например:

20

[A-Z]+ printf("%s",yytext);

По этому правилу распознается слово, содержащее прописные

латинские буквы и выводится с помощью printf, если оно выде-

лено. Операция вывода распознанного выражения используется

очень часто, поэтому имеется сокращенная форма записи этого

действия:

[A-Z]+ ECHO;

Результат действия этого правила будет аналогичен результату

предыдущего примера. В выходном файле lex.yy.c ECHO опреде-

лено как макроподстановка:

#define ECHO fprintf(yyout, "%s",yytext);

Когда необходимо знать длину обнаруженной последовательности

символов, используется счетчик найденных символов yyleng,

который также доступен в действиях. Например:

[A-Z]+ printf("%c",yytext[yyleng-1]);

В этом примере будет выводится последний символ слова, соот-

ветствующего регулярному выражению [A-Z]+. Рассмотрим еще

один пример:

[A-Z]+ {число_слов++;число_букв += yyleng;}

Здесь ведется подсчет числа распознанных слов и количества

символов во всех словах.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]