- •Введение.
- •1 Задание на проектирование
- •2 Цели и требования
- •3 Внешний проект
- •3.1 Входные и выходные данные
- •3.2 Определение синтаксиса языка
- •3.3 Общая структура проекта
- •3.4 Структура выходного файла
- •3.5 Организация листинга
- •4 Проект архитектуры
- •4.1 Структуры данных
- •4.2 Алгоритмы основных функций
- •4.3 Схема вызовов процедур и функций
- •4.4 Организация процедуры компиляции
- •4.5 Спецификация основных процедур и функций
- •4.6 Обработка ошибок
- •5 Реализация
- •5.1 Тестирование
- •5.2 Документация для пользователя
3.3 Общая структура проекта
В общем виде процесс компиляции представлен на схеме:
3.4 Структура выходного файла
Определим следующую структуру выходного файла на языке ассемблера:
; ---- primitive asm code generator (.pas to .asm)
;include procedure call and expression enterpriter
.386
.model flat, stdcall
option casemap :none
include masm32.inc
includelib lib1.lib
includelib masm32.lib
ExitProcess PROTO :DWORD
outdec PROTO :DWORD
__codeblock000 PROTO
…
__codeblockXXX PROTO
.data
out_ db 200 dup (0)
real_ db 200 dup (0)
nl_ db 0Dh, 0Ah, 00h
nul_ db 30h, 00h
mm_ db '-', 00h
.code
outdec proc NUM:DWORD
pusha
push es
push ds
pop es
lea edi, out_
mov eax, NUM
cmp eax, 0
jl _otr
jne _ok
invoke StdOut, offset nul_
ret
_otr:
invoke StdOut, offset mm_
ret
_ok:
xor ebx, ebx
mov bl, 10
xor ecx, ecx
;===
cld
ll:
cmp eax, 0
jle ex
xor edx, edx
div ebx
xchg eax, edx
add al, 30h
stosb
mov al, 00h
stosb
xchg eax, edx
jmp ll
ex:
invoke StdOut, edi
sub edi, 2
cmp edi, offset out_
jge ex
;===
pop es
popa
ret
outdec endp
EntryPoint:
mov ebp, esp
sub esp, 20 ; vars to block 0
call __codeblock000
invoke ExitProcess,0
__codeblock000 proc
…
ret
__codeblock000 endp
END EntryPoint
3.5 Организация листинга
Листинг не организуется в ходе трансляции и не выводится в выходной файл в виде комментариев. Листинг заменен выводом технической информации о ходе компилирования на экран.
4 Проект архитектуры
4.1 Структуры данных
typedef enum {
typenspace,
typevar,
typeconst,
typefunc
} IdentTypes;
typedef struct __typeGIT
{ char * name;
IdentTypes type;
unsigned int ext;
unsigned long value;
unsigned int level;
} typeGIT, * lpGIT;
typedef struct __typeBlock
{ int slPos, swPos; // Начало блока
int elPos, ewPos; // Конец блока
int GITidx; //индекс старта переменных блока в IDT
int GITend; //индекс конца переменных блока в IDT
lpdgram * code;
} typeBlock, *lpBlock;
typedef enum
{ opset,
opcall,
opadd,
opsub,
opdiv,
opmul,
opmod,
opvar,
opconst,
op_count, //endline & count of ops
op_error,
opignore,
opret,
opneg
} operations;
typedef struct __dgram
{ operations type;
int ext;
struct __dgram * left, * right;
} typedgram, *lpdgram;
char *** GCode;
int lPos;
int wPos;
typeGIT * GIT;
int GIT_size;
typeBlock * Block;
int Block_size;
int Block_cur;
BOOL _stop;
4.2 Алгоритмы основных функций
синтаксического анализатора
Syntax_Analiz_1.
1. если есть лексемы в таблице лексем, то
2. если лексема ключевое слово: обработать блок лексем
3. если лексема ‘;’ – завершить строку выборки, если ‘.’ – игнорировать поток
4. если во время обработки строки выборки произошли ошибки – выдать сообщение и выйти
Обработка блоков.
1. program:
1.1. получить лексему, если лексема не слово – выйти с ошибкой
1.2. иначе создать таблицу идентификаторов с соответствующей лексеме полю 0
1.3. выйти без ошибок
2. var:
2.1. выбрать лексему
2.2. запомнить позицию (lp, lw)
2.3. пока не встретится ‘:’ выбирать лексемы
2.4. выбрать лексему, отвечающую за тип, определить тип
2.5. вернуться на (lp, lw) и произвести выборку в таблицу идентификаторов, пока не встречено ‘:’
2.6. пропустить одну лексему вперед
2.7. текущая лексема должна быть ‘;’
3. function:
3.1. выборка лексемы, лексема является именем функции, слово добавить к таблице идентификаторов
3.2. запуск процедуры выборки переменных
3.3. выбрать лексему типа функции и изменить тип текущей функции в таблице идентификаторов
3.4. добавить в стек ожидания ‘begin’
4. begin:
4.1. извлечь из стека индекс начала блока
4.2. добавить элемент к таблице блоков
4.3. выборка лексем пока не встретится конечный ‘end’, выборка ‘end’-‘begin’ идет с учетом соответствия
4.4. установить текущему блоку маркер ‘конец блока’
4.5. выход без ошибок
5. end:
5.1. выдать ошибку отсутствия ‘begin’
insertGIT
1. выделить память под элемент
2. выполнить поиск в GIT на наличие лексемы
3. если есть – выйти с ошибкой (duplicate identifier)