Автор: Пользователь скрыл имя, 20 Ноября 2012 в 23:12, курсовая работа
Посредством среды разработки «Borland C++ Builder6» осуществляется создание варианта программы-транслятора с одного языка высокого уровня на другой. Созданная программа имеет возможность находить некоторые лексические и синтаксические ошибки, которые могут быть допущены в исходном текстовом файле, предназначенном для трансляции и сообщать о них пользователю.
1. Пояснительная записка………………………………………………………..2
1.1. Задание на проектирование…………………………………………..2
1.2. Содержание…………………………………………………...……….3
1.3. Введение………………………………..………………………………4
1.4. Описание процесса решения задачи…………………………………5
1.5. Блок-схемы основной программы и процедур…………………….15
2. Распечатка программных модулей………………………………………….17
3. Описание программы………………………………………………………...39
3.1. Назначение и общее описание программы………………………...39
3.2. Описание логической структуры программы…………………… ..39
3.3. Способ обращения к программе……………………………………40
3.4. Перечень технических средств………………………………… …..40
4. Описание входных и выходных данных……………………………………40
5. Тестовые примеры работы программы………………..……………………41
int ARV(int mass[], int i) – функция
работает аналогично
int YSLOVIE (int mass[], int i) анализирует весь оператор условия, определяет наличия оператора «if», «than», «else затем вызывается функция для проверки правильности написания условия, после чего требуется наличие после условия какого-либо оператора: присваивания, другого условия или операции ввода-вывода.
int PRISV(int mass[], int i) – проверка правильности написания операции присваивания. Последовательно проверяется наличие идентификатора, следующего за ним знака «=», а после него – арифметического выражения (определяется с помощью вызова ARV()).
int VVOD(int mass[], int i) – оператор ввода проверяется следующим образом: вначале распознается терминальный символ read, скобки, после чего следует перечисление переменных через запятую. В случае отсутствия операндов выдается ошибка.
int VIVOD(int mass[], int i) – оператор вывода проверяется следующим образом: вначале распознается терминальный символ writeln, скобки, после чего следует перечисление переменных через запятую. В случае отсутствия операндов выдается ошибка.
int OPERATOR(int mass[], int i) – основная функция проверки, вызываемая для каждой лексемы в функции ANALIS(). Здесь последовательно вызываются основные функции проверки (цикла, присваивания, ввода-вывода и т.д.), таким образом организуется нисходящий метод проверки. Для удобства функция возвращает разные значения в зависимости от того, какая функция вернула истинное значение.
Подведем итог работы анализирующих функций: каждая такая процедура старается во входном массиве лексем найти попадающую под начальное условие лексему. В процессе своей работы она может вызывать другие функции или рекурсивно саму себя для поиска нетерминальных символов. Если эта процедура находит соответствующий нетерминальный символ, то она заканчивает работу и передает в вызывающую ее процедуру признак успешного выполнения (res=1). Затем рассматривается следующая лексема, идущая за распознанной. Если же функция не может найти подходящее условие для данной лексемы (т.е. она не вписывается ни в одно правило данного языка), то она заканчивается с признаком неудачи и вызывает функцию анализа ошибки (её описание будет приведено ниже). Таким образом, если будет обнаружена неверная последовательность кодов лексем, то программа выдаст сообщение о синтаксической ошибке. В отдельной глобальной переменной ведется учет всех ошибок, если их количество отлично от нуля, то функция, генерирующая код не вызывается (это не имеет смысла при наличии ошибок).
Отличительной чертой программы является особая функция ERRORM(int err, int mass[], int i), где err – код ошибки, передаваемый из функций проверки, mass – массив лексем, а i – номер лексемы, в которой обнаружена ошибка (или та, относительно которой будет рассчитываться это положение). Чтобы исключить повторное отображение одной и той же ошибки (например, после проверки правильности множителя и выражения одна и та же лексема будет проверена дважды, что приведет к двум сообщениям), существует специальный массив флагов, заполняемый по мере появления ошибок. После определения ошибки происходит дальнейший анализ следующей по счету лексемы. Ниже приведены все используемые в программе ошибки:
Код ошибки |
Описание ошибки |
0 |
Повторное объявление идентификатора |
1 |
Неизвестный тип данных |
2 |
Лишняя запятая |
3 |
Необъявленная переменная |
4 |
Обнаружена неизвестная константа |
5 |
Отсутствует первый множитель |
6 |
Отсутствует множитель (константа) |
7 |
Отсутствует множитель (идентификатор) |
8 |
Отсутствует слагаемое |
9 |
Отсутствует первое слагаемое в выражении |
10 |
Неправильно записано отношение в условии |
11 |
Отсутствует вторая часть неравенства или закрывающая скобка |
12 |
Отсутствует первая часть неравенства или открывающая скобка |
13 |
Отсутствует оператор после условного оператора |
14 |
Некорректно задано условие |
15 |
Некорректное арифметическое выражение |
16 |
Некорректные атрибуты операции вывода |
17 |
Отсутствует выражение слева от оператора присваивания |
18 |
Некорректные атрибуты операции ввода |
19 |
Некорректно записан оператор ввода-вывода |
20 |
Недопустимое арифметическое действие (деление на ноль) |
21 |
Отсутствует ; или : |
22 |
Ошибка в имени программы |
23 |
Отсутствует begin |
24 |
Отсутствует end |
25 |
Количество begin!= количеству end |
26 |
Отсутствует var |
27 |
Неправильное окончание программы (нет end и точки) |
Генерация кода.
После успешного синтаксического анализа (количество ошибок равно нулю) происходит вызов функции GENERATOR(). Функция считывает проверенные лексемы из файла в массив и начинает последовательный анализ и на основании определенных условий записывает в итоговый файл (code.txt) программный код на новом языке. Т.к. транслируемые языки являются языками высокого уровня и похожи по организации структуры программы, то не требуется использование внутреннего представления.
Процесс генерации кода довольно прост, стоит отметить лишь несколько моментов. Во-первых, операции распознаются не по операндам, а по символам операторов, т.е. выражение «а+5» определится только после обнаружения знака «+». Следовательно, происходит проверка, какие операнды используются – константы или идентификаторы, чтобы избежать ошибочной записи. Вторым моментом является возникающая из-за этого сложность перевода выражений вида «х+у+5+1», которое рассматривается как «х+у у+5 5+1», поэтому для каждого арифметического оператора прописано дополнительное условие, определяющее, стоит ли плюс только между двумя операндами, либо включен в некую последовательность операндов. Третий момент – объявление переменных в ПЛ1 отличается от такого в Паскале. Последним отличием является иная запись оператора цикла, условие которого записывается единым блоком через запятую.
1.5. Блок-схема транслятора
Блок-схема синтаксического анализатора
2. Распечатка программных модулей
#include <vcl.h>
#pragma hdrstop
#include<math.h>
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include "Unit1.h"
//----------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//----------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Memo2->Clear();
Memo3->Clear();
}
char *filename="vhod.txt";
#define MAX 10
#define MAXL 1000
int allstr=0;
int enddo=-1;
class Ident
{
public:
int nomer;
char name[20];
char type[20];
};
int DECLAR(int mass[], int i);
int MNOG(int mass[], int i);
int SLAG(int mass[], int i);
int ARV(int mass[], int i);
int PRISV(int mass[], int i);
int OPERATOR(int mass[], int i);
int VVOD(int mass[], int i);
int VIVOD(int mass[], int i);
void TYPESETUP(int mass[], int i);
void BEGINEND(int mass[]);
int YSLOVIE(int mass[], int i);
void ERRORM(int err, int mass[], int i);
Ident ID[MAX];
Ident CNST[MAX];
int idsw=0;
int cnstsw=0;
int SELECTLEX(int one, int two,char str[80])
{
char str1[80];
int h=0,j=0;
if(one==two)
{
}
for(h=0;h<80;h++) str1[h]='\0';
for(h=one;h<two;h++) str1[j++]=str[h];
if(strcmp(str1,"program")==0) return 1;
if(strcmp(str1,"var")==0) return 2;
if(strcmp(str1, "begin")==0) return 3;
if(strcmp(str1,"end")==0) return 4;
if(strcmp(str1, "if")==0) return 5;
if(strcmp(str1, "then")==0) return 6;
if(strcmp(str1,"else")==0) return 7;
if(strcmp(str1,"write")==0) return 25;
if(strcmp(str1, "read")==0) return 26;
if(strcmp(str1,"integer")==0) return 8;
if(strcmp(str1,"real")==0) return 9;
return 99;
}
void TYPESETUP(int ar[], int i)
{
Ident Buf;
if (ar[i]==1 )strcpy(Buf.type,"real");
if (ar[i]==2 )strcpy(Buf.type,"integer");
int p=i;
int peremen=idsw-1;
if(ar[p-2]==18)
{
do
{
p--;
strcpy(ID[ar[p]].type,Buf.
p=p-2;
}
while(ar[p]==16);
}
}
void READCODE()
{
FILE* df, *lexem,*lexemdeb;
if((df=fopen(filename,"r"))==
if((lexem=fopen("lexem.txt","
if((lexemdeb=fopen("
char dt[80][80];
char ch[]="";
int mass[200], z=0;
int numstr=0, i=0,k=0,m=0,l=0;;
int strz=0;
char buf[80];
while(!feof(df))
{
//fgets(dt[numstr++],79,df);
fgets(buf,79,df);
for(int i=0;i<80;i++)
{
if(buf[i]<32)
{
i=i;
for(int j=i;j<80;j++) buf[j]='\0';
i=80;}
if(buf[i]==';') {
for(int j=i+1;j<80;j++) buf[j]='\0';} }
Form1->Memo1->Lines->Add(buf);
strcpy(dt[numstr],buf);
strcpy(buf," ");
numstr++;
}
allstr=numstr;
for(int j=0;j<allstr;j++)
{
for(i=0;i<strlen(dt[j]);i++)
{
if(dt[j][i]=='<') mass[z++]=8;
if(dt[j][i]=='>') mass[z++]=9;
if(dt[j][i]=='(') mass[z++]=10;
if(dt[j][i]==')') mass[z++]=11;
if(dt[j][i]=='*') mass[z++]=12;
if(dt[j][i]=='/') mass[z++]=13;
if(dt[j][i]=='+') mass[z++]=14;
if(dt[j][i]=='-') mass[z++]=15;
if(dt[j][i]==',') mass[z++]=16;
if(dt[j][i]==';') mass[z++]=17;
if(dt[j][i]=='.') mass[z++]=24;
if(dt[j][i]==':'&&dt[j][i+1]!=
if(dt[j][i]==':'&&dt[j][i+1]==
if(isalpha(dt[j][i])!=0)
{
for(k=i;k<strlen(dt[j]);k++)
if(isalpha(dt[j][k])==0)
break;
for(m=i;m<k;m++)
dt[j][m]=tolower(dt[j][m]);
l=SELECTLEX(i,k,dt[j]);
switch(l)
{
case 1: {mass[z++]=1; break;}
case 2: {mass[z++]=2; break;}
case 3: {mass[z++]=3; break;}
case 4: {mass[z++]=4; break;}
case 5: {mass[z++]=5; break;}
case 6: {mass[z++]=6; break;}
case 7: {mass[z++]=7; break;}
case 8: {mass[z++]=20;
mass[z++]=1;
Ident Buf;
strcpy(Buf.type,"integer");
int p=z-1;
int peremen=idsw-1;
if(mass[p-2]==18)
{
p=p-2;
do
{
p--;
if(!strcmp(ID[mass[p]].type,"
strcpy(ID[mass[p]].type,Buf.
else
ERRORM(0,mass,p);
p=p-2;;
}
while(mass[p]==16);
}
break;}
case 9: {mass[z++]=20;
mass[z++]=2;
Ident Buf;
strcpy(Buf.type,"real");
int p=z-1;
int peremen=idsw-1;
if(mass[p-2]==18)
{
p=p-2;
do
{
p--;
if(!strcmp(ID[mass[p]].type,"
strcpy(ID[mass[p]].type,Buf.
else
ERRORM(0,mass,p);
p=p-2;;
}
while(mass[p]==16);
}
break;}
case 25: {mass[z++]=25; break;}
case 26: {mass[z++]=26; break;}
default:
{
int flag1=0;
int q=0; char qt[20];
for(int qq=0;qq<20;qq++) qt[qq]='\0';
if((dt[j][i]>=65&&dt[j][i]<=
for(int r=i;r<k;r++)
qt[q++]=dt[j][r];
int f;
Ident Buf;
strcpy(Buf.type,"unknown");
int poisk=z;
int peremen=idsw-1;
strcpy(Buf.name,qt);
for(f=0;f<MAX;f++)
{
if(!strcmp(ID[f].name,Buf.
{
flag1=1;
break;
}
}
if(flag1==1)
{
if((!strcmp(ID[f].type,Buf.
{
mass[z++]=21;
mass[z++]=ID[f].nomer;
}
else
{
//int poisk=z;
if(z-1==0) strcpy(Buf.type,"program");
strcpy(ID[idsw].name,Buf.name)
strcpy(ID[idsw].type,Buf.type)
ID[idsw].nomer=idsw;
mass[z++]=21;
mass[z++]=ID[idsw].nomer;
idsw++;
}
}
else
{
if(z-1==0) strcpy(Buf.type,"program");
strcpy(ID[idsw].name,Buf.name)
strcpy(ID[idsw].type,Buf.type)
ID[idsw].nomer=idsw;
mass[z++]=21;
mass[z++]=ID[idsw].nomer;
idsw++;
}
}
}
i=k-1;
}
else
{
int flag1=0;
int q=0; char qt[20];
for(int qq=0;qq<20;qq++) qt[qq]='\0';
if(dt[j][i]>=48&&dt[j][i]<=57)
{
for(k=i;k<strlen(dt[j]);k++)
if(isalpha(dt[j][k])!=0||(dt[
break;
int q=0;
for(int y=i;y<k;y++)
qt[q++]=dt[j][y];
int f;
for(f=0;f<MAX;f++)
{
if(!strcmp(CNST[f].name,qt))
{
flag1=1;
break;
}
}
if(flag1==1)
{
mass[z++]=22;
mass[z++]=CNST[f].nomer;
}
else
{
strcpy(CNST[cnstsw].name,qt);
CNST[cnstsw].nomer=cnstsw;
mass[z++]=22;
mass[z++]=CNST[cnstsw].nomer;
cnstsw++;
}
}
}
}
for(int e=strz;e<z;e++)
fprintf(lexem,"%d ",mass[e]);
fprintf(lexem,"\n");
strz=z;
}
fprintf(lexemdeb,"Позиция\t\
for(int t=0;t<z;t++)
{
fprintf(lexemdeb,"%d\t\t %d \n",t, mass[t]);
}
fclose(lexem);
fclose(df);
fclose(lexemdeb);
}
void READCODE2()
{
FILE* df;
if((df=fopen("vhod.txt","w"))=
for(int i=0;i<Form1->Memo1->Lines->
fprintf(df,"%s\n",Form1->
fclose(df);
Form1->Memo1->Clear();
strcpy(filename,"vhod.txt");
READCODE();
}
int errornumber=0;
int flag0=0;
int errmass[28];
void ERRORM(int err, int mass[], int i)
{ char s[80];
strcpy(s,"");
switch(err)
{
case 0: {if(errmass[err]!=i){sprintf( s, "[Лексема
%d-%d]Повторное объявление идентификатора
%s\n",i,i+1,ID[mass[i]].name);
case 1: {if(errmass[err]!=i){sprintf( s, "[Лексема
%d]Неизвестный тип данных\n",i);errornumber++;
case 2: {if(errmass[err]!=i){sprintf( s, "[Лексема
%d]Лишняя запятая \n",i-3);errornumber++;break;}
case 3: {if(errmass[err]!=i){sprintf( s, "[Лексема
%d]Необъявленная переменная %s\n",i,ID[mass[i]].name);
Информация о работе Разработка трехпроходного транслятора с исходного языка на язык ПЛ-1