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

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

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

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

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

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

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

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

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

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

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

  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+.

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

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

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

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

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

  3. 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).