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

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ

Государственное образовательное учреждение высшего профессионального образования

САНКТ,ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ АЭРОКОСМИЧЕСКОГО ПРИБОРОСТРОЕНИЯ

ТЕОРИЯ ЯЗЫКОВ ПРОГРАММИРОВАНИЯ И МЕТОДЫ ТРАНСЛЯЦИИ

СРЕДСТВА АВТОМАТИЗАЦИИ ПОСТРОЕНИЯ СИНТАКСИЧЕСКИХ АНАЛИЗАТОРОВ

Методические указания к выполнению лабораторных работ № 1–2

Санкт,Петербург

2006

Составители:А.В.Бржезовский,Т.М.Максимова,А.А.Янке,

левич

Рецензент доктор технических наук, профессор А. В. Гордеев

В методические указания включены краткие теоретические све, дения об автоматных моделях распознавателей формальных языков, описание возможностей утилит flex и bison по автоматической гене, рации программного кода лексического и синтаксического анали, заторов, варианты индивидуальных заданий на выполнение лабора, торных работ.

Предназначены для студентов всех форм обучения, проходящих подготовку по специальностям 230105 и 010503.

Подготовлены кафедрой компьютерной математики и програм, мирования и рекомендованы к изданию редакционно,издательским советом Санкт,Петербургского государственного университета аэро, космического приборостроения.

Редактор Г. Д. Бакастова Верстальщик И. С. Чернышев

Подписано к печати 06.09.06. Формат 60 84 1/16. Бумага офсетная. Печать офсетная. Усл. печ. л. 2,3. Уч. ,изд. л. 2,4. Тираж 100 экз. Заказ № 00

Редакционно,издательский центр ГУАП 190000, Санкт,Петербург, ул. Б. Морская, 67

©ГОУ ВПО «Санкт,Петербургский государственный университет аэрокосмического приборостроения», 2006

2

Лабораторная работа №1

Сканирование и лексический анализ текстов c применением утилиты FLEX

1. Лексический анализ и регулярные выражения

Лексическийанализ–разбиениепоследовательностисимволоввход, ноготекстанапоследовательностьслов,илилексем.Выделениелексем из текста обычно предшествует стадии синтаксического анализа, на, пример, при построении компилятора с какого,нибудь языка програм, мирования, хотя может потребоваться и для решения других задач, не связанных с синтаксическим анализом текстов. Обычно все лексемы делятся на классы. Примерами таких классов являются числа (целые, восьмеричные, шестнадцатеричные, действительные и т. д.), иденти, фикаторы, строки. Отдельно выделяются ключевые слова и символы пунктуации (иногда их называют символы,ограничители). Какправи, ло,ключевыеслова–этонекотороеконечноеподмножествоидентифика, торов. В большинстве случаев лексический анализ выполняется перед синтаксическим.Программныйкомпонент,осуществляющийподобную операцию,называетсялексическиманализатором,илисканером.

Разделение сканирования текста с целью выделения лексем и даль, нейшего синтаксического анализа с генерацией кода либо данных позволяет сделать программу,распознаватель модульной, исключить ненужные зависимости синтаксического и других модулей от особен, ностей форматирования входных текстов и в конечном итоге упрос, тить каждый из компонентов.

Использование специализированных утилит, генерирующих про, граммный код для сканирования текстов, позволяет облегчить про, цесс создания программного обеспечения для обработки текстовой информации. Генерируемый программный код (на языке С/С++ для случая использования flex), не содержит дополнительных ошибок, которые могут быть внесены при ручной разработке сканера, и может быть включен практически в любой конечный программный продукт без какой бы то ни было модификации.

Утилита генерации сканера использует описание возможных пос, ледовательностей входных символов, которые следует распознать как

3

лексемы, в виде регулярных выражений. Набор регулярных выраже, ний, составленный с учетом особенностей анализируемого языка, задается во входном файле для утилиты flex, которая на выходе по, рождает файлы с исходным кодом сканера.

Пусть T – конечный алфавит. Регулярное множество в алфавите T определяется рекурсивно следующим образом:

1){} (пустое множество) – регулярное множество в алфавите T;

2){a} – регулярное множество в алфавите T для каждого a T; 3){е} – регулярное множество в алфавите T (e – пустая цепочка);

4)если P и Q – регулярные множества в алфавите T, то таковы же

имножества:

P Q (объединение),

