Лингвистическое обеспечение САПР Песков
Заказать
Цель работы
Целью данной лабораторной работы является применение на практике алгоритма рекурсивного спуска на основе библиотеки обработки входной строки.
Инструменты
Для выполнения данной лабораторной работы Вам потребу-ется любой компилятор языка С, способный генерировать 32-раз-рядные программы для той ОС, с которой Вы работаете. Для ОС Windows рекомендуется использовать бесплатную среду разра-ботки Microsoft Visual C++ Express.
Основная Ваша работа будет заключаться в формировании программы перевода выражения в постфиксную запись, которая была разобрана на лекции. Для первичной обработки строк пред-лагается использовать модуль match.
Процедура рекурсивного спуска
prim()
{
int s;
if (match("(")) {
if (expr()==0) return 0;
if (!match(")")) { cerror(E_RIGHT_BRACKET); return 0; }
}
else if (a=numb(&s)) {
printf("%d ", s);
} else { cerror(E_EXPRESS_SINTAX); return 0; }
return 1;
}
mult()
{
if (prim()==0) return 0;
while (1) {
if (match("*")) {
if (prim()==0) return 0;
printf("* ");
} else if (match("/")) {
if (prim()==0) return 0;
printf("/ ");
} else break;
}
return 1;
}
add()
{
if (mult()==0) return 0;
while (1) {
if (match("+")) {
if (mult()==0) return 0;
printf("+ ");
} else if (match("-")) {
if (mult()==0) return 0;
printf("- ");
} else break;
}
return 1; }
Модуль match
Данный модуль предназначен для первичной обработки строк и позволяет выделять из строки лексемы. Здесь описаны ин-терфейсные функции модуля match.
void match_init(char* line);
Процедура инициализации. Разбор строки всегда начинается с вызова этой функции. В качестве параметра передается входная строка.
void match_done(void);
Процедура деинициализации. После разбора строки необхо-димо вызвать данную функцию.
int match(char *lit);
Поиск указанной подстроки в начале входной строки. Если есть, то найденная подстрока удаляется и функция возвращает 1.
int amatch(char *lit, int len);
Аналогично предыдущему, но дополнительно указывается длина подстроки. Это используется для того, чтобы различать вы-ражения типа 'for' и 'formula', где первое, это ключевое слова, а второе - идентификатор.
int symname(char *sname);
Ищет идентификатор (метку) во входной строке. Метка начи-нается с подчеркивания или буквы, далее следуют буквы, подчер-кивание или цифры.
int number(int val[]);
Ищет целое знаковое число во входной строке
void skipblanks(void);
Пропускает последовательность пробельных символов (про-бел, табуляция) во входной строке.
skipchars(void);
Пропускает лексемы и следующие пустые символы. Исполь-зуется для обработки ошибок.
Задание
1. Реализовать программу рекурсивного спуска выражения и перевода в постфиксный вид.
2. Реализовать главную программу, считывающую строки из входного потока и выдающую в конце сообщения "OK" в случае успешного разбора или "FAIL" в случае неуспешного разбора.
3. Добавить в процедуру разбора задание по номеру вариан-та.
4. (Дополнительное.) Изучить разработку make файлов и раз-работать make файл для сборки проекта из двух модулей.
5. (Дополнительное.) Функция разбора вещественного числа в инженерной форме.
Список вариантов
1. Комплексные числа
Обеспечить поддержку вещественных и комплексных чисел. Числа вводить в нижеследующем формате
<вещ.число>::=<число>
<вещ.число>::=<число>.<число>
<комплксн.число>::=i
<комплксн.число>::=i+<вещ.число>
<комплксн.число>::=<вещ.число>i
<комплксн.число>::=<вещ.число>i+<вещ.число>
На выходе комплексные числа представлять в следующем виде:
complex(<комплексн.часть>,<реальн.часть>)
где комплексн.часть и реальн.часть - вещественные числа. Веще-ственные числа выводить без изменений.
Например
5.6i+4.9 на выходе complex(5.6,4.9)
0.6i на выходе complex(0.6,0)
i+7 на выходе complex(1,7)
2. Матрицы
Обеспечить поддержку матриц, состоящих из целых чисел. Матрицы вводить в нижеследующем формате:
<матрица>::=[<строки>]
<строки>::=<строка> | <строка> ; <строки>
<строка>::=<число> | <число> , <строка>
Например:
Матрица будет записана в виде [1,2,3;4,5,6]
вектор-столбец (матрица) будет записан в виде [1;4;5]
запись вида [1,2,3;5,6] будет считаться ошибочной.
На выходе матрицы предствлять в виде:
matrix(<строк>,<столбцов>,<значения>)
где <строк> и <столбцов> это целые числа - количество строк и столбцов соответственно, а значения, это перечисленные через за-пятую слева направо и сверху вниз, значения элементов матрицы - целые числа.
3. Строки
Обеспечить поддержку строки. Строки записываются в ка-вычках. Дополнительно необходимо обеспечить ввод кавычки в виде последовательности из двух кавычек. На выходе строки вы-давать в следующем формате:
string("<строка>")
где строка есть последовательность символов. Кавычка, если она была в исходной строке, должна быть заменена последовательно-стью символов \".
Например
"Hello World!" на выходе string("Hello World!")
"Hello ""World""!" на выходе string("Hello \"World!\"")
"""" на выходе string("\"")
4. Массивы
Обеспечить поддержку массивов чисел. Массивы вводить в нижеследующем формате:
<массив>::=( <числа> )
<числа>::=<число> , <числа> | <число>
На выходе массивы записывать в следующем виде:
array(<размер>, <числа>)
где, размер - это целое число - размер массива, числа - это элементы массива, перечисленные через запятую.
Например
(1, 2, 3, 4, 5) на выходе array(5,1,2,3,4,5)
5. Диапазоны
Обеспечить поддержку диапазонов (аналогично MathCAD). Диапазоны записывать в следующем формате:
<диапазон>::=<старт> ... <финиш>
<диапазон>::=<старт>, <приращение> ... <финиш>
где старт - целое число - начало диапазона, финиш - целое число - конец диапазона, приращение - целое число - прира-щение (по умолчанию 1 или -1, в зависимости от того, что больше старт или финиш). Приращение может быть отрицательным. Обес-печить контроль существования диапазона.
На выходе диапазоны записывать в следующем виде:
range(<старт>, <приращение>, <финиш>)
Например
5...10 на выходе range(5,1,10)
5...0 на выходе range(5,-1,0)
5,2...10 на выходе range(5,2,10)
5,-2...10 выдает ошибку "Неправильно задан диапазон"
6. Функции многих переменных
Обеспечить поддержку функций с любым количеством пара-метров (от 0).
<функция>::=<имя>(<параметры>)
<параметры>::=<выражение> | <выражение> < параметры > | e
На выходе функцию необходимо записывать в следующем виде:
Перечислить ее параметры слева направо (выражения долж-ны вычисляться), а затем имя функции.
Например
pow(3,5) на выходе 3 5 pow
pow(4+1,2) на выходе 4 1 + 2 pow
Дополнительно после обработки всех строк вывести список всех функций, использованных в строках.
Лабораторная работа 2
Цель работы
Изучение принципов построения виртуальных машин (ВМ) на основе реальных процессоров.
Исходные данные
Введем следующие обозначения абстракций ВМ.
данные (value) вещественное число (float или double)
адреса (addr) целое 16-битное число
В связи с тем, что ОУ принимает на вход вещественные числа, нам необходимо в нашей виртуальной машине сделать поддержку вещественных чисел. Однако полностью отказываться от под-держки целочисленных операций тоже нельзя. Она потребуется, по крайней мере, для вычисления адресов. Поэтому фактически приходится в виртуальной машине делать 2 блока арифметики - целочисленный и вещественный.
Самый простой способ, как можно поступить в этой ситуа-ции, заключается в выделении вещественной арифметики в про-блемно-ориентированный блок виртуальной машины. А в систем-ном блоке оставить только целочисленную арифметику. Так по-ступали практически во всех реальных вычислительных системах, так поступают обычно и при разработке ВМ.
Структура части ВМ, отвечающая за вещественную арифме-тику (назовем ее блок вещественной арифметики (БВА)), может выглядеть по-разному. Но в любом случае она включает некото-рое вещественное арифметико-логическое устройство (ВАЛУ). Главный вопрос, который нужно решить проектировщику, - откуда ВАЛУ должно брать операнды. В зависимости от типа виртуальной машины вообще и желания проектировщика в частности, это могут быть внутренний стек данных БВА, пара (тройка) внутренних регистров БВА или заданный адрес в основной памяти виртуальной машины.
Набор проблемно-ориентированных команд у разных типов виртуальных машин принципиально различаться не будет и обыч-но сводится к следующим группам:
- вещественные арифметические операции (сложение, вычи-тание, умножение, деление);
- функции (корень квадратный, тригонометрия и так далее);
- команды управления ОУ.
Набор системных команд по группам обычно выглядит так:
- целочисленные арифметические операции (целочисленные операции сложения, вычитания, умножения, иногда деления);
- управление логикой (переходы условные и безусловные, вызовы подпрограмм, возвраты из подпрограмм);
- операции со стеком (загрузка значения (целочисленного!), запись значения с вершины стека в указанный адрес).
Задание
Разработать стековую машину.
Системная часть:
- память команд - 64 килобайта;
- стек адресов в основной памяти, обычно в конце блока;
- регистры:
- SP - указатель стека,
- PC - указатель команд.
Проблемно-ориентированная часть:
память данных - в основной памяти, обычно после кода;
стек данных - 256 ячеек данных;
регистры:
SPF - указатель стека (8 бит),
PSW - слово состояния.
Разработка стековой виртуальной машины - одно из самых простых заданий. Все арифметические команды работают со сте-ком, то есть не имеют операндов. Целочисленные арифметические команды работают со стеком адресов. Вещественные арифметиче-ские команды работают со стеком данных. Команд, обладающих операндами, минимум:
Load <addr> Команда укладывает значение параметра в стек адресов.
Push <addr> Команда укладывает значение по адресу addr в стек адресов.
Pull <addr> Команда вытаскивает из стека адресов значение и записывает его по указанному в качестве параметра адресу.
Лабораторная работа 3
Цель работы
Целью данной лабораторной работы является разработка программы рекурсивного спуска с использованием генератора лексических анализаторов - Lex.
Общие сведения
Lex - программа для генерации сканеров (лексических ана-лизаторов). Входной язык содержит описания лексем в терминах регулярных выражений. Результатом работы LEX'a является про-грамма на языке Си, которая читает файл yyin (обычно это стан-дартный ввод) и выделяет из него последовательности символов (лексемы), соответствующие регулярным выражениям.
Рассмотрим способы записи регулярных выражений во вход-ном языке Lex'а. Алфавит Lex'а совпадает с алфавитом используе-мой ЭВМ. Символ из алфавита, естественно, представляет регу-лярное выражение из одного символа. Специальные символы (в том числе +-*?()[]{}|/\^$.<> ) записываются после специального префикса \. Кроме того, применимы все традиционные способы кодирования символа в языке C. Символы и цепочки можно брать в кавычки:
Например:
а "а" \а - три способа кодирования символа а
\n \t \007 "continue"
Имеется возможность задания класса символов:
[0-9] или [0123456789] - любая цифра
[A-Za-z] - любая буква
[^0-7] - любой символ, кроме восьмиричных цифр
. - любой символ, кроме \n
Грамматика для записи регулярных выражений (в порядке убывания приоритета):
<р> : <р>* повторение 0 или более раз
<р> : <р>+ повторение 1 или более раз
<р> : <р>? необязательный фрагмент
<р> : <р><р> конкатенация
<р> : <р>{m,n} повторение от m до n раз
<р> : <р>{m} повторение m раз
<р> : <р>{m,} повторение m или более раз
<р> : ^<р> фрагмент в начале строки
<р> : <р>$ фрагмент в конце строки
<р> : <р>|<р> любое из выражений
<р> : <р>/<р> первое выражение, если за ним следует второе
<р> : (р) скобки, используются для группировки
Примеры:
[A-Za-z]([A-Za-z0-9]{0,7}) - идентификатор (имя) в языке C до 8 символов.
^#" "*define - начало #define в языке C
Программа на входном языке Lex состоит из трех частей, раз-деленных символами %%:
Описания
%%
Правила
%%
Программы
Раздел описаний содержит определения макросимволов (ме-тасимволов) в виде:
ИМЯ ВЫРАЖЕНИЕ
Если в последующем тексте в регулярном выражении встре-чается {ИМЯ}, то оно заменяется на ВЫРАЖЕНИЕ. Если строка описаний начинается с пробелов или заключена в скобки %{ ... }%, то она просто копируется в выходной файл.
Раздел правил содержит строки вида
ВЫРАЖЕНИЕ {ДЕЙСТВИЕ}
ДЕЙСТВИЕ - это фрагмент программы на C, который вы-полняется тогда, когда обнаружена цепочка, соответствующая ВЫРАЖЕНИЮ. Действие, указанное в начале раздела без выраже-ния, выполняется до начала разбора. Lex делает попытку выделить наиболее длинную цепочку из входного потока. Если несколько правил дают цепочку одинаковой длины, применяется первое пра-вило. Так, при разборе по следующим правилам для цепочки "123" будет применено первое правило, а для цепочки "123." - третье:
[0-9]+
(\+|\-)?[0-9]+
(\+|\-)?[0-9]+"."[0-9]+
Если ни одно из правил не удастся применить, входной сим-вол будет скопирован в yyout. Если это нежелательно, в конец правил можно добавить, например, строки:
. {/* Ничего не делать */}
\n { }
Раздел программ может содержать произвольные тексты на C и целиком копируется в выходной файл. Обычно здесь записыва-ется функция yywrap(), которая определяет, что делать при дости-жении автоматом конца входного файла. Ненулевое возвращаемое значение приводит к завершению разбора, нулевое - к продолже-нию (перед продолжением, естественно, надо открыть какой-нибудь файл как yyin).
Интерпретатор таблиц КА имеет имя yylex(). Автомат пре-кращает работу (происходит возврат из функции yylex()), если в одном из действий выполнен оператор return (результат yylex() будет совпадать с указанным в операторе) или достигнут конец файла и значение yywrap() отлично от 0 (результат yylex() будет равен 0).
Традиционный пример входной программы для Lex'а - под-счет числа слов и строк в файле (обратите внимание на пробелы, этот текст нормально компилируется Lex'ом):
/********** Раздел определений ***********/
/* NODELIM означает любой символ, кроме разделителей слов */
NODELIM [^" "\t\n]
int l, w, c; /* Число строк, слов, символов */
%% /******************** Раздел правил **************/
{ l=w=c=0; /* Инициализация */ }
{NODELIM}+ { w++; c+=yyleng; /* Слово */ }
\n { l++; /* Перевод строки */ }
. { c++; /* Остальные символы */ }
%% /*************** Раздел программ *************/
main() { yylex(); }
yywrap() {
printf( " Lines - %d Words - %d Chars - %d\n", l, w, c );
return( 1 );
}
Внутри действий в правилах можно использовать некоторые специальные конструкции и функции Lex'а:
char* yytext - указатель на отождествленную цепочку сим-волов, терминированную нулем;
int yyleng - длина этой цепочки
void yyless(int n) - вернуть последние n символов цепочки обратно во входной поток;
void yymore() - считать следующие символы в буфер yytext после текущей цепочки
void yyunput(char c) - поместить байт c во входной поток
ECHO - копировать текущую цепочку в yyout
В некоторых случаях бывает удобно описать необходимые действия в терминах нескольких разных состояний (т.е. разных ко-нечных автоматов) с явным переключением с одного на другое. В этом случае набор имен состояний следует перечислить в специ-альной строке %Start, а перед выражениями записывать имя соот-ветствующего состояния в угловых скобках. Переключение в но-вое состояние выполняется с помощью оператора BEGIN. Напри-мер, следующая программа удаляет комментарии из программ на C (out - вне комментария, in - внутри):
%Start out in
%%
{ BEGIN out; }
<out>"/*" { BEGIN in; }
<out>.|\n { printf("%s",yytext); }
<in> "*/" { BEGIN out; }
<in> .|\n { }
%%
yywrap() { return(1); }
main() { yylex(); }
Обычным приемом при разработке трансляторов с использо-ванием Lex является следующий способ. Записываются правила для поиска нужных лексем, в действиях этих правил ставят опера-тор return для выхода из функции yylex(). Данный оператор дол-жен вернуть одно из предопределенных значений. Функция или функции, организующие разбор входной строки для получения очередной лексемы, пользуются функцией yylex(), если результат этой функции (идентификатор лексемы) совпадает с ожидаемой в данной точке лексемой, то считается, что лексема получена, иначе нет. В этой технологии есть две тонкости. 1. При обработке лексе-мы (в действии) зачастую требуется запомнить значение получен-ной лексемы, для того чтобы передать её в вызывающую функ-цию. 2. Всегда требуется помнить текущую лексему, так как если ее значение не совпало с требуемым, то это еще не значит, что вы-явлена ошибка. Вполне вероятно, что в другом месте программы (в другой функции по иерархии или в следующей проверке в этой же функции) полученное значение лексемы окажется именно ис-комым.
В данной лабораторной работе необходимо пользоваться именно этим механизмом.
Для вызова программы Lex следует ввести команду "lex имя_исходного_файла". Выходной файл по умолчанию имеет имя "lex.yy.c".
Задание
Ваша задача сформировать регулярную грамматику для язы-ка из лабораторной работы №1, записать ее в виде исходного тек-ста для lex и сгенерировать программу, на вход (входной поток) которой подается последовательность строк, предположительно принадлежащих данной грамматике. Каждая строка заканчивается символом \n. Программа должна выдать результат в виде числа (0 или 1) для каждой строки о ее принадлежности к грамматике.
Лабораторная работа 4
Цель работы
Целью данной лабораторной работы является разработка калькулятора на базе алгоритма рекурсивного спуска с использо-ванием генератора лексических анализаторов - Lex.
Общие сведения
Существует два вида трансляторов - интерпретаторы и ком-пиляторы. Первые из них выполняют программу сразу же в про-цессе ее разбора. Соответственно, если в программе есть какая-то синтаксическая или другая ошибка, интерпретатор обнаружит ее, только дойдя до этой строчки. Это одновременно и плюс, и минус. Плюс в том, что теоретически можно предложить пользователю тут же исправить ошибку и продолжить дальше (многие интерпре-таторы, снабженные средой разработки, так и поступают, например старые версии языка Basic). Компилятор, напротив, сперва перево-дит весь текст программы в последовательность команд некоторой реальной или виртуальной машины, а затем процессор или вирту-альная машина (программа) исполняет эту последовательность.
В данной работе Вам предстоит разработать калькулятор - это такая программа, которая позволяет производить вычисления арифметических выражений. Всего есть два варианта реализации калькулятора - интерпретатор и компилятор. В первом случае код, отвечающий за вычисления, должен находиться непосред-ственно в алгоритме рекурсивного спуска. Например, так:
add()
{
double op1,op2;
if (mult()==0) return 0;
while (1) {
if (match("+")) {
if (mult()==0) return 0;
op1 = pull();
op2 = pull();
push(op2+op1);
} else if (match("-")) {
if (mult()==0) return 0;
op1 = pull();
op2 = pull();
push(op2-op1);
} else break;
}
return 1;
}
Для компилятора все чуть-чуть сложнее. Вместо вычислений нужно генерировать некоторый исполняемый код. Будем считать, что генерируем код для некоторой виртуальной машины, поддер-живающей некоторый небольшой набор операций.
add()
{
double op1,op2;
if (mult()==0) return 0;
while (1) {
if (match("+")) {
if (mult()==0) return 0;
put_commd(&ptr, CADD);
} else if (match("-")) {
if (mult()==0) return 0;
put_commd(&ptr, CSUB);
} else break;
}
return 1;
}
где функция put_cmd размещает в буфере или выводит во внешний (бинарный) файл код этой команды. Примеры системы команд, ре-ализации виртуальной машины, а также пример функций кодоге-нератора приведены в архиве lab3vm.rar. Эта виртуальная машина поддерживает работу с вещественными числами, строками и пере-менными. А также команды ввода и вывода. Поддерживаются 4 стандартные математические операции.
Задания
1. Разработать калькулятор-интерпретатор. Поддерживаемые операции - из предыдущей лабораторной работы + (обязательно для всех) обеспечить работу с переменными, добавить операцию (или оператор) присваивания. Те, у кого был вариант №4, поддер-живаемые функции берут из варианта № 3. Обеспечить консоль-ный ввод и вывод переменных. Текст разбираемой программы те-перь многострочный. Необходимо также обеспечить возможность записи комментариев языка Си /* … */.
2. Разработать калькулятор-компилятор. Поддерживаемые операции - из предыдущей лабораторной работы. Те, у кого был вариант №4, поддерживаемые функции берут из варианта №3. Обеспечить консольный ввод и вывод переменных. Текст разбира-емой программы теперь многострочный. Если в виртуальной ма-шине нет какой-то необходимой вам операции (например, возведе-ние в степень) - добавьте ее. Необходимо также обеспечить воз-можность записи комментариев языка С++ (от // … и до конца строки). Обратите внимание, что виртуальная машина - это дру-гая исполняемая программа. И передача информации от вашего компилятора к виртуальной машине осуществляется через внеш-ний двоичный файл.
КУРСОВОЙ ПРОЕКТ
Заданием на курсовой проект является разработка транслято-ра одного из семи языков. Все задания на курсовой проект разде-ляются на четыре группы:
Тип транслятора:
1. Интерпретатор.
2. Компилятор и виртуальная машина.
Способ реализации транслятора:
" Рекурсивный спуск
" Генератор лексического и синтаксического анализатора (lex+yacc или какой-либо другой генератор, который Вам больше нравится).
Ниже приведена таблица, по которой Вы можете узнать тип языка, тип транслятора и способ реализации Вашего транслятора по номеру варианта. А далее описаны семь вариантов языка, один из которых Вам необходимо реализовать.
Результатом Вашей работы, которую Вы пришлете на про-верку, должны быть:
" Исходный текст Вашего транслятора: все *.c, *.cpp, *.h файлы, исходные тексты на lex и yacc (если Вы реализуете данный вариант) и виртуальной машины, если Вы реализу-ете компилятор и виртуальную машину.
" Не менее трех примеров корректного исходного текста, то есть такого текста, который обрабатывается Вашим транс-лятором как правильный.
" Не менее трех примеров некорректного исходного текста, то есть такого текста, который корректно обрабатывается Вашим транслятором как неправильный, то есть выдает ошибки.
" Makefile или пакетный файл, при помощи которого проис-ходит сборка вашего проекта и прогон тестовых примеров.
" Сопровождающий readme.txt, в котором описано назначе-ние каждого файла, а также для каждого тестового приме-ра описан результат, который выдает Ваш транслятор. Обязательно необходимо указать, какими компиляторами (C/C++, а также lex и yacc) и какой версии Вы пользова-лись для сборки Вашего проекта.
" Документ, оформленный обычным образом, как курсовой проект. Данный документ должен включать:
" описание грамматики;
" описание семантики операторов и операций Вашего языка.
Варианты курсовых проектов
№
варианта Вариант синтаксиса Тип транслятора Способ реализации
1 1 Интерпретатор Рекурсивный спуск
2 2 Компилятор Генератор анализаторов
3 3 Интерпретатор Рекурсивный спуск
4 4 Компилятор Генератор анализаторов
5 5 Интерпретатор Рекурсивный спуск
6 7 Интерпретатор Рекурсивный спуск
7 1 Компилятор Генератор анализаторов
8 2 Интерпретатор Рекурсивный спуск
9 3 Компилятор Генератор анализаторов
10 4 Интерпретатор Рекурсивный спуск
11 5 Компилятор Генератор анализаторов
12 6 Интерпретатор Рекурсивный спуск
13 7 Компилятор Генератор анализаторов
14 1 Интерпретатор Генератор анализаторов
15 2 Компилятор Рекурсивный спуск
16 3 Интерпретатор Генератор анализаторов
17 4 Компилятор Рекурсивный спуск
18 5 Интерпретатор Генератор анализаторов
19 7 Интерпретатор Генератор анализаторов
20 1 Компилятор Рекурсивный спуск
21 2 Интерпретатор Генератор анализаторов
22 3 Компилятор Рекурсивный спуск
23 4 Интерпретатор Генератор анализаторов
24 5 Компилятор Рекурсивный спуск
25 6 Интерпретатор Генератор анализаторов
26 7 Компилятор Рекурсивный спуск
Варианты синтаксиса
Вариант № 1. Pascal-подобный алгоритмический язык
В данном задании необходимо реализовать относительно простой язык программирования. За основу возьмите синтаксис языка Паскаль. Вам необходимо реализовать поддержку нижесле-дующих элементов:
" Стандартная структура программы языка Pascal (program name; переменные, подпрограммы, begin … end).
" Типы данных real, boolean.
" Подпрограммы: процедуры, функции. Можно не делать поддержку вложенных процедур и функций, достаточно будет обеспечить поддержку процедур и функций на верхнем уровне (уровне программы). Обязательно необ-ходимо обеспечить поддержку локальных переменных в подпрограммах. Для проверки реализуйте на Вашем языке рекурсивный алгоритм вычисления чисел Фибоначчи, он должен работать корректно.
" Операторы:
" for … to … [step …] do
" if … then … [else …]
" Системные процедуры:
" write, writeln: достаточно будет, если эти процедуры бу-дут принимать на вход ровно два параметра - строку и вещественное выражение для печати.
" read, readln: эти процедуры должны принимать ровно один параметр: переменную для ввода значения.
" Оператор присваивания. Слева от символа :=, а справа выражение с операциями, которые описаны ниже.
" Операции:
" Арифметические (для вещественных чисел): +, -, *, /.
" Сравнения (операнды могут быть вещественного типа, а результат операции булев): <, >, <>, ><, <=, =<, >=, =>, =
" Логические (операнды булевы, результат булев): and, or, xor
Примечание: Ваш транслятор должен быть реализован как консольное приложение, принимающее на вход (не в качестве входного потока, а как параметр приложения) исходный текст Ва-шей программы. Процедуры read/readln и write/writeln должны ра-ботать соответственно с входным и выходным потоками, что поз-волит делать автоматическое тестирование на основе заранее заго-товленных примеров. Сообщения об ошибках должны попадать в поток stderr (для языка C) или cerr (для C++). В случае если была хотя бы одна ошибка, программа должна возвращать значение -1, а если ошибок не было, то 0.
Вариант № 2. Экранный калькулятор выражений
В данном задании Вам необходимо реализовать простой калькулятор выражений, аналогичный тому, что Вы делали в рам-ках лабораторных работ. Однако ввод выражения может осу-ществляться при помощи экранной клавиатуры, похожей на ту, что можно увидеть у обычного калькулятора. Также необходимо обеспечить:
1) возможность загрузки готового выражения из файла;
2) выгрузки результата вычисления в файл;
3) копирование в буфер обмена и из буфера обмена;
4) возможность ввода многострочного выражения;
5) операции +, -, *, /, возведение в степень;
6) нахождение корня квадратного и корня любой степени;
7) основные тригонометрические функции, sin, cos, tg, ctg, arcsin, arcos, arctg, arcctg;
8) гиперболические функции;
9) скобки;
10) поддержку работы с переменными: для этого нужно обеспечить операцию присваивания, все переменные с их значени-ями должны отображаться в виде таблицы в калькуляторе, коли-чество переменных может быть ограничено.
Примечание: если Вам необходимо реализовать данный калькулятор на основе lex+yacc, то необходимо подменить в lex функции ввода символа. Сделать это можно, например, следую-щим образом:
int get_next_simbols(char* buf,int max_size)
{
if (max_size == 0) return 0;
if (*bufptr == 0) return 0;
*buf = *bufptr++;
return 1;
}
#define YY_INPUT(buf,result,max_size) \
{ \
result = get_next_simbols(buf,max_size); \
}
Данный текст, вставленный в секцию определений в скобки %{ … %}, позволит подменить ввод символов из входного потока на ввод символов из буфера bufptr, в который Вы должны загру-зить буфер с символами до начала разбора.
Вариант № 3. Консольный текстовый процессор
Задача данного текстового процессора - обработка строк входного файла. Проблемной частью команд виртуальной маши-ны, встроенной в интерпретатор или внешней (для компилятора), будут являться команды навигации по тексту и обработки текста, как это обычно происходит в обычном текстовом редакторе, одна-ко в отличие от обычного текстового редактора никакого графи-ческого или даже консольного отображения данного текста не требуется. Вся обработка должна происходить в оперативной па-мяти. Ближайший аналог такого текстового процессора - sed.
Команды навигации:
" перейти в начало файла, в конец файла, в начало строки, в конец сроки;
" перейти на строку N (по возможности сохранив теку-щую позицию);
" перейти на позицию N в текущей строке;
" перейти на N строк ниже, на N строк выше;
" перейти на N символов влево, на N символов вправо;
" перейти на N слов влево, на N слов вправо.
Команды работы с блоками:
" начать выделение (затем после нескольких команд пере-хода), закончить выделение;
" выделить текущий символ;
" выделить текущее слово;
" выделить текущую строку;
" выделить текущую строку от начала до текущей пози-ции;
" выделить текущую строку от текущей позиции до кон-ца;
" запомнить блок (аналогично копированию в буфер об-мена);
" вставить блок в текущую позицию (аналогично вставке из буфера обмена).
Команды редактирования:
" удалить текущий символ или выделенный блок;
" вставить заданную последовательность символов.
Поиск:
" найти заданную строку от начала файла;
" найти заданную строку от текущей позиции до конца документа;
" найти заданную строку от текущей позиции до начала документа;
" найди следующее вхождение.
Примечание 1:
" не важно, как эти команды будут называться - приду-майте разумные, понятные Вам названия;
" если блок уже выделен (то есть закончено выделение блока), то любая операция навигации сбрасывает выде-ленный блок (разумеется, это не касается блока, скопи-рованного в буфер;
" было бы неплохо сделать поддержку нескольких бло-ков, но это на Ваше усмотрение;
" в качестве дополнительного параметра для команд по-иска можно указать - требуется ли найденную строку выделить как блок;
" каждая команда возвращает значение - удалось ли ей выполнить задачу, это значение может быть использо-вано в команде if или проигонорировано.
Общие команды:
" Команда if - проверяет, успешно ли завершилась предыдущая команда, и позволяет выполнить какой-то блок действий в случае успеха. Конкретный синтаксис команды остается на Ваше усмотрение.
" Цикл пока. По синтаксису данная команда должна быть похожа на команду if, но все команды, включенные в блок, выполняются пока выполняется условие (по же-ланию).
Примечание 2: Ваш транслятор должен быть реализован как консольное приложение, исходный текст на Вашем языке переда-ется в качестве параметра транслятора (см. примечание для вари-анта №1). Обрабатываемый текстовый файл подается на входной поток, а обработанный файл, который получается после работы Вашей программы, выдается на выходной поток.
Вариант № 4. Графический язык
В данном варианте Вашей задачей является создание языка, который описывает в виде алгоритмов и графических примитивов векторный рисунок (приблизительно на таких принципах строится, например, отображение TTF шрифтов). Входным файлом для дан-ного транслятора будет являться исходный текст на описанном здесь языке, а выходным - либо окно с нарисованным рисунком, либо графический файл одного из популярных форматов (BMP, PNG etc). См. Примечание к варианту языка № 2.
Графические команды:
" задать параметры вывода:
- пера (толщина, цвет);
- кисти (тип, цвет);
- вывода текста (шрифт, размер);
" сохранить параметры вывода (в стек);
" восстановить параметры вывода (из стека);
" переместить перо в заданную позицию (x, y);
" переместить перо на заданную позицию (дельта x, дель-та y);
" нарисовать линию от текущей позиции до указанной (перо перемещается в эту позицию);
" нарисовать линию от текущей позиции до позиции в ви-де смещения от текущей позиции (перо перемещается в эту позицию);
" нарисовать прямоугольник с заданными координатами;
" нарисовать прямоугольник от текущей позиции до по-зиции, заданной в виде смещения;
" нарисовать эллипс с заданными координатами;
" нарисовать эллипс от текущей позиции до позиции, за-данной в виде смещения;
" нарисовать ломанную линию (каждая узловая точка ло-манной задается в виде смещения предыдущей точки).
Команды и конструкции общего назначения:
" задать глобальную переменную;
" вычислить выражение (стандартный минимум арифме-тических операций);
" повторить блок N раз (аналог цикла for);
" оператор if (конкретный синтаксис остается на Ваше усмотрение);
" оператор while (конкретный синтаксис остается на Ваше усмотрение);
" процедура (подпрограмма);
" обеспечить работу с локальными переменными.
Примечания:
" все замкнутые фигуры, такие, как прямоугольник, эл-липс и т.д., рисуются с учетом текущей кисти, но она может иметь тип "нет заливки", тогда фигура должна рисоваться без заливки;
" в качестве любого параметра проблемно-ориентиро-ванных команд могут использоваться выражения.
Вариант № 5. Язык управления "черепахой"
Данный язык является вариацией на тему известного языка для обучения программированию Лого. Рисовать "черепашку" можно в виде простого треугольничка. См. Примечание к варианту языка № 2.
Для данного варианта Ваш интерпретатор или виртуальная машина для компилятора должны представлять собой GUI-приложение, в котором требуется обеспечить как минимум коман-ду открытия файла (бинарного для компилятора и текстового для интерпретатора). Также требуется обспечить возможность указа-ния параметра задержки в миллисекундах, который будет исполь-зоваться для отображения после выполнения каждой команды, а также требуется отобразить и дать возможность изменить любой параметр - азимут "черепашки", ее текущие координаты. На вы-ходе Вы должны получить, в отличие от всех остальных вариан-тов, не файл, а процесс движения "черепашки".
Команды "черепашки":
" опусти хвост (после этого в процессе движения "чере-пашки" за хвостом остается линия), параметры - цвет и толщина линия;
" подними хвост (линия не остается);
" повернись на заданный азимут (азимут задается в граду-сах от севера, север - направление вверх);
" повернись на заданный угол (то есть к текущему азиму-ту нужно прибавить указанный);
" подвинься на заданное число шагов вперед (в ту сторо-ну, куда она смотрит);
" функция "впереди след хвоста".
Команды и конструкции общего назначения:
" создать переменную;
" вычислить выражение (стандартный минимум арифме-тических операций);
" условный оператор;
" цикл "пока";
" подпрограмма (желательно, но не обязательно, обеспе-чить работу с локальными переменными).
Примечание: в качестве относительно простого примера Вы можете реализовать построение какого-то лабиринта, а в качестве более сложного примера - выход из любого лабиринта, с любой позиции.
Вариант № 6. Интерпретатор командной строки
Основным назначением данного языка должна стать замена привычного Вам cmd.exe. сommand.com или shell. Соответственно, основными абстракциями, с которыми работает данный интерпре-татор, являются внешние программы, которые он может выпол-нять, передавая им параметры командной строки, и получать от них результат в виде кода завершения. Для примера можете изу-чить работу csh. Настоятельно рекомендую Вам реализовать сбо-рочный скрипт на Вашем языке, вместо использования обычных BAT или CMD файлов.
Необходимо обеспечить:
" запуск произвольного приложения со всеми его пара-метрами;
" работу перенаправления ввода-вывода для входного по-тока, выходного потока и потока вывода ошибок, в том числе работу канала передачи выхода одного приложе-ния входу другого при помощи "|";
" сохранение результата работы программы (кода завер-шения) в переменную;
" операции над переменными:
- конкатенацию переменных (то есть работу с ними как со строками);
- арифметические и логические операции над перемен-ными (то есть работу с ними, как с числами, стандарт-ный минимум арифметических операций);
" печать на экране (echo);
" поддержку параметров скриптового файла (то есть воз-можность передачи внешних параметров при запуске Вашего интерпретатора) и использование этих парамет-ров внутри скрипта как переменных;
" работу подпрограмм и локальных переменных;
" условный оператор;
" цикл "пока".
Вариант № 7. C-подобный алгоритмический язык
Требуется создать алгоритмический язык программирования, с синтаксисом, аналогичным языку C. Вам необходимо реализо-вать поддержку нижеследующих элементов.
" Стандартная структура программы языка C (глобальные переменные, функции, главная функция с именем main).
" Типы данных int и указатель на int.
" Функции. Обязательно необходимо обеспечить поддержку локальных переменных в функциях. Для проверки реали-зуйте на Вашем языке рекурсивный алгоритм вычисления чисел Фибоначчи, он должен работать корректно.
" Операторы:
" for
" if … [else …]
" Системные процедуры:
" print: достаточно, если эта функция будет принимать на вход ровно два параметра - строку и целочисленное выражение для печати;
" scanf: эта функция должна принимать ровно один пара-метр: переменную для ввода значения.
" Операции:
" Арифметические: +, -, *, /, %.
" Сравнения (операнды могут быть целого типа, результат целого типа): <, >, !=, <=, >=, ==
" Бинарные: &, |, ^, ~
" Логические (операнды булевы, результат булев): &&, ||, ^^, !
" Операции c указателем: *, &
Примечание:
" поддержка препроцессора и заголовочных файлов не требуется.
Для удобства наших клиентов, проходящих обучение на ФДО ТУСУРа, была создана данная форма заказа, с помощью которой Вы можете БЕСПЛАТНО УЗНАТЬ СТОИМОСТЬ оказания помощи в выполнении работ по тем дисциплинам, которые Вам необходимы. Если Вы хотите заказать ОПТОМ выполнение одного и более семестров, то мы предложим Вам выполнение работ под ключ по самым выгодным ценам. Пожалуйста свяжитесь с нами по следующим контактам