Синтаксический и лексический анализатор
Составление транслятора на языке С для перевода кода программы из языка Pascal в код программы на языке Cи. Распознавание и перевод конструкций: for, type, function, integer. Вешняя спецификация, описание, структура, текст программы; распечатка текстов.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 24.06.2011 |
Размер файла | 287,8 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Oглaвлeниe
- Введение
- 1. Постановка задачи
- 2. Внешняя спецификация
- 3. Описание программы
- 4. Структура программы
- 5. Текст программы
- 6. Распечатка текстов и результатов
- Выводы
- Список литературы
Ввeдeниe
Синтаксический и лексический анализ - это одни из самых широко используемых инструментов в информационных технологиях. От компиляторов, что позволили говорить с компьютером “на человеческом языке”, до современных переводчиков и, даже, спеллчекеров, встроенных повсеместно - в браузерах, текстовых редакторах, клиентах передачи сообщений. Анализ синтаксиса формальных языков программирования (таких как Pascal или Си) представляется наиболее простым в силу строгости описания. Несмотря на это, процедура анализа текста в обоих случаях проходит похожим образом. Сначала следует лексический анализ, и текст разбирается на лексемы, которые так же могут называться токенами. Затем следует фаза синтаксического анализа, используя специальные таблицы соответствий операторов, программа распознает код. В данном курсовом проекте, мы создадим упрощенную программу, работающую в двух данных фазах. Программа будет переводить некоторые операторы языка Pascal на код на языке Си.
1. Постановка задачи
В этом курсовом проекте необходимо написать транслятор на языке С для перевода кода программы из языка Pascal в код программы на языке Cи
В соответствии с вариантом №10, требуется, что бы транслятор распознавал и переводил следующие конструкции:
- for
- type
- function
- integer
А так же обрабатывал арифметическое и логическое выражение
(рис. 1.1 и рис.1.2).
Программа так же обрабатывает комментарии, объявление переменных и операции присваивания, а при встрече незнакомых конструкций выдавать сообщение об ошибке. Между лексемами может быть любое количество пробелов или знаков табуляции, переводов строк и т.д. При формировании можно не учитывать правила отступа, но для реализации более удобно читаемых программ этот пункт желателен.
Программа предоставляет пользователю выбрать входной файл и путь, по которому будет записан выходной файл. При этом должна быть предусмотрена обработка ошибок ввода и запрос о повторном вводе пути файла.
2. Внешняя спецификация
Тeхничeскoe зaдaниe дoлжнo сoдepжaть слeдующиe paздeлы:
- нaзнaчeниe пpoгpaммы;
- тpeбoвaния к пpoгpaммe;
- тpeбoвaния к пpoгpaммнoй дoкумeнтaции;
- стaдии и этaпы paзpaбoтки.
Арифметическое выражение Ae1:
Рисунок 1.1 - Разбор арифметического выражения
Логическое выражение Le2:
Рисунок 1.2 - Разбор логического выражения
Нaзнaчeниe пpoгpaммы - укaзывaeтся, для peшeния кaкoй зaдaчи paзpaбaтывaeтся пpoгpaммa.
Тpeбoвaния к пpoгpaммe- дoлжны быть слeдующиe пoдpaздeлы:
- «тpeбoвaния к функциoнaльным хapaктepистикaм» - пepeчисляются всe функции, кoтopыe выполняет пpoгpaммa.
- «тpeбoвaния к нaдeжнoсти» - укaзывaются тpeбoвaния к oбeспeчeнию нaдeжнoгo работоспособности.
- «тpeбoвaния к сoстaву тeхничeских сpeдств» - здeсь укaзывaeтся сoстaв тeхничeских сpeдств: тип ЭВМ, кoмплeкт внeшних устpoйств, и т. п.;
- «тpeбoвaния к инфopмaциoннoй и пpoгpaммнoй сoвмeстимoсти» - этo тpeбoвaния к инфopмaциoнным стpуктуpaм нa вхoдe и выхoдe, мeтoдaм peшeния, ЯП, oпepaциoнным систeмaм и дpугим пpoгpaммным сpeдствaм, кoтopыми будeт пользоваться дaннaя пpoгpaммa. В куpсoвoм пpoeктe paзpaбaтывaeтся пpoгpaммa нa языкe Си.
Тpeбoвaния к пpoгpaммнoй дoкумeнтaции укaзывaются пpoгpaммныe дoкумeнты, кoтopыe слeдуeт paзpaбoтaть.
Стaдии и этaпы paзpaбoтки устaнaвливaются стaдии paзpaбoтки, этaпы и сoдepжaниe paбoт.
Внешняя спецификация
Полное название программы: Мини-транслятор с языка Pascal на Cи.
Вхoд
Исхoдныйфтeкст пpoгpaммы пишется заранее с пoмoщью тeкстoвoгo peдaктopa и сохpaняется в тeкстoвoм фaйлe, имя кoтopoгo ввoдится в oтвeт нa зaпpoс пpoгpaммы:
В качестве входного файла в данном курсовом проекте используется файл с кодом на языке Pascal: <infileislam.pas>.
Выхoд
Выхoднoйфтeкст создается кoнвepтopoм и хранится в тeкстoвoм фaйлe, имя кoтopoгo ввoдится в oтвeт нa зaпpoс пpoгpaммы:
Выходной файл имеет имя <outfileislam.c>;
В консоли после ввода пути и названия файла, пользователю будет выведено одно из двух возможных сообщений:
- об успешности операции.
- сообщение об ошибке.
При успешной операции, запустится специальная подпрограмма обработки текста.
При ошибке, на экран будет выведено предложение повторного ввода названия файла.
Похожая реакция программы должна быть предусмотрена и для исходящего файла. Таким образом, при невозможности создания файла на экран поступит сообщение об ошибке. И что бы не потерять обработанную информацию, весь текст транслируемой программы должен храниться в оперативной памяти компьютера. В результате, можно предусмотреть множественный запрос имени выходного файла, без нанесения вреда данным.
3. Oписaниe aлгopитмa
Точного определения алгоритма не существует, так же, как не существует определения информации, множества и т.д. Однако можно дать достаточно полное представление о таком понятии как алгоритм.
Под алгоритмом понимают совокупность точных и однозначных инструкций для некоторого исполнителя данного алгоритма, предназначенных для решения какой-либо задачи (достижения какой-либо цели). При этом предполагается выполнение следующих свойств:
1. Дискретность - команды, инструкции алгоритма представляют собой разделимую последовательность действий.
2. Конечность - число шагов алгоритма должно быть конечно.
3. Определенность (однозначность, детерминированность) - каждая команда алгоритма должна быть однозначно воспринята исполнителем.
4. Массовость - алгоритм предназначен для решения множества задач заданного вида.
5. Эффективности - интерес представляют в первую очередь такие алгоритмы, которые решают поставленную задачу в пределах допустимого времени с желательно меньшим расходом ресурсов исполнителя.
Способы представления алгоритмов
Любое представление алгоритма является некоторым информационным блоком, то есть представление алгоритма является информацией, и она расположена на некотором носителе информации.
Представление алгоритма можно понимать как отображение множества алгоритмов для фиксированного исполнителя во множество некоторых данных, например, символов или рисунков.
Существует три основных способа представления алгоритмов:
1) графический;
2) неформальная языковая (алгоритмическая) нотация (запись);
3) запись на алгоритмическом языке.
Любая форма записи (представления) алгоритма должна обеспечивать свойства алгоритма: дискретности, конечности, определенности, массовости.
В графической форме алгоритм представлен в виде геометрических фигур. Обычно они связываются линиями, которые показывают направление передачи информации при исполнении алгоритма. Существует несколько вариантов графического представления алгоритмов, но широкую известность получило (и стало фактическим стандартом графического представления) представление в виде блок-схем.
Алгоритм может быть представлен в виде записей литературного языка, например, русского. В этом случае последовательностью предложений описывается последовательность действий исполнителя, которым может быть в большинстве случаев только человек. Никаких специальных правил и требований к таким записям алгоритмов не предъявляется. Главное, что бы выполнялись требования, предъявляемые к алгоритмам.
Третий способ представления алгоритмов - это способ записи алгоритмов с использованием алгоритмических языков, либо языков программирования. Алгоритмический язык - это система правил и обозначений для точной и однозначной записи алгоритмов. Такая запись является формализованной. Это означает, что запись подчиняется строгим требованиям синтаксиса языка.
Алгоритм трансляции в данной программе заключается в следующем, весь входной файл представляется в виде одной символьной строки размером константы lenprog=10000. После чего вводится массив ключевых слов, которые программа и будет распознавать. Каждому из этих слов пишется подпрограмма, которая заменяет эти слова аналогичными в языке C. Помимо этого считается количество операторов в входном файле - koper1, и в выходном - koper2, и ошибочные - ker. Помимо этого программа переводит комментарии Begin, End, var, оператор присваивания.
Для реализации транслирования создаются переменные, которые помогают выполнять наиболее частые операции, типа: пропуск пробела, копирование символа, постановка или удаление отступа, добавление нового символа или целой фразы.
Программа распознает несколько типов данных, integer, Boolean и real. Что позволяет выводить в результате программы почти скомпилированный код.
Обобщенный алгоритм конвертора
Анализ текста программы можно разделить на два хода. Первым ходом будет являться анализ отдельных символов, а вторым сопоставление с правилами обработки этих символов. Для этого существует специальная функция, которая перемещает указатель на начало слова (это так же могут быть символы и любые другие текстовые конструкции) и возвращает тип этого слова. В зависимости от типа слова программа переходит к выбору действий. К примеру, при встрече слова var, программа запускает специальную функцию анализа переменных.
Все переменные заносятся в динамический список в памяти, и затем используются в главной программе в качестве проверки правильности введенных арифметических и логических выражений. При анализе блока переменных, так же используется подфункция обработки типов. К примеру когда программа встречает ключевое слово integer в выходной буфер она записывает int и далее выводит созданный ранее список переменных. Примерно то же самое происходит, если программа встречает ключевое слово type, но в данном случае создается еще одна динамическая конструкция (стэк) в которую помещаются все пользовательские типы. Динамически создается и таблица идентификаторов этих типов и правила обработки этих типов при объявлении. Таким образом, основная программа обработки представляет собой цикл обрабатывающие различные разделы программы - function, var, type и главную программу. Внутри каждой подпрограммы существуют специальные функции обработки конструкций языка.
Таким образом повышается строгость проверки синтаксиса, ведь даже верно описанные синтаксические конструкции языка Pascal в неверном разделе будут обработаны программой как ошибки.
4. Структура программы
Назначение подпрограмм:
Errore_oper - Подпрограмма обработки ошибок, определяет места ошибки и заносит данные о количестве ошибок в специальную переменную.
find_Comment - Находит в коде транслируемой программы комментарии
ReadWord - Подпрограмма анализа текста на наличие токенов. Определяет тип токена и делает его проверку. Возвращает позицию начала, количество символов в токене, а так же его тип. Заодно пропускает пробелы.
isBegin - Подпрограмма обработки блока операторов, запускается после того как во входном файле встречено слово begin.
isVarBlock - Подпрограмма обработки блока переменных - var. Проверяет конструкции на их тип: обычные переменные или метка. После чего передает поток управления в ту или иную функцию.
fin_comment - Подпрограмма обработки окончания комментария.
ReadWords - Подпрограмма посимвольно просматривает файл и определяет к чему можно отнести данный символ.
Assign_a_var - Подпрограмма обработки операции присваивания. Замещает:= на = также проверяет соответствие переменных в выражении с объявленными ранее переменными.
funcfunction - подпрограмма обработки конструкции function в тексте.
funcelse - подпрограмма оставляющая оперaтор else.
funcif - подпрограмма обрабатывающая оператор if.
funcrecord - Подпрограмма обрабатывает блок после слова type, в котором, в соответствии со спецификой нашей программы, могут быть только конструкция record или ошибочные операторы.
isKeyWord - Подпрограмма обрабатывает массив с ключевыми словами, проверяет на наличие данного слова и возвращает его номер, если слово было найдено. Если же слово незнакомо, то подпрограмма возвращает 0, что означает что встреченное слово не является ключевым словом.
funcread - подпрограмма распознающая конструкцию read и заменяющая ее на scanf.
funcbegin - подпрограмма находит операторы Begin и End и заменяет их на фигурные скобки, она включает все функции по обработке текста.
Описание констант
Key_Words_num - число, обозначающее размер словаря ключевых слов. В нашей программе оно равно 16. Это такие слова как: "true", "var", "real", "boolean", "false", "type","record", "and", "or", "repeat", "do", “until”, "begin", "end", “procedure”, “read”
lenprog - Данная константа необходима, так как мы представляем всю программу в виде одной строки, поэтому она является ограничителем работы программы.
Таблицы идентификаций:
Таблица 4.1
Таблица номеров идентификации для ключевых слов
Ключевое слово |
Идентификационный номер |
|
KeyW_begin |
1 |
|
KeyW _end |
2 |
|
KeyW _var |
3 |
|
KeyW _real |
4 |
|
KeyW _boolean |
5 |
|
KeyW _false |
6 |
|
KeyW _true |
7 |
|
KeyW _do |
8 |
|
KeyW _else |
9 |
|
KeyW _for |
10 |
|
KeyW _function |
11 |
|
KeyW _type |
12 |
|
KeyW _record |
13 |
|
KeyW _and |
14 |
|
KeyW _or |
15 |
|
KeyW _read |
16 |
Таблица 4.2
Таблица идентификаторов типов переменных
Тип |
Идентификационный номер |
|
IntType |
1 |
|
RealType |
2 |
|
BoolType |
3 |
|
ArrayType |
4 |
транслятор pascal спецификация текст
Таблица 4.3
Таблица типов слов
Тип слова |
Идентификационный номер |
|
errore_word |
0 |
|
w_spa |
1 |
|
string_word |
2 |
|
number |
3 |
|
w_ch |
4 |
5.Текст программы
// Islam.cpp: определяет точку входа для консольного приложения.
//
#include <stdafx.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
FILE *file_in, *file_out;
const int lenprog = 10000;//весь исходный текст представляется одной большой символьной строкой, а не массивом символов, это максимальная длина
const int Key_Words_num = 16;
char * KWs[Key_Words_num] =
{
"begin", "end", "var", "real",
"boolean", "false","true", "do",
"repeat", "until", "function","type",
"record", "and", "or", "read"
};// это массив ключевых слов, которые обрабатываются данной программой
//ключевыей слова
//каждому ключевому слову присвоен номер, это будет дальше испоьзоваться в проге
#define keyW_begin 1
#define keyW_end 2
#define keyW_var 3
#define keyW_real 4
#define keyW_boolean 5
#define keyW_false 6
#define keyW_true 7
#define keyW_do 8
#define keyW_else 9
#define keyW_for 10
#define keyW_function 11
#define keyW_type 12
#define keyW_record 13
#define keyW_and 14
#define keyW_or 15
#define keyW_read 16
//типы
//тоже присвоены номера
#define IntType 1 //целый
#define RealType 2 //дробный
#define BoolType 3 //логический
#define ArrayType 4 //массив
const int cuservars = 6;
int uvars;
//тип "слова"
#define errore_word 0 //ошибка
#define w_spa 1 //пробелы
#define string_word 2 //строка
#define number 3 //число
#define w_ch 4 //символ (разделитель)
//собственно это наши входные и выходные большие строки, в эти большие
//строки записываются также символы конца строки '\n', что и используется в дальнейшем для формирования выходного теста построчно
char instr[lenprog],
outstr[lenprog];
int inlen,outlen,inpos;//текущие позиции (строки входные, выходные, позиция в строке входной)
int koper1,koper2,ker;//эти переменные считают количество операторов во входном, выходном файле и кол-во ошибок
int lenght_world; //длина "слова"
int wtype; //тип "слова"
int wnumf; //0 - целое число, 1 - дробное
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();
// Дальнейшие функции описывают работу с динамической памятью,
// В которой создается список с переменными, их типами и названием
// Используя этот список, затем идет построение раздела объявления переменных
// в c++
//добавить переменную в список
// где gl - тип переменной, глобальная или локальная.
int addvar(int gl){
var *np, *p;
if (gl) p = vars; else p = lvars;
// int memcmp(const void *buf1, const void *buf2, size_t count);
// Функция memcmp() сравнивает первые count символов массивов, адресуемых параметрами buf1 и buf2.
// buf1 меньше buf2 = меньше нуля
// buf1 равен buf2 = 0
// buf1 больше buf2 = больше нуля
while (p) {
if (strlen(p->s)==lenght_world&&
!memcmp(p->s,&instr[inpos],lenght_world)) return 0;
p = p->next;
}
np = new var;
// void *memcpy(void *to, const void *from, size_t count);
// Функция memcpy() копирует count символов из массива,
// адресуемого параметром from, в массив, адресуемый параметром to.
// Если заданные массивы перекрываются, поведение функции memcopy() не определено.
memcpy(np->s,&instr[inpos],lenght_world);
// после имени переменной мы записываем 0 (метка
// что бы потом читать имя переменной до этого символа)
np->s[lenght_world]=0;
// тип переменной задаем как -1 (метка, что бы потом переопределить)
np->tp = -1;
// Если глобальная переменная, то добавляем этот элемент в начало
// (т.е. получается стек из переменных) списка глобальных переменных
// иначе в начало списка локальных
if (gl) {
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)==lenght_world&&
!memcmp(head->s,&instr[inpos],lenght_world)) return 0;
head = head->next;
}
ntype = new types;
memcpy(ntype->s,&instr[inpos],lenght_world);
ntype->s[lenght_world]=0;
ntype->tid = uvars;
uvars++;
ntype->next = typeslist;
typeslist = ntype;
return 1;
}
//установка типа переменной
// если gl - идентификатор глобальности = 1, то это глобальная переменная
// иначе локальная
// есть четыре типа переменных (описаны выше)
// конструкцию while можно расшифровать так:
// пока указатель на структуру p существует выполнять:
// если тип переменной -1 то присвоить ей заданный тип
// и далее шаг вперед
void settype(int gl, int type){
var *p;
if (gl) 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)==lenght_world&& // если слово во входном тексте равно названию переменной (в списке),
!memcmp(p->s,&instr[inpos],lenght_world)) return p->tp; // то вернуть тип переменной
p = p->next;
}
// обработка глобальных переменных
p = vars;
while (p) {
if (strlen(p->s)==lenght_world&&
!memcmp(p->s,&instr[inpos],lenght_world)) return p->tp;
p = p->next;
}
return 0;
}
char* usertype()
{
types * p;
// обработка локальных переменных
p = typeslist;
while (p) {
if (strlen(p->s)==lenght_world&& // если слово во входном тексте равно названию переменной (в списке),
!memcmp(p->s,&instr[inpos],lenght_world)) return p->s; // то вернуть тип переменной
p = p->next;
}
return 0;
}
// освобождение списка переменных
// просто удаление обоих списков
// как для локальных переменных, так и для глобальных
void freevars(int gl){
var *p, *pp;
p = lvars;
while (p) {
pp = p;
p = p->next;
delete pp;
}
lvars = NULL;
if (gl) {
p = vars;
while (p) {
pp = p;
p = p->next;
delete pp;
}
vars = NULL;
}
}
// Одна из главных функций получение слова, здесь посимвольно анализируется текст
// Вкратце описание выглядит так
// прога анализирует текст посимвольно и каждый раз определяет тип символа
// (число, буква, пробел ит.д.),
// когда удается ясно определить значение этого символа (цифра, переменная и т.д.)
// или последовательности символов( перемнная, ключевое слово и т.д.)
// выполнение функции прерывается она возвращает тип этого слова
//Функция возвращает один из следующих кодов
////тип "слова"
// errore_word 0 //ошибка
// w_spa 1 //пробелы
// string_word 2 //строка
// number 3 //число
// w_ch 4 //символ (разделитель, ...)
// чтение слова
int ReadWord()
{
int st = 0;
char c; // символ который сравнивается
lenght_world = 0;// длина анализуруемого слова
while (lenght_world+inpos<inlen ){
c = instr[inpos+lenght_world];
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=='\''
)
{ lenght_world = 1; return wtype = w_ch; }//возвращает, что это символ
else { lenght_world = 0; return wtype = errore_word; }
break;
case 1:
if (c==' ' || c=='\t' || c=='\n') lenght_world++;
else return wtype = w_spa; ///возвращает, что это символ пробел
break;
case 2:
if (
(c>='A' && c<='Z') ||
(c>='a' && c<='z') ||
(c>='0' && c<='9') ||
c=='_'
) lenght_world++;
else return wtype = string_word;
break;
case 3:
if (c>='0' && c<='9') lenght_world++; else
if (c=='.'&& instr[inpos+lenght_world+1]!='.') { // говорит, что есть точка в числе, т.е оно дробное
lenght_world++;
st = 5;
}
else{
wnumf = 0;
return wtype = number;//возвращает, что это число
}
break;
case 5:
if (c>='0' && c<='9') lenght_world++; else {
wnumf = 1;
return wtype = number;//возвращает, что это число (дробную часть)
}
}
}
lenght_world = 0;
return 0;
}
//запись строки в выходной буфер
void put_str(char * s){
int l = strlen(s);
memcpy(&outstr[outlen],s,l);
outlen += l;
}
int scmp(char * m, char * s, int n){
int l = strlen(s);
if (n>l) l = n;
/*int memicmp (buf1, buf2, cnt);
char *buf1; первый буфер
char *buf2; второй буфер
unsigned cnt; количество символов
Функция memicmp лексикографически сравнивает первые cnt
байтов из buf1 и buf2 вне зависимости от типа регистра, т.е. буквы верхнего и нижнего регистров считаются эквивалентными. Функция
memicmp возвращает значение, указывающее соотношение buf1 и buf2,
а именно:
Величина Значение
меньше 0 buf1 меньше, чем buf2
0 buf1 идентично buf2
больше 0 buf1 больше, чем buf2*/
return _memicmp(m,s,l);
}
//запись символа в выходной буфер
void put_char(char c){
outstr[outlen] = c;
outlen++;
}
void wcopy(){
memcpy(&outstr[outlen],&instr[inpos],lenght_world);
inpos += lenght_world;
outlen += lenght_world;
}
int wequ(char * s){
return (!scmp(&instr[inpos],s,lenght_world));
}
//пропускает пробелы
void wskip(){
inpos += lenght_world;
}
void wstr(char * s){
// char *strncpy (char *dst, const char *src, size_t len);
// dst -- указатель на буфер назначения.
// src -- указатель на исходную строку.
// len -- максимальное количество копируемых символов (см. раздел Безопасность ниже).
// Функция копирует из строки src в буфер dst не более чем len символов
// (включая нулевой символ), не гарантируя завершения строки
// нулевым символом (если длина строки src больше или равна len).
// Если длина строки src меньше len, то буфер добивается до len нулями.
// Функция возвращает значение dst.
strncpy(s,&instr[inpos],lenght_world);
}
//получение слов, и если тип слова пробелы, запускает процедуру, пропускающую пробелы
int ReadWordS(){
ReadWord();
if (wtype==w_spa) {
wskip();
ReadWord();
}
return wtype;
}
//увеличение отступа
void inc_dt()
{
dt += 2;
}
//уменьшение отступа
void dec_dt()
{
dt -= 2;
}
//вывод отступа
void put_dt()
{
for (int i=0; i<dt; i++) put_char(' ');
}
//вывод отступа
void put_dt11()
{
char s[10];
for (int i=0; i<dt; i++) {
sprintf(s,"%d",i/2);
put_str(s);
}
}
//открытие файла
int ReadText(char * s1)
{
if ((file_in = fopen(s1, "rt")) == NULL){
return 0;
}
fseek(file_in, 0, SEEK_END);
inlen = ftell(file_in);
fseek(file_in, 0, SEEK_SET);
if (inlen>lenprog) inlen = lenprog;
inlen = fread(instr,1,inlen,file_in);
instr[inlen] = 0;
inpos = 0;
outlen = 0;
return 1;
}
//вывод обработанного текста
int PutText(char * s2)
{
if ((file_out = fopen(s2, "wt")) == NULL){
return 0;
}
fwrite(outstr,outlen,1,file_out);
return 1;
}
//вывод ошибочного оператора
void Errore_oper()
{
put_char('\n');
put_str("< Ошибка! > \n");
int k;
while (1){
ReadWordS();
if (instr[inpos]== ';' || inpos>= inlen) {
wcopy();
break;
};
wcopy();
}
ker++; // увеличение счетчика ошибок
}
//проверка на комментарий
int find_Comment(){
return (instr[inpos]=='{' ||
instr[inpos]=='(' ||instr[inpos+1]=='*');
}
//проверка на закрытие комментария
void fin_Comment(){
if (instr[inpos]=='{'){
outstr[outlen] = '/';
outstr[outlen+1] = '*';
inpos++;
outlen += 2;
while (instr[inpos]!='}' && inpos<inlen) {
if (inpos>=inlen) return;
outstr[outlen] = instr[inpos];
inpos++;
outlen++;
}
outstr[outlen] = '*';
outstr[outlen+1] = '/';
inpos++;
outlen += 2;
}
else{
outstr[outlen] = '/';
outstr[outlen+1] = '*';
inpos += 2;
outlen += 2;
while (!(instr[inpos]=='*' && instr[inpos+1]==')')
&& inpos<inlen) {
if (inpos>=inlen) return;
outstr[outlen] = instr[inpos];
inpos++;
outlen++;
}
outstr[outlen] = '*';
outstr[outlen+1] = '/';
inpos += 2;
outlen += 2;
}
put_char('\n');
}
// здесь идет проверка на ключевое слово,
// сравниваются полученное нами слово со словом из списка
// и если да, то возвращается номер слова в списке
// проверка на ключевое слово
int funckeyW(){
for (int i=0; i<Key_Words_num; i++){// просмотр всего массива Key_Words_num
if (!scmp(&instr[inpos],KWs[i],lenght_world))
return i+1;
}
return 0;
}
// вот это обработка переменных после слова var,
// здесь идут обращения к тем четырем функциям работающим со списком перемнных
// обработка описания переменных: x1,..,xn: тип;
int fIntRealBoolAr(int svar, int gl){
char s[256];
int label;
int sp = 0;
ReadWordS();
while (1){
if (wtype!=string_word||funckeyW()|| gl>0&&vartype() ) return 0;
addvar(gl);
if (svar) {
s[sp] = '&';
s[sp+1] = ' ';
sp += 2;
}
memcpy(&s[sp],&instr[inpos],lenght_world);
inpos += lenght_world;
sp += lenght_world;
ReadWordS();
if (instr[inpos]==','){
s[sp]=',';
inpos++;
sp++;
} else break;
ReadWordS();
} // while(1)
if (instr[inpos]==':'){ //тип переменных
inpos++;
ReadWordS();
if (wtype!=string_word) return 0;
if (!scmp(&instr[inpos],"boolean",lenght_world)){
settype(gl,BoolType);
put_str("int ");
wskip();
memcpy(&outstr[outlen],&s[0],sp);
outlen += sp;
}
else
if (!scmp(&instr[inpos],"real",lenght_world)){
settype(gl,RealType);
put_str("float ");
wskip();
memcpy(&outstr[outlen],&s[0],sp);
outlen += sp;
}
else
if (!scmp(&instr[inpos],"integer",lenght_world)){
settype(gl,IntType);
put_str("int ");
wskip();
memcpy(&outstr[outlen],&s[0],sp);
outlen += sp;
}
else
if (!scmp(&instr[inpos],usertype(),lenght_world)){
put_str(usertype());
put_str(" ");
wskip();
memcpy(&outstr[outlen],&s[0],sp);
outlen += sp;
}
else
if (!scmp(&instr[inpos],"array",lenght_world)){
wskip();
settype(gl,ArrayType);
ReadWordS();
if (instr[inpos]!='[') return 0;
s[sp]='[';
inpos++;
sp++;
while (1) {
ReadWordS();
if (instr[inpos]!='1') return 0;
wskip();
ReadWordS();
if (instr[inpos]!='.'||instr[inpos+1]!='.')
return 0;
inpos += 2;
ReadWordS();
if (wtype!=number) return 0;
memcpy(&s[sp],&instr[inpos],lenght_world);
inpos += lenght_world;
sp += lenght_world;
ReadWordS();
if (instr[inpos]==']'){
s[sp]=']';
inpos++;
sp++;
break;
}
if (instr[inpos]==','){
inpos++;
s[sp]=']';
sp++;
s[sp]='[';
sp++;
}
}
ReadWordS();
if (wtype!=string_word) return 0;
if (scmp(&instr[inpos],"of",lenght_world)) return 0;
wskip();
ReadWordS();
if (wtype!=string_word) return 0;
if (scmp(&instr[inpos],"real",lenght_world)) return 0;
wskip();
put_str("float ");
memcpy(&outstr[outlen],&s[0],sp);
outlen += sp;
}
}
else return 0;
return 1;
}
//обработка описания блока переменных
int funcvar(int gl){
inpos += lenght_world;
ReadWordS();
do{
koper1++;
if (find_Comment()){ //комментарии
fin_Comment();
koper2++;
continue;
}
put_dt();
if (!fIntRealBoolAr(0,gl)) Errore_oper();
else koper2++;
ReadWordS();
if (instr[inpos]!=';')
return 0;
wskip();
put_str(";\n");
ReadWordS();
if (wtype!=string_word || funckeyW())
return 1;
}while(1);
}
//обработка блока описания переменных
int funcvardescr(){
inpos += lenght_world;
int k,svar;
ReadWordS();
do{
k = funckeyW();
svar = k==keyW_var;
if (svar) {
wskip();
ReadWordS();
}
if (!fIntRealBoolAr(svar,0)) return 0;
ReadWordS();
if (instr[inpos]!=';') return 1;
wskip();
put_str(", ");
ReadWordS();
k= funckeyW();
if (wtype!=string_word || k&&k!=keyW_var) return 0;
}while(1);
}
int funcbegin(int k);
//обработка процедуры
int funcprocedure(){
//чтение заголовка процедуры
wskip();
put_str("\nvoid ");
ReadWordS();
if (wtype!=string_word||vartype()) return 0;
addvar(1);
settype(1,10); //резервируем идентификатор
wcopy();
ReadWordS();
if (instr[inpos]!='(') return 0;
put_char('(');
//список параметров
if (!funcvardescr()) return 0;
ReadWordS();
if (instr[inpos]!=')') return 0;
wcopy();
ReadWordS();
if (instr[inpos]!=';') return 0;
wskip();
put_str("\n{\n");
inc_dt();
//тело процедуры
int b;
do{
b = 1;
ReadWordS();
if (!scmp(&instr[inpos],"var",lenght_world)){
koper1++;
if (!funcvar(0)) return 0;
}
else
if (!scmp(&instr[inpos],"begin",lenght_world)){
if (!funcbegin(2)) return 0;
b = 0;
}
else
if (find_Comment()) fin_Comment();
else return 0;
} while (b==1);
freevars(0);
inpos++;
return 1;
}
//обработка оператора record
int funcrecord(){
wskip();
put_str("struct ");
ReadWordS();
if (wtype!=string_word || funckeyW()) return 0;
addnewtype();
wcopy();
ReadWordS();
if (instr[inpos]!='=') return 0;
wskip();
ReadWordS();
if (!wequ("record")) return 0;
put_str("\n{\n");
inc_dt();
if (!funcvar(-1)) return 0;
dec_dt();
ReadWordS();
if (!wequ("end")) return 0;
wskip();
put_char('}');
ReadWordS();
if (instr[inpos]!=';') return 0;
wcopy();
put_str("\n\n");
inpos += lenght_world;
return 1;
}
//обработка оператора read
int funcread(int ln){
char s[256];
int sp;
int t;
wskip();
put_dt();
put_str("scanf");
ReadWordS();
if (instr[inpos]!='(') return 0;
inpos++;
put_str("(\"");
sp=0;
while (1) {
ReadWordS();
if (wtype!=string_word) return 0;
t = vartype();
if (t==IntType) put_str("%d");
else if (t==RealType) put_str("%f");
else return 0;
s[sp] = '&';
sp += lenght_world;
memcpy(&s[sp],&instr[inpos],lenght_world);
inpos += lenght_world;
sp += lenght_world;
ReadWordS();
if (instr[inpos]!=',') break;
s[sp] = instr[inpos];
inpos++;
sp++;
}
put_str("\",");
memcpy(&outstr[outlen],s,sp);
outlen += sp;
ReadWordS();
if (instr[inpos]!=')') return 0;
inpos++;
put_char(')');
ReadWordS();
if (instr[inpos]!=';') return 0;
inpos++;
if (ln) put_str("; printf(\"\\n\");\n");
else put_str(";\n");
return 1;
}
//обработка арифметического выражения
int fae() {
ReadWordS();
if (instr[inpos]=='+'){
wcopy();
}
else
if (instr[inpos]=='-'){
wcopy();
}
while (1){
ReadWordS();
if (wtype==number) wcopy(); else
if (wtype==string_word&&vartype()==IntType) wcopy(); else
if (wtype==string_word&&vartype()==RealType) wcopy(); else
if (wtype==string_word&&vartype()==ArrayType) {
wcopy();
ReadWordS();
if (instr[inpos]=='['){
wcopy();
while (1) {
if (!fae()) return 0;
put_str("-1");
ReadWordS();
if (instr[inpos]==']'){
wcopy();
break;
}
if (instr[inpos]==','){
wskip();
put_str("][");
}
}
}
} else
if (instr[inpos]=='('){
wcopy();
if (!fae()) return 0;
ReadWordS();
if (instr[inpos]!=')') return 0;
inpos++;
put_char(')');
}
else return 0;
ReadWordS();
char c = instr[inpos];
if (c=='+'||c=='-'||c=='*'||c=='/') wcopy();
else return 1;
}
}
//обработка арифметического выражения
int ae(){
char c,c1;
if (!fae()) return 0;
ReadWordS();
c = instr[inpos];
c1 = instr[inpos+1];
if (c=='<'&&c1=='>') {
inpos += 2;
put_str("!=");
}
else
if (c=='=') {
inpos++;
put_str("==");
}
else
if (c=='>'||c=='<') {
if (c1=='='){
inpos += 2;
}
else wcopy();
}
ReadWordS();
if (!fae()) return 0;
return 1;
}
//обработка логического выражения
int fle() {
int k;
char c,c1;
int arifm, ip,op;
while (1){
ReadWordS();
k = funckeyW();
int ip, op;
ip = inpos;
op = outlen;
arifm = 0;
if(instr[inpos]=='+'||
instr[inpos]=='('||
instr[inpos]=='-'||
wtype==string_word&&!funckeyW() ||
wtype==number)
arifm = ae();
if (!arifm){
inpos = ip;
outlen = op;
ReadWordS();
k = funckeyW();
//------
if (wtype==string_word&&k==keyW_true){
wskip();
put_char('1');
}
else
if (wtype==string_word&&k==keyW_false) {
wskip();
put_char('0');
}
else
if (wtype==string_word&&vartype()==BoolType) wcopy(); else
if (instr[inpos]=='('){
wcopy();
if (!fle()) return 0;
ReadWordS();
if (instr[inpos]!=')') return 0;
inpos++;
put_char(')');
}
else return 0;
}
ReadWordS();
k = funckeyW();
if (k==keyW_or) put_str("||"); else
if (k==keyW_and) put_str("&&");
else return 1;
wskip();
}
}
//проверка на присваивание
int asign_a_var(){
int type = vartype();
if (!(type==BoolType||type==RealType||type==IntType)) return 0;
//put_char('\n');
put_dt();
wcopy();
ReadWordS();
if (instr[inpos]!=':'||instr[inpos+1]!='=')
return 0;
put_char('=');
inpos += 2;
if (type==BoolType) {
if (!fle()) return 0;
}
else
if (!fae()) return 0;
ReadWordS();
if (instr[inpos]!=';') return 0;
wcopy();
put_char('\n');
return 1;
}
//обработка оператора repeat
int funcelse () {
wskip();
put_dt();
put_str("do {\n");
inc_dt();
return 1;
}
//обработка оператора repeat
int funcif() {
wskip();
dec_dt();
put_dt();
put_str("} if (");
if (!fle()) return 0;
put_char(')');
ReadWordS();
if (instr[inpos]!=';') return 0;
inpos++;
put_str(";\n");
return 1;
}
//обработка блока операторов
int funcbegin(int gl){
int rep_n = 0;
if(gl!=3) wskip();
if (gl==1) put_str("\n\nvoid main()\n");
if ((gl!=2)||(gl!=3)) {
put_dt();
put_str("{\n");
inc_dt();
}
int b;
do{
b = 1;
ReadWordS();
if (find_Comment()){
fin_Comment();
continue;
}
switch(funckeyW()){
case keyW_begin:
koper1++;
if (!funcbegin(0)) return 0;
koper2++;
break;
case keyW_read:
koper1++;
if (!funcread(0)) return 0;
koper2++;
break;
case keyW_repeat:
koper1++;
rep_n++;
if (!funcrepeat()) return 0;
break;
case keyW_until:
if (rep_n>0){
rep_n--;
if (!funcuntil()) return 0;
koper2++;
}
else return 0;
break;
case keyW_procedure:
if (!funcprocedure()) return 0;
break;
case keyW_end:
koper1++;
if(gl == 3) return 3;
wskip();
dec_dt();
put_dt();
put_str("}\n");
ReadWordS();
if (gl==1&&instr[inpos]=='.' ||
gl!=1&&instr[inpos]==';'){
wskip();
koper2++;
return 1;
}
else
{
wskip();
return 0;
}
case 0:
if (!asign_a_var()) return 0; //присваивание
break;
default:
return 0;
}
} while (b);
return 1;
}
//главная функция преобразования ттекста
//преобразование текста
int Translate()
{
int b;
int k;
koper1 = koper2 = 0;
put_str("#include <stdio.h>\n\n"); //для scanf и printf
do{
b = 1;
ReadWordS();
k = funckeyW(); //проверка на ключевое слово
if (k==keyW_var){ //начало блока переменных
koper1++;
if (!funcvar(1)) {
Errore_oper();
}
else koper2++; }
else
if (k==keyW_type){ //блок описания типов
koper1++;
if (!funcrecord()) {
Errore_oper();
}
else koper2++;
}
else
if (k==keyW_procedure){ //процедура
if (!funcprocedure()) {
Errore_oper();
}
}
else
if (k==keyW_begin){ //начало блока операторов
if (!funcbegin(1)) {
Errore_oper();
}
b = 0;
}
else
if (find_Comment()) fin_Comment(); //комментарии
else {
koper1++;
Errore_oper();
};
} while (b==1);
if (instr[inpos]!='.') return 0; //точка в конце программы
inpos++;
return 1;
}
void main()
{
setlocale(LC_ALL,"Russian");
char s[128];
printf("Введите имя файла(с расширением) с кодом на языке Pascal:");
scanf("%s",s);
if (!ReadText(s))
{
printf("\nОшибка открытия файла!");
}
vars = NULL;
lvars = NULL;
uvars = cuservars;
Translate();
freevars(1);
printf("\nВведите имя выходного файлас расширением .с:");
scanf("%s",s);
if (!PutText(s))
{
printf("\nОшибка создания файла!");
}
printf("\nКоличество операторов"
" в исходном файле: %d", koper1);
printf("\nКоличество операторов"
" в полученном файле: %d", koper2);
printf("\nКоличество ошибочных операторов"
" которые не были обработаны: %d", ker);
printf("\n\nРезультат хранится в файле: %s",s);
fclose(file_in);
fclose(file_out);
while (!kbhit()) ;
}
6.Распечатка тестов и результатов
Рисунок 1 - Вид экрана после обработки входного файла
Листинг программы до трансляции:
type
rec = record
x,y: real;
end;
var
t:rec;
a,b,k,s: real;
f: boolean;
{Vars}
{Begin pr}
procedure pr(k: integer; var d: real);
begin
repeat
read(a);
until f or f;
End; {End pr}
begin
f:= true;
repeat
read(a);
until f and f;
write(a);
end.
Листинг программы после трансляции:
#include <stdio.h>
struct rec
{
float x,y;
};
rec t;
float a,b,k,s;
int f;
/*Vars*/
/*Begin pr*/
void pr(int k, float & d)
{
{
do {
scanf("%f",&a);
} while (f||f);
}
/*End pr*/
void main()
{
f=1;
do {
scanf("%f",&a);
} while (f&&f);
< Ошибка! >
write(a);
Вывод
В ходе работы над курсовым проектом поставленная задача была полностью выполнена. В ходе разработки программы были исправлены ошибки синтаксического характера, а так же ошибки выполнения. В результате тестирования на контрольном примере ошибок выполнения не обнаружено, все функции программы выполняют возложенные на них задачи.
Список литературы
Oснoвнaя
Зaйцeвa, Л.В. Aлгopитмичeскиe языки и пpoгpaммиpoвaниe [тeкст] / Л.В. Зaйцeвa. - М.: МГГУ, 1996.
Фapoнoв, В.В. Пpoгpaммиpoвaниe нa ПЭВМ в сpeдe Туpбo-Пaскaль [тeкст] / В. В. Фapoнoв. - М.: МГТУ, 1999.
Дoпoлнитeльнaя
Кpaсoв, A.В. Пpoгpaммиpoвaниe нa Borland C пoд MS Windows [тeкст] / A.В. Кpaсoв. - СПб.: СПбГУТ, 2001.
Зaйцeвa, Л.В. Мeтoдичeскиe укaзaния для выпoлнeния куpсoвoгo пpoeктa пo дисциплинe «Aлгopитмичeскиe языки и пpoгpaммиpoвaниe» пo спeц. 2203 / Л.В. Зaйцeвa, В.Г. Ссopин, E.A. Epoхинa, 2005.
Размещено на Allbest.ru
Подобные документы
Создание транслятора, обрабатывающего код программы на языке Паскаль и за счет эквивалентных операторов генерирующего программу на Си. Особенности внешней спецификации и работы лексического анализатора. Структура программы, вывод результатов на экран.
курсовая работа [254,0 K], добавлен 02.07.2011Программный комплекс для разработки программы транслирующей программу с языка Pascal на язык С++. Построение логической и арифметической модели решения. Разработка компилятора для программы. Методы отладки программы и создание для нее документации.
курсовая работа [742,6 K], добавлен 03.07.2011Схема разбора арифметического и логического выражения. Внешняя спецификация конвертора и алгоритм перевода программ на языке Паскаль в текст на языке Си. Назначение подпрограмм, особенности констант и переменных. Код программы и ее тестирование.
курсовая работа [567,5 K], добавлен 03.07.2011Написaние прoграммы, выполняющей трансляцию с языка программирования Пaскaль нa язык прoгрaммирoвaния Си и транслирующей конструкции, такие кaк integer, repeat … until Le, procedure, type, record для type. Обработка арифметических и логических выражений.
курсовая работа [314,3 K], добавлен 03.07.2011Создание приложения, исполняющего трансляцию программы из языка Паскаль в язык Си: разработка алгоритма реализации задачи, описание необходимых констант, переменных, функций и операторов, представление листинга программы и распечатка результатов.
курсовая работа [305,9 K], добавлен 03.07.2011Проектирование программы-анализатора, состоящей из двух частей: лексического анализатора, разбивающего исходный текст программы на лексемы и заполняющего таблицу имен; синтаксического анализатора, проверяющего соответствие текста заданной грамматике.
курсовая работа [2,0 M], добавлен 14.06.2010Создание программы для перевода кодов с языка Pascal на язык Си. Обработка программ операторами case, assign, rewrite и write. Способы объявления файла, комментария, переменных, логических и арифметических выражений. Виды синтаксических анализаторов.
курсовая работа [461,0 K], добавлен 03.07.2011Выбор метода проектирования транслятора с языка Паскаль на язык Си, разработка и кодирование алгоритма программы. Использование допустимых операторов в исходном тексте, определение типов переменных и синтаксиса логических и арифметических выражений.
курсовая работа [1,0 M], добавлен 03.07.2011Написание программы, которая выполняет лексический и синтаксический анализ входного языка программирования, порождает таблицу лексем с указанием их типов и значений, а также строит синтаксическое дерево; текст входного языка вводится с клавиатуры.
курсовая работа [761,5 K], добавлен 23.02.2012Написание транслятора посредством языка Си, обрабатывающего конструкции integer, if Le then, записи (record), а также реализующего обработку new для выделения динамической памяти: разработка алгоритма реализации задачи, представление листинга программы.
курсовая работа [171,7 K], добавлен 03.07.2011