Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
19
Добавлен:
02.01.2020
Размер:
108.09 Кб
Скачать
  1. Реализация компилятора

2.1. Реализация лексического блока

Основным назначением ЛБ является разбиение цепочки литер, представляющей программу на исходном языке, в цепочку символов языка, опознание этих цепочек, начальное заполнение таблиц, замена символов кодами. При этом, если в программе были комментарии, то ЛБ их должен удалить.

Т.о. ЛБ представляет собой программу, в которой:

  1. открывается на чтение файл с текстом программы на исходном языке программирования;

  2. открывается на запись файл, в который будем заносить версию программы на исходном языке программирования в виде кодов символов;

  3. читаем построчно файл с исходным текстом программы;

  4. обрабатываем строку:

  • удаляем комментарии;

  • выделяем очередную цепочку литер до ближайшего разделителя, распознаем ее и записываем в файл в виде кода;

  • все это продолжаем, пока не дойдем до конца считанной строки;

  1. пункты 3,4 повторяем до тех пор, пока не дойдем до конца файла.

Для запуска программы используем головную процедуру Button1Click (TObject *Sender), в которой последовательно реализуются все блоки компилятора.

В Лексическом блоке были использованы следующие функции:

  • char *NextLex(char *, char *) – выделяет лексему в строке str и возвращает ее в строку ls и ее код.

  • void Lex (char *) - получает строку из входного файла, распознает и удаляет многострочные комментарии, обнаруживает незакрытые комментарии и принудительно их закрывает, распознает служебные слова, идентификаторы, константы и символы - разделители, заносит коды всех символов в файл с расширением .lex и отображает содержимое файла в поле Memo1 формы Form2.

  • int IsDlm(char) - определяет символ-разделитель c.

  • int LitRecogn(char *) - распознает константы в строке, возвращает соответствующий код, а также создает таблицу констант с частичным заполнением полей таблицы.

  • int IdRecogn(char *) – распознает идентификаторы в строке , возвращает их код и создает таблицу идентификаторов с частичным заполнением полей таблицы.

  • int TermRecogn(char *) - распознает терминальные символы, заданные грамматикой языка, в строке s и возвращает их код.

  • int DlmRecogn(char *) - распознает символы-разделители в строке s и возвращает соответствующий код.

  • int LexRecogn(char *) - распознает лексему.

2.2. Реализация синтаксического блока

При синтаксическом разборе выражений необходимо не только провести проверку синтаксиса, но и более явно указать порядок выполнения операций. При этом в грамматику можно добавлять символы действия, выполняющие не проверку синтаксиса, а какие-то другие действия, например, работа с таблицами, преобразование выражения и т.д.

Как известно, есть 3 способа записи выражений:

  • инфиксная a+b

  • префиксная +ab

  • постфиксная ab+

Префиксная и постфиксная формы известны как, соответственно, прямая и обратная польские записи (по стране ее изобретателя, поляка, Яна Лукасевича).

Это, так называемые бесскобочные формы записи.

Среди множества известных алгоритмов перехода от инфиксной формы записи выражения к обратной польской, рассмотрим следующий, состоящий из трех действий:

  1. G1 – если при чтении выражения слева направо встречается идентификатор, печатаем его;

  2. G2 – если при чтении выражения слева направо встречается знак операции, заносим его в стек;

  3. G3 – если при чтении выражения слева направо встречается конец выражения или подвыражения, извлекаем знак из стека и печатаем его.

В синтаксическом блоке использованы следующие функции:

  • struct tbl *FndId(int);- ищет идентификатор по коду, переданному в качестве параметра, и возвращает структуру, содержащую искомый идентификатор.

  • struct tbl *FndLit(int);-ищет константу по коду, переданному в качестве параметра, и возвращает структуру, содержащую искомую константу.

  • int NextSymb(void) – выделяет следующий символ из входного потока данных.

  • void DclOp(void) – проверяет оператор объявления

  • void ExeOp(void) – проверяет структуру выполняемых операторов

  • void List(int type) – проверяет список ввода

  • void ListVar(void) – проверяет список вывода

  • void Expr(void) – разбирает выражение, преобразуя его в обратную польскую запись.

Функции, реализующие эти преобразования:

  • void litem2(void);

  • void litem(void);

  • void lfactor(void);

  • void lfactor2(void);

  • void arithm(void);

  • void item2(void);

  • void item(void);

  • void factor2(void);

  • void prim(void);