
- •Министерство образования и науки российской федерации
- •Оглавление
- •3. Содержание отчета
- •4. Задание на курсовую работу
- •4.1. Пример перевода
- •5. Постановка задачи
- •6. Внешняя спецификация программы
- •6.1. Вход
- •6.2. Выход
- •6.3. Аномалии
- •7. Метод решения задачи
- •8. Описание алгоритма
- •8.1. Структура данных
- •8.2. Алгоритм главной программы
- •8.3. Выделение подпрограмм
- •8.4. Алгоритм подпрограммы обработки комментария (fcomment)
- •8.5. Алгоритм подпрограммы обработки оператора if (fif)
- •8.6. Обработка арифметического выражения
- •9. Структура программы
- •10. Синтаксические диаграммы арифметических и логических выражений
- •11. Пример программы мини-транслятора на Паскале
- •12. Варианты индивидуальных заданий
- •13. Библиографический список
- •109028 Москва, б. Трехсвятительский пер., 3/12.
- •113054 Москва, ул. М. Пионерская, 12.
9. Структура программы
В данном разделе описывается структура программы в виде диаграммы, определяющей вызовы подпрограмм. Указывается назначение каждой подпрограммы. Например:
Назначение подпрограмм:
fcomment |
обработка комментария |
fif |
обработка условного оператора |
fkw |
выделение ключевого слова |
fassign |
обработка оператора присваивания |
ferror |
обработка ошибки |
ffind |
поиск заданного символа в строке, начиная с указанной позиции |
fae1 |
обработка арифметического выражения |
fcopy |
копирование подстроки |
fform |
формирование строки с полным текстом оператора без пробелов |
foperand |
обработка операнда |
fvar |
обработка переменной |
10. Синтаксические диаграммы арифметических и логических выражений
Ниже приведены синтаксические диаграммы трёх видов арифметических выражений (ae1,ae2,ae3) и двух видов логических выражений (le1,le2), которые используются в описании вариантов индивидуальных заданий на курсовую работу. В данной работе принимается, что синтаксические диаграммы одинаковы для языков Паскаль и Си. В логических выражениях следует использовать то арифметическое выражение (ae1, ae2 или ae3), которое указано виндивидуальном задании.
Арифметическое выражение ae3
Арифметическое выражение ae2
Арифметическое выражение ae1
Логическое выражение le2
Логическое выражение le1
11. Пример программы мини-транслятора на Паскале
В данном разделе дан пример программы мини-транслятора на Паскале, который иллюстрирует её оформление. Пример отражает некоторый этап разработки программы, так как в нём почти все подпрограммы обработки синтаксических элементов представлены в виде “заглушек”, которые имитируют работу реальных подпрограмм. Использование “заглушек” отражает реальный процесс разработки программы методом пошаговой детализации и позволяет приступить к отладке программы до её полного написания (приведённая программа, хотя и не выполняет всех требуемых функций, но является работающей программой). Следует отметить, что каждая подпрограмма составляется после разработки текста соответствующего алгоритма на псевдокоде, который вносится в текст подпрограммы в виде комментариев (это иллюстрирует подпрограмма обработки комментария fComment). Представленная программа является некоторой основой, на базе которой можно разработать реальный мини-транслятора в соответствии с заданным вариантом.
programMini_Translator_Pascal_C;
{***********************************************************************
Мини-транслятор конвертирует программу на Паскале, содержащую
следующие операторы:
присваивание v:=ae3
if le2 then
for
while le2 do
комментарии,
в программу на Си
***********************************************************************}
usesCrt;
Type
kwType = (kwNothing, kwFor, kwWhile, kwIf);
Const
KWArray : array [kwFor..kwIf] of string = ( 'FOR', 'WHILE', 'IF');
MaxStr1 = 50;
MaxStr2 = 50;
MaxLen = 80;
FName1 = 'Text1.pas'; { имя входного файла с текстом программы на Паскале }
FName2 = 'Text2.c'; { имя выходного файла с текстом программы на Си }
var
KStr1, KStr2, NStr1, NStr2,
NPos1, NPos2, KindComment, i : integer;
Text1 : array [1..MaxStr1] of string[MaxLen];
Text2 : array [1..MaxStr2] of string[MaxLen];
Err : boolean;
F1 : Text;
ch : char;
NomKW : kwType;
{-----------------------------------------OutText -------------------------------------------------
Выдача в выходной массив Text2 подстроки S.}
procedureOutText(S : string);
begin
Text2[NStr2] := Text2[NStr2] + S;
Inc(NPos2, Length(S));
end;
{-----------------------------------------UpperCase -------------------------------------------------
Преобразование символов строки S в символы верхнего регистра.}
function UpperCase (S : string) : string;
var
i : integer;
begin
for i := 1 to Length(S) do S[i] := UpCase(S[i]);
UpperCase := S;
end;
{-----------------------------------------GetText1----------------------------------------------------
Ввод исходного текста программы из файла в массив Text1}
procedureGetText1;
begin
Assign ( F1, FName1 );
{$I-}
Reset ( F1 );
{$I+}
if IOResult <> 0 then
begin
writeln ( 'Файл ' + FName1 + ' не найден! Нажмите любую клавишу...');
ch := ReadKey; halt;
end;
KStr1:=0;
while not eof(F1) do
begin
inc(KStr1);
readln(F1,Text1[KStr1]);
end;
Close(F1);
end;
{-------------------------------------------- PutText2 ------------------------------------------------
Вывод полученного текста программы на Си из массива Text2 в файл FName2}
procedurePutText2;
var
i : integer;
begin
Assign(F1, FName2);
{$I-}
Rewrite(F1);
{$I+}
for i:=1 to NStr2-1 do
begin
writeln(F1, Text2[i]); { вывод в файл }
writeln(Text2[i]); { вывод на экран }
end;
Close(F1);
end;
{-----------------------------------------OutText -------------------------------------------------
Выдача в выходной массив Text2 подстроки S.}
procedureOutText(S : string);
begin
Text2[NPos2] := Text2[NPos2] + S;
Inc(NPos2, Length(S));
end;
{------------------------------------------ OutTextFromTo ---------------------------------------------
Копирование в текущую строку NStr2 массива Text2, начиная с позиции NPos2, символов строки S, расположенных в ней в позициях с NPosBeg по NPosEnd}
procedure OutTextFromTo (S : string; NPosBeg : integer; NPosEnd : integer);
var
i : integer;
cnt : integer;
begin
{ копирование (NPosEnd - NPosBeg + 1) символов из области памяти S[NPosBeg] в память Text2[NStr2, NPos2] }
Cnt := NPosEnd - NPosBeg + 1;
move(Text2[NStr2, NPos2], S[NPosBeg], Cnt);
Inc (NPos2,Cnt); { сдвигаем указатель на текущий выходной символ }
Inc(Text2[NStr2, 0],Cnt); { увеличиваем размерность строки }
{ for i := NPosBeg to NPosEnd do
begin
Text2[NStr2,NPos2] := S[i];
Inc(NPos2);
end;}
end;
{-----------------------------------------------isComment--------------------------------------------
Проверка наличия скобки комментария'{' или '/*' в текущей позиции NPos1 текущей строки NStr1 массива Text1. Вид скобки комментария запоминается в глобальной переменной KindComment.}
function isComment : boolean;
begin
if Text1[NStr1,NPos1]='{' then
begin
isComment:=true; KindComment:=1; inc(NPos1);
end
else
if Copy(Text1[NStr1], NPos1, 2) = '(*' then
begin
isComment:=true; KindComment:=2; inc(NPos1,2);
end
else
isComment:=false;
end;
{---------------------------------------------- fComment --------------------------------------------
Обработка комментария}
procedurefComment;
var
EndComment : string;
NPosEnd, NStrBeg : integer;
NomPos : Byte;
begin
NStrBeg:=NStr1;
{Запись в текущую строку Text2 символов ‘/*’}
{Text2[NStr2,NPos2] := '/'; Text2[NStr2,NPos2+1] := '*'; inc(NPos2, 2);}
OutText(‘/*’);
{Определение символов конца комментария в исходном тексте в зависимости от символов начала комментария }
if KindComment = 1 then EndComment := '}'
elseEndComment := '*)';
{Копирование текста комментария из Text1 в текущую строку Text2 пока не встретятся символы конца комментария или не будет достигнут конец массива Text1. При каждом переходе на следующую строку Text1 происходит увеличение на 1 счётчика nstr1.}
repeat
NomPos := Pos(EndComment, Text1[NStr1]);
if NomPos = 0 then
NPosEnd := Length(Text1[NStr1])
else
NPosEnd := NomPos-1;
{OutText(Copy(Text1[NStr1], NPos1, NPosEnd - NPos1 + 1));}
OutTextFromTo(Text1[NStr1], NPos1, NPosEnd);}
inc(NStr1);
NPos1 := 1;
until (NomPos<>0) or (NStr1>KStr1);
{Если символы конца комментария не найдены, то печать диагностического сообщения и аварийное завершение программы.}
if NomPos = 0 then
begin
writeln('Нет конца комментария, начинающегося в строке ', NStrBeg);
exit;
end;
{Запись в Text2 символов */}
OutText(‘*/’);
{Text2[NStr2,NPos2]:='*'; Text2[NStr2,NPos2+1]:='/'; inc(NPos2);}
{Text2[NStr2,0] := Chr(NPos2); {конец строки}
NStr2 := NStr2 + 1;
end;
{-------------------------------------------------- fKW------------------------------------------------
Выделение одного из ключевых слов, указанных в массиве KWArray, в текущей строке NStr1 массива Text1, начиная с позиции NPos1. Вид ключевого слова запоминается в глобальной переменной NomKW.}
function fKW :boolean;
var
i, LenKW : integer;
currWord : string;
begin
fKW := false; NomKW := kwNothing;
if (NPos1 <= Length(Text1[NStr1])) and
(Text1[NStr1, NPos1] in [‘a’..’z’,’A’..’Z’] then { возможно ключевое слово }
begin
i := NPos1;
repeat
Inc(i);
until (i <= Length(Text1[NStr1])) and (Text1[NStr1, i] in [‘a’..’z’,’A’..’Z’, ‘0’..’9’]);
{ такое условие позволяет не путать ключевое слово и идентификатор вида ‘while00023’ или ‘ifYetMore09Another’ }
currWord := Copy(Text1[NStr1], NPos1, i ‑ NPos1);
end
else
Exit;
for NomKW := kwFor to kwIf do
begin
{LenKW:=Length(KWArray[NomKW]);}
{if UpperCase(Copy(Text1[NStr1], 1, LenKW)) = KWArray[NomKW] then}
if UpperCase(currWord) = KWArray[NomKW] then
begin
inc(NPos1,LenKW); fKW := true; Exit;
end;
end;
end;
{------------------------------------------------- Zaglushka ------------------------------------------
Копирует в текущую строку массива Text2 символы текущей строки массива Text1 со вставкой перед ними комментария из строки S}
procedure Zaglushka ( S : string );
begin
S:='/*'+S+': '+Text1[NStr1]+'*/';
OutText(S)
inc(NStr1);inc(NStr2);
end;
{--------------------------------- Обработка оператора For -----------------------------------}
function fFor :boolean;
begin
Zaglushka('fFor');
fFor:=false;
end;
{------------------------------- Обработка оператора While ----------------------------------}
function fWhile :boolean;
begin
Zaglushka('fWhile');
fWhile:=false;
end;
{-------------------------------- Обработка оператора If ---------------------------------------}
function fIf :boolean;
begin
Zaglushka('fIf');
fIf:=false;
end;
{------------------------- Обработка оператора присваивания ------------------------------}
function fAssign :boolean;
begin
if Pos( ':=' , Text1[NStr1] ) > 0 then
begin
fAssign:=false; Zaglushka('fAssign');
end
else fAssign:=true;
end;
{--------------------- Обработка оператора с ключевым словом---------------------------}
procedurefStatKey;
begin
case NomKW of
kwFor: Err:=fFor; { Обработка оператора For }
kwWhile: Err:=fWhile; { Обработка оператора While }
kwIf: Err:=fIf; { Обработка оператора If }
end;
end;
{---------------------------------- Обработка ошибки ------------------------------------------}
procedurefError;
begin
Zaglushka('fError');
end;
{---------------------------------------- Трансляция -----------------------------------------------}
procedureTranslator;
begin
fillchar(Text2, sizeof (Text2), 0);
{ обнуляем массив Text2 }
NStr1:=1; NStr2:=1;
while NStr1 <= KStr1 do |
{ цикл просмотра строк исходной программы |
} |
Begin |
|
|
NPos1:=1; NPos2:=1; |
|
|
if isComment then |
{ если комментарий то |
} |
fComment |
{ обработка комментария |
} |
Else |
{ иначе |
} |
begin |
|
} |
if fKW then |
{ если есть ключевое слово то |
} |
fStatKey |
{ обработка оператора с ключевым словом |
} |
else |
{ иначе |
} |
Err:=fAssign; |
{ обработка оператора присваивания |
} |
if Err then |
{ если ошибка то |
} |
fError; |
{ обработка ошибки |
} |
end;
end;
end;
begin {--------------------начало основной программы------------------------------------}
ClrScr;
GetText1; { ввод исходного текста программы из файла }
Translator; { конвертирование программы на Паскале в программу на Си }
PutText2; { вывод результата в файл }
end.