PQ (конкатенация, т. е. множество {pq}, p P, q Q),

P* (итерация: P*={e} P PP ...,

ничто другое не является регулярным множеством в алфавите T. Итак, множество в алфавите T регулярно тогда и только тогда,

когда оно либо {}, либо {e}, либо {a} для некоторого a T, либо его можно получить из этих множеств применением конечного числа операций объединения, конкатенации и итерации.

Приведенное выше определение регулярного множества одновре, менно определяет и форму его записи, которую будем называть регу лярным выражением. ДлясокращенногообозначениявыраженияPP* будем пользоваться записью P+ и там, где это необходимо, использо, вать скобки. В этой записи наивысшим приоритетом обладает опера, ция *, затем – конкатенация и, наконец, операция , для записи кото, рой иногдабудемиспользоватьзначок‘|’.Так,0|10*означает(0|(1(0*))).

Кроме того, будем использовать запись вида d1 = r1 d2 = r2,..., dn = = rn, где di – различные имена, а каждое ri – регулярное выражение над символами T {d1, d2, ..., di–1}, т. е. символами основного алфа, вита и ранее определенными символами. Таким образом, для любого ri можно построить регулярное выражение над Т, повторно заменяя имена регулярных выражений на обозначаемые ими регулярные вы, ражения.

Несколько примеров регулярных выражений и обозначаемых ими множеств.

Идентификатор – это регулярное выражение: Идентификатор = Буква (Буква|Цифра)* Буква = {a, b, ..., z} Цифра = {0, 1, ..., 9};

Число в десятичной записи – это регулярное выражение: Целое = Цифра+ Дробная_часть =. Целое | е Степень = ( Е ( + | – | е ) Целое ) | е

4

Число = Целое Дробная_часть Степень Состав набора регулярных выражений зависит от того, какие лек,

семы ожидается получить на выходе сканера, и обычно определяется тем, какого рода синтаксический анализ следует проводить в даль, нейшем. Например, для языка basic в качестве лексем могут рассмат, риваться: десятичное число, идентификатор, ключевое слово IF, клю, чевое слово THEN и т. д. В то же время для сканирования и дальней, шей обработки некоего произвольного текста, например табличной информации в виде ASCII документа, может потребоваться набор лексем, зависящий от того, как и каким образом сканируемая ин, формация будет в дальнейшем использована. Набор лексем может для рассматриваемого примера включать: ключевые слова DATE и AMOUNT, используемые в заголовке таблицы; лексему,разделитель колонок, роль которой играет символ «Табуляция»; лексему,разде, литель шапки таблицы от остальной ее части, роль которой играет последовательность символов “=====”; лексему «дата», определя, ющую дату в формате MM/DD/YYYY; а также лексему – число с фик, сированной запятой.

По составленному набору регулярных выражений возможна авто, матическая генерация программы,распознавателя.

2. Структура сканера текстов, создаваемого утилитой flex

Использование flex позволяет синтезировать сканер, имеющий внешний API (программный интерфейс) для встраивания в приложе, ния на языке C, а также, при необходимости, синтезировать C++, класс, инкапсулирующий функциональность сканера, для встраи, вания в C++,приложения.

Структура процедурного сканера c процедурным API приведена на рис. 1.Классыобъектно,ориентированногосканерапоказанынарис.2. Для С++,сканера создаются два файла: lex.yy.cc и FlexLexer.h, после, дний содержит объявления для обоих классов.

Для процедурного сканера создается один файл, обычно именуе, мый “lex.yy.c”

Глобальные переменные, функции и методы классов имеют спе, циальное значение. Наиболее важные из них:

– yytext – указатель на последнее распознанное сканером слово (строка, ограниченная нулевым байтом). Для C++,сканера роль этой переменной играет метод YYText();

yyin – указатель на дескриптор файла, из которого производится чтение. Пользовательская программа должна инициализировать этот указатель. По умолчанию этим файлом является stdin;

5

1234 1234566578

553783 975649

1 45512 498 3 2349

455 3 49412 3 9

967289 2 29

123 44556789 1

23 7 2 288 3 4 2 45

23 7 6 288 3 2 2 9 6795

4

5 92 72 7 8 2 2342 9

123 55 9

1

5

 

2 3

7 2 288 3 4 2 42

45

 

9 6 2 6728 2 6 8 2349 5

123455 7 3 39 412

1

2 3 7 6 288 3 2 2 9 6792

45

Рис. 1

123453436 1

789 7 6 34 1 9 63 61

123453436 1

9 2341

7 63 1

Рис. 2

– yyout – указатель на дескриптор файла, в который будет по, мещаться «эхо» сканера. По умолчанию прочтенные символы, если не удается сопоставить их с заданными шаблонами, поступа, ют в данный файл. Туда же направляется вывод от макро ECHO, используемого в правилах. По умолчанию этим файлом является stdout.

Функция yyrestart() позволяет реинициализировать сканер и установить указатель для входного файла. Функция может быть вызвана перед началом работы сканера для установки входного файла.

Функция yywrap() вызывается по достижении конца файла. Если пользовательская реализация данной функции возвращает 0, то ска, нер продолжает работу, предполагая, что yyin инициализирован ука, зателем на новый файл. Если возвращено 1, то сканер завершает ра, боту и возвращает 0 в вызвавшую его программу. Пользователь не

6

обязан реализовывать данную функцию, по умолчанию подразуме, вается значение 1 (останов по концу файла).

Функция yylex() и одноименный метод в C++,классе являются главной точкой входа в сканер. При вызове yylex() сканер начинает процесс сканирования, завершающийся либо при завершении файла (yylex возвращает 0), либо при обнаружении очередного слова (воз, вращается код лексемы). yylex() должна вызываться вновь, для по, лучения каждого следующего слова.

3. Файл описания сканера

Для задания сканера создается специальный текстовый файл, который впоследствии обрабатывается утилитой flex для построе, ния исходного программного кода. Файл включает в себя 3 секции: Определения, Правила и Пользовательский код. Последняя из них не является обязательной. Для разделения секций используется стро, ка с символами %%

Общая структура файла описания:

Определения

%%

Правила

%%

Пользовательский код

Если секция пользовательского кода отсутствует, то вторую стро, ку с символами %% можно опустить.

Утилита flex выполняет чтение файла и на основании содержимо, го секции определений производит построение размещаемых в вы, ходном файле lex.yy.c (или lex.yy.cc для объектно,ориентированно, го сканера) внутренних таблиц для распознавания символов. На ос, нове секции правил flex строит также размещаемый в файле lex.yy.c код обработки для каждой встреченной в исходном файле последова, тельности символов, удовлетворяющей заданному шаблону; а содер, жимое секции пользовательского кода копирует в выходной файл lex.yy.c без изменений. Таким образом, файл определений изначаль, но содержит некоторые фрагменты кода на C/C++, которые впослед, ствии добавляются к коду, создаваемому flex, и вместе образуют пользовательский сканер текстов.

В секциях определений и правил возможно указывать фрагменты (необходимые определения и объявления на языке С/С++), которые также будут попадать в результирующий файл без изменений, по аналогии с содержимым секции пользовательского кода. Это позво, ляет задать все необходимые с точки зрения С/С++,объявления до

7

их использования в разделе правил. Для выделения таких конструк, ций используются разделители {% и %}. Эти символы удаляются flex, а текст между ними помещается в выходной файл с исходным С/С++,кодом без изменений. Например:

{%

#include <stdio>

#define MAX_BUFFER_SIZE 4096 void print_error(int iErrorCode); %}

позволяет вставить в нужное место результирующего файла с ис, ходным программным текстом сканера директиву подключения за, головочного файла, объявить макроконстанту и задать прототип функции.

Основным элементом секции определений является объявление регулярного выражения в виде двух компонент:

<имя регулярного выражения> <выражение >, задаваемых в од, ной строке и разделяемых стандартными разделителями (пробелы, табуляции).

Например, строка:

Digit [0 9]

задает регулярное выражение, определяющее символ – десятичную цифру от 0 до 9.

Выражение:

Number Digit ({Digit})*

задает регулярное выражение, определяющее произвольное десятич, ное число, состоящее из цифр, определенных предыдущим выраже, нием.

Набор выражений позволяет построить шаблоны, по которым ска, нер выполняет поиск определенных последовательностей символов во входном тексте.

Секция правил состоит из строк вида: <выражение> <действие>,

где выражением может быть регулярное выражение или ссылка на его определение в области правил в виде имени. В последнем случае данный элемент имеет вид:

{<имя регулярного выражения>} <действие>

Действием является конструкция языка C/C++ или специаль, ные макросы, обрабатываемые flex. Если действие состоит из не, скольких операторов, для расположения их на нескольких стро, ках могут использоваться операторные скобки { <действие> }. При задании пустого действия входное слово, удовлятворяющее шаб,

8

лону, будет просто проигнорировано без дополнительной обработ, ки. Типичным действием при обнаружении слова, удовлетворяю, щего шаблону, является его сохранение в глобальной переменной для возможной дальнейшей обработки в программе и возврат кода (лексемы), который соответствует данному слову во внутреннем представлении программы. Сканирование должно быть приоста, новлено, и функция yylex() должна вернуть данный код в вызыва, ющую программу для обработки:

{%

#define LEXEM_NUMBER

1

long iCurrNumLexValue = 0;

%}

%%

{Number} {

iCurrNumLexValue = atol(yytext); return LEXEM_NUMBER;

}

Всоответствии с рассмотренным правилом при обнаружении во входном тексте десятичного числа сканер сохранит значение этого числа в переменной iCurrNumLexValue и вернет код LEXEM_NUMBER как результат вызова yylex(). Вызывающая про, грамма может обработать результаты и вновь вызвать yylex() для получения следующей лексемы.

Вправилах можно обращаться к глобальным переменным скане, ра, например yytext.

Порядок расположения правил имеет принципиальное значение. Если правило, выделяющее обобщенное множество слов (например, все слова, удовлетворяющие шаблону «идентификатор»), встреча, ется раньше, чем правило, выделяющее конкретное слово (напри, мер, “WHILE”) из данного множества, то последнее правило никогда не будет активизировано.

Более полную информацию по структуре файла и доступным фун, кциям можно получить в руководстве по flex.

4.Параметры flex

Всобранном виде flex включает в себя основной запускаемый файл, flex.exe, и, возможно, файл с шаблоном сканера flex.skl. В общем случае для запуска утилиты и получения результирующего С/C++, файла сканера можно воспользоваться следующей командой:

9

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

[^\\"]

10

11

AP_USERS

Users

 

tmpstr = strdup(yytext);

AP_ASPECT

Aspect

 

return AP_COLON;

AP_DATABASE

Database

 

}

AP_PAGE

Page

 

 

AP_DEFAULT

Default

 

 

AP_PROFILE

Profile

{AP_TYPE}

{

AP_LASTNAME

Last{Spc}Name

 

tmpstr = strdup(yytext);

AP_FIRSTNAME

First{Spc}Name

 

return AP_TYPE_KW;

AP_TYPE

Type

 

}

AP_GROUP

Group

{AP_AGENT}

{

AP_TEAM

Team

 

tmpstr = strdup(yytext);

AP_AGENT

Agent

 

return AP_AGENT_KW;

AP_EXT

Ext

 

}

AP_TOTAL

Total

 

 

AP_RECORDS

Records

{AP_USERS}

{

 

 

 

tmpstr = strdup(yytext);

Id

[a zA Z]([a zA Z0 9]|[\x5F])*

 

return AP_USERS_KW;

String

[\"]({Escape}|{AnyStrChr})*[\"]

 

}

Identifier

([a zA Z0 9])*

 

 

SqString

{Sq}(.)*{Sq}

 

 

Colon

[:]

{AP_ASPECT}

{

nl

\n

 

tmpstr = strdup(yytext);

 

 

 

return AP_ASPECT_KW;

%%

 

 

}

{Number}

{

{AP_DATABASE}

{

 

tmpstr = strdup(yytext);

 

tmpstr = strdup(yytext);

 

return AP_NUMBER;

 

return AP_DATABASE_KW;

 

}

 

}

{Semi}

{

{AP_PAGE}

{

 

tmpstr = strdup(yytext);

 

tmpstr = strdup(yytext);

 

return AP_SEMI;

 

return AP_PAGE_KW;

 

}

 

}

 

 

 

{Num}

{

{AP_DEFAULT}

{

 

tmpstr = strdup(yytext);

 

tmpstr = strdup(yytext);

 

 

 

return AP_DEFAULT_KW;

 

return AP_NUM;

 

 

 

}

 

}

 

 

{AP_LASTNAME}

{

 

 

{Slash}

{

 

tmpstr = strdup(yytext);

 

return AP_LASTNAME_KW;

 

tmpstr = strdup(yytext);

 

 

 

}

 

return AP_SLASH;

 

 

{AP_FIRSTNAME}

{

 

}

 

 

tmpstr = strdup(yytext);

 

 

 

 

 

 

return AP_FIRSTNAME_KW;

{Colon}

{

 

}

 

 

12

13

{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, где сохраняется до прочтения следующей лексемы.

6. Использование синтезированного программного кода

Если с помощью flex получен процедурный сканер, с ним может работать, например, следующая программа:

#include <stdio.h> #include <string>

extern FILE *yyin, *yyout; // referenced from flex generated scanner extern int yylineno;

extern std::string tmpstr;

int yylex();

int main(int argc, char* argv[])

{

yyin = fopen("test.txt","r"); //yyout will ptr to stdout int iRes = 0;

while ((iRes = yylex()) > 0)

{ //read something useful from file

printf ("Read '%s' (token values is %d) at

line %d\n",tmpstr.c_str(), iRes, yylineno);

}

printf ("Scanner return %d code\n",iRes); return 0

Результатом ее работы при условии, что в файле “test.txt” нахо, дятся данные, описанные в приведенном выше примере, будет вывод на экран следующей информации:

Read ‘Ext’ (token values is 279) at line 1

Read ‘999’ (token values is 283) at line 1

Read ‘7’ (token values is 283) at line 1

Read ‘:’ (token values is 262) at line 1

Read ‘10’ (token values is 283) at line 1

Read ‘AM’ (token values is 284) at line 1

Read ‘,’ (token values is 285) at line 1

Read ‘12’ (token values is 283) at line 1

Read ‘/’ (token values is 286) at line 1

Read ‘11’ (token values is 283) at line 1

Read ‘/’ (token values is 286) at line 1

Read ‘2003’ (token values is 283) at line 1

Read ‘Aspect’ (token values is 257) at line 1

Read ‘Page’ (token values is 263) at line 1

Read ‘1’ (token values is 283) at line 1

14

15

Read ‘Users’ (token values is 259) at line 2

Read ‘Database’ (token values is 260) at line 2

Read ‘Default’ (token values is 270) at line 4

Read ‘Default’ (token values is 270) at line 4

Read ‘Ext’ (token values is 279) at line 5

Read ‘#’ (token values is 287) at line 5

Read ‘Last Name’ (token values is 272) at line 5

Read ‘First Name’ (token values is 273) at line 5

Read ‘Type’ (token values is 274) at line 5

Read ‘Group’ (token values is 275) at line 5

Read ‘Team’ (token values is 276) at line 5

Read ‘201’ (token values is 283) at line 7

Read ‘TEST’ (token values is 284) at line 7

Read ‘TEST’ (token values is 284) at line 7

Read ‘Agent’ (token values is 258) at line 7

Read ‘20’ (token values is 283) at line 7

Read ‘0’ (token values is 283) at line 7

Read ‘202’ (token values is 283) at line 8

Read ‘TEST’ (token values is 284) at line 8

Read ‘TEST’ (token values is 284) at line 8

Read ‘Agent’ (token values is 258) at line 8

Read ‘21’ (token values is 283) at line 8

Read ‘0’ (token values is 283) at line 8

Read ‘203’ (token values is 283) at line 9

Read ‘TEST’ (token values is 284) at line 9

Read ‘TEST’ (token values is 284) at line 9

Read ‘Agent’ (token values is 258) at line 9

Read ‘23’ (token values is 283) at line 9

Read ‘0’ (token values is 283) at line 9

Read ‘Total’ (token values is 280) at line 11

Read ‘Records’ (token values is 281) at line 11

Read ‘:’ (token values is 262) at line 11

Read ‘3’ (token values is 283) at line 11

Scanner return 0 code

Для случая C++ сканера аналогичная программа выглядит следу, ющим образом:

#include <fstream> #include <iostream> #include <string> #include "FlexLexer.h"

std::string tmpstr; //do not used in this sample,for compile time only

16

int main(int argc, char* argv[])

{

if (argc < 2) {

std::cout << "USE: ccflexscan <source file>" << std::endl; return 0;

}

std::ifstream infile(argv[1]);

FlexLexer* lexer = new yyFlexLexer(&infile); int iRes = 0;

while ((iRes = lexer >yylex()) > 0)

{

std::cout << "Read " << lexer >YYText()

<<" (token value is "

<<iRes << ") at line "

<<lexer >lineno() << std::endl;

}

return 0;

}

Приведенная программа может быть скомпилирована с использо, ванием Visual C++ 6.0. Компиляция сканера, синтезированного в режиме C++ – с использованием компилятора Microsoft.

Примечание. Visual C++ 7.1 (2003) требует некоторой модифика, ции как поставляемого с flex файла FlexLexer.h, в котором содер, жится объявление класса,сканера, так и создаваемого утилитой фай, ла с программным кодом сканера (lex.yy.cc по умолчанию).

Данная (и более новые) версия компилятора не поддерживает ста, рого механизма потоков, существовавшего в С++ до его стандартиза, ции (такие файлы, как “iostream.h”) и требует использования новых потоковых классов, объявленных в заголовочном файле “iostream”. Новый заголовочный файл необходимо указать в FlexLexer.h. Кроме того, требуется убрать из создаваемого утилитой файла объявление class iostream, заменив его на включение нового заголовочного файла и использование директивы using namespace std;

7. Задание на выполнение лабораторной работы

Используя утилиту flex, разработать сканер для чтения тексто, вой таблицы с данными, выбранной по номеру варианта задания. Предусмотреть вывод лексем на стандартный выход сканера (экран). Архитектуру сканера (процедурный/объектный) выбрать произволь, но. Скомпилировать действующую программу любым доступным компилятором C/C++. В отчете привести текст описания сканера вме, сте с протоколом тестового выполнения, созданного на основе описа, ния программы,включаяисходныеданные иполученные результаты.

17

 

 

8.

Варианты заданий

 

1)

 

 

 

 

 

Executed on: 10/12/2003 User: Alex

 

ID

NAME

GRADE

AVERAGE_SCORE TEACHER

==

=====

======

===========

=======

1250

Alex Petroff

10

B

WES HAYDEN

1251

Eric Lieb

 

10

A

WES HAYDEN

1251

Duane Lindsley

10

A

WES HAYDEN

1301

Sandra Lim

 

11

C

AD NEDERLOF

2)

….

DN 1002

CPND

NAME BRIAN WALSH XPLN 27

DISPLAY_FMT FIRST,LAST VMB

VMB_COS 4

SECOND_DN

THIRD_DN

VMB_STATE CONFIGURED TYPE SL1

TN 004 0 00 02 KEY 00 H MARP DES BRIAN 1 JUN 2001 (2616)

DN 1003

CPND

NAME Norris Lam XPLN 27

DISPLAY_FMT FIRST,LAST VMB

VMB_COS 4

SECOND_DN

THIRD_DN

VMB_STATE CONFIGURED TYPE SL1

TN 024 0 06 14 KEY 00 H MARP DES LAM 29 JUN 2000 (2008)

DN 1004

18

CPND

NAME IRINA SEMENYURA XPLN 27

DISPLAY_FMT FIRST,LAST VMB

VMB_COS 4

SECOND_DN

THIRD_DN

VMB_STATE CONFIGURED TYPE SL1

TN 025 0 06 14 KEY 00 H MARP DES SEMENYURA 30 JUN 2000

(2008)

3)

KВИТАНЦИЯ АБОНЕНТ 313,70,43 ПОЛУЧАТЕЛЬ: филиал "ПТС"

 

№ 016 от 30.11.05 г. Номер лицевого счета ОАО "Северо,Западный Телеком"

Ноябрь 2005 г. 1002900415

 

 

 

 

 

 

 

 

 

 

Информация

Сумма

 

Начислено к оплате

 

335,05

о расчетах

 

 

 

 

 

 

 

 

 

 

 

Остаток на счете

200,

 

Абонентская плата за декабрь

 

200,00

 

 

 

 

 

 

Задолженность

0,

 

Итого к оплате

 

435,05

 

 

 

 

 

 

Начислено

 

 

 

 

 

в ноябре

435,

 

 

 

 

 

 

 

 

 

 

Начислено

 

 

Просим Вас оплптить счет до 20.12.2005 г.

к оплате

235,

 

 

 

 

 

 

 

 

 

 

 

4)

Сводный перечень услуг

Kол,во

Стоимость

Сумма

 

 

 

 

Абонентская плата

200

 

 

 

 

Междугородняя связь

25

17

425

 

 

 

 

Международная связь

10

56

560

 

 

 

 

Итого предоставлено услуг

 

 

1185

 

 

 

 

19

Соседние файлы в папке ТЯПиМТ