Транслятор для перевода текста программы с языка Паскаль на язык Си (integer, if Le then, записи (record))

Написание транслятора посредством языка Си, обрабатывающего конструкции integer, if Le then, записи (record), а также реализующего обработку new для выделения динамической памяти: разработка алгоритма реализации задачи, представление листинга программы.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 03.07.2011
Размер файла 171,7 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Министерство образования и науки Российской Федерации Федеральное агентство по образованию Государственное образовательное учреждение высшего профессионального образования "Северо-кавказский государственный университет"

КУРСОВОЙ ПРОЕКТ

по дисциплине "Программирование на языке высокого уровня"

Исполнитель:

Гладской Д.Е.

Группа АСОУ-091

Руководитель:

Братченко Н.Ю.

Ставрополь, 2011

Оглавление

  • Введение
  • Постановка задачи
  • Внешняя спецификация
  • Описание алгоритма
  • Структура программы и описание функций и операторов
  • Листинг программы
  • Распечатка тестов и результатов
  • Выводы
  • Список литературы

Введение

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

Процесс решения задачи на ЭВМ можно разбить на этапы (фазы). Рассмотрим каждый этап подробнее.

Первый этап - постановка задачи

Работа над программным обеспечением начинается с составления документа, называемого "Задание на разработку программного обеспечения (техническое задание)". В нем указывается следующее.

Название задачи: Дается краткое определение решаемой задачи, название программного комплекса, указывается система программирования для ее реализации и требования к аппаратному обеспечению.

Описание: Подробно излагается постановка задачи, описывается применяемая математическая модель для задач вычислительного характера, метод обработки входных данных для задач невычислительного характера и т. д.

Управление режимами работы программы: Формулируются основные требования к способу взаимодействия пользователя с программой (интерфейс пользователь - компьютер).

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

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

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

Пример работы программного комплекса: Приводится один или несколько примеров работы программного комплекса, на которых в простейших случаях проводится его отладка и тестирование.

Второй этап - выбор метода решения

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

Третий этап - разработка алгоритма решения задачи

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

Алгоритм представляет собой точное предписание, последовательность действий, приводящих к решению вычислительной или логической задачи.

Определяется схема взаимодействия программных модулей, т.е. схема потоков данных программного комплекса.

Результатом выполнения этого этапа является блок-схема алгоритма решения поставленной задачи.

Блок-схема - это графическое изображение логической структуры алгоритма. Блок - схема состоит из блоков и линий потоков информации.

Блоки указывают на процессы обработки данных, а линии потоков информации показывают движение данных от одного блока к другому.

Правила изображения блок-схем и условные обозначения, используемые в них, регламентированы стандартом (ГОСТ 19.701-90) и подробно будут рассмотрены ниже.

Четвертый этап - кодирование алгоритма

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

Как и другие текстовые файлы, они могут быть созданы, просмотрены и отредактированы с помощью любых текстовых редакторов. Но рекомендуется для этой цели пользоваться текстовым редактором, встроенным в среду Turbo Pascal 7.0.

В каталогах файлы, содержащие исходные тексты программ, написанные на языке Паскаль, имеют вид <имя >.pas. Расширение pas говорит о том, что это файлы паскаль-программ.

Пятый этап - трансляция и компиляция программы

После того как закончено кодирование (написание программы на языке программирования) и исходный текст программы введен в память компьютера, производят транслирование и компилирование программы.

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

Затем происходит сборка программы (компиляция), т.е. к программе подключаются все заказанные ей библиотеки, процедуры, функции и т.д. Если какой-либо компонент не обнаружен, выдается соответствующее сообщение и процесс прекращается. Необходимо убедиться в наличии ненайденного компонента, в правильности указанного имени его или пути к нему. Затем снова повторить компиляцию. При успешном завершении процесса образуется исполняемый файл программы (файл с расширением EXE). С помощью этого файла запускают программу на выполнение.

Шестой этап - тестирование программы

Различается два вида тестирования: автономное и комплексное. При автономном тестировании подвергаются отдельные программные модули, из которых состоит программный комплекс. Комплексное тестирование заключается в проверке всего программного комплекса.

