 
        
        - •Расчетно-графическая работа
- •Оглавление
- •Введение
- •Проектирование компилятора
- •Общие сведения
- •Грамматика языка
- •Разработка интерфейса
- •Реализация компилятора
- •2.1. Реализация лексического блока
- •2.2. Реализация синтаксического блока
- •2.3. Реализация генератора кода
- •2.4. Реализация р-ичной библиотеки
- •Тестирование и анализ результатов
- •Заключение
- •Список использованной литературы
- 
Реализация компилятора
2.1. Реализация лексического блока
Основным назначением ЛБ является разбиение цепочки литер, представляющей программу на исходном языке, в цепочку символов языка, опознание этих цепочек, начальное заполнение таблиц, замена символов кодами. При этом, если в программе были комментарии, то ЛБ их должен удалить.
Таким образом,ЛБ представляет собой программу, в которой:
- 
открывается на чтение файл с текстом программы на исходном языке программирования; 
- 
открывается на запись файл, в который будем заносить версию программы на исходном языке программирования в виде кодов символов; 
- 
читаем построчно файл с исходным текстом программы; 
- 
обрабатываем строку: 
- 
удаляем комментарии; 
- 
выделяем очередную цепочку литер до ближайшего разделителя, распознаем ее и записываем в файл в виде кода; 
- 
продолжаем, пока не дойдем до конца считанной строки; 
- 
пункты 3,4 повторяем до тех пор, пока не дойдем до конца файла. 
Для запуска программы используем головную процедуру Button1Click (TObject *Sender), в которой последовательно реализуются все блоки компилятора.
В Лексическом блоке были использованы следующие функции:
- 
char *NextToken(char *, char *) – выделяет лексему в строке «str» и возвращает ее в строку «ls» и ее код. 
- 
voidDoLexicalAnalysis (char *) – получает строку из входного файла и дубликатэтой же строки для отображения ее оригинального вида в окне лексического блока, распознает и удаляет многострочные комментарии, обнаруживает незакрытые комментарии и принудительно их закрывает, распознает служебные слова, идентификаторы, константы и символы-разделители, заносит коды всех символов в файл с расширением .lex и отображает содержимое файла в поле Memo1 формы LexForm. 
- 
intIsDelimiter(char) - определяет символ-разделитель«c». 
- 
intRecognizeConstant(char *) - распознает константы в строке, возвращает соответствующий код, а также создает таблицу констант с частичным заполнением полей таблицы. 
- 
intRecognizeIdentifier(char *) – распознает идентификаторы в строке, возвращает их код и создает таблицу идентификаторов с частичным заполнением полей таблицы. 
- 
intRecognizeReservedToken(char *) - распознает терминальные символы, заданные грамматикой языка, в строке s и возвращает их код. 
- 
intRecognizeDelimiter(char *) - распознает символы-разделители в строке s и возвращает соответствующий код. 
- 
intRecognizeToken(char *) - распознаетлексему. 
2.2. Реализация синтаксического блока
При синтаксическом разборе выражений необходимо не только провести проверку синтаксиса, но и более явно указать порядок выполнения операций. При этом в грамматику можно добавлять символы действия, выполняющие не проверку синтаксиса, а какие-то другие действия, например, работа с таблицами, преобразование выражения и т.д.
Как известно, есть 3 способа записи выражений:
- 
инфиксная a+b; 
- 
префиксная +ab; 
- 
постфиксная ab+. 
Префиксная и постфиксная формы известны как, соответственно, прямая и обратная польские записи (по стране ее изобретателя, поляка, Яна Лукасевича).
Это, так называемые бесскобочные формы записи.
Среди множества известных алгоритмов перехода от инфиксной формы записи выражения к обратной польской, рассмотрим следующий алгоритм, состоящий из трех действий:
- 
PushSymbol(PS)– если при чтении выражения слева направо встречается идентификатор, печатаем его; 
- 
PushToStack (PTS) – если при чтении выражения слева направо встречается знак операции, заносим его в стек; 
- 
PopFromStack(PFS) – если при чтении выражения слева направо встречается конец выражения или подвыражения, извлекаем знак из стека и печатаем его. 
В синтаксическом блоке использованы следующие функции:
- 
structtbl *FindTblByCode(int)– ищет идентификатор по коду, переданному в качестве параметра, и возвращает структуру, содержащую искомый идентификатор; 
- 
structtbl *FindLitByCode(int)–ищет константу по коду, переданному в качестве параметра, и возвращает структуру, содержащую искомую константу; 
- 
intNextSymb(void) – выделяет следующий символ из входного потока данных 
- 
voidTitleOperator (void) – обрабатывает и проверяет заголовок программы; 
- 
voidDeclareOperator(void) – обрабатывает и проверяет объявление переменных; 
- 
voidExeсutionOperator(void) –обрабатывает и проверяет структуру выполняемых операторов и функций; 
- 
voidBaseOperator(void) – обрабатывает и проверяет установку основания системы счисления; 
- 
voidReadOperator(inttype) –обрабатывает и проверяетсписок переменных ввода; 
- 
voidWriteOperator(void) – обрабатывает и проверяет список переменных вывода; 
- 
voidAssignmentOperator (void) – обрабатывает и проверяет операции присваивания переменных; 
- 
voidEndOperator (void) – обрабатывает и проверяет окончание программы; 
- 
voidexpr(void) – разбирает выражение, преобразуя его в обратную польскую запись. 
Функции, реализующие эти преобразования:
- 
voidlitem(void); 
- 
voidlitem2(void); 
- 
voidlfactor(void); 
- 
void lfactor2(void); 
- 
void item (void); 
- 
void item2 (void); 
- 
void factor2 (void); 
- 
void arithm (void); 
- 
void arithm2 (void); 
- 
voidprim (void). 
