- •1. Введение
- •2. Регулярные выражения в Lex-правилах
- •2.1. Обозначения символов в выражениях
- •2.2. Операторы регулярных выражений
- •2.3. Оператор выделения классов символов
- •2.4. Повторители
- •2.5. Операторы выбора
- •2.6. Оператор {}
- •3. Структура Lex-программы
- •3.1. Раздел определений Lex-программы
- •3.2. Раздел правил
- •3.2.1. Действия в правилах Lex-программы
- •3.2.2. Порядок действия активных правил
- •3.3. Раздел программ пользователя
- •3.4. Комментарии Lex-программы
- •3.5. Примеры Lex-программ
- •4. Структура файла lex.Yy.C
- •5. Функция yywrap()
- •6. Функция reject
- •7. Функции yyless и yymore
- •8. Совместное использование lex и yacc
- •9. Использование Ратфора
- •10. Флаги Lex
3. Структура Lex-программы
Lex-программа включает разделы опредeлений, правил и
пользовательских программ. Рассмотрим подробнее способы
оформления этих разделов.
Все строки, в которых занята первая позиция, относятся
к Lex-программе. Любая строка, не являющаяся частью правила
или действия, которая начинается с пробела или табуляции,
копируется в сгенерированную программу lex.yy.c - результат
работы lex.
3.1. Раздел определений Lex-программы
Определения, предназначенные для lex, помещаются перед
первым %%. Любая строка этого раздела, не содержащаяся между
%{ и %} и начинающаяся в первой колонке, является определе-
нием строки подстановки lex. Раздел определений Lex-
программы может включать:
начальные условия,
определения,
фрагменты программы пользователя,
таблицы наборов символов,
указатели host-языка,
изменения размеров внутренних массивов,
комментарии в формате host-языка.
НАЧАЛЬНЫЕ УСЛОВИЯ задаются в форме:
%START имя1 имя2 ...
Если начальные условия определены, то эта строка должна быть
первой в Lex-программе.
ОПРЕДЕЛЕНИЯ задаются в форме:
имя трансляция
В качестве разделителя используется один или более пробелов
или табуляций. Пример:
БУКВА [A-ZА-Яa-zа-я_]
DIGIT [0-9]
ИДЕНТИФИКАТОР {БУКВА}({БУКВА}|{DIGIT})*
Имя - как обычно, любая последовательность букв и цифр,
начинающаяся с буквы. Трансляция - это регулярное выражение
(или его часть), которое будет подставлено всюду там, где
указано имя (смотрите третью строку этого примера).
15
ФРАГМЕНТЫ ПРОГРАММЫ ПОЛЬЗОВАТЕЛЯ указываются двумя спо-
собами:
- в виде "пробел фрагмент";
- в виде:
%{
строки
фрагмента
программы
пользователя
%}
Такая форма включения пользовательского фрагмента
необходима для ввода, например, макроопределений Си,
которые должны начинаться в первой колонке строки.
Все строки фрагмента пользовательской программы, раз-
мещенные в разделе определений, будут являться внеш-
ними для любой функции программы lex.yy.c
ТАБЛИЦА НАБОРОВ СИМВОЛОВ задается в виде:
%T
целое_число строка_символов
.........
целое_число строка_символов
%T
Сгенерированная программа lex.yy.c осуществляет ввод-вывод
символов посредством библиотечных функций lex с именами
input, output, unput. Таким образом, lex помещает в yytext
символы в представлении, используемом в этих библиотечных
функциях. Для внутреннего использования символ представля-
ется целым числом, значение которого образовано набором
битов, представляющих символ в конкретной ЭВМ. Пользователю
предоставляется возможность менять представление символов
(целых констант) с помощью таблицы наборов символов. Если
таблица символов присутствует в разделе определений, то
любой символ, появляющийся либо во входном потоке, либо в
правилах, должен быть определен в таблице символов. Символам
нельзя назначать число 0 и число, большее числа, выделенного
для внутреннего представления символов конкретной ЭВМ.
Пример:
16
%T
1 Aa
2 Bb
3 Cc
.
.
.
26 Zz
27
28 +
29 -
30 0
31 1
.
.
.
39 9
%T
В этом примере символы верхнего и нижнего регистров перево-
дятся в числа 1-26, символ новой строки в 27, "+" и "-"
переводятся в числа 28 и 29, а цифры - в числа 30-39.
ИЗМЕНЕНИЯ РАЗМЕРА ВНУТРЕННИХ МАССИВОВ задаются в форме:
%x число
число - новый размер массива;
x - одна из букв:
p - позиции;
n - состояния;
e - узлы дерева;
a - упакованные переходы;
k - упакованные классы символов;
o - массив выходных элементов.
lex имеет внутренние таблицы, размеры которых ограничены.
При построении программы лексического анализа может прои-
зойти переполнение любой из этих таблиц, о чем lex сообщает
при построении лексического анализатора. Пользователю пре-
доставляется возможность изменить размеры таблиц (сокращая
размеры одних и увеличивая размеры других) таким образом,
чтобы они не переполнялись. Естественно, эти изменения воз-
можны лишь в пределах той памяти, которая выделяется под
процесс.
Ниже перечислены размеры таблиц, которые устанавлива-
ются по умолчанию:
17
p - позиций 1500
n - состояний 300
e - узлов 600
a - упакованных переходов 1500
k - упакованных классов символов 1000
o - выходных элементов 1500
Для того чтобы определить, каковы размеры таблиц и насколько
они заняты, можно использовать флаг -v, например:
% lex -v source.l
33/600 узлов(%e)
97/1500 позиций(%p)
17/300 состояний(%n)
2551 переходов
18/1000 упакованных классов символов(%k)
41/1500 упакованных переходов(%a)
68/1500 выходных элементов(%o)
%
Здесь показано сообщение, которое выводит lex по флагу -v.
Число перед символом "/" указывает сколько элементов массива
занято, а число за символом "/" указывает установленный раз-
мер массива.
КОММЕНТАРИИ в разделе определений задаются в форме
host-языка и должны начинаться не с первой колонки строки.