
- •Федеральное агентство по образованию
- •190000, Санкт-Петербург, ул. Б. Морская, 67 Лабораторная работа №1 Сканирование и лексический анализ текстов c применением утилиты flex
- •1. Лексический анализ и регулярные выражения
- •2. Структура сканера текстов, создаваемого утилитой flex
- •3. Файл описания сканера
- •4. Параметры flex
- •5. Пример описания сканера
- •6. Использование синтезированного программного кода
- •7. Задание на выполнение лабораторной работы
- •8. Варианты заданий
- •Лабораторная работа №2 Синтаксический анализ текстов c применением утилиты bison
- •1. Синтаксический анализ и магазинные автоматы
- •2. Построение набора правил для описания формального языка
- •3. Структура анализатора, создаваемого утилитой bison
- •4. Файл описания синтаксического анализатора
- •5. Параметры утилиты bison
- •6. Типичные ошибки при составлении грамматики
- •7. Пример описания синтаксического анализатора
- •8. Использование синтезированного программного кода
- •9. Задание на лабораторную работу
- •10. Варианты заданий
- •Библиографический список
- •Содержание
4. Параметры flex
В собранном виде flex включает в себя основной запускаемый файл, flex.exe, и, возможно, файл с шаблоном сканера flex.skl. В общем случае для запуска утилиты и получения результирующего С/C++ файла сканера можно воспользоваться следующей командой:
Flex.exe –o<имя результирующего файла> -Sflex.skl <имя файла описания>
Результатом запуска будет выходной файл с программным кодом.
Дополнительно, в командной строке могут быть указаны следующие опции:
- генерация C++ сканера “-+”;
- нечувствительность генирируемого сканера к регистру: “-i “;
- создание сканера, выводящего на stdout отладочные сообщения (при установленной в “1” глобальной переменной yy_flex_debug в коде сканера) : “-d”;
Для полного списка опций следует обратиться к руководству по flex.
Кроме параметров, в командной строке, можно указывать аналогичные значения в разделе определений файла описания сканера, используя синтаксис:
%option <код опции>
Полезные коды опций:
%option c++
%option yylineno
%option noyywrap
Последние две опции недоступны через командную строку и могут быть заданы лишь в файле описания. yylineno позволяет включить поддержку функции lineno(). Вызов этой функции в пользовательском коде позволяет получить номер строки, из которой прочитана очередная лексема или в которой возникла ошибка. Опцию noyywrap необходимо указывать при отсутствии пользовательской реализации функции yywrap().
5. Пример описания сканера
В качестве примера, рассмотрим следующий текстовый файл, подлежаший обработке:
Ext 999 7:10 AM , 12/11/2003 Aspect Page 1
Users Database
Default Default
Ext # Last Name First Name Type Group Team
201 TEST TEST Agent 20 0
202 TEST TEST Agent 21 0
203 TEST TEST Agent 23 0
Total Records: 3
Файл содержит распечатку конфигурации телефонной станции Aspect. Построим сканер, способный распознавать все допустимые лексемы из подобного документа.
Описание сканера может иметь следующий вид:
%option noyywrap
%option yylineno
%option never-interactive
%{
#include <stdio.h>
#include <string>
#include "tokens.h"
std::string tmpstr = "";
%}
ws [ \t]+
Digit [0-9]
HexDigit [0-9a-fA-F]
Number [0-9]({Digit})*
HexNumber 0x({HexDigit})*
Tab [\t]
Usk [\x5F]
At [\x40]
Dot [\x2E]
Smc [\x3A]
Sbra [\x5B]
Sket [\x5D]
Bra [\x28]
Cket [\x29]
Spc [\x20]
Pls [\x2B]
Min [\x2D]
Sq [\x27]
Semi [\x2C]
Num [#]
Slash [\x2F]
Escape [\\]([n]|[\"]|[\\])
AnyStrChr [^\\"]
AP_USERS Users
AP_ASPECT Aspect
AP_DATABASE Database
AP_PAGE Page
AP_DEFAULT Default
AP_PROFILE Profile
AP_LASTNAME Last{Spc}Name
AP_FIRSTNAME First{Spc}Name
AP_TYPE Type
AP_GROUP Group
AP_TEAM Team
AP_AGENT Agent
AP_EXT Ext
AP_TOTAL Total
AP_RECORDS Records
Id [a-zA-Z]([a-zA-Z0-9]|[\x5F])*
String [\"]({Escape}|{AnyStrChr})*[\"]
Identifier ([a-zA-Z0-9])*
SqString {Sq}(.)*{Sq}
Colon [:]
nl \n
%%
{Number} {
tmpstr = strdup(yytext);
return AP_NUMBER;
}
{Semi} {
tmpstr = strdup(yytext);
return AP_SEMI;
}
{Num} {
tmpstr = strdup(yytext);
return AP_NUM;
}
{Slash} {
tmpstr = strdup(yytext);
return AP_SLASH;
}
{Colon} {
tmpstr = strdup(yytext);
return AP_COLON;
}
{AP_TYPE} {
tmpstr = strdup(yytext);
return AP_TYPE_KW;
}
{AP_AGENT} {
tmpstr = strdup(yytext);
return AP_AGENT_KW;
}
{AP_USERS} {
tmpstr = strdup(yytext);
return AP_USERS_KW;
}
{AP_ASPECT} {
tmpstr = strdup(yytext);
return AP_ASPECT_KW;
}
{AP_DATABASE} {
tmpstr = strdup(yytext);
return AP_DATABASE_KW;
}
{AP_PAGE} {
tmpstr = strdup(yytext);
return AP_PAGE_KW;
}
{AP_DEFAULT} {
tmpstr = strdup(yytext);
return AP_DEFAULT_KW;
}
{AP_LASTNAME} {
tmpstr = strdup(yytext);
return AP_LASTNAME_KW;
}
{AP_FIRSTNAME} {
tmpstr = strdup(yytext);
return AP_FIRSTNAME_KW;
}
{AP_TYPE} {
tmpstr = strdup(yytext);
return AP_TYPE_KW;
}
{AP_GROUP} {
tmpstr = strdup(yytext);
return AP_GROUP_KW;
}
{AP_TEAM} {
tmpstr = strdup(yytext);
return AP_TEAM_KW;
}
{AP_EXT} {
tmpstr = strdup(yytext);
return AP_EXT_KW;
}
{AP_TOTAL} {
tmpstr = strdup(yytext);
return AP_TOTAL_KW;
}
{AP_RECORDS} {
tmpstr = strdup(yytext);
return AP_RECORDS_KW;
}
{Identifier} {
tmpstr = strdup(yytext);
return AP_IDENTIFIER;
}
{nl} {
/* nothing, ate new line */
}
. {
/* nothing */
}
%%
В файле описания использованы константы AP_XXX, заданные во внешнем включаемом файле "tokens.h". Константы определены через директиву #define и являются числовыми константами – токенами (кодами лексем), используемыми программой. Каждому токену соотвествует ключевое слово или иная лексема, которую выделяет из исходного текста сканер. Сама лексема помещается в переменную tmpstr, где сохраняется до прочтения следующей лексемы.