
- •Московский государственный институт электроники и математики
- •Требования к надежности
- •Оглавление
- •Задание на курсовую работу
- •Постановка задачи
- •Требуется
- •Связь (примеры конвертирования)
- •Внешняя спецификация
- •Аномалии
- •Метод решения задачи
- •Описание алгоритма
- •Алгоритм решения задачи
- •Выделение подпрограмм
- •Диаграммы анализа выражений
- •Распечатка тестов и результатов работы программы
- •Входной файл
- •Выходнойфайл
- •Входной файл
- •Выходной файл
- •Список литературы
Выделение подпрограмм
Подпрограммы детального анализа ключевых слов
Каждая из подпрограмм детального анализа ключевого слова выполняет следующие действия:
Выясняет, правильно ли оформлены логическое или арифметическое выражение, если оно предполагается в предложении Паскаля, содержащего соответствующее ключевое слово..
Определяет, нет ли в предложении признака продолжения (текст расширения). Если есть, то соответствуещее окончание предложение отрезается и отсылается снова в началобуфераstr_bufдля последующего анализа. Например, в предложении
If a>b then begin c:=d;
текст If a>b будет выделен и обработан, а текст then begin c:=d; будет отправлен в str_buf.
Проводит преобразование текста, непосредственно следующего за ключевым словом (кроме текста расширения) в эквивалентный текст на языке С.
Выводит полученный текст предложения на С в выходной файл. При выводе в файл выполняется дополнение текста слева необходимым количеством пробелов в соответствии с логикой генерируемого текста (подпрограммы increase_indentиdecrease_indent). Например, предложение
if (a>b) { с =2;d =1;}
выводится в следующем формате:
if (a>b)
{
с =2;
d =1;
}
Подпрограммы анализа выражений
В составе программы есть подпрограммы анализа арифметического и логического выражений. Они вызываются из тех подпрограмм анализа ключевых слов, в которых необходимо провести соответствующий анализ:
Подпрограмма анализа логического выражения (Analyze_LE1) вызывается при обработке предложений ПаскаляIfиUntil.
Подпрограма анализа арифметического выражения (Analyze_AE2) вызывается при обработке логического выражения, а также при обработке оператора присваивания.
Подпрограмма анализа имени идентификатора (Analyze_Identify) вызывается при анализе оператора присваивания, оператораFunction,в секцияхVar, Const, Uses, Label.
Cлужебные подпрограммы
Подпрограмма замены подстрок Replace используется при подготовке исходного текста к анализу и к выводу в выходной файл (напр., замена двойных пробелов на одиночный, для удаления точки с запятой и т.п.)
Подпрограммы Ltrim, Rtrim, Pos, Reverse, GetHead, GetTailиспользуются для анализа и преобразования строк символов.
Подпрограмма Output_C_Linesвыводит полученный текст на языке С в файл вывода и увеличивает счетчик выходных строк.
Диаграммы анализа выражений
Арифметическое выражение ae2
Логическое выражение le1
Структура программы
Текст программы
/////////////////////////////////////////////////////////////////////////////
// //
// Ковертор из Паскаля в Си А.Шиндин, МИЭМ 2005 //
// Курсовой проект. Обработка исходного текста на Паскале //
// и получение текста на Си по правилам заданного варианта. //
// //
/////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define buf_len 255 //максимальный размер рабочих строк
#define buf_len_short 32
#define ZNAK *s_cur=='-' || *s_cur=='+'
#define true 0
#define false 1
char str_expr[80];//глобальная переменная строка с выражением Ae2
char *s_cur;//указатель на номер текущей позиции в str_expr
char pas_prog_name[buf_len];//имя исходной программы на языке Pascal
char c_prog_name[buf_len]; //имя получаемой программы на языке C
FILE *file_in, *file_out; //входной файл (*.pas) и выходной файл (*.c)
int count_source_lines=0; //счетчик строк на Pascal'е
int count_out_lines=0; //счетчик законченных предложений на C (translated to C)
int other_oper_flag=0; //см. подпрограму Analyze_Other_Operator
int main_flag=0; //используется для определения контекста исполнения:
//анализируется текст внутри главной программы или
//внутри подпрограммы или функции
int function_flag=0; // этой переменной присваивается значение 1,
//если встречается кл.слово "function";
int function_end_level=0;
// если установлен function_flag=1 и далее
//встречается кл.слово "begin", то переменная
//"function_end_level" увеличивается на 1;
// если установлен function_flag=1 и встречается
//кл.слово "end", то "function_end_level"
//уменьшается на 1.;
// если function_end_level становится равной 0
//после очередного "end", то флажок
//"function_flag" снова становится равным 0.
//Такой подход позволяет точно установить "begin",
//относящийся к главной программе на Паскале.
//Когда это происходит, переменная
//"function_flag" устанавливается в 2.
int indent=0; //отступ для строки на C (от начала строки).
int indent_delta=2; //прирост отступа (для его уменьшения/увеличения)
char indent_text[buf_len]; //строка символов, используемая для вставки
//отступа (пробелы)
int errors_counter=0; //счетчик ошибок
int anomaly_counter=0; //счетчик аномалий
char anomaly_text[buf_len];//сообщение об аномалии
char str_in[buf_len]; //путь доступа к входному файлу
//на Паскале
char str_out[buf_len]; //путь доступа к выходному файлу
//на C
char str_temp[buf_len]; //для чтения исходных строк
char str_temp_nocomments[buf_len]; //для накопления исходного текста,
//очищенного от комменатриев
char str_buf[buf_len]; //буфер накопления текста на Паскале
char w_str[buf_len]; //рабочая строка для обр-ки буфера
char str_sep[buf_len]=";"; //строка разделителей исходных операторов
char comments_buf[buf_len]; //буфер накопления комменариев
char non_comments_buf[buf_len]; //фрагмент исходного текста, очищенного
//от комментариев
char anykey[1]=" "; //строка используется для остановки
//программы во время выполнения
//через gets(anykey)
int fid=0; //function id;
//прототипы функций и процедур
int pos(char *str1, char *str2);
char* GetHead(char *str1, char *str2);
char* GetTail(char *str1, char *str2);
void Reverse(char *str1, char *str2);
void GetPaths();
void Pas_to_C(char* pas_str, char* c_str);
void ClearOffBlanks(char *str1, char* str2);
void LTrim(char* str1, char* seps, char* str2);
void RTrim(char* str1, char* seps, char* str2);
void Press_Blanks(char *str1, char* str2);
void Analyze_Assignment(char* str1, char* str2);
void Analyze_Repeat(char *str1, char *str2);
void Analyze_If(char *str1, char *str2);
void Analyze_Then(char *str1, char *str2);
void Analyze_Else(char *str1, char *str2);
void Analyze_Until(char *str1, char *str2);
void Analyze_Begin(char *str1, char *str2);
void Analyze_End(char *str1, char *str2);
void Analyze_End_Prog(char *str1, char *str2);
void Analyze_GoTo(char *str1, char *str2);
void Analyze_Function(char *str1, char *str2);
void Analyze_Var(char *str1, char *str2);
void Analyze_Var_Oper(char *str1, char *str2);
void Analyze_Const(char *str1, char *str2);
void Analyze_Const_Oper(char *str1, char *str2);
void Analyze_Uses(char *str1, char *str2);
void Analyze_Uses_Oper(char *str1, char *str2);
void Analyze_Label(char *str1, char *str2);
void Analyze_Label_Oper(char *str1, char *str2);
void Analyze_Other_Operator(char *str1, char *str2);
void Analyze_Program_Start();
void Output_C_lines(char* str);
void Replace(char* str1, char* str2, char* str3, char* str4);
void Reformat_Logical_Expression(char *str1, char *str2);
void Reformat_Other_Operators(char *str1, char *str2);
void increase_indent();
void decrease_indent();
int Analyze_Const(); //функция анализа константы без знака
int Analyze_Identify();//функция анализа идентификатора
int Analyze_Mnog(); //функция анализа множителя
int Analyze_Slag(); //функция анализа слагаемого
int Analyze_Perem(); //функция анализа переменной
int Analyze_Ae2(); //функция анализа арифметического выражения Ae2
int Analyze_Le1(); //функция анализа логического выражения Le1(на входе-Ae2)
int Analyze_Symb_Le1();//функция анализа символа между двумя Ae2
//блок подпрограмм
/*=========================================================================*/
void increase_indent()
//увеличиваем отступ для формируемых строк на С
{
fid=1;
char bl[buf_len]
=" ";
indent = indent+indent_delta;
if (indent <= 0)
{
*indent_text=0;
}
else
{
strncpy(indent_text,bl,indent);
indent_text[indent]='\0';
}
return;
}
/*=========================================================================*/
void decrease_indent()
//уменьшаем отступ для формируемых строк на С
{
fid=2;
char bl[buf_len]
=" ";
indent = indent-indent_delta;
if (indent < 0) indent=0;
if (indent <= 0)
{
*indent_text=0;
}
else
{
strncpy(indent_text,bl,indent);
indent_text[indent]='\0';
}
return;
}
/*=========================================================================*/
void Analyze_Program_Start()
//формирование начала программы на С
{
fid=3;
char c_prog_line[buf_len];//the output prog header line
Output_C_lines("/*Pascal to C converter by A.Shindin MIEM 2005*/");
strcpy(c_prog_line,"#include <stdio.h>");Output_C_lines(c_prog_line);
strcpy(c_prog_line,"#include <conio.h>");Output_C_lines(c_prog_line);
strcpy(c_prog_line,"#include <ctype.h>");Output_C_lines(c_prog_line);
strcpy(c_prog_line,"#include <string.h>");Output_C_lines(c_prog_line);
strcpy(c_prog_line,"#include <stdlib.h>");Output_C_lines(c_prog_line);
strcpy(c_prog_line,"#define buf_len 255");Output_C_lines(c_prog_line);
}
/*=========================================================================*/
void Output_C_lines(char *str)
//подрограмма вывода в результирующий файл строки str
{
//fid=4;
if (strcmp(str,";")==0)
{}
else
{
char out_c_str[buf_len];
strcpy(out_c_str,indent_text);
strcat(out_c_str,str);
fputs(out_c_str,file_out);
fputs("\n",file_out);
count_out_lines++;
}
}//proc
/*=================================================*/
void ClearOffBlanks(char *str1, char* str2)
//подпрограмма выполняет следующие действия:
// 1. Очищает слева строку от "пропусков" (пробелов, знаков tab и т.п.)
// 2. Добавляет пробелы в начале и конце строки, до и после скобок,
// перед точкой с запятой.
// 3. Двойные пробелы заменяет на одиночные.
// Полученная строка записывается в str2.
{
fid=5;
char sw1[buf_len];
char sw2[buf_len];
//добавление пробелов
strcpy(sw1," ");
strcat(sw1,str1);
strcat(sw1," ");
//замена пропусков (табуляторов и концов строк) на пробелы
Replace(sw1,"\t "," ",sw2);strcpy(sw1,sw2);
Replace(sw1," \t"," ",sw2);strcpy(sw1,sw2);
//excluding the line break character
Replace(sw1,"\n"," ",sw2);strcpy(sw1,sw2);
//замена ";" на " ;"
Replace(sw1,";"," ;",sw2);strcpy(sw1,sw2);
//замена скобок на комбинации пробелов и скобок
Replace(sw1,"("," ( ",sw2);strcpy(sw1,sw2);
Replace(sw1,")"," ) ",sw2);strcpy(sw1,sw2);
//замена двойных пробелов на одиночные
while (pos(sw1," ")>=0)
{
Replace(sw1," "," ",sw2);strcpy(sw1,sw2);
}
strcpy(str2,sw1);
return;
}//proc
/*=========================================================================*/
void Analyze_Other_Operator(char *str1, char *str2)
{
//Анализ и преобразование строк с "прочими" ключевыми словами
// Здесь мы анализируем строку на Паскале, в которой не обнаружены
//ключевые слова, входящие в задачу курсовой работы.
// При анализе учитывается значение флажка ожидаемого оператора
//(переменная "other_oper_flag")
// Этот флажок может иметь одно из следующих значений:
// 0 мы находимся внутри программы, подпрограммы или функции
// 1 мы находимся в секции uses
// 2 мы находимся в секции const
// 3 мы находимся в секции label
// 4 мы находимся в секции var
fid=6;
switch (other_oper_flag)
{
case 0:
Analyze_Assignment(str1, str2);
break;
case 1:
Analyze_Uses_Oper(str1, str2);
break;
case 2:
Analyze_Const_Oper(str1, str2);
break;
case 3:
Analyze_Label_Oper(str1, str2);
break;
case 4:
Analyze_Var_Oper(str1, str2);
break;
}
}
/*=========================================================================*/
void Analyze_If(char *str1, char *str2)
//анализ и преобразование строки на Паскале, содержащей
//ключевое слово IF
//str1=ключевое слово
//str2=список параметров или конец исходной строки
{
fid=7;
int pos_then;
int log_exp_len;
char logical_expression[buf_len];
char *sw;
char sw1[buf_len];
char sw2[buf_len];
char c_expr[buf_len];
char _tail[buf_len];
char str_buf_work[buf_len];
//обработка исходной строки
strcpy(sw1,str2);
pos_then = pos(strupr(sw1),"THEN");
if (pos_then==-1)
{//THEN не найдено - это ошибка - концевик очищаем
log_exp_len=strlen(sw1);
*_tail=0;
//создаем строку на С с комментарием about wrong expression
//*anomaly_text=0;
//strcat(anomaly_text,"\n{");
//strcat(anomaly_text,"Не обнаружен оператор Then");
//strcat(anomaly_text,"}");
//Output_C_lines(c_expr);
//anomaly_counter++;
}
else
{//THEN найдено - берем концевик после "then"
log_exp_len=pos_then;
*_tail=0;
strcpy(_tail,str2+pos_then);
}
//выделяем логическое выражение в IF
*sw2=0;
strncat(sw2,str2,log_exp_len);
//strncat(sw2,"",1);
//Analyze_Le1() работает с переменной str_expr
//убираем пробелы перед анализм le
strcpy(sw1,sw2);
Replace(sw1," ","",sw2);
strcpy(str_expr,sw2);
//printf("\nstr_expr=<%s>",str_expr);
//анализ Le1
fid=7;
s_cur=str_expr;
if(Analyze_Le1()==true)
{
//printf("\n correct logical expr=<%s>",str_expr);
strcpy(sw2,str_expr);
//преобразуем логическое выражение
Reformat_Logical_Expression(sw2,logical_expression);
//создаем строку на С с логическим выражением
*c_expr=0;
strcat(c_expr,"if ( ");
strcat(c_expr,logical_expression);
strcat(c_expr," ) ");
Output_C_lines(c_expr);
}
else
{
//printf("\n incorrect logical expr=<%s>",str_expr);
*c_expr=0;
strcat(c_expr,str1);
strcat(c_expr," ");
strcat(c_expr,str2);
strcat(c_expr,"/*ERR: Error in logical expression*/");
errors_counter++;
Output_C_lines(c_expr);
}
//возвращаем концевик в начало буфера str_buf
*str_buf_work=0;
strcat(str_buf_work,_tail);
strcat(str_buf_work,str_buf);
strcpy(str_buf,str_buf_work);
//gets(anykey);
return;
}//proc
/*=========================================================================*/
void Analyze_Then(char *str1, char *str2)
//анализ и преобразование строки на Паскале, содержащей
//ключевое слово THEN
//str1=ключевое слово
//str2=список параметров или конец исходной строки
{
fid=8;
char str_buf_work[buf_len];
//возвращаем концевик в начало буфера str_buf
*str_buf_work=0;
strcat(str_buf_work,str2);
strcat(str_buf_work,str_buf);
strcpy(str_buf,str_buf_work);
return;
}//proc
/*=========================================================================*/
void Analyze_Until(char *str1, char *str2)
//анализ и преобразование строки на Паскале, содержащей
//ключевое слово UNTIL
//str1=ключевое слово
//str2=список параметров или конец исходной строки
{
fid=9;
int pos_then;
int log_exp_len;
char logical_expression[buf_len];
char *sw;
char sw1[buf_len];
char sw2[buf_len];
char c_expr[buf_len];
char _tail[buf_len];
char str_buf_work[buf_len];
fid=9;
//выделяем логическое выражение
strcpy(sw1,str2);
//вычеркиваем ";"
Replace(sw1,";","",sw2);strcpy(sw1,sw2);
//убираем пробелы перед анализм le
Replace(sw1," ","",sw2);strcpy(sw1,sw2);
strcpy(str_expr,sw1);
//printf("\nstr_expr=<%s>",str_expr);
//Analyze_Le1() работает с переменной str_expr
//анализ
s_cur=str_expr;
if (Analyze_Le1()==true)
{
strcpy(sw1,str_expr);
//преобразуем логическое выражение
Reformat_Logical_Expression(sw1,logical_expression);
//создаем эквивалентные строки на С
*c_expr=0;
strcat(c_expr,"}");
Output_C_lines(c_expr);
decrease_indent(); //уменьшаем отступ, увеличенный по "repeat"
*c_expr=0;
strcat(c_expr,"while !( "); //until (le) ==> while !(le)
strcat(c_expr,logical_expression);
strcat(c_expr," );");
Output_C_lines(c_expr);
}
else
{
printf("\n incorrect logical expr=<%s>",str_expr);
*c_expr=0;
strcat(c_expr,str1);
strcat(c_expr," ");
strcat(c_expr,str2);
strcat(c_expr,"/*ERR: Error in logical expression*/");
errors_counter++;
Output_C_lines(c_expr);
}
return;
}//proc
/*=========================================================================*/
void Analyze_End(char *str1, char *str2)
//анализ и преобразование строки на Паскале, содержащей
//ключевое слово END
//str1=ключевое слово
//str2=список параметров или конец исходной строки
{
fid=10;
char c_expr[buf_len];
char _tail[buf_len];
char str_buf_work[buf_len];
char sw1[buf_len];
char sw2[buf_len];
//формируем эквивалентный текст на С
// end ==> }
*c_expr=0;
strcat(c_expr,"}");
Output_C_lines(c_expr);
decrease_indent(); //уменьшаем отступ
//очищаем str2 от ;
//Replace(str2,";","",sw2);
//strcpy(str2,sw2);
//если после "end" есть текст, то возвращаем его в начало str_buf
*str_buf_work=0;
strcat(str_buf_work,str2);
strcat(str_buf_work,str_buf);
strcpy(str_buf,str_buf_work);
//анализируем, не закончился ли оператор "function"
if (function_flag == 1) //был "function"
{
function_end_level=function_end_level-1; //уменьшаем уровень "end"
if (function_end_level == 0) //если достигли 0, то этот "end"
{ //завершил функцию
function_flag = 0;
}
}
return;
}//proc
/*=========================================================================*/
void Analyze_End_Prog(char *str1, char *str2)
//анализ и преобразование строки на Паскале, содержащей
//ключевое слово END.
//str1=ключевое слово
//str2=список параметров или конец исходной строки
{
fid=11;
char c_expr[buf_len];
char _tail[buf_len];
char str_buf_work[buf_len];
decrease_indent();//уменьшаем отступ
//формируем эквивалентный текст на С
// end. ==> }
*c_expr=0;
strcat(c_expr,"}");
Output_C_lines(c_expr);
return;
}//proc
/*=========================================================================*/
void Analyze_Else(char *str1, char *str2)
//анализ и преобразование строки на Паскале, содержащей
//ключевое слово ELSE
//str1=ключевое слово
//str2=список параметров или конец исходной строки
{
fid=12;
char c_expr[buf_len];
char _tail[buf_len];
char str_buf_work[buf_len];
decrease_indent();//уменьшаем отступ
//формируем эквивалентный текст на С
*c_expr=0;
strcat(c_expr,"else");
Output_C_lines(c_expr);
//возвращаем концевик текста в начало str_buf
*str_buf_work=0;
strcat(str_buf_work,str2);
strcat(str_buf_work,str_buf);
strcpy(str_buf,str_buf_work);
//increase_indent();//снова увеличиваем отступ
return;
}//proc
/*=========================================================================*/
void Analyze_Begin(char *str1, char *str2)
//анализ и преобразование строки на Паскале, содержащей
//ключевое слово BEGIN
//str1=ключевое слово
//str2=список параметров или конец исходной строки
{
fid=13;
char c_expr[buf_len];
char _tail[buf_len];
char str_buf_work[buf_len];
char sw1[buf_len];
char sw2[buf_len];
//копируем концевик от "begin" в рабочую строку
strcpy(_tail,str2);
increase_indent(); //увеличиваем отступ
//Проверяем, относится ли "begin" к тексту главной программы на Паскале
if (function_flag == 0)
{//Да, этот "begin" относится к тексту главной программы
indent=0; //сбрасываем отступ
*indent_text=0; //и очищаем строку отступа
//формируем текст на С эквивалентный началу программы
*c_expr=0;
strcat(c_expr,"\n/*MAIN PROGRAM*/\n");//обозначаем место
Output_C_lines(c_expr); //главной программы
*c_expr=0;
strcat(c_expr,"void main()");
Output_C_lines(c_expr);
function_flag = 2;//теперь мы находимся в главной программе
}
other_oper_flag=0;
function_end_level = function_end_level+1;//мы нашли "begin" -
//увеличим уровень "begin-end"
//printf("\nbeg_stmt: <%s> f_flag: <%d> fe_level: <%d>",str2,function_flag,function_end_level);
//формируем начало блока, если это не первый begin внутри function
if ((function_flag == 1) && (function_end_level == 1))
{
//printf("\n first begin in function");
}
else
{
//printf("\n non-first begin in function");
*c_expr=0;
strcat(c_expr,"{");
Output_C_lines(c_expr);
}
//весь концевик после "begin" отправляем в начало str_buf
*str_buf_work=0;
strcat(str_buf_work,_tail);
strcat(str_buf_work,str_buf);
strcpy(str_buf,str_buf_work);
return;
}//proc
/*=========================================================================*/
void Reformat_Logical_Expression(char *str1, char *str2)
//анализ и преобразование строки на Паскале, содержащей
//логическое выражение, в эквивалентное выражение на С
//str1=исходное выражение
//str2=выходное выражение
{
fid=14;
char sw1[buf_len];
char sw2[buf_len];
strcpy(sw1,str1);
//преобразуем выражение в канонический вид (проводим замены)
//это необходимо, чтобы отличить обработку "=" от ">=" и т.п.
//сначала заменяются более длинные операции, затем короткие
//длинные
Replace(sw1,">=",".GE.",sw2);strcpy(sw1,sw2);
Replace(sw1,"<=",".LE.",sw2);strcpy(sw1,sw2);
Replace(sw1,":=",".ASGN.",sw2);strcpy(sw1,sw2);
//короткие
Replace(sw1,">",".GT.",sw2);strcpy(sw1,sw2);
Replace(sw1,"<",".LT.",sw2);strcpy(sw1,sw2);
Replace(sw1,"=",".EQ.",sw2);strcpy(sw1,sw2);
//теперь преобразуем из канонического вида в вид на С
Replace(sw1,".GE.",">=",sw2);strcpy(sw1,sw2);
Replace(sw1,".LE.","<=",sw2);strcpy(sw1,sw2);
Replace(sw1,".GT.",">",sw2);strcpy(sw1,sw2);
Replace(sw1,".LT.","<",sw2);strcpy(sw1,sw2);
Replace(sw1,".EQ.","==",sw2);strcpy(sw1,sw2);
Replace(sw1,".ASGN."," = ",sw2);strcpy(sw1,sw2);
//проводим дополнительные замены для др. лог.операций
Replace(sw1," and "," && ",sw2);strcpy(sw1,sw2);
Replace(sw1," And "," && ",sw2);strcpy(sw1,sw2);
Replace(sw1," AND "," && ",sw2);strcpy(sw1,sw2);
Replace(sw1," or "," || ",sw2);strcpy(sw1,sw2);
Replace(sw1," Or "," || ",sw2);strcpy(sw1,sw2);
Replace(sw1," OR "," || ",sw2);strcpy(sw1,sw2);
strcpy(str2,sw1);
return;
}//proc
/*=========================================================================*/
void Reformat_Other_Operators(char *str1, char *str2)
//str1=исходное выражение
//str2=выходное выражение
{
fid=30;
char sw1[buf_len];
char sw2[buf_len];
strcpy(sw1,str1);
Replace(sw1,"writeln","printf",sw2);strcpy(sw1,sw2);
Replace(sw1,"readln","scanf",sw2);strcpy(sw1,sw2);
strcpy(str2,sw1);
}
/*=========================================================================*/
void Analyze_Repeat(char *str1, char *str2)
//подрограмма на анализ оператора "Repeat"
//преобразуется в оператор do {
//str1=исходное выражение
//str2=выходное выражение
{
fid=15;
char c_expr[buf_len];
char _tail[buf_len];
char str_buf_work[buf_len];
char sw1[buf_len];
char sw2[buf_len];
//выделение концевика от "repeat"
strcpy(_tail,str2);
//формируем эквивалентный текст на С (repeat ==> do {)
*c_expr=0;
strcpy(c_expr,"do");
Output_C_lines(c_expr);
increase_indent();//увеличиваем отступ (он будет уменьшен в until)
strcpy(c_expr,"{");
Output_C_lines(c_expr);
//возвращаем концевик в начало буфера накпления Паскаля str_buf
*str_buf_work=0;
strcat(str_buf_work,_tail);
strcat(str_buf_work,str_buf);
strcpy(str_buf,str_buf_work);
return;
}//proc
/*=========================================================================*/
void Analyze_Function(char *str1, char *str2)
{
fid=16;
//подрограмма на анализ оператора "Function"
//str1=исходное выражение
//str2=выходное выражение
char c_str[buf_len];
char function_name[buf_len];
char function_type[buf_len];
char function_parametres[buf_len];
char function_parametres_temp[buf_len];
char *sw,*sw1,*sw2;//рабочие строки для GetHead и GetTail
char w_str[buf_len];//рабочая строка
char w_str2[buf_len];//рабочая строка
char str_buf_work[buf_len];//рабочая строка
char w_str_par[buf_len];
char convert_str[buf_len];
char p_sep[1]="Й"; //строка используется для разделения групп параметров
int more_par_groups=1; //флажок продолжения анализа групп параметров
int more_parameters=1; //флажок продолжения анализа групп параметров
char parm_group[buf_len]; //для группы параметров
char parm[buf_len]; //для параметров
char parm_type[buf_len]; //для типа параметра
char parm_type_valid[buf_len]; //для допустимых типов параметров
char parm_tstr[buf_len]; //для анализа параметров
char c_parms [buf_len]; //для накопления эквивалентного
//описания параметров на С
int p_zs; //поз.закр.скобки
int p_ptype; //поз.корр.типа параметра
int flag_not_OK=0; //флажок некорректности предложения function
strcpy(parm_type_valid,",INTEGER,STRING,");
//чистим строки для С
*c_str=0;
*c_parms=0;
//очищаем строку от пробелов и формируем рабочую строку
//Replace(str2," ","",w_str);
strcpy(w_str,str2);
//анализируем, есть ли закр. скобка
p_zs=pos(str2,")");
if (p_zs==-1) //это еще не полный вариант оператора function
{
*w_str=0;
strcat(w_str,str1);
strcat(w_str, " ");
strcat(w_str,str2);
Replace(w_str,";",p_sep,w_str2); //заменяем ";" на разделитель
//возвращаем все неоконченное предложение в начало str_buf
*str_buf_work=0;
strcat(str_buf_work,w_str2);
strcat(str_buf_work,str_buf);
strcpy(str_buf,str_buf_work);
}
else //теперь обрабатываем весь оператор function с разделителями групп параметров
{
//выделяем имя функции
sw=GetHead(w_str,"(");
strcpy(function_name,sw);
free(sw);
//printf("function name:<%s>\n",function_name);
//анализ имени функции на идентификатор
strcpy(str_expr,function_name);
s_cur=str_expr;
if(Analyze_Identify()==true)
{}
else
{flag_not_OK++;}
//if (flag_not_OK > 0) {printf("func.name");}
//уменьшаем рабочую строку
strcpy(w_str,str2);
sw=GetTail(w_str,")");
strcpy(w_str,sw);
free(sw);
//printf("w_str 1:<%s>\n",w_str);
sw=GetTail(w_str,":");
strcpy(w_str,sw);
free(sw);
//printf("w_str 2:<%s>\n",w_str);
sw=GetHead(w_str,";");
strcpy(w_str,sw);
free(sw);
//printf("w_str 3:<%s>\n",w_str);
Replace(w_str," ","",convert_str);
strcpy(w_str,convert_str);
//printf("w_str 4:<%s>\n",w_str);
//выделяем тип функции
strcpy(function_type,w_str);
//printf("function type 1:<%s>\n",function_type);
//преобразуем тип функции
if(strcmp(function_type,"integer")==0)
{
Replace(function_type,"integer","int",convert_str);
}
if(strcmp(function_type,"string")==0)
{
Replace(function_type,"string","char",convert_str);
}
strcpy(function_type,convert_str);
//printf("function type 2:<%s>\n",function_type);
//параметры
strcpy(w_str,str2);
//выделяем параметры функции
sw1=GetTail(w_str,"(");
strcpy(w_str_par,sw1);
free(sw1);
sw2=GetHead(w_str_par,")");
strcpy(function_parametres,sw2);
free(sw2);
//printf("function par:<%s>\n",function_parametres);
//сохраняем function_parametres
strcpy(function_parametres_temp,function_parametres);
//добавляем в конец function_parametres p_sep для корр.анализа
strcat(function_parametres,p_sep);
//обрабатываем группы параметров
more_par_groups=1;
while(more_par_groups==1)
{
sw1=GetHead(function_parametres,p_sep);
strcpy(parm_group,sw1);
free(sw1);
if (strlen(parm_group)==0) //очередная группа не выделена
{
more_par_groups=0;
}
else //анализируем параметры группы
{
//printf("parm group:<%s>\n",parm_group);
//удаляем описатель "var", если он есть и пробелы
Replace(parm_group,"var","",parm_tstr);strcpy(parm_group,parm_tstr);
Replace(parm_group,"Var","",parm_tstr);strcpy(parm_group,parm_tstr);
Replace(parm_group," ","",parm_tstr);strcpy(parm_group,parm_tstr);
//выделяем тип параметров
sw1=GetTail(parm_group,":");
strcpy(parm_type,sw1);
free(sw1);
//допустим ли этот тип параметра?
strcpy(parm_tstr,",");
strcat(parm_tstr,parm_type);
strcat(parm_tstr,",");
strupr(parm_tstr);
p_ptype=pos(parm_type_valid,parm_tstr);
if (p_ptype==-1) //если это некорр.тип параметра
{
flag_not_OK++;
strcpy(parm_type,"illegal");
//if (flag_not_OK > 0) {printf("parm.type");}
}
//printf("parm type:<%s>\n",parm_type);
//временно заменяем : на ,: для корректного анализа параметров
Replace(parm_group,":",",:",parm_tstr);strcpy(parm_group,parm_tstr);
//обрабатываем параметры
more_parameters=1;
while(more_parameters==1)
{
sw1=GetHead(parm_group,",");
strcpy(parm,sw1);
free(sw1);
//printf("parm:<%s>\n",parm);
if (strlen(parm)==0) //очередной параметр не выделен
{
more_parameters=0;
}
else
{
//анализ имени параметра корректность идентификатор
strcpy(str_expr,parm);
s_cur=str_expr;
if(Analyze_Identify()==true)
{
}
else
{
flag_not_OK++;
//if (flag_not_OK > 0) {printf("parm.name");}
}
//формируем строку для С
if (strcmp(strupr(parm_type),"INTEGER")==0)
{
strcat(c_parms, "int ");
strcat(c_parms, parm);
}
else if (strcmp(strupr(parm_type),"STRING")==0)
{
strcat(c_parms, "char* ");
strcat(c_parms, parm);
}
else
{
strcat(c_parms, "illegal ");
strcat(c_parms, parm);
}
strcat(c_parms, ", ");
//остаток строки parm_group переписываем в parm_group
//для продолжения анализа параметров
sw1=GetTail(parm_group,",");
strcpy(parm_group,sw1);
free(sw1);
}
}
//остаток строки function_parametres переписываем в
//function_parametres для продолжения анализа групп
sw1=GetTail(function_parametres,p_sep);
strcpy(function_parametres,sw1);
free(sw1);
}
}
//убираем из c_parms последнюю запятую
Reverse(c_parms,parm_tstr);
sw1=GetTail(parm_tstr,",");
strcpy(parm_tstr,sw1);
free(sw1);
Reverse(parm_tstr,c_parms);
//анализируем, все ли корректно
if (flag_not_OK > 0)
{
*c_str=0;
strcat(c_str,"\n/*ERR: Incorrect identifier(s) or parameter(s) in the function*/");
errors_counter++;
Output_C_lines(c_str);
}
//делаем эквивалентную строку на C
*c_str=0;
strcat(c_str,function_type);
strcat(c_str," ");
strcat(c_str,function_name);
strcat(c_str," (");
strcat(c_str,c_parms);
strcat(c_str,") ");
//printf("c_str:<%s>\n",c_str);
Output_C_lines(c_str);
*c_str=0;
strcat(c_str," {");
Output_C_lines(c_str);
function_flag=1;
other_oper_flag=0;
}
return;
}//proc
/*=========================================================================*/
void Analyze_GoTo(char *str1, char *str2)
//подрограмма на анализ оператора goto
//str1=исходное выражение
//str2=выходное выражение
{
fid=17;
char sw1[buf_len];
char sw2[buf_len];
char c_str[buf_len];
*c_str=0;
strcat(c_str,str1);
strcat(c_str," ");
strcat(c_str,str2);
strcat(c_str," ");
Output_C_lines(c_str);
return;
}//proc
/*=========================================================================*/
void Analyze_Assignment(char *str1, char *str2)
//подрограмма на анализ оператора присваивания ':=' and others
//str1=исходное выражение
//str2=выходное выражение
{
fid=18;
char sw1[buf_len];
char sw2[buf_len];
char temp_str[buf_len];
char c_str[buf_len];
char *tsw1;
char *swork1;//строки для GetHead и GetTail
char *swork2;
char left_side[buf_len];
char right_side[buf_len];
int flag_ok=0;//признак правильности присваивания
int pasgn; //позиция оператора присваивания
*c_str=0;
*left_side=0;
*right_side=0;
Replace(str1," ","",sw1);
strcpy(str1,sw1);
Replace(str2," ","",sw2);
strcpy(str2,sw2);
*sw1=0;
*sw2=0;
//это оператор присваивания?
pasgn=pos(str1,":=");
if (pasgn>0) //это оператор присваивания
{
//printf("\ncorrect asgn left=<%s> right=<%s>",str1,str2);
//формируем общую строку
strcpy(sw1,str1);
strcat(sw1,str2);
Replace(sw1," ","",sw2);
strcpy(sw1,sw2);
//выделяем левую сторону
swork1=GetHead(sw1,":=");
strcpy(left_side,swork1);
free(swork1);
//выделяем правую сторону
swork2=GetTail(sw1,":=");
strcpy(right_side,swork2);
free(swork2);
swork2=GetHead(right_side,";");
strcpy(right_side,swork2);
free(swork2);
//printf("\nre-asgn left=<%s> right=<%s>",left_side,right_side);
//анализ левой части на идентификатор
strcpy(str_expr,left_side);
s_cur=str_expr;
if(Analyze_Identify()==false)
{
flag_ok=0;
}
else
{
flag_ok++;
}
//анализ правой части присваивания
strcpy(str_expr,right_side);
s_cur=str_expr;
if(Analyze_Ae2()==false)
{
flag_ok=0;
}
else
{
flag_ok++;
}
if(flag_ok==2)//обе части верны
{
strcat(c_str,left_side);
strcat(c_str,":=");
strcat(c_str,right_side);
strcat(c_str,";");
strcpy(sw1,c_str);
Reformat_Logical_Expression(sw1,sw2);
strcpy(c_str,sw2);
Reformat_Other_Operators(c_str,sw1);
strcpy(c_str,sw1);
}
else //одна из частей неверна
{
strcat(c_str,left_side);
strcat(c_str,":=");
strcat(c_str,right_side);
strcat(c_str,";");
strcat(c_str,"/*ERR:Error in assignment*/");
errors_counter++;
}
}
else //это не оператор присваивания
{
//printf("\nincorr asgn left=<%s> right=<%s>",str1,str2);
strcat(c_str,str1);
strcat(c_str,str2);
strcpy(sw1,c_str);
Reformat_Logical_Expression(sw1,sw2);
strcpy(c_str,sw2);
Reformat_Other_Operators(c_str,sw1);
strcpy(c_str,sw1);
}
fid=18;
Output_C_lines(c_str);
//gets(anykey);
return;
}//proc
/*=========================================================================*/
void Analyze_Uses(char *str1, char *str2)
//подпрограмма анализа ключевого слова 'uses'
//str1=исходное выражение
//str2=выходное выражение
{
fid=19;
char *work_str;
char str_buf_work[buf_len];
char c_str[buf_len];
//устанавливаем флажок ожидаемых операций other_oper_flag в 1.
//этот флажок анализируется в функции Analyze_Other_Operator
other_oper_flag=1; //означает: вошли в секцию Uses
//write as comment
*c_str=0;
strcat(c_str, "/*<USES>*/");
Output_C_lines(c_str);
//возвращаем концевик в начало str_buf
*str_buf_work=0;
strcat(str_buf_work,str2);
strcat(str_buf_work,str_buf);
strcpy(str_buf,str_buf_work);
return;
}//proc
/*=========================================================================*/
void Analyze_Uses_Oper(char *str1, char *str2)
//!!
//str1=исходное выражение
//str2=выходное выражение
{
fid=20;
char *work_str;
char str_buf_work[buf_len];
char c_str[buf_len];
//writing out as comments
*c_str=0;
strcat(c_str,"/*<uses> ");
strcat(c_str,str1);
strcat(c_str,str2);
strcat(c_str,"*/");
Output_C_lines(c_str);
return;
}
/*=========================================================================*/
void Analyze_Const(char *str1, char *str2)
//подпрограмма анализа ключевого слова 'Const'
//str1=исходное выражение
//str2=выходное выражение
{
fid=21;
char *work_str;
char str_buf_work[buf_len];
char c_str[buf_len];
//устанавливаем флажок ожидаемых операций other_oper_flag в 1.
//этот флажок анализируется в функции Analyze_Other_Operator
other_oper_flag=2; //означает: вошли в секцию Const
//writing comment
*c_str=0;
strcat(c_str, "/*<CONST>*/");
Output_C_lines(c_str);
//возвращаем концевик в начало str_buf
*str_buf_work=0;
strcat(str_buf_work,str2);
strcat(str_buf_work,str_buf);
strcpy(str_buf,str_buf_work);
return;
}//proc
/*=========================================================================*/
void Analyze_Const_Oper(char *str1, char *str2)
//!!
//str1=исходное выражение
//str2=выходное выражение
{
fid=22;
char sw1[buf_len];
char sw2[buf_len];
char *sw;
char const_name[buf_len];
char const_val[buf_len];
char tmp[buf_len];
char c_str[buf_len];
*sw1=0;
*sw2=0;
//printf("<str1:%s>\n",str1);
//printf("<str2:%s>\n",str2);
//extracting the const name
*const_name=0;
sw=GetHead(str1,"=");
strcpy(const_name,sw);
free(sw);
Replace(const_name," ","",tmp);
strcpy(const_name,tmp);
//extracting the const value
sw=GetTail(str1,"=");
strcpy(const_val,sw);
free(sw);
Replace(const_val," ","",tmp);
strcpy(const_val,tmp);
s_cur=const_name;
if(Analyze_Identify()==true)
{
//writing out constants
*c_str=0;
strcat(c_str,"#define ");
strcat(c_str,const_name);
strcat(c_str," ");
strcat(c_str,const_val);
//printf("<c_str:>%s",c_str);
Output_C_lines(c_str);
}
else
{
*c_str=0;
strcat(c_str,str1);
strcat(c_str," ");
strcat(c_str,str2);
strcat(c_str,"/*ERR: Error in logical expression*/");
errors_counter++;
Output_C_lines(c_str);
}
return;
}
/*=========================================================================*/
void Analyze_Label(char *str1, char *str2)
//подпрограмма анализа ключевого слова 'Label'
//str1=исходное выражение
//str2=выходное выражение
{
fid=23;
char *work_str;
char str_buf_work[buf_len];
char c_str[buf_len];
//устанавливаем флажок ожидаемых операций other_oper_flag в 1.
//этот флажок анализируется в функции Analyze_Other_Operator
other_oper_flag=3; //означает: вошли в секцию Label
//write as comment
*c_str=0;
strcat(c_str, "/*<LABEL>*/");
Output_C_lines(c_str);
//возвращаем концевик в начало str_buf
*str_buf_work=0;
strcat(str_buf_work,str2);
strcat(str_buf_work,str_buf);
strcpy(str_buf,str_buf_work);
return;
}//proc
/*=========================================================================*/
void Analyze_Label_Oper(char *str1, char *str2)
//!!
//str1=исходное выражение
//str2=выходное выражение
{
fid=24;
char *work_str;
char str_buf_work[buf_len];
char c_str[buf_len];
//writing out as comments
*c_str=0;
strcat(c_str,"/*<label> ");
strcat(c_str,str1);
strcat(c_str,str2);
strcat(c_str,"*/");
Output_C_lines(c_str);
return;
}
/*=========================================================================*/
void Analyze_Var(char *str1, char *str2)
//подпрограмма анализа ключевого слова 'Var'
//str1=исходное выражение
//str2=выходное выражение
{
fid=25;
char *work_str;
char str_buf_work[buf_len];
char c_str[buf_len];
//устанавливаем флажок ожидаемых операций other_oper_flag в 1.
//этот флажок анализируется в функции Analyze_Other_Operator
other_oper_flag=4; //означает: вошли в секцию Var
//записываем заголовок секции в комментарий
*c_str=0;
strcat(c_str, "/*<VAR>*/");
Output_C_lines(c_str);
//возвращаем концевик в начало str_buf
*str_buf_work=0;
strcat(str_buf_work,str2);
strcat(str_buf_work,str_buf);
strcpy(str_buf,str_buf_work);
return;
}//proc
/*=========================================================================*/
void Analyze_Var_Oper(char *str1, char *str2)
//!!
//str1=исходное выражение
//str2=выходное выражение
{
fid=26;
char *work_str;
char str_buf_work[buf_len];
char c_str[buf_len];
char sw1[buf_len];
char sw2[buf_len];
char *tsw1;
char *tsw2;
char varoper[buf_len];
char varoper_up[buf_len];
char varname[buf_len];
char vararray[buf_len];
char vararray_tail[buf_len];
char vartype[buf_len_short];
char vartype_init[buf_len_short];
char seps[buf_len_short];
char arr_low_bound[buf_len_short];
char arr_high_bound[buf_len_short];
char arr_sz[buf_len_short];
int more_arr_desc;
int posnspace;
int string_size;
char string_size_char[buf_len_short];
int pas_lb_val;
int pas_hb_val;
int c_arr_size;
strcpy(seps," ");
//printf("var_oper: str1: <%s> str2: <%s>\n",str1,str2);
//gets(anykey);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//forming the whole asgn expression
*sw1=0;
strcat(sw1," ");
strcat(sw1,str1);
strcat(sw1," ");
strcat(sw1,str2);
strcat(sw1," ");
Replace(sw1,";"," ",sw2);strcpy(sw1,sw2);
Replace(sw1,":"," : ",sw2);strcpy(sw1,sw2);
Replace(sw1," "," ",sw2);strcpy(sw1,sw2);
strcpy(varoper,sw2);
strcpy(varoper_up,strupr(sw2));
//extracting the variable name
tsw1=GetHead(varoper,":");
strcpy(varname,tsw1);
free(tsw1);
LTrim(varname,seps,sw1);
RTrim(sw1,seps,sw2);
strcpy(varname,sw2);
//analyze varname on identify
Replace(varname," ","",str_expr);
strcpy(varname,str_expr);
s_cur=varname;
if(Analyze_Identify()==true)
{}
else
{
*c_str=0;
strcat(c_str,str1);
strcat(c_str," ");
strcat(c_str,str2);
strcat(c_str,"/*ERR: Error in logical expression*/");
errors_counter++;
Output_C_lines(c_str);
}
//printf("var_name: <%s>\n",varname);
//gets(anykey);
//extracting the variable array descriptor and type
tsw1=GetTail(varoper_up,"ARRAY");
strcpy(sw1,tsw1);
free(tsw1);
tsw1=GetHead(sw1,"OF");
strcpy(sw1,tsw1);
free(tsw1);
strcpy(vararray,sw1);
//extracting the variable type
strcpy(sw1,varoper);
LTrim(sw1,seps,sw2);strcpy(sw1,sw2);
RTrim(sw1,seps,sw2);strcpy(sw1,sw2);
Reverse(sw1,sw2);
tsw1=GetHead(sw2," ");
strcpy(sw1,tsw1);
free(tsw1);
Reverse(sw1,sw2);
strcpy(vartype_init,sw2);
strcpy(vartype,strupr(sw2));
//printf("varname:<%s> vararray:<%s> vartype:<%s>\n",varname,vararray,vartype);
*c_str=0;
//analyzing var type
string_size=-1;//not a string
if (strcmp(vartype,"INTEGER")==0)
{
strcat(c_str,"int");
}
else if (pos(vartype,"STRING")>-1)
{
strcat(c_str,"char");
string_size=0; //this is a string
strcpy(sw1,vartype_init);
tsw1=GetHead(sw1,"]");
strcpy(sw1,tsw1);
free(tsw1);
tsw1=GetTail(sw1,"[");
strcpy(sw1,tsw1);
free(tsw1);
if (strlen(sw1) > 0) //string size is specified
{
LTrim(sw1,seps,sw2);strcpy(sw1,sw2);
RTrim(sw1,seps,sw2);strcpy(sw1,sw2);
strcpy(string_size_char,sw1);
string_size=1;
}
}
else
{
strcat(c_str,"illegal");
}
strcat(c_str," ");
//adding var name
strcat(c_str,varname);
//printf("after var name: <%s>\n",c_str);
//was it a string with size?
if (string_size>0)
{
strcat(c_str,"[");
strcat(c_str,string_size_char);
strcat(c_str,"]");
}
//parsing the array descriptor
more_arr_desc=1;
if (strlen(vararray)==0)
{
more_arr_desc=0;
}
while (more_arr_desc==1)
{
tsw1=GetHead(vararray,"]");
strcpy(sw1,tsw1);
free(tsw1);
//printf("vararray1: <%s>\n",vararray);
tsw2=GetTail(vararray,"]");
strcpy(vararray_tail,tsw2);
free(tsw2);
//printf("vararray_tail1: <%s>\n",vararray_tail);
//gets(anykey);
tsw1=GetTail(sw1,"[");
strcpy(sw1,tsw1);
free(tsw1);
//printf("vararray_pas: <%s>\n",sw1);
if (strlen(sw1)==0)
{
more_arr_desc=0;
}
else
{
strcpy(arr_sz,sw1);
//low boundary
tsw1=GetHead(arr_sz,"..");
strcpy(sw1,tsw1);
free(tsw1);
LTrim(sw1,seps,sw2);strcpy(sw1,sw2);
RTrim(sw1,seps,sw2);strcpy(sw1,sw2);
pas_lb_val=atoi(sw1);
//high boundary
tsw1=GetTail(arr_sz,"..");
strcpy(sw1,tsw1);
free(tsw1);
LTrim(sw1,seps,sw2);strcpy(sw1,sw2);
RTrim(sw1,seps,sw2);strcpy(sw1,sw2);
pas_hb_val=atoi(sw1);
//C array size
c_arr_size = abs(pas_hb_val - pas_lb_val + 1);
//adding C definition of the array
itoa(c_arr_size, sw2, 10);
strcat(c_str,"[");
strcat(c_str,sw2);
strcat(c_str,"]");
strcpy(vararray,vararray_tail);//deleting the arr descr from vararray
//printf("c_str: <%s> vararray: <%s>\n",c_str,vararray);
//gets(anykey);
}
}
strcat(c_str,";");
//writing out
Output_C_lines(c_str);
return;
}
/*=========================================================================*/
void Pas_to_C(char* pas_str, char* c_str)
//подпрограмма анализа предложения на Паскале на ключевые слова и вызов
//необходимых подпрограмм обработки ключевых слов
{
fid=27;
char sw1[buf_len];
char sw2[buf_len];
char keyw_name0[buf_len]; //initial operator name
char keyw_name[buf_len]; //uppercased operator name
char keyw_list[buf_len];
char c_work[buf_len];
char c_work_work[buf_len];
char *sw;
int res;
strcpy(sw1,pas_str);
ClearOffBlanks(sw1,sw2); //обрабатываем пробелы
strcpy(c_work,sw2);
//анализ строки на ключевое слово
//выделяем само ключевое слово
strcpy(sw1,c_work);
sw=GetTail(sw1," ");
strcpy(sw1,sw);
free(sw);
//выделяем список параметров кл.слова (концевик)
sw=GetTail(sw1," ");
strcpy(keyw_list,sw);
free(sw);
//формируем для анализа ключевое слово в верхнем регистре
sw=GetHead(sw1," "); //ключевое слово - это первое слово (до пробела)
strcpy(keyw_name0,sw); //исходное ключевое слово
strcpy(keyw_name,sw); //ключевое словов верхнем регистре (загл.буквы)
free(sw);
if (strcmp(strupr(keyw_name),"IF")==0)
{
//анализ оп-ра "if"
Analyze_If(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"THEN")==0)
{
//анализ оп-ра "then"
Analyze_Then(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"ELSE")==0)
{
//анализ оп-ра "else"
Analyze_Else(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"BEGIN")==0)
{
//анализ оп-ра "begin"
Analyze_Begin(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"REPEAT")==0)
{
//анализ оп-ра "repeat"
Analyze_Repeat(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"UNTIL")==0)
{
//анализ оп-ра "until"
Analyze_Until(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"END")==0)
{
//анализ оп-ра "end"
Analyze_End(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"FUNCTION")==0)
{
//анализ оп-ра "function"
Analyze_Function(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"VAR")==0)
{
//анализ оп-ра "var"
Analyze_Var(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"CONST")==0)
{
//анализ оп-ра "const"
Analyze_Const(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"USES")==0)
{
//анализ оп-ра "uses"
Analyze_Uses(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"LABEL")==0)
{
//анализ оп-ра "label"
Analyze_Label(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"END.")==0)
{
//анализ оп-ра "end."
Analyze_End_Prog(keyw_name0,keyw_list);
}
else if (strcmp(strupr(keyw_name),"GOTO")==0)
{
//анализ оп-ра "goto"
Analyze_GoTo(keyw_name0,keyw_list);
}
else
{
//other
Analyze_Other_Operator(keyw_name0,keyw_list);
}
//здесь мы проводим отладочную выдачу в выходной файл
//исходного текста на Паскале как комментария на С
*c_work_work=0;
strcat(c_work_work,"{Pascal:<");
strcat(c_work_work,c_work);
strcat(c_work_work,"}");
strcpy(c_work,c_work_work);
//Output_C_lines(c_work);
}//proc
/*=========================================================================*/
int pos(char *str1, char *str2)
//функция pos находит позицию строки str2 внутри строки str1
{
char* strFind=strstr(str1,str2);
if(strFind==NULL)
{
return -1;
}
else
{
return strFind-str1;
}
}//proc
/*=================================================*/
void Replace(char* str1, char* str2, char* str3, char* str4)
{
//подпрограмма замены подстроки в строке
//str1-строка, в которой осуществляется перестановка
//str2-часть строки str1, которую нужно заменить на str3
//str3-строка, заменяющая все вхождения str2 в str1
//str4-полностью преобразованная строка
int str1_pos;
int str1_len;
int str2_pos;
int str2_len;
int str3_len;
str1_len = strlen(str1);
str2_len = strlen(str2);
str3_len = strlen(str2);
*str4=0;
if (str1_len==0)
{//если str1 - пустая строка, то возвращается пустая строка str4
return;
}
else if (str2_len==0)
{//если str2 - пустая строка, то строка str4 равна str1
strcpy(str4,str1);
return;
}
else
{
for (str1_pos=0;str1_pos<str1_len;str1_pos++)
{
str2_pos=pos(str1+str1_pos,str2);
if (str2_pos==0)
{
if (str3_len==0)
{//не приписываем пустую строку str3 к str4
}
else
{//приписываем строку str3 к str4
strcat(str4,str3);
str1_pos = str1_pos+str2_len-1; //перемещаемся в str1 в позицию,
} //следующую за подстрокой str2
}
else
{//приписываем текущий символ из str1 к str4
strncat(str4,str1+str1_pos,1);
}
}
}
}//proc
/*=========================================================================*/
void Reverse(char *str1, char *str2)
//Процедура переворачивает строку "с ног на голову"
{
int n, //длина строки str
i, //счетчик
l;
n=strlen(str1);
*str2=0;
if (n<=1)
{
strcpy(str2,str1);
}
else
{
i=0;
l=n-1;
while(i<n)
{
str2[i]=str1[l];str2[i+1]='\0';
l--;i++;
}
str2[i]='\0';
}
return;
}//proc
/*=================================================*/
void LTrim(char *str1, char *seps, char *str2)
//trims left chars in string str1 (chars from seps); result is copied to str2
{
int posnspace;
posnspace=strspn(str1,seps);
strcpy(str2,str1+posnspace);
//printf("LTrim: str1:<%s>, seps:<%s>, str2:<%s>\n",str1,seps,str2);
}
/*=================================================*/
void RTrim(char *str1, char *seps, char *str2)
//trims right chars in string str1 (chars from seps); result is copied to str2
{
int posnspace;
char sw1[buf_len];
char sw2[buf_len];
Reverse(str1,sw1);
//printf("reverse in: <%s> out: <%s>\n",str1,sw1);
LTrim(sw1,seps,sw2);
Reverse(sw2,sw1);
//printf("reverse in: <%s> out: <%s>\n",sw2,sw1);
strcpy(str2,sw1);
//printf("RTrim: str1:<%s>, seps:<%s>, str2:<%s> \n",str1,seps,str2);
}
/*=================================================*/
char* GetHead(char *str1, char *str2)
//функция GetHead ищет в строке str1 строку str2.
//Если такая строка найдена, то возвращается указатель на
//динамически формируемую строку, содержащую текст из str1
//c 0-й позиции по позицию, предшествующую str2.
//Если такая строка не найдена, то возвращается указатель на
//динамически формируемую строку, содержащую пустой текст.
//Вызывающая программа должна освободить память ответной строки.
{
char *strres=NULL;
int ipos=pos(str1,str2);
if(ipos==-1)
{
strres=(char*)malloc(1);
*strres=0;
return(strres);
}
else
{
strres=(char*)malloc(ipos+1);
strncpy(strres,str1,ipos);
strres[ipos]='\0';
return strres;
}
}//proc
/*=================================================*/
//функция GetTail ищет в строке str1 строку str2.
//Если такая строка найдена, то возвращается указатель на
//динамически формируемую строку, содержащую текст из str1
//c позиции, следующей после конца str2 по последнюю позицию str1.
//Если такая строка не найдена, то возвращается указатель на
//динамически формируемую строку, содержащую пустой текст.
//Вызывающая программа должна освободить память ответной строки.
char* GetTail(char *str1, char* str2)
{
char *strres;
int istrlen=0;
int ipos=pos(str1,str2);
if(ipos==-1)
{
strres=(char*)malloc(1);
strres[0]='\0';
return strres;
}
istrlen=strlen(str1)-(ipos+strlen(str2));
strres=(char*)malloc(istrlen+1);
strres[0]='\0';
if(istrlen==0)
return strres;
strncpy(strres,str1+ipos+strlen(str2),istrlen);
strres[istrlen]='\0';
return strres;
}//proc
/*=================================================*/
void GetPaths()
{//получение путей доступа и имен исходного и выходного файлов
fid=28;
int RC=0;
int in_path_ok=0;
int out_path_ok=0;
char pas_name [buf_len];
char c_name [buf_len];
char in_path [buf_len];
char out_path [buf_len];
char sw1 [buf_len];
char sw2 [buf_len];
char *swork1; //рабочие строки (GetHead, GetTail)
char *swork2;
//входной файл
while (in_path_ok == 0)
{
printf("Введите имя входного файла\n");
gets(in_path);
*sw1=0;*sw2=0;
strcpy(sw1,in_path);
Reverse(sw1,sw2);
// swork1=GetHead(sw2,"\");
// strcpy(sw2,swork1);
// free(swork1);
Reverse(sw2,pas_name);
// free (swork1);
//проверка правильности ввода входного файла
if (strlen(pas_name)==0)
{//пустой путь
printf("Неверный путь: <%s>\n",in_path);
anomaly_counter++;
}
else
{
swork1=GetHead(pas_name,".pas");
strcpy(sw2,swork1);
free(swork1);
if (strlen(sw2)==0)
{//это не файл .pas
printf("Имя файла :<%s> задано некорректно. Это не .pas файл.\n",pas_name);
anomaly_counter++;
}
else
{
file_in=fopen(in_path, "r"); //открываем файл на чтение
if(file_in==NULL)
{//ошибка открытия файла
printf("Ошибка открытия входного файла <%s> - файл не найден; проверьте путь.\n",in_path);
anomaly_counter++;
}
else
{
strcpy(str_in,in_path);
//printf("OK: открытиe входного input файла <%s>\n",out_path);
fclose(file_in); //закрытие файла
in_path_ok=1;
}
}
}
}
//проверка правильности ввода выходного файла
while (out_path_ok == 0)
{
printf("Введите имя выходного файла\n");
gets(out_path);
*sw1=0;*sw2=0;
strcpy(sw1,out_path);
Reverse(sw1,sw2);
// swork1=GetHead(sw2,"\\");
// strcpy(sw2,swork1);
// free(swork1);
Reverse(sw2,c_name);
// free (swork1);
if (strlen(c_name)==0)
{//пустой путь
printf("Некорректный путь: <%s>\n",out_path);
anomaly_counter++;
}
else
{
swork1=GetHead(c_name,".c");
strcpy(sw2,swork1);
free(swork1);
if (strlen(sw2)==0)
{//это не файл .c
printf("Имя файла :<%s> задано некорректно. Это не .c файл.\n",c_name);
anomaly_counter++;
}
else
{
file_out=fopen(out_path, "w"); //открываем файл на запись
if(file_in==NULL)
{//ошибка открытия файла
printf("Ошибка открытия выходного файла %s - проверьте путь.\n",out_path);
anomaly_counter++;
}
else
{
strcpy(str_out,out_path);
strcpy(sw1,c_name);
Replace(sw1,".","_",sw2); //заменяем . на _
strcpy(c_prog_name,sw2); //формируем имя программы
//printf("OK: открытиe выходного файла %s\n",out_path);
fclose(file_out); //закрытие файла
out_path_ok=1;
}
}
}
}
return;
}
/*=========================================================================*/
int Analyze_Ae2()
//функция анализа арифметического выражения Ae2
//функция возвращает 0, если выражение соответствует приведенной диаграмме
//функция возвращает 1, если выражение не соответствует приведенной диаграмме
{
if(ZNAK)
{
s_cur++;
}
while(false)
{
if(Analyze_Slag())
{
return false;
}
if(ZNAK)
{
s_cur++;
}
else
{
return true;
}
}
}//proc
/*=========================================================================*/
int Analyze_Slag()
//функция анализа слагаемого
{
while(false)
{
if(Analyze_Mnog())
{
return false;
}
if(*s_cur=='*' || *s_cur=='/')
{
s_cur++;
}
else
{
return true;
}
}
}//proc
/*=========================================================================*/
int Analyze_Mnog()
//функция анализа множителя
{
if(*s_cur=='(')
{
s_cur++;
if(Analyze_Ae2()) return false;
if(*s_cur!=')') return false;
else s_cur++;
}
else
{
if(Analyze_Perem() && Analyze_Const()) return false;
}
return true;
}//proc
/*=========================================================================*/
int Analyze_Perem()
{
if(Analyze_Identify()) return false;
if(*s_cur=='[')
{
do
{
s_cur++;
if(Analyze_Ae2()) return false;
}
while(*s_cur==',');
if(*s_cur!=']') return false;
s_cur++;
}
return true;
}//proc
/*=========================================================================*/
int Analyze_Identify()
//функция анализа идентификатора
{
if(isalpha(*s_cur)==0)
{
return false;
}
while(isalpha(*s_cur) || isdigit(*s_cur))
{
s_cur++;
}
return true;
}//proc
/*=========================================================================*/
int Analyze_Const()
//функция анализа константы без знака
{
int flag=false; //отвечает за наличие цифр в мантиссе
while(isdigit(*s_cur))
{
flag=0;
s_cur++;
}
if(*s_cur=='.')
{
s_cur++;
while(isdigit(*s_cur))
{
flag=0;
s_cur++;
}
}
if(flag)
{
return false;
}
if(*s_cur=='E')
{
s_cur++;
if(ZNAK)
{
s_cur++;
}
if(!isdigit(*s_cur))
{
return false;
}
while(isdigit(*s_cur))
{
s_cur++;
}
}
return true;
}//proc
/*=========================================================================*/
int Analyze_Symb_Le1()
//функция анализа символа между двумя Ae2
{
//1-й случай(начало - символ "=")
if(*s_cur=='=')
{
s_cur++;
return true;
}
//2-й случай(начало - символ "<")
if(*s_cur=='<')
{
s_cur++;
if(*s_cur=='=')
{
s_cur++;
return true;
}
if(*s_cur=='>')
{
s_cur++;
return true;
}
return true;
}
//3-й случай(начало - символ ">")
if(*s_cur=='>')
{
s_cur++;
if(*s_cur=='=')
{
s_cur++;
return true;
}
return true;
}
return false;
}//proc
/*=========================================================================*/
int Analyze_Le1()
//функция анализа анализа логического выражения Le1(на входе-Ae2)
{
if(Analyze_Ae2()==false)
{
return false;//Ae2 неверно
}
else
{
if(Analyze_Symb_Le1()==true && *s_cur!='\x0')
{
if(Analyze_Ae2()==true && *s_cur=='\x0')
{
return true;
}
}
return false;
}
return false;
}//proc
/*=========================================================================*/
/*=====================================================================*/
/*=====================================================================*/
/*=====================================================================*/
void main()
{
char sw1[buf_len];
char sw2[buf_len];
char *pas_str; //найденное оконченное предложение на Pascal'е
char *c_str; //часть предложения на C
char *swork1; //рабочие строки
char *swork2;
int more_pas_in_buf; //признак наличия ';' в буфере обработки
int pos_sep; //позиция символа ';'
int comments_flag; //флажок обработки комментария (0 или 1)
char comment_beg[buf_len]="{";
//строка - признак начала комментария в Паскале
char comment_end[buf_len]="}";
//строка - признак конца комментария в Паскале
int pos_comment; //позиция комментария в исходнои тексте
int pos_c; //текущая позиция в исходной строке
int pos_comment_beg;//позиция начала комментария от текущей позиции
int pos_comment_end;//позиция конца комментария от текущей позиции
int last_comment_beg; //позиция последнего открытого комментария
clrscr(); //чистим экран
//*str_in=0;
//*str_out=0;
//GetPaths(); //получаем пути исходного (str_in) и выходного (str_out) файлов
fid=29;
strcpy(str_in,"D:\\file_in2.pas");
strcpy(str_out,"D:\\file_out.c");
file_in=fopen(str_in, "r"); //открываем файл на чтение
file_out=fopen(str_out, "w"); //открываем файл на запись
Analyze_Program_Start(); //выводим
//очистка буфера накопления чистого текста на Паскале
*str_buf=0;
//установка флажка обработки комментария
// 0=если комментарии еще найдены или уже обработаны (удалены)
// 1=в процессе накопления текста комментариев в буфер комментариев
comments_flag=0;
*comments_buf=0; //очистка буфера комменариев
*non_comments_buf=0; //очистка буфера Паскаля
while(fgets(str_temp, buf_len, file_in)) //чтение исходных строк
{
count_source_lines++;
//обработка комментариев
strcpy(str_temp_nocomments,str_temp);//в str_temp_nocomments - весь текст
//strcpy(sw1,str_temp); //замена коментариев '{' и '}'
//Replace(sw1,"{","/*",sw2);//на '/*' и '*/' соответственно
//strcpy(sw1,sw2);
//Replace(sw1,"}","*/",sw2);
//strcpy(str_temp,sw2);
for (pos_comment=0;pos_comment<strlen(str_temp_nocomments);pos_comment++)
{//выделение в str_temp_nocomments комментариев
pos_comment_beg=pos(str_temp_nocomments+pos_comment,comment_beg);
pos_comment_end=pos(str_temp_nocomments+pos_comment,comment_end);
if ((comments_flag==0) && (pos_comment_beg==0))
{//нашли начало комментария
strcpy(comments_buf,comment_beg);
last_comment_beg=pos_comment;
comments_flag=1;//теперь обрабатваем комментарии
}
else if ((comments_flag==1) && (pos_comment_end==0))
{//нашли конец комментария
strcat(comments_buf,comment_end);
//преобразуем комментарии { и } на '/*' и '*/' соответственно
strcpy(sw1,comments_buf);
Replace(sw1,"{","/*",sw2);
strcpy(sw1,sw2);
Replace(sw1,"}","*/",sw2);
strcpy(comments_buf,sw2);
Output_C_lines(comments_buf);//выводим накопленный
count_out_lines++; //комментарий
comments_flag=0; //снова ищем начало комментария
*comments_buf=0; //очищаем буфер комментария
}
else
{//либо мы внутри комментария и копим его,
//либо мы вне комментария и копим Паскалевский текст
if (comments_flag==1)
{//мы внутри комментария - накапливаем текст комментария
strncat(comments_buf,str_temp_nocomments+pos_comment,1);
}
else
{//мы вне комментария - накапливаем текст Паскаля
strncat(non_comments_buf,str_temp_nocomments+pos_comment,1);
}
}
}
//пополняем справа буфер накопления текстом на Паскале без комментариев
strcat(str_buf,non_comments_buf);
*non_comments_buf=0; //и очищаем буфер Паскаля
//обрабатываем буфер накопления Паскаля
more_pas_in_buf=1;//признак: в буфере накопления Паскаля еще есть текст
while(more_pas_in_buf==1)
{
//обработка предложения Паскаля (текст, оканчивающийся на ";")
pos_sep=pos(str_buf,str_sep);//ищем в строке ';'
if(pos_sep==-1)
{//если нет ";" то добавляем пробел и завершаем поиск
strcat(str_buf," ");
more_pas_in_buf=0;
}
else
{//обработка первого из находящихся в буфере предложения
swork1=GetHead(str_buf,str_sep);//выделяем
strcpy(pas_str,swork1); //предложение
strcat(pas_str,";"); //на Паскале
free (swork1);
//выделяем концевик буфера
swork2=GetTail(str_buf,str_sep);//выбираем остальные предложения
strcpy(str_buf,swork2);//и возвращаем их в начало буфера
free (swork2);
//далее вызываем п/п анализа предложения на Паскале
//и получаем эквивалентное предложение на языке C
Pas_to_C(pas_str, c_str);
}
}
}
fid=30;
strcpy(pas_str,str_buf); //обработка остатка буфера после
Pas_to_C(pas_str, c_str);//чтения всего исходного файла
fclose(file_in); //закрытие входного файла
fclose(file_out);//закрытие в ходного файла
if (errors_counter > 0)
{
printf("Количество ошибок: %d\n",errors_counter);
}
else
{
printf("Обработан текст программы на языке Pascal в файле <%s>\n",str_in);
printf("Сформирован текст программы на языке C в файле <%s>\n",str_out);
printf("Количество входных строк: %d\n",count_source_lines);
printf("Количество выходных строк: %d\n",count_out_lines);
printf("Ошибок не обнаружено\n");
if (anomaly_counter == 0)
{
printf("Аномалий не обнаружено\n");
}
else
{
printf("Количество аномалий: %d\n",anomaly_counter);
}
}
getch();
}