Для тестирования подбираются такие исходные данные, для которых результат выполнения программы заранее известен.

После того как при тестировании обнаружена ошибка, начинается процесс отладки тестируемого программного модуля или программного комплекса. Тестирование и отладка чередуются и завершаются после того, как будет принято решение об отсутствии в программном комплексе ошибок.

Относительная стоимость обнаружения и исправления ошибок ("тяжесть ошибки") зависит от времени их обнаружения. Чем позже обнаружена ошибка, тем выше "тяжесть ошибки".

Седьмой этап - создание документации

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

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

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

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

Это руководство в качестве основных документов включает:

1) задание на разработку программного обеспечения (техническое задание);

2) спецификацию;

3) прокомментированные исходные тексты (листинги) модулей программы и управляющего модуля;

4) схему разбиения программного комплекса на программные модули;

5) схему потоков данных программного комплекса;

6) схему взаимодействия программных модулей;

7) планы и данные для тестирования программного комплекса;

8) другие материалы, иллюстрирующие проект, например: блок-схемы программного комплекса и программных модулей.

Отметим, что стоимость разработки хорошей документации достаточно высока и оценивается в 1 человеко-месяц на 1000 команд исходного текста программы.

Восьмой этап - сопровождение и эксплуатация

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

Данный тип работ с программным комплексом в период его эксплуатации называется сопровождением.

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

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

Постановка задачи

транслятор динамический память листинг программа

Заданием курсового проекта является написание транслятора, обрабатывающего следующие конструкции:

- integer

- if Le then

- Записи (record)

- указатели на записи

- Так же реализуем обработку new для выделения динамической памяти

Программа так же должна обрабатывать арифметическое (рис. 1.1) и логическое выражения (рис. 1.2)

Написание транслятора, как уже было сказано в введении будет выполняться посредством языка программирования Си. Будет предусмотрена обработка ошибочных операторов. Программа будет обрабатывать синтаксис программы до первой ошибки, т.к. дальнейший проход может вызвать еще больше ошибок. Таким образом, сократится время обработки ошибочного файла.

Арифметическое выражение Ae3:

Рисунок 1.1 - Диаграмма арифметического выражения Ae3

Логическое выражение Le1:

Рисунок 1.2 - Диаграмма логического выражения Le1

Таблица правил трансляции

Таблица 1.1 - Таблица перевода

Конструкции Pascal

Конструкции C

Операторные скобки bеgin…еnd

{...}

Оператор var

vаr <nаme>:<type>; <name>,<nаme>:<type>; label <nаme>;

<type> <nаme>,<nаme>; <type> <nаme>;

Тип переменной

<name>:intеgеr;

Int <name>;

If <statement> then

