Разработка компилятора
Оглавление
1 ТЕХНИЧЕСКОЕ ЗАДАНИЕ. 4
2 ОПИСАНИЕ ПРОГРАММЫ. 7
3 ТЕКСТ ПРОГРАММЫ. 17
4 КОНТРОЛЬНЫЙ ПРИМЕР ИСПОЛЬЗОВАНИЯ 47
ЗАКЛЮЧЕНИЕ 64
1 ТЕХНИЧЕСКОЕ ЗАДАНИЕ.
1.1 Введение
Наименование программного продукта – «Компилятор».
Область применения программного продукта – разработка программного обеспечения, трансляция с языка высокого уровня на язык ассемблера.
1.2 Основания для разработки.
Разработка данного рода программного средства ведется в рамках курсовой работы на основании «Задания на курсовую работу» от 19 марта 2012 года, утвержденного Зав. Кафедрой «Вычислительная техника и автоматизированные системы управления» Е.Г. Шепиловой. Руководитель доцент В.В. Жуков.
1.3 Назначение разработки.
Разработка предназначена для компиляции программы из исходного кода в код на языке ассемблера.
1.4 Требования к программе.
1.4.1 Требования
к функциональным
Программа должна осуществлять лексический анализ, синтаксический анализ и генерацию кода на языке ассемблера для заданной грамматики входного языка при входной строке произвольной длины.
Входной язык должен удовлетворять следующим требованиям и включать в себя следующие возможности:
- типы данных (простые типы – логический, целые числа без знака, символы);
- структурные типы – одномерный массив, символьные константы;
- Операторы (оператор ввода, оператор вывода, оператор присваивания, условный оператор, оператор цикла с предусловием, оператор цикла ‘do’ по типу Бэйсика).
Способ реализации лексического и синтаксического анализаторов остается на усмотрение разработчика.
- Требования к надежности.
Лексический анализатор должен производить разбор текста любого содержания и произвольной длины. При нахождении символа, не относящегося ни к одному из классов лексем, должна быть вызвана ошибка и работа алгоритма должна быть остановлена. Данное требование не относится к содержимому литералов и символьных констант, в которых содержимое ничем не ограничено.
Синтаксический анализатор должен контролировать выход за границы таблицы лексем, чтобы избежать возникновения критических ошибок, останавливать работу алгоритма разбора и выдавать соответствующее сообщение об ошибке.
- Условия эксплуатации.
Программа разработана для эксплуатации в условиях офисных помещений.
- Требования к составу и параметрам технических средств.
Минимальные требования к аппаратному обеспечению компьютера для обеспечения стабильной работы программы должны быть следующими:
– центральный процессор – версии Intel ® Pentium III и старше;
– совместимая видеокарта;
– оперативное запоминающее устройство емкостью не менее 256 Мб;
– устройство ввода-вывода.
- Требования к информационной и программной совместимости.
Программа
должна быть спроектирована и разработана
для использования под
1.4.6 Требования к маркировке и упаковке.
Требований к маркировке и упаковке не предъявляется.
1.4.7 Требования к транспортировке и хранению.
Требований к транспортировке и хранению не предъявляется.
1.5 Требования к программной документации.
Программная документация должна включать в себя следующие разделы:
- текст программы;
- описание программы.
1.6 Технико-экономические показатели.
Расчет технико-экономических показателей не требуется.
1.7 Стадии и этапы разработки.
Разработка должна быть разделена на три стадии:
- разработка лексического анализатора;
- разработка синтаксического анализатора;
- разработка генератора кода.
1.8 Порядок контроля и приемки.
Приемка готового продукта осуществляется после демонстрации его работоспособности. Работоспособность продукта проверяется путем генерации из исходного кода заведомо верной программы кода на языке ассемблера, компиляции и компоновки из кода на языке ассемблера исполняемого файла программы и проверки ее работоспособности.
2 ОПИСАНИЕ ПРОГРАММЫ.
2.1 Общие сведения.
Программа написана на языке Паскаль. Графический интерфейс не реализован. Для запуска программы необходимо будет запустить Паскаль и исходный текс программы для компиляции записать в файл «primer.txt».
2.2 Лексический анализатор.
Лексический анализатор не является обязательной частью компилятора, однако при разработке данного проекта было принято решение выделить лексический анализатор отдельной процедурой leksich и сам процесс лексического анализа производить за отдельный проход.
Лексический анализатор (сканер) предназначен для выделения из входного текста лексем – неделимых единиц программы. Лексемами являются имена переменных, процедур и функций, зарезервированные слова, числа, разделители, знаки операций, символьные константы и литералы (строковые константы).
Помимо выделения лексем лексический анализатор предназначен для удалений комментариев и пробельных символов (пробел, символ табуляции, символ конца строки).
Приведем
список зарезервированных слов: Program,begin,end,write,read,
var,then,for,If,do,while,
True,false,not,and,of,or,
Приведем список однолитерных разделителей (состоящих из одного символа): ‘(‘, ‘)’, ‘+’, ‘-‘, ‘*’, ‘/’, ‘<’, ‘>’, ‘=’, ‘”’, ‘;’, ‘[‘, ‘]’, ‘:’, ‘,’, ‘|’, ‘.’.
Приведем список двулитерных разделителей (состоящих из двух символов): ‘<>’, ‘>=’, ‘<=’, ‘:=’.
Лексемы разделены на классы, называемые токенами. Таким образом, существует токен имен переменных, зарезервированных слов, чисел, разделителей, символьных констант и литералов. Токены имен, чисел, литералов и символьных констант заполняются в процессе лексического анализа, остальные же токены заполняются на этапе инициализации лексического анализатора и их состав и положение элементов в них не меняется.
Выходными данными работы лексического анализатора является ошибка разбора, выходной поток лексем и токены, содержимое которых формируется на этапе лексического анализа.
Выделение из текста программы лексем осуществляется с помощью конечных автоматов. Каждый автомат предназначен для выделения из текста отдельного класса лексем.
Для анализа текста реализована процедура leksich. Данная процедура представляет собой цикл с предусловием, из которого вызываются с помощью оператора case .. of процедуры для разбора отдельных.
Приведем правила лексической грамматики для построения автоматов выделения лексем:
<Лексема>
→ <Имя>|<Число>|<Литерал>|<
<Имя> → <Буква>{<Буква>|<Цифра>}
<Число> → <Цифра>{<Цифра>}
<Литерал> →’”’ {<Символ>|(‘”’’”’)}’”’
<Символьная константа> → ‘<Символ>’
<Однолитерный разделитель> → ‘(‘ | ’)’ | ‘+’ | ‘-‘ | ‘*’ | ‘/’ | ‘<’ | ‘>’ | ‘=’ | ‘”’ | ‘;’ | ‘[‘ | ‘]’ | ‘:’ | ‘,’ | ‘|’ | ‘.’
<Двулитерный разделитель> → ‘<>’ | ‘>=’ | ‘<=’ | ‘:=’ | ‘..’
<Комментарий> → //{<Символ>}<Конец строки> | ‘/*’{<Символ>}’*/’ | ‘{‘ {<Символ>} ‘}’
<Цифра> → ‘0’ .. ‘9’
<Буква> → ‘A’ .. ‘Z’ | ‘a’ .. ‘z’
<Конец строки> → eoln
Приведем графы работы автоматов для выделения имен, чисел, и литералов, а также автоматы для удаления комментариев
Граф работы автомата для выделения имен, зарезервированных слов и чисел.
Рис. 1
Граф работы автомата для выделения литералов.
Рис. 2
Граф работы автомата, предназначенного для удаления комментариев.
Рис. 3
Граф работы автомата для выделения простых и сложных разделителей.
Рис. 4
Выходной поток лексем представляет собой одномерный массив записей, каждая из которых включает в себя имя таблицы, номер в этой таблице.
2.3 Синтаксический анализатор.
Синтаксический анализатор предназначен для выделения синтаксических конструкций и правильности их построения. В задачу синтаксического анализа входят следующие функции:
- найти
и выделить синтаксические
- установить
тип и проверить правильность
каждой синтаксической
- управление ходом трансляции
текста исходной программы в
текст результирующей
Синтаксический анализатор – это основная часть компилятора.
Синтаксический анализатор воспринимает выход лексического анализатора и разбирает его в соответствии с грамматикой входного языка.
В основе
синтаксического анализатора
Приведем правила синтаксической грамматики, на основе которой построен синтаксический анализатор:
<программа> → 'program' I <декларация> <блок операторов> ‘end’,'.'
<декларация
> → 'var' ,{ I {‘,’I}’:’ ('integer'|'char'|’byte’|'
<mas> → 'array'
'['C'..'C']' 'of' ('integer'|'char'|'boolean'|’
<блок операторов> → 'begin' { <оператор>‘;’} ‘end’
<оператор> → <присваивание>|<условный оператор>|<оператор цикла While>|<оператор ввода>|<оператор вывода>|<оператор цикла DO>
<присваивание> → I([E]| ε){‘,’I|[E]| ε}’:=’ E|L|CH
<оператор цикла while> → ‘while’ L ‘do’ <оператор>
<оператор ввода> → ‘read’ ‘(‘I(|[E] ε)){‘,’ I([E]| ε)}
<оператор вывода> → ‘write’’(’{E|L|<литерал>}’)’
<условный оператор> → ‘if’ L ‘then’ <оператор> (‘else’ <оператор>| ε)
<оператор цикла do> → ‘do’ {<оператор>} ‘loop’ ‘while|until’ L
L →Т L
ТL → FL {‘or’ TL}
FL → ‘true’ | ’false’ | I [‘[‘E’]’] | ‘not ‘(‘FL’)’ | ’!’E <предикат сравнения> E’!’
<предикат
сравнения> → ‘=’|’<>’|’>’|’<’|
E → T {‘+’ T | ‘-‘ T}
T → F {‘*’ F | ‘/’ F}
F → I [‘[‘E’]’] | ‘(‘E’)’
Приведем
расшифровку некоторых
E – математическое выражение;
L – логическое выражение;
CH – символьное выражение;
C – число;
I – имя переменной.
На этапе
синтаксического анализа
Синтаксический анализатор реализован в отдельной процедуре sintax. Для осуществления синтаксического анализа необходимо импортировать из лексического анализатора выходной поток лексем, а также токены имен переменных, чисел, литералов и символьных констант, а также массив чисел для локализации местоположения ошибки. Импорт происходит путем использования глобальных переменных.
В данном случае был применен нисходящий синтаксический анализ путем рекурсивного спуска. Название данного метода происходит из его реализации, которая заключается в последовательности рекурсивных вызовов процедур разбора. Для начала разбора входной цепочки нужно вызвать процедуру для целевого символа грамматики. В данном случае целевым символом грамматики является нетерминальный символ <program>.
Для каждого нетерминала грамматики записывается отдельная распознающая процедура. При этом соблюдаются следующие соглашения:
- Перед
началом работы процедуры
- В процессе
работы процедура считывается
все символы входной цепочки,
относящиеся к данному
- По окончании
работы процедуры текущим
Список процедур разбора:
procedure pr();
// процедуры описания заголовка программы и символа конца программы
procedure error(kod:integer);
//процедура вывода ошибок
procedure declar();
//процедура описания блока декларации
procedure block();
// процедуры описания раздела блока операторов
procedure E();
procedure T();
procedure F();
// арифметические выражения
procedure L();
procedure TL();
procedure FL();
// логические выражения
procedure block();
// процедура описания блока операторов
procedure operator();
// процедура выбора оператора
procedure op_if();
// оператор условия
procedure op_while();
// оператор цикла while
procedure op_read();
// оператор ввода
procedure op_write();
// оператор вывода
procedure op_do();
// оператор цикла do
Procedure op_pr();
// оператор присваивания
Синтаксический разбор начинается с вызова процедуры procedure sintax(). Из данной процедуры вызывается процедура разбора целевого символа грамматики pr.
В процедуре pr() выполняются следующие действия:
- проверяется
наличие ключевого слова ‘
- вызывается
процедура разбора блока
- вызывается процедура разбора блока кода block();
- проверяется наличие ключевого слова ‘end’ и разделителя ‘.’.
Процедура разбора блока переменных declar() выполняет следующие действия:
- проверяет наличие ключевого слова ‘var’;
- выполняет разбор и заполнение таблицы переменных.
Процедура разбора блока кода block() выполняет следующие функции:
- выполняется цикл с предусловием, в котором идентификация оператора и передается управление его процедуре разбора operator:
- если текущим
символом является имя
- если текущим
символом является ключевое
- если текущим
символом является ключевое
- если текущим
символом является ключевое
- если текущим
символом является ключевое
- если текущим
символом является ключевое
Следует
также отметить, что в классе синтаксического
анализа предусмотрена
2.4 Генерация кода.
Параллельно
с синтаксическим анализом производится
генерация кода программы на языке
ассемблера. Данный метод называется
синтаксически управляемой
Генерация кода - последняя фаза трансляции. Результатом ее является ассемблерный файл (*.asm). В процессе генерации кода могут выполняться некоторые локальные оптимизации, такие как распределение регистров, выбор длинных или коротких переходов, учет стоимости команд при выборе конкретной последовательности команд.
Задача генератора кода - построение эквивалентной программы на ассемблере по программе на входном языке. Обычно в качестве входного для генератора кода служит некоторое промежуточное представление программы.
Генерация осуществляется на этапе рекурсивного спуска, когда разобранному правилу ставится в соответствие определенная команда или набор команд ассемблера.
3 ТЕКСТ ПРОГРАММЫ.
Program kompil;
type
lek=record
table:string;
nomer:integer;
type_i:string;
znachenie:string;
mas:integer;
end;
var
f1,f2,f3,f4,f5,f6,f7:text;
analiz:array [1..1000] of lek;
x1,x2:string;
S,i,dlina,n,dl,met,k,nom_
alfavit: set of char;
cifri: set of char;
razdel: set of char;
zn_ot:set of char;
tab_I:array [1..1000] of string;
bol_tab_i,firstrun:boolean;
t:string;
tab_ident:array [1..1000] of string;
count_ident:integer;
tab_cifri:array [1..1000] of string;
count_cifri:integer;
tab_liter:array [1..1000] of string;
count_liter:integer;
tab_hardrazdel:array[1..1000] of string;
tab_razdel:array[1..1000] of string;
count_razdel:integer;
er:real;
ch1_mas,ch2_mas:integer;
cur_met:integer;
g_met:string;
procedure leksich;
Procedure CMP_tab_liter(var str:string);
var id:boolean;i:integer;
begin
id:=false;
for i:=1 to count_liter do
begin
If tab_liter[i]=x2 then
begin
t:='l';
n:=i;
id:=true;
end;
end;
If id=false then
begin
tab_liter[count_liter]:=x2;
t:='l';
n:=count_liter;
end;
count_liter:=count_liter+1;
end;
Procedure CMP_tab_razdel(var str:string);
var id:boolean;i:integer;
begin
id:=false;
for i:=1 to count_razdel do
begin
If tab_razdel[i]=x2 then
begin
t:='s';
n:=i;
id:=true;
end;
end;
If id=false then
begin
tab_razdel[count_razdel]:=x2;
t:='s';
n:=count_razdel;
count_razdel:=count_razdel+1;
end;
end;
Procedure CMP_tab_cifri(var str:string);
var id:boolean;i:integer;
begin
id:=false;
for i:=1 to count_cifri do
begin
If tab_cifri[i]=x2 then
begin
t:='c';
n:=i;
id:=true;
end;
end;
If id=false then
begin
tab_cifri[count_cifri]:=x2;
t:='c';
n:=count_cifri;
count_cifri:=count_cifri+1;
end;
end;
Procedure CMP_tab_I(var str:string);
begin
t:='';
n:=0;
k:=1;
While tab_i[k]<>'' do
begin
If tab_i[k]=x2 then begin t:='k';n:=k; end;
K:=k+1;
end;
end;
Procedure CMP_tab_hardrazdel(var str:string);
begin
t:='';
n:=0;
k:=1;
While tab_hardrazdel[k]<>'' do
begin
If tab_hardrazdel[k]=str then begin t:='h';n:=k; end;
K:=k+1;
end;
end;
Procedure CMP_tad_ident(var str:string);
var id:boolean;i:integer;
begin
id:=false;
for i:=1 to count_ident do
begin
If tab_ident[i]=x2 then
begin
t:='i';
n:=i;
id:=true;
end;
end;
If id=false then
begin
tab_ident[count_ident]:=x2;
t:='i';
n:=count_ident;
count_ident:=count_ident+1;
end;
end;
begin
Repeat
readln(f2,x1);
tab_I[k]:=x1;
k:=k+1;
until eof(f2);
K:=1;
Repeat
readln(f3,x1);
tab_hardrazdel[k]:=x1;
k:=k+1;
until eof(f3);
s:=0;
nom_analiz:=1;
Repeat
readln(f1,x1);
dlina:=Length(x1);
For i:=1 to dlina+2 do
begin
case s of
0: Begin If (x1[i] in alfavit) then Begin S:=11; x2:=x2+x1[i] end else begin If (x1[i] in cifri) then Begin S:=13; x2:=x2+x1[i] end else S:=0;end;
If x1[i]='''' then begin S:=21;dl:=1;end else if (x1[i] in razdel ) and (x1[i+1]<>'/') and (x1[i+1]<>'*') then begin S:=41; x2:=x2+x1[i];i:=i-1; end;
If x1[i]='{' then begin S:=31;x2:=x2+x1[i];met:=
begin
if x1[i]='/' then begin S:=33;x2:=x2+x1[i] end;// else x2:=x2+x1[i];
If dlina=i then begin S:=32;i:=i-1; end;
end;
end;
11: Begin If (x1[i] in alfavit) or (x1[i] in cifri) then x2:=x2+x1[i] else begin S:=12;i:=i-1; end; If i=dlina then begin S:=12;end; end;
12: Begin CMP_tab_I(x2); If (n=0) and (x2[1] in alfavit) then CMP_tad_ident(x2)
else if x2[1] in cifri then cmp_tab_cifri(x2);writeln(f4,' ',t,' ',n);analiz[nom_analiz].table:
13: Begin If (x1[i] in cifri) then x2:=x2+x1[i] else begin S:=12;i:=i-1; end;; If i=dlina then begin i:=i-1;S:=12;end;end;
21:begin If x1[i]='''' then begin S:=23; end else begin x2:=x2+x1[i];dl:=dl+1;end; end;
22:begin cmp_tab_liter(x2); writeln(f4,' ',t,' ',n);analiz[nom_analiz].table:
23:begin If x1[i]='''' then begin x2:=x2+x1[i];dl:=dl+1;S:=21;
31:begin If x1[i]='}' then begin S:=32;delete(x2,met,dl)end else begin x2:=x2+x1[i];dl:=dl+1; end; If (eof(f1)=true) and (dlina=i) then begin S:=32;i:=i-1;end; end;
32:begin If dlina<>i then i:=i-1;if x2<>'' then begin
writeln(f4);delete(x2,1,dlina)
33:begin If x1[i]='*' then begin S:=34; met:=Length(x2);dl:=dl+2;x2:=
34:begin If x1[i]='*' then begin S:=35; x2:=x2+x1[i];dl:=dl+1; end else begin x2:=x2+x1[i];dl:=dl+1;end;If (eof(f1)=true) and (dlina=i) then begin S:=32;i:=i-1;end;end;
35:begin If x1[i]='/' then begin S:=32;delete(x2,met,dl) end else
begin x2:=x2+x1[i];S:=34;dl:=dl+1;
36:begin If dlina=i then begin S:=32;i:=i-1;delete(x2,met,2)
41:begin n:=0;t:=''; If (x1[i+1] in razdel) then begin x2:=x2+x1[i+1];
cmp_tab_hardrazdel(x2);end; If n<>0 then begin S:=42;i:=i+1;
end else begin S:=42;delete(x2,1,dlina);x2:=
42:begin writeln(f4,' ',t,' ',n);analiz[nom_analiz].table:
end;
end;
Until eof(f1);
end;
procedure sintax;
var current_analiz:integer;
type_virag: array[1..10] of string;
cur_vir:integer;
cur_stroka:integer;
procedure block;forward;
procedure declar;forward;
procedure mass;forward;
procedure AddProcedures;
begin
writeln(F6,'R_B proc near');
writeln(F6,'CMP BUFS,''t''');
writeln(F6,'JNZ FN');
writeln(F6,'PUSH 1 ; TRUE');
writeln(F6,'JMP PBEnd');
writeln(F6,'FN: CMP BUFS, ''f''');
writeln(F6,'JNZ EndKode1');
writeln(F6,'EndKode1:');
writeln(F6,'JMP EndKode');
writeln(F6,'PUSH 0');
writeln(F6,'PBEnd:');
writeln(F6,'RET');
writeln(F6,'ENDP');
writeln(F6,'');
writeln(F6,'R_Ch proc near');
writeln(F6,'mov bx,0');
writeln(F6,'M:');
writeln(F6,'mov ah,08h');
writeln(F6,'int 21h');
writeln(F6,'mov dl,al');
writeln(F6,'mov ah,02h');
writeln(F6,'int 21h');
writeln(F6,'cmp al,'' ''');
writeln(F6,'jz M');
writeln(F6,'cmp al,13');
writeln(F6,'jz M');
writeln(F6,'mov BUFS[bx],al');
writeln(F6,'M1:');
writeln(F6,'mov ah,08h');
writeln(F6,'int 21h');
writeln(F6,'mov dl,al');
writeln(F6,'mov ah,02h');
writeln(F6,'int 21h');
writeln(F6,'cmp al,'' ''');
writeln(F6,'jz M2');
writeln(F6,'cmp al,13');
writeln(F6,'jz M2');
writeln(F6,'inc bx');
writeln(F6,'mov BUFS[bx],al');
writeln(F6,'jmp M1');
writeln(F6,'M2:');
writeln(F6,'mov cx,bx');
writeln(F6,'mov al,13');
writeln(F6,'mov ah,02h');
writeln(F6,'int 21h');
writeln(F6,'ret');
writeln(F6,'ENDP');
writeln(F6,'');
writeln(F6,'PR_Int proc near');
writeln(F6,'push bx');
writeln(F6,'push cx');
writeln(F6,'push dx');
writeln(F6,'test ax,ax');
writeln(F6,'push -1');
writeln(F6,'mov cx,10');
writeln(F6,'wrem:');
writeln(F6,'xor dx,dx');
writeln(F6,'div cx');
writeln(F6,'push dx');
writeln(F6,'test ax,ax');
writeln(F6,'jnz wrem');
writeln(F6,'mov ah,02h');
writeln(F6,'orem:');
writeln(F6,'pop dx');
writeln(F6,'test dx,dx');
writeln(F6,'js output_int_exit');
writeln(F6,'add dl,''0''');
writeln(F6,'int 21h');
writeln(F6,'jmp orem');
writeln(F6,'output_int_exit:')
writeln(F6,'pop dx');
writeln(F6,'pop cx');
writeln(F6,'pop bx');
writeln(F6,'ret');
writeln(F6,'ENDP');
writeln(F6,'');
writeln(F6,'R_Int proc near');
writeln(F6,'push bx');
writeln(F6,'push cx');
writeln(F6,'push dx');
writeln(F6,'mov bx,0');
writeln(F6,'mov ax,0');
writeln(F6,'inc cx');
writeln(F6,'mov bufs3,cx');
writeln(F6,'m_start:');
writeln(F6,'mov cx,10');
writeln(F6,'mul cx');
writeln(F6,'mov dx,0');
writeln(F6,'push ax');
writeln(F6,'mov dl,BUFS[bx]');
writeln(F6,'mov cx,dx');
writeln(F6,'sub dx,30h');
writeln(F6,'pop ax');
writeln(F6,'add ax,dx');
writeln(F6,'inc bx');
writeln(F6,'mov cx,bufs3');
writeln(F6,'cmp cx,bx');
writeln(F6,'jnz m_start');
writeln(F6,'m_exit:');
writeln(F6,'pop bx');
writeln(F6,'pop cx');
writeln(F6,'pop dx');
writeln(F6,'ret');
writeln(F6,'ENDP');
writeln(F6,'');
writeln(F6,'outline proc');
writeln(F6,'push dx');
writeln(F6,'mov ah,02h');
writeln(F6,'mov dl,0dh');
writeln(F6,'int 21h');
writeln(F6,'mov dl,0Ah');
writeln(F6,'int 21h');
writeln(F6,'pop dx');
writeln(F6,'ret');
writeln(F6,'outline endp');
writeln(F6,'');
writeln(F6,'output_logic proc');
writeln(F6,'push dx');
writeln(F6,'test ax,ax');
writeln(F6,'jz output_logic_false');
writeln(F6,'mov dx, offset $logic_true');
writeln(F6,'jmp output_logic_end');
writeln(F6,'output_logic_
writeln(F6,'mov dx, offset $logic_false');
writeln(F6,'output_logic_end:'
writeln(F6,'mov ah,9h');
writeln(F6,'int 21h');
writeln(F6,'pop dx');
writeln(F6,'ret');
writeln(F6,'output_logic endp');
writeln(F6,'');
end;
procedure error(kod:integer);
begin
//cur_stroka:=cur_stroka+1;
case kod of
1:Writeln('Ожидалось слово Program',' строка-',cur_stroka);
2:writeln('Ожидался идентификатор',' строка-',cur_stroka);
3:writeln('ожидалась ";"',' строка-',cur_stroka);
4:writeln('Ожидалось end',' строка-',cur_stroka);
5:writeln('Ожидалось "."',' строка-',cur_stroka);
6:writeln('Ожидалось var',' строка-',cur_stroka);
7:writeln('Ожидалось ","',' строка-',cur_stroka);
8:writeln('Ожидалось ":"',' строка-',cur_stroka);
9:writeln('Ожидалось begin',' строка-',cur_stroka);
10:writeln('Не известный тип данных',' строка-',cur_stroka);
11:writeln('Неверное
12:writeln('Ожидалось "]"',' строка-',cur_stroka);
13:writeln('Ожидалось ")"',' строка-',cur_stroka);
14:writeln('неверный знак сравнения',' строка-',cur_stroka);
15:writeln('Ожидалось "!"',' строка-',cur_stroka);
16:writeln('Неверное
17:writeln('Переменная не оъявлена',' строка-',cur_stroka);
18:writeln('Ожидалось :=',' строка-',cur_stroka);
19:writeln('Ожидалось then',' строка-',cur_stroka);
20:writeln('Ожидалось do',' строка-',cur_stroka);
21:writeln('Ожидалось "("',' строка-',cur_stroka);
22:writeln('Ожидалось "["',' строка-',cur_stroka);
23:writeln('Ожидалось число',' строка-',cur_stroka);
24:writeln('Ожидалось ".."',' строка-',cur_stroka);
25:writeln('Ожидалось of',' строка-',cur_stroka);