Схема вызовов процедур и функций
синтаксического анализатора
compiller-2—main -- Syntax_Analiz_1
|
NextLexema
|
p_prog—isWord—InsertGIT
|
p_var—NextLex—isWord—isOperator—GetTypeByWord—InsertGIT
|
p_func—isWord—Syntax_Analiz_1
|
p_beg—isOperator--insertBlock
|
p_end—error
4.4 Организация процедуры компиляции
Процедура компиляции состоит из следующих этапов:
1. Подготовка к компиляции
2. Проверка лексики входного файла
3. Проверка синтаксиса входного файла
4. Проверка блочной структуры входного файла
5. Генерация кода
6. Вывод кода ошибки при ее обнаружении
4.5 Спецификация основных процедур и функций
lpdgram *p_block(int b)
{Входные параметры: номер разбираемого блока
Выходные параметры: массив из бинарных деревьев (диаграмм Вирта)
Выполняемая функция: преобразование таблицы лексем к таблице идентификаторов и массивам диаграмм Вирта
}
lpdgram p_codeline(int b)
{Входные параметры: номер разбиваемого блока
Выходные параметры: бинарное дерево (диаграмма Вирта)
Выполняемая функция: преобразование одной строки на языке Pascal из таблицы лексем в диаграмму Вирта
}
int getnumArg(int f)
{Входные параметры: индекс функции в таблице идентификаторов
Выходные параметры: количество аргументов функции
Выполняемая функция: получение количества аргументов для функции, заданной индексом в таблице идентификаторов
}
operations operationType(char * op, int block)
{Входные параметры: символьное представление операции (лексема) и блок, в котором она находится
Выходные параметры: тип операции
Выполняемая функция: определение типа диаграммы Вирта
}
lpdgram initDgram(operations type, int ext, lpdgram left, lpdgram right)
{Входные параметры: тип операции, индекс в таблице идентификаторов (для переменных и функций) или значение константы (для константы), левая и правая связи
Выходные параметры: корень дерева кода
Выполняемая функция: инициализация элемента или корня дерева кода
}
void dropDgram(lpdgram Dgram)
{Входные параметры: корень или элемент дерева
Выходные параметры: нет
Выполняемая функция: освобождение памяти из-под диаграммы Вирта
}
void atLexima(int sl, int sw)
{Входные параметры: индексы в таблице лексем
Выходные параметры: нет
Выполняемая функция: переход к указанному слову в таблице лексем
}
void rewindLexima(void)
{Входные параметры: нет
Выходные параметры: нет
Выполняемая функция: переход на одну лексему назад
}
char * nextLexima(void)
{Входные параметры: нет
Выходные параметры: лексема
Выполняемая функция: получение новой лексемы из таблицы лексем
}
int Delimeter(char * line)
{Входные параметры: символьная строка
Выходные параметры: код разделителя
Выполняемая функция: определение типа и кода разделителя
}
int isOperator(char * line)
{Входные параметры: символьная строка
Выходные параметры: код оператора
Выполняемая функция: определение, является ли line оператором, если является, то определяется его код, если нет – возвращается -1
}
int isKeyWord(char * line)
{Входные параметры: символьная строка
Выходные параметры: код ключевого слова
Выполняемая функция: определяет, является ли line ключевым словом, возвращает его код, если является
}
BOOL Syntax_Analiz_1(void)
{Входные параметры:нет
Выходные параметры: true – анализ успешен, false – обнаружена ошибка
Выполняемая функция: преобразование программы к блокам кода, извлечение идентификаторов в таблицу идентификаторов и подготовка к разбиению блоков на строки диаграмм Вирта
}
void p_program(void)
{Входные параметры: нет
Выходные параметры: нет
Выполняемая функция: обработка ключевого слова program и помещение его в таблицу GIT (Global Ident Table)
}
void p_var(int _ext)
{Входные параметры: тип хранения переменной: переменная локальная для функции, глобальная для программы или параметр для вызова функции
Выходные параметры: нет
Выполняемая функция: обработка ключевого слова var и помещение его в таблицу GIT (Global Ident Table)
}
void p_function(void)
{Входные параметры: нет
Выходные параметры: нет
Выполняемая функция: обработка ключевого слова function и помещение его в таблицу GIT (Global Ident Table)
}
void p_begin(void)
{Входные параметры: нет
Выходные параметры: нет
Выполняемая функция: обработка ключевого слова begin, создание метки блока, добавление нового блока к таблице блоков, создание связи блока с таблицей идентификаторов
}
void p_end(void)
{Входные параметры: нет
Выходные параметры: нет
Выполняемая функция: обработка ошибки отсутствия соответствующего ключевого слова begin
}
BOOL p_other_sym(char * lex)
{Входные параметры: lex – лексема
Выходные параметры: true – продолжать анализ, false – анализ прекратить
Выполняемая функция: анализ дополнительных лексем (например ;)
}
BOOL insertGIT(char * lex, IdentTypes type, unsigned int ext, unsigned long val)
{Входные параметры: лексема, тип идентификатора, тип хранения переменной: переменная локальная для функции, глобальная для программы или параметр для вызова функции, значение
Выходные параметры: успешно добавлен элемент или нет
Выполняемая функция: добавляет элемент в таблицу идентификаторов
}
int searchGIT(char * name)
{Входные параметры: имя лексемы
Выходные параметры: номер строки в таблице идентификаторов, -1 в случае не обнаружения идентификатора
Выполняемая функция: осуществляет поиск идентификаторов в таблице и возвращает номер строки в случае, если она найдена.
}
int searchGITfrom(char * name, int _from)
{Входные параметры: имя лексемы; номер блока, с которого осуществляется поиск
Выходные параметры: номер строки в таблице идентификаторов, -1 в случае не обнаружения идентификатора в таблице
Выполняемая функция: осуществляет поиск идентификатора в таблице для определенного блока, с учетом его “видимости”
}
int searchGITblock(char * name, int block)
{ Входные параметры: имя лексемы; номер блока, с которого осуществляется поиск
Выходные параметры: номер строки в таблице идентификаторов, -1 в случае не обнаружения идентификатора в таблице
Выполняемая функция: осуществляет поиск идентификатора в таблице для определенного блока, внутри его
}
int searchGITto(char * name, int block)
{Входные параметры: имя лексемы; номер блока, с которого осуществляется поиск
Выходные параметры: номер строки в таблице идентификаторов, -1 в случае не обнаружения идентификатора в таблице
Выполняемая функция: осуществляет поиск идентификатора в таблице для определенного блока, внутри его, в глобальном пространстве и передаваемых функции параметров
}
int insertBlock(int varIdx)
{Входные параметры: индекс начала блока в таблице идентификаторов
Выходные параметры: индекс добавленного блока
Выполняемая функция: добавление блока к таблице блоков
}
void addBlockStart(void)
{Входные параметры: нет
Выходные параметры: нет
Выполняемая функция: изменение метки начала блока в таблице блоков
}
void addBlockEnd(void)
{Входные параметры: нет
Выходные параметры: нет
Выполняемая функция: изменение метки конца блока в таблице блоков
}
void freeGIT(void)
{Входные параметры: нет
Выходные параметры: нет
Выполняемая функция: освобождение памяти от таблицы идентификаторов
}
void freeBlock(void)
{Входные параметры: нет
Выходные параметры: нет
Выполняемая функция: освобождение памяти от блоков кода
}
BOOL isWord(char * tmp)
{Входные параметры: слово
Выходные параметры: true в случае, если слово, false – если нет.
Выполняемая функция: определение, принадлежит ли tmp к словам или нет
}
int GetIdentTypeByWord(char * type)
{Входные параметры: символьная строка
Выходные параметры: -1 – ошибка, иначе код для типа
Выполняемая функция: получение типа идентификатора по его символьному названию (integer)
}
4.6 Обработка ошибок
Разработанный синтаксический анализатор обнаруживает следующие виды ошибок:
№ | Ошибка | Причина |
Error in program structure detected, may be an `;' expected | ||
Unexpected end-of-file detected | ||
Error detected during compilation... Stopped... | ||
Error unexpected end-of-file at line | ||
program name must be a word | ||
Wrong type definition, may be expected `:' | ||
Invalid identificator name | ||
expected type declaration | ||
Function must have some name | ||
Here must be variable or const definition | ||
`;' Expected | ||
`:' Expected | ||
Function type specific-word must be a WORD! | ||
Unknown type definition | ||
Begin expected | ||
Syntax error: Dublicate identificator | ||
unknow identificator | ||
Boolean operation dont supported |
Реализация
Тестирование
5.1.1 Внешние тесты
Входной файл на языке Паскаль test.pas:
program test;
var x:integer;
cy,h,c:integer;
function f(x:integer; var i,j:integer):integer;
var
d:integer;
begin
f:=x+i*j;
end;
var a:integer;
begin
cy:= 6;
c:= 9;
x:=c/cy + f(4,c ,cy);
end.
Выходной файл на языке Ассемблера test.asm:
; ---- 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
__codeblock001 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
mov eax, 6
mov DWORD PTR [ebp-4], eax
mov eax, 9
mov DWORD PTR [ebp-12], eax
sub esp, 16 ; vars to block 1
mov eax, 4
push eax
mov eax, 12
push eax
mov eax, 4
push eax
call __codeblock001
add esp, 28
push eax
mov eax, DWORD PTR [ebp-4]
mov ebx, DWORD PTR [ebp-12]
xchg eax, ebx
xor edx, edx
idiv ebx
pop ebx
add eax, ebx
mov DWORD PTR [ebp-0], eax
ret
__codeblock000 endp
__codeblock001 proc
mov eax, DWORD PTR [ebp-0]
mov ebx, DWORD PTR [ebp-16]
xor edx, edx
imul ebx
add eax, DWORD PTR [ebp-16]
ret
__codeblock001 endp
END EntryPoint
Входной файл на языке Паскаль test1.pas
program test1;
var i,j:integer;
x:integer;
function sum(i,j:integer):integer;
var
s:integer;
begin
s:=i+j;
sum:=s;
end;
begin
x:=sum (5,6);
end.
Выходной файл на языке Ассемблера test1.asm
; ---- 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
__codeblock001 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, 12 ; vars to block 0
call __codeblock000
invoke ExitProcess,0
__codeblock000 proc
sub esp, 12 ; vars to block 1
mov eax, 6
push eax
mov eax, 5
push eax
call __codeblock001
add esp, 20
mov DWORD PTR [ebp-8], eax
ret
__codeblock000 endp
__codeblock001 proc
mov eax, DWORD PTR [ebp-0]
add eax, DWORD PTR [ebp-16]
mov DWORD PTR [ebp-8], eax
mov eax, DWORD PTR [ebp-0]
ret
__codeblock001 endp
END EntryPoint
2 невъебенных теста…