If(<statement) {

<name> record

<name> : <type >;

<name> : <type>;

end;

Struct <name> {

<type> <nаme>;

<type> <nаme>;

}

{ комментарий 1 } (*комментарий 2*)

/*комментарий 1*/ /*комментарий 2*/

<name>:^<type>;

<type> * <name>;

New(<name>)

<name> = new(<type>)

Приведем пример перевода программы с языка си на Паскаль

Таблица 1.2 - Вид программы на паскале и си

Паскаль

Си

type

mobile = record

coast:integer;

weight:integer;

end;

var

i,k:integer;

mob:^mobile;

ids:^integer;

begin

k := 6;

i := 3;

if (k>i) then

begin

new(mob);

end;

else

begin

new(ids);

end;

end.

#include <stdio.h>

struct mobile

{

int coast;

int weight;

};

int i,k;

mobile * mob;

integer * ids;

void main()

{

k=6;

i=3;

if ((k>i))

{

mob = new(mobile);

}

else

{

ids = new(int);

}

}

Внешняя спецификация

Программа будет запрашивать имя файла для осуществления трансляции. Данное сообщение будет выглядеть следующим образом:

Введите имя файла:

При возникновении ошибки открытия файла на экран будет выведено сообщение:

Возникла ошибка при открытии файла!

После осуществления обработки текстового файла, экран пример следующий вид:

n1 операторов в исходном файле.

n2 операторов было перенесено в новый файл.

n3 операторов не было обработано

Где n1, n2 и n3 - это число операторов.

После данных действий будет предложено записать результат в новый файл. Вид экрана:

Введите имя нового файла:

И ошибочное сообщение:

Возникла ошибка при создании файла!

Программа будет не требовательна к аппаратным ресурсам, сможет работать из под DOS, на компьютере с процессором более 500Гц и оперативной памятью более 32 Мб

Описание алгоритма

Трансляция программы -- преобразование программы, представленной на одном из языков программирования, в программу на другом языке и, в определённом смысле, равносильную первой.

Существуют различные виды трансляторов:

§ Адресный. Функциональное устройство, преобразующее виртуальный адреc в реальный адрес.

§ Диалоговый. Обеспечивает использование языка программирования в режиме разделения времени.

§ Многопроходной. Формирует объектный модуль за несколько просмотров исходной программы.

§ Обратный. То же, что детранслятор.

§ Однопроходной. Формирует объектный модуль за один последовательный просмотр исходной программы.

§ Оптимизирующий. Выполняет оптимизацию кода в создаваемом объектном модуле.

§ Синтаксически-ориентированный (синтаксически-управляемый). Получает на вход описание синтаксиса и семантики языка и текст на описанном языке, который и транслируется в соответствии с заданным описанием.

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

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

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

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

В целом процесс компиляции состоит из двух основных этапов - анализа и синтеза. На этапе анализа выполняется распознавание текста исходной программы, создание и заполнение таблиц идентификаторов. Результатом его работы служит некое внутреннее представление программы, понятное транслятору. На этапе синтеза на основании внутреннего представления программы и информации, содержащейся в таблице идентификаторов, порождается текст результирующей программы. Результатом этого этапа является код на языке Си.

Важная функция компилятора состоит в том, чтобы записывать имена

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

Фазы связаны с логической организацией компилятора. При реализации работа разных фаз может быть сгруппирована в проходы (pass), которые считывают входной файл и записывают выходной. Например, фазы анализа -- лексический анализ, синтаксический анализ, семантический анализ и генерация промежуточного кода -- могут быть объединены в один проход. Оптимизация кода может представлять собой необязательный проход. Затем может быть еще один проход, заключающийся в генерации кода для конкретной целевой машины. Некоторые наборы компиляторов созданы вокруг тщательно разработанного промежуточного представления, которое позволяет начальной стадии для некоторого языка программирования взаимодействовать с заключительной стадией для определенной целевой машины. При наличии таких наборов можно создавать компиляторы для различных исходных языков и одной целевой машины, комбинируя различные начальные стадии с заключительной стадией для этой целевой машины. Аналогично можно разрабатывать компиляторы для различных целевых машин, комбинируя начальную стадию с заключительными стадиями для различных целевых машин.

Разработчики компиляторов, как и разработчики любого другого

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

Структура программы и описание функций и операторов

Назначение подпрограмм:

trnslt - главная транислирующая программа

fcomm - подпрограмма проверяющая текст на наличие комментариев

frecord - подпрограмма обрабатывающая записи

fif - подпрограмма обрабатывающая структуру if then else

asign - подпрограмма обрабатывающая знаки присваивания

errors1 - подпрограмма обрабатывающая ошибки

lexAnalyser - подпрограмма реализующая лексический анализ

copy_w - подпрограмма копирующая строки из входного буфера в выходной

begin - подпрограмма обрабатывающая тело раздела

new - подпрограмма обрабатывающая выделение памяти под структуры в динамической памяти

fvar - подпрограмма обрабатывающая блок операторов после ключевого слова var

Таблицы с идентификаторами:

Таблица 4.1 - Таблица с ключевыми словами

Ключевое слово

Номер

begin

1

end

2

var

3

boolean

4

false

5

true

6

type

7

record

8

and

9

or

10

if

11

else

12

New

13

Таблица 4.2 - Таблица с типами переменных

Тип

Идентификационный номер

Целочисленный тип

1

Логический тип

3

Таблица 4.3 - Таблица с типами слов

Тип слова

Идентификационный номер

Ошибочный оператор

0

Знак пропуска

1

Строка

2

Число

3

Символ

4

При этом, входным файлом является файл с программой, написанной на языке программирования Паскаль 3.pas.

Выходным же файлом является файл с текстом программы на языке Си 3.с.

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

Листинг программы

#include <conio.h>

#include <stdio.h>

#include <string.h>

#include <locale.h>

FILE *fkrd, *fkod;

const int buflen = 10000;

const int KWn = 13;

char * KWs[KWn] =

{

"begin", "end", "var", "boolean",

"false", "true", "type", "record",

"and", "or", "if", "else",

"new"

};

#define kw_begin 1

#define kw_end 2

#define kw_var 3

#define kw_boolean 4

#define kw_false 5

#define kw_true 6

#define kw_type 7

#define kw_record 8

#define kw_and 9

#define kw_or 10

#define kw_if 11

#define kw_else 12

#define kw_new 13

#define t_Int 1

#define t_Bool 2

const int cuservars = 3;

int uvars;

#define w_error 0

#define w_space 1

#define w_str 2

#define w_numb 3

#define w_char

char inar[buflen],

oarr[buflen];

int inlen,pos2,pos1;

int koper1,koper2,ker;

int odew;

int wtype;

int wnumf;

int dt;

typedef struct var{

char s[64];

int tp;

var * next;

};

typedef struct types{

char s[64];

int tid;

types * next;

};

var *vars, *lvars;

types * typeslist;

int fle();

int fae();

int asign();

int addvar(int zse){

var *np, *p;

if (zse) p = vars; else p = lvars;

while (p) {

if (strlen(p->s)==odew&&

!memcmp(p->s,&inar[pos1],odew)) return 0;

p = p->next;

}

np = new var;

memcpy(np->s,&inar[pos1],odew);

np->s[odew]=0;

np->tp = -1;

if (zse) {

np->next = vars;

vars = np;

} else {

np->next = lvars;

lvars = np;

}

return 1;

}

int addnewtype()

{

types *head=typeslist, *ntype;

while (head) {

if (strlen(head->s)==odew&&

!memcmp(head->s,&inar[pos1],odew)) return 0;

head = head->next;

}

ntype = new types;

memcpy(ntype->s,&inar[pos1],odew);

ntype->s[odew]=0;

ntype->tid = uvars;

uvars++;

ntype->next = typeslist;

typeslist = ntype;

return 1;

}

int u_varsw()

{

types *head=typeslist;

while(head)

{

if (strlen(head->s)==odew&&

!memcmp(head->s,&inar[pos1],odew)) return head->tid;

head = head->next;

}

return 0;

}

char* utname(int number)

{

types *head=typeslist;

while(head)

{

if (head->tid==number) return head->s;

head = head->next;

}

return 0;

}

void heretp(int zse, int type){

var *p;

if (zse) p = vars; else p = lvars;

while (p) {

if (p->tp==-1) p->tp = type;

p = p->next;

}

}

int vartype(){

var * p;

p = lvars;

while (p) {

if (strlen(p->s)==odew&&

!memcmp(p->s,&inar[pos1],odew)) return p->tp;

p = p->next;

}

p = vars;

while (p) {

if (strlen(p->s)==odew&&

!memcmp(p->s,&inar[pos1],odew)) return p->tp;

p = p->next;

}

return 0;

}

char* usertype()

{

types * p;

p = typeslist;

while (p) {

if (strlen(p->s)==odew&&

!memcmp(p->s,&inar[pos1],odew)) return p->s;

p = p->next;

}

}

void freevars(int zse){

var *p, *pp;

p = lvars;

while (p) {

pp = p;

p = p->next;

delete pp;

}

lvars = NULL;

if (zse) {

p = vars;

while (p) {

pp = p;

p = p->next;

delete pp;

}

vars = NULL;

}

}

int GetWord()

{

int st = 0;

char c;

odew = 0;

while (odew+pos1<inlen ){

c = inar[pos1+odew];

switch (st){

case 0:

if (c==' ' || c=='\t' || c=='\n') st = 1;

else

if ((c>='A' && c<='Z')||(c>='a' && c<='z')) st = 2;

else

if (c>='0' && c<='9') st = 3;

else

if (

c=='.' || c<=',' || c >=':' || c<=';' ||

c=='+' || c<='-' || c>='*' || c<='/' ||

c=='\''

)

{ odew = 1; return wtype = w_char; }

else { odew = 0; return wtype = w_error; }

break;

case 1:

if (c==' ' || c=='\t' || c=='\n') odew++;

else return wtype = w_space;

break;

case 2:

if (

(c>='A' && c<='Z') ||

(c>='a' && c<='z') ||

(c>='0' && c<='9') ||

c=='_'

) odew++;

else return wtype = w_str;

break;

case 3:

if (c>='0' && c<='9') odew++; else

if (c=='.'&& inar[pos1+odew+1]!='.') {

odew++;

st = 5;

}

else{

wnumf = 0;

return wtype = w_numb;

}

break;

case 5:

if (c>='0' && c<='9') odew++; else {

wnumf = 1;

return wtype = w_numb;

}

}

}

odew = 0;

return 0;

}

void strputter(char * s){

int l = strlen(s);

memcpy(&oarr[pos2],s,l);

pos2 += l;

}

int scmp(char * m, char * s, int n){

int l = strlen(s);

if (n>l) l = n;

return memicmp(m,s,l);

}

void qstr(char c){

oarr[pos2] = c;

pos2++;

}

void copy_w(){

memcpy(&oarr[pos2],&inar[pos1],odew);

pos1 += odew;

pos2 += odew;

}

int wequ(char * s){

return (!scmp(&inar[pos1],s,odew));

}

void lex_skip(){

pos1 += odew;

}

void wstr(char * s){

strncpy(s,&inar[pos1],odew);

}

int lexAnalyser(){

GetWord();

if (wtype==w_space) {

lex_skip();

GetWord();

}

return wtype;

}

void inc_dt()

{

dt += 2;

}

void dec_dt()

{

dt -= 2;

}

void put_dt()

{

for (int i=0; i<dt; i++) qstr(' ');

}

void put_dt11()

{

char s[10];

for (int i=0; i<dt; i++) {

sprintf(s,"%d",i/2);

strputter(s);

}

}

int GetText(char * s1)

{

if ((fkrd = fopen(s1, "rt")) == NULL){

return 0;

}

fseek(fkrd, 0, SEEK_END);

inlen = ftell(fkrd);

fseek(fkrd, 0, SEEK_SET);

if (inlen>buflen) inlen = buflen;

inlen = fread(inar,1,inlen,fkrd);

inar[inlen] = 0;

pos1 = 0;

pos2 = 0;

return 1;

}

int PutText(char * s2)

{

if ((fkod = fopen(s2, "wt")) == NULL){

return 0;

}

fwrite(oarr,pos2,1,fkod);

return 1;

}

void errors1()

{

qstr('\n');

strputter("< Ошибка! > \n");

int k;

while (1){

lexAnalyser();

if (inar[pos1]== ';' || pos1>= inlen) {

copy_w();

break;

};

copy_w();

}

ker++;

}

int fcomm(){

return (inar[pos1]=='{' ||

inar[pos1]=='(' ||inar[pos1+1]=='*');

}

void endcom(){

if (inar[pos1]=='{'){

oarr[pos2] = '/';

oarr[pos2+1] = '*';

pos1++;

pos2 += 2;

while (inar[pos1]!='}' && pos1<inlen) {

if (pos1>=inlen) return;

oarr[pos2] = inar[pos1];

pos1++;

pos2++;

}

oarr[pos2] = '*';

oarr[pos2+1] = '/';

pos1++;

pos2 += 2;

}

else{

oarr[pos2] = '/';

oarr[pos2+1] = '*';

pos1 += 2;

pos2 += 2;

while (!(inar[pos1]=='*' && inar[pos1+1]==')')

&& pos1<inlen) {

if (pos1>=inlen) return;

oarr[pos2] = inar[pos1];

pos1++;

pos2++;

}

oarr[pos2] = '*';

oarr[pos2+1] = '/';

pos1 += 2;

pos2 += 2;

}

qstr('\n');

}

int odw(){

for (int i=0; i<KWn; i++){

if (!scmp(&inar[pos1],KWs[i],odew))

return i+1;

}

return 0;

}

int VarOpq(int svar, int zse){

char s[256];

int sp = 0;

lexAnalyser();

while (1){

if (wtype!=w_str||odw()|| zse>0&&vartype() ) return 0;

addvar(zse);

if (svar) {

s[sp] = '&';

s[sp+1] = ' ';

sp += 2;

}

memcpy(&s[sp],&inar[pos1],odew);

pos1 += odew;

sp += odew;

lexAnalyser();

if (inar[pos1]==','){

s[sp]=',';

pos1++;

sp++;

} else break;

lexAnalyser();

}

if (inar[pos1]==':'){

pos1++;

lexAnalyser();

if ((wtype!=w_str)&&(wtype!=w_char)) return 0;

if (!scmp(&inar[pos1],"boolean",odew)){

heretp(zse,t_Bool);

strputter("int ");

lex_skip();

memcpy(&oarr[pos2],&s[0],sp);

pos2 += sp;

}

else

if (!scmp(&inar[pos1],"integer",odew)){

heretp(zse,t_Int);

strputter("int ");

lex_skip();

memcpy(&oarr[pos2],&s[0],sp);

pos2 += sp;

}

else

if (!scmp(&inar[pos1],usertype(),odew)){

strputter(usertype());

strputter(" ");

lex_skip();

memcpy(&oarr[pos2],&s[0],sp);

pos2 += sp;

}

else

if (!scmp(&inar[pos1],"^",odew)){

lex_skip();

lexAnalyser();

if(u_varsw())

heretp(zse,u_varsw());

else if(wequ("integer"))

heretp(zse,t_Int);

copy_w();

strputter(" * ");

memcpy(&oarr[pos2],&s[0],sp);

pos2 += sp;

}

}

else return 0;

return 1;

}

int fvar(int zse){

pos1 += odew;

lexAnalyser();

do{

koper1++;

if (fcomm()){

endcom();

koper2++;

continue;

}

put_dt();

if (!VarOpq(0,zse)) errors1();

else koper2++;

lexAnalyser();

if (inar[pos1]!=';')

return 0;

lex_skip();

strputter(";\n");

lexAnalyser();

if (wtype!=w_str || odw())

return 1;

}while(1);

}

int evet(){

pos1 += odew;

int k,svar;

lexAnalyser();

do{

k = odw();

svar = k==kw_var;

if (svar) {

lex_skip();

lexAnalyser();

}

if (!VarOpq(svar,0)) return 0;

lexAnalyser();

if (inar[pos1]!=';') return 1;

lex_skip();

strputter(", ");

lexAnalyser();

k= odw();

if (wtype!=w_str || k&&k!=kw_var) return 0;

}while(1);

}

int begprc(int k);

int frecord(){

lex_skip();

strputter("struct ");

lexAnalyser();

if (wtype!=w_str || odw()) return 0;

addnewtype();

copy_w();

lexAnalyser();

if (inar[pos1]!='=') return 0;

lex_skip();

lexAnalyser();

if (!wequ("record")) return 0;

strputter("\n{\n");

inc_dt();

if (!fvar(-1)) return 0;

dec_dt();

lexAnalyser();

if (!wequ("end")) return 0;

lex_skip();

qstr('}');

lexAnalyser();

if (inar[pos1]!=';') return 0;

copy_w();

strputter("\n\n");

pos1 += odew;

return 1;

}

int fif()

{

lex_skip();

put_dt();

strputter("if (");

if (!fle()) return 0;

strputter(")\n");

lexAnalyser();

if(wequ("then")) lex_skip();

else return 0;

return 1;

}

int felse()

{

lex_skip();

put_dt();

strputter(" else\n");

return 1;

}

int fnew()

{

int utype;

lex_skip();

put_dt();

pos1++;

lexAnalyser();

switch(utype=vartype())

{

case t_Int:

copy_w();

strputter(" = new(int);\n");

pos1++;

if (inar[pos1]!=';') return 0;

pos1++;

break;

}

if(utype>=cuservars)

{

copy_w();

strputter(" = new(");

strputter(utname(utype));

strputter(");\n");

pos1++;

if (inar[pos1]!=';') return 0;

pos1++;

}

return 1;

}

int fae() {

lexAnalyser();

if (inar[pos1]=='+'){

copy_w();

}

else

if (inar[pos1]=='-'){

copy_w();

}

while (1){

lexAnalyser();

if (wtype==w_numb) copy_w(); else

if (wtype==w_str&&vartype()==t_Int) copy_w(); else

if (inar[pos1]=='('){

copy_w();

if (!fae()) return 0;

lexAnalyser();

if (inar[pos1]!=')') return 0;

pos1++;

qstr(')');

}

else return 0;

lexAnalyser();

char c = inar[pos1];

if (c=='+'||c=='-'||c=='*'||c=='/') copy_w();

else return 1;

}

}

int ae(){

char c,c1;

if (!fae()) return 0;

lexAnalyser();

c = inar[pos1];

c1 = inar[pos1+1];

if (c=='<'&&c1=='>') {

pos1 += 2;

strputter("!=");

}

else

if (c=='=') {

pos1++;

strputter("==");

}

else

if (c=='>'||c=='<') {

if (c1=='='){

pos1 += 2;

}

else copy_w();

}

lexAnalyser();

if (!fae()) return 0;

return 1;

}

int fle() {

int k;

char c,c1;

int arifm, ip,op;

while (1){

lexAnalyser();

k = odw();

int ip, op;

ip = pos1;

op = pos2;

arifm = 0;

if(inar[pos1]=='+'||

inar[pos1]=='('||

inar[pos1]=='-'||

wtype==w_str&&!odw() ||

wtype==w_numb)

arifm = ae();

if (!arifm){

pos1 = ip;

pos2 = op;

lexAnalyser();

k = odw();

if (wtype==w_str&&k==kw_true){

lex_skip();

qstr('1');

}

else

if (wtype==w_str&&k==kw_false) {

lex_skip();

qstr('0');

}

else

if (wtype==w_str&&vartype()==t_Bool) copy_w(); else

if (inar[pos1]=='('){

copy_w();

if (!fle()) return 0;

lexAnalyser();

if (inar[pos1]!=')') return 0;

pos1++;

qstr(')');

}

else return 0;

}

lexAnalyser();

k = odw();

if (k==kw_or) strputter("||"); else

if (k==kw_and) strputter("&&");

else return 1;

lex_skip();

}

}

int asign(){

int type = vartype();

if (!(type==t_Bool||type==t_Int)) return 0;

put_dt();

copy_w();

lexAnalyser();

if (inar[pos1]!=':'||inar[pos1+1]!='=')

return 0;

qstr('=');

pos1 += 2;

if (type==t_Bool) {

if (!fle()) return 0;

}

else

if (!fae()) return 0;

lexAnalyser();

if (wequ("to")||wequ("downto")) return 1;

if (inar[pos1]!=';') return 0;

copy_w();

qstr('\n');

return 1;

}

int begprc(int zse){

int rep_n = 0;

if(zse!=3) lex_skip();

if (zse==1) strputter("\n\nvoid main()\n");

if ((zse!=2)||(zse!=3)) {

put_dt();

strputter("{\n");

inc_dt();

}

int b;

do{

b = 1;

lexAnalyser();

if (fcomm()){

endcom();

continue;

}

switch(odw()){

case kw_begin:

koper1++;

if (!begprc(0)) return 0;

koper2++;

break;

case kw_if:

koper1++;

if (!fif()) return 0;

break;

case kw_new:

koper1++;

if (!fnew()) return 0;

break;

case kw_else:

koper1++;

if (!felse()) return 0;

break;

case kw_end:

koper1++;

if(zse == 3) return 3;

lex_skip();

dec_dt();

put_dt();

strputter("}\n");

lexAnalyser();

if (zse==1&&inar[pos1]=='.' ||

zse!=1&&inar[pos1]==';'){

lex_skip();

koper2++;

return 1;

}

else

{

lex_skip();

return 0;

}

case 0:

if (!asign()) return 0;

break;

default:

return 0;

}

} while (b);

return 1;

}

int trnslt()

{

int b;

int k;

koper1 = koper2 = 0;

strputter("#include <stdio.h>\n\n");

do{

b = 1;

lexAnalyser();

k = odw();

if (k==kw_var){

koper1++;

if (!fvar(1)) {

errors1();

}

else koper2++; }

else

if (k==kw_type){

koper1++;

if (!frecord()) {

errors1();

}

else koper2++;

}

else

if (k==kw_begin){

if (!begprc(1)) {

errors1();

}

b = 0;

}

else

if (fcomm()) endcom();

else {

koper1++;

errors1();

};

} while (b==1);

if (inar[pos1]!='.') return 0;

pos1++;

return 1;

}

void main()

{

setlocale(LC_ALL,"Russian");

char s[128];

printf("Введите имя файла: ");

scanf("%s",s);

if (!GetText(s))

{

printf("\nВозникла ошибка при открытии файла!");

getch();

return;

}

vars = NULL;

lvars = NULL;

uvars = cuservars;

trnslt();

freevars(1);

printf("\n%d операторов в исходном файле.", koper1);

printf("\n%d операторов было перенесено в новый файл.", koper2);

printf("\n%d операторов не было обработано", ker);

printf("\n\nВведите имя нового файла:");

scanf("%s",s);

if (!PutText(s))

{

printf("\nВозникла ошибка при создании файла!");

getch();

return;

}

printf("\nНовый файл: %s",s);

fclose(fkrd);

fclose(fkod);

while (!kbhit()) ;

}

Распечатка тестов и результатов

Входной файл 3.pas

type

mobile = record

coast:integer;

weight:integer;

end;

var

i,k:integer;

mob:^mobile;

ids:^integer;

begin

k := 6;

i := 3;

if (k>i) then

begin

new(mob);

end;

else

begin

new(ids);

end;

end.

Вид экрана:

Новый файл:

#include <stdio.h>

struct mobile

{

int coast;

int weight;

};

int i,k;

mobile * mob;

integer * ids;

void main()

{

k=6;

i=3;

if ((k>i))

{

mob = new(mobile);

}

else

{

ids = new(int);

}

}

Пример ошибочного ввода:

Пример ошибочного оператора:

type

mobile = record

coast:integer;

weight:integer;

end;

var

i,k:integer;

mob:^mobile;

ids:^integer;

begin

k := 6;

i := 3;

if (k>i) then

begin

new(mob);

end;

else

begin

new(ids);

lg(ids);

end;

end.

Вид экрана:

Новый файл:

#include <stdio.h>

struct mobile

{

int coast;

int weight;

};

int i,k;

mobile * mob;

integer * ids;

void main()

{

k=6;

i=3;

if ((k>i))

{

mob = new(mobile);

}

else

{

ids = new(int);

< Ошибка! >

lg(ids);

Выводы

Таким образом, написан простой транслятор с языка программирования Паскаль на язык программирования Си.

В ходе разработки дипломного проекта, были приобретены необходимые навыки для дальнейшего улучшения и развития программы. Программу можно расширить под обработку всех операторов, а так же добавить этап оптимизации кода, в следствии чего, программа будет больше похожа на компилятор. Но так или иначе работа перевода программ на другой язык программирования будет качественно выполнена лишь человеком. Данная программа лишь облегчает эту работу.

Список литературы

· В., Е. (2006). c++ builder сборник рецептов. Москва: Кудиц-Образ.

· Эккель, Б. (2007). Философия C++. Санк-Петербург: Питер.

· Якушев, Д. (2006). Философия программирования на C++. Москва: Бук-пресс.

Размещено на Allbest.ru


Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.