Более сложные элементы lex'а
lex предоставляет средства, позволяющие обрабатывать входной текст, пропуская его сквозь весьма хитроумные шаблоны. Среди этих средств - соглашения, определяющие, какую спецификацию выбрать, если на первый взгляд подходит более одной; функции, которые трансформируют один сопоставляемый шаблон в другой; использование определений и функций. Прежде чем перейти к упомянутым средствам, убедитесь в своем понимании изложенного выше, изучив пример, затрагивающий сразу несколько из рассмотренных вопросов.
%% -[0-9]+ printf("отрицательное число"); \+?[0-9]+ printf("положительное число"); -0\.[0-9]+ { printf("отрицательная дробь, целая часть отсутствует"); } rail[ ]+road printf("railroad - одно слово"); crook printf("Это crook"); function subprogcount++; G[a-zA-Z]* { yytext [yyleng] = (char) 0; printf("G-слово: %s", yytext); Gstringcount++; }
Первые три правила распознают отрицательные числа, положительные числа и отрицательные дроби от -1 до 0. Использование + в конце каждой спецификации определяет, что рассматриваемое число составлено из одной или более цифр. Символ . является знаком операции, поэтому перед десятичной точкой в третьем правиле указан \. Каждое из трех следующих правил распознает особый шаблон. Спецификация для railroad сопоставляется в случаях, когда между двумя слогами слова вклинивается один или боле пробелов. В случаях railroad и crook можно просто печатать синоним, а не выдавать сообщения. Правило, распознающее function, увеличивает на единицу счетчик. Последнее правило иллюстрирует несколько возможностей:
- Скобки задают последовательность действий на нескольких строках.
- Действие использует массив yytext[], в который заносится распознанная цепочка символов;
- Спецификация использует символ *, обозначающий, что за G может следовать нуль или более букв.