Транслятор на языке Си для перевода текста программы с языка Паскаль на язык Си (операторы real, case, записи, указатель (на запись))
Министерство
образования и науки Российской Федерации
Федеральное
агентство по образованию
Государственное
образовательное учреждение
высшего
профессионального образования
«Северо-Кавказский
государственный технический университет»
КУРСОВОЙ
ПРОЕКТ
по
дисциплине «Программирование на языке высокого уровня»
Вариант 13
Исполнитель:
Студент: Мишустина Юлия
группа АСОУ-091
Руководитель: Братченко Н.Ю.
Ставрополь
Содержание:
Введение
. Цели и задачи курсового проекта
. Постановка задачи
. Внешняя спецификация
. Описание алгоритма программы
. Описание констант, переменных и функций
программы
. Листинг программы
. Распечатка тестов и результатов
Выводы
Список используемой литературы
Введение
Объектно-ориентированное программирование - это новый способ
подхода к программированию. Такое программирование, взяв лучшие черты
структурного программирования, дополняет его новыми идеями, которые переводят в
новое качество подход к созданию программ.
Концепция объектно-ориентированного программирования подразумевает,
что основой управления процессом реализации программы является передача
сообщений объектам. Поэтому объекты должны определяться совместно с
сообщениями, на которые они должны реагировать при выполнении программы. В этом
состоит главное отличие ООП от процедурного программирования, где отдельно
определённые структуры данных передаются в процедуры (функции) в качестве
параметров. Таким образом, объектно-ориентированная программа состоит из
объектов - отдельных фрагментов кода, обрабатывающего данные, которые
взаимодействуют друг с другом через определённые интерфейсы.
Объектно-ориентированный язык программирования должен
обладать следующими свойствами:
- абстракции - формальное о качествах или
свойствах предмета путем мысленного удаления некоторых частностей или
материальных объектов;
- инкапсуляции - механизма, связывающего
вмести код и данные, которыми он манипулирует, и защищающего их от внешних
помех и некорректного использования;
- наследования - процесса, с помощью
которого один объект приобретает свойства другого, т.е. поддерживается
иерархической классификации;
- полиморфизма - свойства, позволяющего
использовать один и тот же интерфейс для общего класса действий.
Разработка объектно-ориентированных программ состоит из
следующих последовательных работ:
. определение основных объектов, необходимых для
решения данной задачи;
. определение закрытых данных (данных состояния) для
выбранных объектов;
. определение второстепенных объектов и их закрытых
данных;
. определение иерархической системы классов,
представляющих выбранные объекты;
. определение ключевых сообщений, которые должны
обрабатывать объекты каждого класса;
. разработка последовательности выражений, которые
позволяют решить поставленную задачу;
. разработка методов, обрабатывающих каждое сообщение;
. очистка проекта, то есть устранение всех
вспомогательных промежуточных материалов, использовавшихся при проектировании;
. кодирование, отладка, компоновка и тестирование.
Объектно-ориентированное программирование позволяет
программисту моделировать объекты определённой предметной области путем
программирования их содержания и поведения в пределах класса. Конструкция
«класс» обеспечивает механизм инкапсуляции для реализации абстрактных типов
данных. Инкапсуляция как бы скрывает и подробности внутренней реализации типов,
и внешние операции и функции, допустимые для выполнения над объектами этого
типа.
1. Цели и задачи курсового проекта
Цель данной курсовой работы: выработка у студентов
практических навыков по проектированию программ, их отладке и документированию.
Выполнение курсового проекта позволяет студенту закрепить полученные знания по
дисциплине «Программирование на языке высокого уровня». Написание курсового
проекта начинается с разработки технического задания (ТЗ) и завершается составлением
отчета, в котором должно содержаться описание всей работы в целом.
. Постановка задачи
Необходимо написать транслятор на языке Си для перевода
текста программы с языка Паскаль на язык Си. Рассмотреть операторы real, case,
записи, указатель (на запись).
Критерии:
- максимальная устойчивость от ошибок,
- учет некорректность вводимых данных.
- Вывод сведений о трансляции.
- максимальна эффективность
- Программа должна транслировать ранее
набранный текст на языке Паскаль в текст на языке Си. При этом ввод имени файла
производится через программу. При введении неверного имени предоставить
возможность повторного ввода.
В программе нам так же необходимо использовать:
Арифметическое выражение ae2
3. Внешняя спецификация
При запуске программа спросит имя исходного файла (без
расширения), если файл не найден, то запрос будет выполняться до тех пор, пока
не будет введено имя существующего файла или до прекращения работы программы.
Затем программа выполнит запрос об имени выходного файла и при наличии ошибок в
тексте при трансляции выведет на экран номер исходящей строки, где найдена
ошибка и саму ошибку. Далее выводится статистика о трансляции кода на экран.
Для запуска программы достаточно запустить откомпилированный
файл Project.exe.
К аппаратным ограничения можно отнести процессор с частотой
не менее 500 Гц, не менее 32М оперативной памяти.
В консоли после ввода пути и названия файла (разрешение может
быть любым) пользователю будет выведено одно из двух возможных сообщений:
. Об успешности операции.
. Сообщение об ошибке.
В случае номер один запустится специальная подпрограмма
обработки текста.
При случае номер два на экран будет выведено предложение
повторного ввода названия файла.
Сообщение об ошибке для открытия файла:
К сожалению, файл не удалось открыть. Проверьте правильность
имени и попробуйте еще раз.
Сообщение об ошибке для создания файла:
К сожалению, файл не удалось создать, возможно, файл с таким
названием заблокирован. Попробуйте ввести другое имя.
4. Описание алгоритма программы
Исходное текстовое представление программы не очень пригодно
для работы компилятора, поэтому во время анализа программа прежде всего
разбивается на последовательность строк, или, как принято говорить, лексем.
Множество лексем разбивается на непересекающиеся подмножества (лексические
классы). Лексемы попадают в один лексический класс, если они неразличимы с
точки зрения синтаксического анализатора. Например, во время синтаксического
анализа все идентификаторы можно считать. Каждому подмножеству сопоставляется
некоторое число, называемое идентификатором лексического класса (token) или
лексическим классом.
. Описание констант, переменных и функций
программы
Константы
KWs[KWn] это массив ключевых слов, которые
обрабатываются данной программой, их 19: "begin", "end", "var", "real", "boolean", "false", "true", "array", "while", "do", "type", "and", "or", *"case", * "assign", "read","write", "rewrite", "reset";inlen,outlen,inpos;
- текущие позиции (строки входные, выходные, позиция в строке входной);
Переменные
int koper1,koper2,ker - эти переменные считают количество
операторов во входном, выходном файле и кол-во ошибок;wlen; - длина
"слова";wtype; - тип "слова";wnumf; - 0 - целое число, 1 -
дробное;dt; -размер отступа (от начала строки);
Функция memcmp() сравнивает первые count символов массивов,
адресуемых параметрами buf1 и buf2.меньше buf2 = меньше нуля;равен buf2 = 0;
buf1 больше buf2 = больше нуля;
void *memcpy(void *to, const void *from, size_t
count);
Функция memcpy() копирует count символов из массива,
адресуемого параметром from, в массив, адресуемый параметром to. Если заданные
массивы перекрываются, поведение функции memcopy() не определено.
если gl - идентификатор глобальности = 1, то это глобальная
переменнаяиначе локальная есть четыре типа переменных (описаны выше)
конструкцию while можно расшифровать так: пока указатель на структуру p
существует выполнять: если тип переменной -1 то присвоить ей заданный тип и
далее шаг вперед.- длина анализуруемого слова;
*int memicmp (buf1, buf2, cnt);*buf1; первый буфер*buf2; второй буферcnt;
количество символов
Функция memicmp лексикографически сравнивает первые cnt
байтов из buf1 и buf2 вне зависимости от типа регистра, т.е. буквы верхнего и
нижнего регистров считаются эквивалентными. Функция memicmp возвращает
значение, указывающее соотношение buf1 и buf2,
а именно; Величина Значение
меньше 0 buf1 меньше, чем buf2
buf1 идентично buf2
больше 0 buf1 больше, чем buf2*strncpy (char *dst, const char *src, size_t
len);
dst - указатель на буфер назначения.- указатель на исходную
строку.- максимальное количество копируемых символов (см. раздел Безопасность
ниже).
Функция копирует из строки src в буфер dst не более чем len
символов (включая нулевой символ), не гарантируя завершения строки нулевым
символом (если длина строки src больше или равна len). Если длина строки src
меньше len, то буфер добивается до len нулями. Функция возвращает значение
dst.GetWordS() - получение слов, и если тип слова пробелы, запускает процедуру,
пропускающую пробелы;inc_dt() - увеличение отступа;dec_dt() - уменьшение
отступа;
void put_dt() - вывод отступа;GetText(char * s1) - открытие файла;
int PutText(char * s2) - вывод обработанного текста;ErrOp() -
вывод ошибочного оператора;flabel(int gl) - проверка на комментарий;CommEnd() -
проверка на закрытие комментария;fkW() - здесь идет проверка на ключевое слово,
сравниваются полученное нами слово со словом из списка и если да, то
возвращается номер слова в списке проверка на ключевое слово.
int fIntRealBoolAr(int svar, int gl) - обработка переменных после слова var, здесь
идут обращения к тем четырем функциям работающим со списком переменных
обработка описания переменных: x1,..,xn: тип;fvar(int gl) - обработка описания
блока переменных;fvardescr() - обработка блока описания переменных;fwrite(int
ln) - обработка оператора write;fae() - обработка арифметического
выражения;fle() - обработка логического выражения;asign() - проверка на
присваивание;frepeat() - обработка оператора repeat;fwhile() - обработка
оператора while;fbegin(int gl) - обработка блока операторов;Translate() -
главная функция преобразования текста- указатель на буфер назначения.
// src - указатель на исходную строку.
// len - максимальное количество копируемых символов
. Листинг программы
#include <stdafx.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>*file1, *file2;int
buflen = 10000;int KWn = 15;* KWs[KWn] =
{ "begin", "end",
"var", "real",
"boolean", "false",
"true", /* "array", */
"while", "do",
"type", "and",
"or", /*"case", */
"assign", /* "read",*/
"write", "rewrite",
/*"reset"*/};
#define kw_begin 1
#define kw_end 2
#define kw_var 3
#define kw_real 4
#define kw_boolean 5
#define kw_false 6
#define kw_true 7
/*#define kw_array 8*/
#define kw_while 8
#define kw_do 9
#define kw_type 10
#define kw_and 11
#define kw_or 12
/*#define kw_case 14*/
#define kw_assign 13
/*#define kw_read 16*/
#define kw_write 14
#define kw_rewrite 15
/*#define kw_reset 19*/
#define t_Int 1 //целый
/*#define t_Real 2 //дробный*/
#define t_Bool 2 //логический
/*#define t_Array 4 //массив*/
#define t_File 3int cuservars = 6;uvars;
#define w_error 0 //ошибка
#define w_space 1 //пробелы
#define w_str 2 //строка
#define w_numb 3 //число
#define w_char 4 //символ (разделитель, ...)
char
instr[buflen],[buflen];inlen,outlen,inpos;koper1,koper2,ker;wlen; //длина "слова"wtype;
//тип "слова"
int wnumf; //0 - целое число, 1 - дробноеdt; //
typedef struct var{s[64];tp;* next; };struct
types{s[64];tid;* next;};*vars, *lvars;* typeslist;fle();addvar(int gl){*np,
*p;(gl) p = vars; else p = lvars;
// int memcmp(const void *buf1, const void *buf2,
size_t count);(p) {(strlen(p->s)==wlen&&
!memcmp(p->s,&instr[inpos],wlen)) return
0;= p->next; }= new var;
} else {>next = lvars;= np; }1;}addnewtype()
{types *head=typeslist, *ntype;(head)
{(strlen(head->s)==wlen&&
!memcmp(head->s,&instr[inpos],wlen))
return 0;= head->next;}= new
types;(ntype->s,&instr[inpos],wlen);>s[wlen]=0;>tid =
uvars;++;>next = typeslist;= ntype;1;}settype(int gl, int type){*p;(gl) p =
vars; else p = lvars;(p) {(p->tp==-1) p->tp = type;= p->next;}}vartype(){*
p;= lvars;(p) {(strlen(p->s)==wlen&&= p->next; }= vars;(p)
{(strlen(p->s)==wlen&&
!memcmp(p->s,&instr[inpos],wlen)) return
p->tp;= p->next;}0;}* usertype()
{ types * p;
// обработка локальных переменных= typeslist;
while (p) {(strlen(p->s)==wlen&&
!memcmp(p->s,&instr[inpos],wlen)) return
p->s;= p->next;}"0";}freevars(int gl){*p, *pp;= lvars;(p) {=
p;= p->next;pp; }= NULL;(gl) {= vars;(p) {= p;= p->next;pp; }=
NULL;}}GetWord()
{st = 0;c;= 0;(wlen+inpos<inlen ){=
instr[inpos+wlen];(st){ case 0:(c==' ' || c=='\t' || c=='\n') st =
1;((c>='A' && c<='Z')||(c>='a' && c<='z')) st =
2;(c>='0' && c<='9') st = 3;(=='.' || c<=',' || c >=':' ||
c<=';' ||=='+' || c<='-' || c>='*' || c<='/' ||=='\'' )
{ wlen = 1; return wtype = w_char; }{ wlen = 0;
return wtype = w_error; };1:(c==' ' || c=='\t' || c=='\n') wlen++;return wtype
= w_space;;2:
((c>='A' && c<='Z') ||
(c>='a' && c<='z') ||
(c>='0' && c<='9') ||=='_' )
wlen++;return wtype = w_str;;3:(c>='0' && c<='9') wlen++;
else(c=='.'&& instr[inpos+wlen+1]!='.') { //++;= 5;}{= 0;wtype =
w_numb; };5:(c>='0' && c<='9') wlen++; else {= 1;wtype = w_numb;}
}}= 0;0;}put_str(char * s){l = strlen(s);(&outstr[outlen],s,l);+=
l;}scmp(char * m, char * s, int n){l = strlen(s);(n>l) l = n;
/*int memicmp (buf1, buf2,
cnt);memicmp(m,s,l);}put_char(char c){[outlen] =
c;++;}wcopy(){(&outstr[outlen],&instr[inpos],wlen);+= wlen;+=
wlen;}wequ(char * s){(!scmp(&instr[inpos],s,wlen));}wskip(){+=
wlen;}wstr(char * s){
// char *strncpy (char *dst, const char *src,
size_t len);(s,&instr[inpos],wlen);}GetWordS(){();(wtype==w_space)
{();();}wtype;}inc_dt()
{+= 2;}dec_dt()
{ dt -= 2;}put_dt()
{(int i=0; i<dt; i++) put_char('
');}put_dt11()
{s[10];(int i=0; i<dt; i++)
{(s,"%d",i/2);_str(s); }
}GetText(char * s1)
{((file1 = fopen(s1, "rt")) ==
NULL){0;}(file1, 0, SEEK_END);= ftell(file1);(file1, 0,
SEEK_SET);(inlen>buflen) inlen = buflen;= fread(instr,1,inlen,file1);[inlen]
= 0;= 0;= 0;1;}PutText(char * s2)
{((file2 = fopen(s2, "wt")) == NULL){0;
}(outstr,outlen,1,file2);1;}ErrOp()
{_char('\n');_str("< Ошибка! >
\n");k;(1){();(instr[inpos]== ';' || inpos>= inlen) {();;};();}++;
}flabel(int gl);
//проверка на комментарий
int IsComment(){
return (instr[inpos]=='{' ||[inpos]=='('
||instr[inpos+1]=='*');}CommEnd(){(instr[inpos]=='{'){[outlen] = '/';[outlen+1]
= '*';++;+= 2;(instr[inpos]!='}' && inpos<inlen) {(inpos>=inlen)
return;[outlen] = instr[inpos];++;++;}[outlen] = '*';[outlen+1] = '/';++;+=
2;}{[outlen] = '/';[outlen+1] = '*';+= 2;+= 2;(!(instr[inpos]=='*' &&
instr[inpos+1]==')')
&& inpos<inlen) {(inpos>=inlen)
return;[outlen] = instr[inpos];++;++;}[outlen] = '*';[outlen+1] = '/';+= 2;+=
2; }_char('\n');}fkW(){(int i=0; i<KWn; i++){// просмотр всего массива
KWn(!scmp(&instr[inpos],KWs[i],wlen))i+1;}0;}fIntRealBoolAr(int svar, int
gl){s[256];label;sp = 0;();(1){(wtype!=w_str||fkW()||
gl>0&&vartype() ) return 0;(gl);(svar) {[sp] = '&';[sp+1] = '
';+= 2;}(&s[sp],&instr[inpos],wlen);+= wlen;+=
wlen;();(instr[inpos]==','){[sp]=',';++;++;
} else break;();
} // while(1)(instr[inpos]==':'){ //тип переменных++;();(wtype!=w_str)
return 0;(!scmp(&instr[inpos],"boolean",wlen)){(gl,t_Bool);_str("int
");();(&outstr[outlen],&s[0],sp);+= sp;}
/*if
(!scmp(&instr[inpos],"real",wlen)){(gl,t_Real);_str("float
");();(&outstr[outlen],&s[0],sp);+=
sp;}*/(!scmp(&instr[inpos],"integer",wlen)){(gl,t_Int);_str("int
");();(&outstr[outlen],&s[0],sp);+=
sp;}(!scmp(&instr[inpos],usertype(),wlen)){_str(usertype());_str("
");();(&outstr[outlen],&s[0],sp);+= sp;}
/* if
(!scmp(&instr[inpos],"array",wlen)){();(gl,t_Array);();(instr[inpos]!='[')
return 0;[sp]='[';++;++;(1) {();(instr[inpos]!='1') return
0;();();(instr[inpos]!='.'||instr[inpos+1]!='.')0;+= 2;();(wtype!=w_numb)
return 0;(&s[sp],&instr[inpos],wlen);+= wlen;+=
wlen;();(instr[inpos]==']'){[sp]=']';++;++;;}
(instr[inpos]==','){++;[sp]=']';++;[sp]='[';++;}
}();(wtype!=w_str) return 0;(scmp(&instr[inpos],"of",wlen))
return 0;();();(wtype!=w_str) return
0;(scmp(&instr[inpos],"real",wlen)) return 0;();_str("float
");(&outstr[outlen],&s[0],sp);+= sp;
}*/(wequ("file"))
{();();(!wequ("of")) return
0;();();_str("FILE *");(&outstr[outlen],&s[0],sp);+=
sp;();(gl,t_File);}
}return 0;1;}fvar(int gl){+=
wlen;();{++;(IsComment()){ //комментарии();++;;}_dt();(!fIntRealBoolAr(0,gl))
ErrOp();koper2++;();(instr[inpos]!=';')0;();_str(";\n");();(wtype!=w_str
|| fkW())1;
}while(1);
}
fvardescr(){+= wlen;k,svar;();{= fkW();=
k==kw_var;(svar) {();();}(!fIntRealBoolAr(svar,0)) return
0;();(instr[inpos]!=';') return 1;();_str(", ");();=
fkW();(wtype!=w_str || k&&k!=kw_var) return 0;
}while(1);}fbegin(int k);();_str("\nvoid
");();(wtype!=w_str||vartype()) return 0;(1);(1,10);();
();(instr[inpos]!='(') return
0;_char('(');(!fvardescr()) return 0;();(instr[inpos]!=')') return
0;();();(instr[inpos]!=';') return 0;();_str("\n{\n");_dt();
//тело процедурыb;
do{= 1;();(!scmp(&instr[inpos],"var",wlen)){++;(!fvar(0))
return 0; }(!scmp(&instr[inpos],"begin",wlen)){(!fbegin(2))
return 0;= 0; }(IsComment()) CommEnd();return 0;
} while (b==1);
(0);++;1;}frecord(){();_str("struct
");();(wtype!=w_str || fkW()) return 0;();();();(instr[inpos]!='=') return
0;();();(!wequ("record")) return
0;_str("\n{\n");_dt();(!fvar(-1)) return
0;_dt();();(!wequ("end")) return
0;();_char('}');();(instr[inpos]!=';') return 0;();_str("\n\n");
+= wlen;1;}fgoto()
{();_dt();_str("goto ");();();(instr[inpos]!=';')
return 0;_str(";\n");++;
//put_str("\n");1;}fcase()
{beg;();_dt();_str("switch");_str("(");();();_str("){\n");();(!wequ("of"))
return 0;();(1)
{();(wequ("end"))
{();++;_dt();_dt();_str("}\n");;}_dt();_str("case
");((wtype!=w_str)&&(wtype!=w_numb)&&(wtype!=w_char))
return 0;(instr[inpos]=='\'') {wskip();
put_str("\'");}();();(instr[inpos]=='\'') {wskip();
put_str("\'");}();(instr[inpos]!=':') return 0;();();= 0; // по умолчанию ожидаем case 1:
blabla;(wequ("begin")) {wskip(); beg = 1;};_str("\n");_dt();
fbegin(3); // 3 - означает обработку case_dt();
if (wequ("end")&&beg)
{put_dt();_str("break;\n");();(instr[inpos]==';')
inpos++;
} else { put_dt();
put_str("break;\n");}}1;}frewrite()
{();(instr[inpos]!='(') return
0;++;_dt();_str("fcreate(");();(vartype()!=t_File) return
0;();(instr[inpos]!=')') return 0;++;_str(")");(instr[inpos]!=';')
return 0;++;_str(";\n");1;}
/*int freset()
{();(instr[inpos]!='(') return
0;++;();();(instr[inpos]!=')') return 0;++;(instr[inpos]!=';') return
0;++;1;}fassign()
{t;();(instr[inpos]!='(') return 0;++;();(t =
vartype())
{(t==t_File)
{_dt();();_str(" =
fopen(\"");(instr[inpos]!=',') return 0;+=2;
(instr[inpos]!= '\'')
{[outlen] =
instr[inpos];++;++;}++;_str("\"");_str(",\"w\"");();(instr[inpos]!=')')
return 0;++;_str(")");(instr[inpos]!=';') return
0;++;_str(";\n");1;} }1;}
/*int fif()
{();_dt();_str("if (");(!fle()) return
0;_str(")\n");();(wequ("then")) wskip();return 0;1;}felse()
{();_dt();_str(" else\n");1;}*/
/*int fnew()
{();_dt();++;();(vartype())
{t_Int:();_str(" =
new(int);\n");++;(instr[inpos]!=';') return 0;++;;t_Real:();_str(" =
new(float);\n");++;(instr[inpos]!=';') return 0;++;;: return 0;}1;
}*/
/*int fdispose()
{();_dt();(instr[inpos]!='(') return
0;_str("delete ");++;();();(instr[inpos]!=')') return 0;_str(";\n");++;(instr[inpos]!=';')
return 0;++;1;}*/
{(t==t_File)
{_str("fscanf(");();(instr[inpos]!=',')
return 0;++;_str(",");(instr[inpos]!= ')')
{[outlen] = instr[inpos];++;++;
}();(instr[inpos]!=')') return
0;++;_str(")");(instr[inpos]!=';') return
0;++;_str(";\n");1;}}_str("scanf");_str("(\"");=0;(1)
{();(wtype!=w_str) return 0;= vartype();(t==t_Int) put_str("%d");if
(t==t_Real) put_str("%f");return 0;[sp] = '&';+=
wlen;();(&s[sp],&instr[inpos],wlen);+= wlen;+=
wlen;();(instr[inpos]!=',') break;[sp] = instr[inpos];++;++;
}_str("\",");(&outstr[outlen],s,sp);+=
sp;();(instr[inpos]!=')') return 0;++;_char(')');();(instr[inpos]!=';') return
0;++;(ln) put_str("; printf(\"\\n\");\n");put_str(";\n");1;
}*/fwrite(int
ln){s[256];sp;t;();_dt();();(instr[inpos]!='(') return 0;++;
/* Обработка файла */();(t = vartype())
{(t==t_File)
{_str("fprintf(");();(instr[inpos]!=',')
return 0;+=2;_str(",\"");(instr[inpos]!= '\'')
{[outlen] = instr[inpos];++;++;
}++;_str("\"");();(instr[inpos]!=')')
return 0;++;_str(")");(instr[inpos]!=';') return
0;++;_str(";\n");1;}_str("printf");_char('(');();(instr[inpos]!='\'')
return 0;_char('"');++;(instr[inpos]!= '\'') {[outlen] = instr[inpos];++;++;}++;(instr[inpos]==')')
{(ln)
put_str("\\n");_char(')');++;(instr[inpos]!=';') return
0;++;_str(";\n");1;}(instr[inpos]!=',') return 0;++;=0;(1)
{();(wtype!=w_str) return 0;= vartype();(t==t_Int) put_str("%d");
/*else if (t==t_Real) put_str("%f");*/return
0;(&s[sp],&instr[inpos],wlen);+= wlen;+= wlen;();(instr[inpos]!=',')
break;[sp] = instr[inpos];++;++;}(ln)
put_str("\\n");_char('"');();_str("\,");(&outstr[outlen],s,sp);+=
sp;();(instr[inpos]!=')') return 0;++;_char(')');();(instr[inpos]!=';') return
0;++;_str(";\n");1;}fae() {();(instr[inpos]=='+'){();
}(instr[inpos]=='-'){();}(1){();(wtype==w_numb) wcopy();
else(wtype==w_str&&vartype()==t_Int) wcopy();
/*else(wtype==w_str&&vartype()==t_Real) wcopy(); else(wtype==w_str&&vartype()==t_Array)
{();();(instr[inpos]=='['){();(1) {(!fae()) return
0;_str("-1");();(instr[inpos]==']'){();;
}(instr[inpos]==','){();_str("]["); } }
}
} else(instr[inpos]=='('){();(!fae()) return
0;();(instr[inpos]!=')') return 0;++;_char(')');
}*/return 0;();c = instr[inpos];(c=='+'||c=='-'||c=='*'||c=='/')
wcopy();return 1;}
}ae(){c,c1;(!fae()) return 0;();= instr[inpos];=
instr[inpos+1];(c=='<'&&c1=='>') {+= 2;_str("!=");
}(c=='=')
{++;_str("==");}(c=='>'||c=='<') {(c1=='='){+= 2;
}wcopy();}();(!fae()) return 0;1;
}fle() {k;c,c1;arifm, ip,op;(1){();= fkW();ip,
op;= inpos;= outlen;=
0;(instr[inpos]=='+'||[inpos]=='('||[inpos]=='-'||==w_str&&!fkW()
||==w_numb)= ae();(!arifm){= ip;= op;();=
fkW();(wtype==w_str&&k==kw_true){();_char('1');}(wtype==w_str&&k==kw_false)
{();_char('0');}(wtype==w_str&&vartype()==t_Bool) wcopy();
else(instr[inpos]=='('){();(!fle()) return 0;();(instr[inpos]!=')') return
0;++;_char(')');}return 0; }();= fkW();(k==kw_or) put_str("||");
else(k==kw_and) put_str("&&");return 1;();}}asign(){type =
vartype();(!(type==t_Bool||/*type==t_Real||*/type==t_Int)) return 0;
//put_char('\n');_dt();();();(instr[inpos]!=':'||instr[inpos+1]!='=')0;_char('=');+=
2;(type==t_Bool) {(!fle()) return 0; }(!fae()) return 0;();(instr[inpos]!=';')
return 0;();_char('\n');1;}
/*int frepeat() {();_dt();_str("do
{\n");_dt();1;}funtil() {();_dt();_dt();_str("} while
(");(!fle()) return 0;_char(')');();(instr[inpos]!=';') return
0;++;_str(";\n");1;}*/fwhile() {();_dt();_str("while
(");(!fle()) return 0;();(wtype!=w_str||fkW()!=kw_do) return 0;();_str(")\n");1;}fbegin(int
gl){rep_n = 0;(gl!=3) wskip();(gl==1) put_str("\n\nvoid
main()\n");((gl!=2)||(gl!=3)) {_dt();_str("{\n");_dt(); }b;{=
1;();(IsComment()){();; }(fkW()){kw_begin:++;(!fbegin(0)) return 0;++;;
/*case kw_case:++;(!fcase()) return 0;;*/
/*case kw_read:++;(!fread(0)) return
0;++;;*/kw_write:++;(!fwrite(0)) return 0;++;;kw_rewrite:++;(!frewrite())
return 0;++;;
/*case kw_reset:++;(!freset()) return
0;++;;*/kw_assign:++;(!fassign()) return 0;++;;kw_while:++;(!fwhile()) return
0;++;;kw_end:++;(gl == 3) return
3;();_dt();_dt();_str("}\n");();(gl==1&&instr[inpos]=='.'
||!=1&&instr[inpos]==';'){();++;1;}
{();0;}0:(!asign()) return 0; //присваивание;:0; }
} while (b);1;}Translate()
{b;k;= koper2 = 0;_str("#include
<stdio.h>\n\n"); //для scanf и printf
do{= 1;();= fkW(); //проверка на ключевое слово(k==kw_var){
//начало блока переменных
koper1++;(!fvar(1)) {();}koper2++; }(k==kw_type){
koper1++;(!frecord()) {(); }koper2++;}(k==kw_begin){(!fbegin(1)) {();}=
0;}(IsComment()) CommEnd(); //комментарии{++;(); };
} while (b==1);
if (instr[inpos]!='.') return 0; //точка в конце программы
inpos++;1;}main()
{(LC_ALL,"Russian");
char s[128];("Введите имя входного файла: ");
scanf("%s",s);(!GetText(s))
{("\nОшибка открытия файла!"); }= NULL;= NULL;= cuservars;();
freevars(1);("\nВведите имя выходного файла:");
scanf("%s",s);(!PutText(s))
{("\nОшибка создания файла!"); }("\nКоличество
операторов"
" в исходном файле: %d",
koper1);("\nКоличество операторов"
" в полученном файле: %d", koper2);("\nКоличество
ошибочных операторов"
" которые не были обработаны: %d",
ker);("\n\nРезультат хранится в файле: %s",s);
fclose(file1);(file2);(!kbhit()) ;
}
7. Распечатка тестов и результатов
Для начала проверим программу на правильную обработку
ошибочного ввода входного файла, для этого введем имя несуществующего файла:
программа алгоритм объектный ориентированный константа
Рисунок 7.1 - Вид экрана при вводе имени несуществующего
файла
Рисунок 7.2 - Вид экрана при обработке файла firstfile
Рисунок 7.3 - Экран программы при обработке программы secondfile
Комментарий к полученным результатам:
Для исходного текста, в котором были записаны только
определенные по заданию операторы, трансляция прошла успешно. При добавлении
ошибочного оператора, трансляция выполнялась только до момента нахождения этой
ошибки.
Выводы
Мы приобрели навыки написания однопроходных трансляторов, в
данном задании нам требовалось создать довольно простой транслятор, однако на
этом примере были видны все фазы обработки файла исходного текста программы. Мы
так же изучили основные виды синтаксических анализаторов и способы их
применения, а так же узнали принципы работы таких программ. Обладая знаниями
языка ассемблер уже можно попробовать написать свой компилятор. Однако
некоторые тонкости построения компиляторов были упущены, что бы упростить
программу. Сегодня любой компилятор это сложная программа, заточенная обычно
под определенный язык, осуществляющая не только анализ и транслирование текста
в машинные коды, но так же и оптимизацию.
Литература:
1.
Дискретная
математика, конспект лекций. В.Г. Засовенко. Запорожье, 1998 г.
2.
Начальный
курс С и С++. Б.И. Березин. Москва: "ДИАЛОГ-МИФИ", 1999 г.
3.
Язык
программирования С++. Б. Страуструп. Киев:"ДиаСофт", 1993г.
4.
А.
Ахо, Р.С. (2001). Компиляторы: принципы, технологии и инструменты. Москва:
Вильямс.