Разработка процессора р-ичной арифметики с функциями DIV ABS ROUND PBASE, страница 2

<знак>-> <буква>|<цифра>| Q | W | E | R | T | Y | U | I | O | P | { | [ | ] | } | ' | : | ; | L | K | J | H | G | F | D | S | A | Z | X | C | V | B | N | M | < | > | , | . | / | ? | ~ | ` | ! | @ | # | $ | % | ^ | & | * | ( | ) | _ | - | + | =

<список ввода> -> <идентификатор> | <идентификатор>, <список ввода>

<WRITE> -> WRITE (< список вывода >);   

<READ> -> READ (< список ввода >);    

<функция> -> <DIV > | <ABS> | <ROUND > 

<DIV> -> DIV(<выражение>) 

<ABS> -> ABS(<выражение >)

<ROUND> -> ROUND(<выражение >)

В грамматике присутствуют символы действия:

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

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

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

1.3. Интерфейс

Программа представляет собой форму, в которой реализовано главное меню:

1. Файл (пункты меню продублированы 1, 2, 3, 4, 9 кнопками на панели инструментов):

1.1. Создать (дублируется горячей клавишей CTRL+N). Создается новый документ. При этом, если открытый документ не сохранен, то запрашивается его сохранение.

1.2. Открыть (дублируется горячей клавишей CTRL+О). Открывается документ. При этом, если открытый документ не сохранен, то запрашивается его сохранение.

1.3. Сохранить (дублируется горячей клавишей CTRL+S). Сохраняется  текущий документ.

1.3. Сохранить как (дублируется горячей клавишей SHIFT+CTRL+S). Сохраняется  текущий документ под другим именем.

1.4. Выход (дублируется горячей клавишей СTRL+Q). Завершение работы программы.

2. Редактировать (пункты меню продублированы 5, 6, 7 кнопками на панели инструментов)

2.1. Копировать (дублируется горячей клавишей СTRL+С). Копировать выделенный фрагмент в буфер обмена.

2.2. Вырезать (дублируется горячей клавишей СTRL+X). Вырезать выделенный фрагмент в буфер обмена.

2.3. Вставить. (дублируется горячей клавишей СTRL+V). Вставить текст из буфера.

3. Компилятор (пункты меню продублированы 10, 11, 12 кнопками на панели инструментов).

3.1. Проверка лексики (дублируется горячей клавишей F7). Лексическая проверка текста.

3.2. Проверка синтаксиса (дублируется горячей клавишей F8). Синтаксическая проверка текста.

3.3. Компилировать (дублируется горячей клавишей F9). Компиляция проекта.

4. Справка (пункт меню продублирован 8 кнопкой на панели инструментов)

4.1. О программе. Содержится информация о программе.

Кнопки панели инструментов л, с, г активны только при условии успешной работы соответствующих блоков (лексического, синтаксического и генератора кодов соответственно). При нажатии на них можно посмотреть в отдельной форме результат работы соответствующего блока.

2. Реализация компилятора

2.1. Общие сведения

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

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

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

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

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

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

char *ConstRecogn(char *s) – проверяет, является ли строка s контсантой.

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

int TxtRecogn (char *s) – распознает произвольный текст в строке s,  возвращает его код и создает таблицу констант с заполнением полей таблицы.

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

void lex(char *s) – получает строку из входного файла; распознает и удаляет многострочные комментарии; распознает служебные слова, идентификаторы, константы и  символы разделители; заносит коды всех символов в файл с расширением .lex и отображает содержимое файла в поле Memo1 формы Form3.

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

is_dlm(char *c) – определяет символ-разделитель c.

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

Синтаксический блок реализован с помощью функций:

ErrPrt(int ns, char *s) – выдает сообщение об ошибке s в строке ns.

struct tbl *FndIdCode(int s) – по коду s находит идентификатор в таблице.

struct lit *FndLitCode(int s) – по коду s находит константу в таблице.

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

void Expr(void) – разбирает выражение, преобразуя его в обратную польскую запись. Функции, реализующие это преобразование: void litem2(void); void litem(void); void lfactor2(void); void lfactor(void); void arithm(void); void item2(void); void item(void); void factor2(void); void factor(void); void prim(void);

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

void ListI(void) – проверяет список ввода.

void ListReal(void) – проверяет список объявленных переменных типа REAL.

void ListInt(void) – проверяет список объявленных переменных типа INT.

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

void Ttl(void) – проверяет заголовок программы.

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

void Beg(void) – проверяет начало программы.

void EndOp(void) – проверяет конец программы.

void snt(void) – выполняет синтаксическую проверку текста.

2.4. Реализация генератора кодов

Генератор кодов реализован с помощью функций:

void IntGen(char **s) – генерация объявления переменных типа INT.

void IntReal(char **s) – генерация объявления переменных типа REAL.

void ReadGen(char **pbuf) – генерация оператора READ.

void WriteGen(char **s) – генерация оператора WRITE.

void PbaseGen (char **s) – генерация функции PBASE.

void AsgnGen(char **pbuf, int t) – генерация выражения.

void NextStr(void) – считывание следующей строки для разбора.

void gen(void) – генерация заголовка, разбор всего текста.

2.5. Реализация p-ичной библиотеки.

float ptof(char*s) – преобразование вещественного p-ичного числа из строки в 10-ичное.

void ftop(float f,char*s) – преобразование вещественного числа из 10-ой системы в p-ичную строку.

void itop(int n,char*s) – преобразование целого числа из 10-ой системы в p-ичную строку

int ptoi(char*s) - преобразование целого p-ичного числа из строки в 10-ичное.

bool IntOp (char *s) – проверяет является ли число целым.

void ppush(char*s) – занесение операнда в стэк.

void ppop(char*s) – извлечение операнда из стэка.

void pplus(char *s1, char *s2) – операция сложения.

void pminus(char *s1, char *s2) – операция вычитания.

void pmul(char *s1, char *s2) – операция умножения.

void pdiv(char*s1,char*s2) – операция деления.

void pumin(char*s) – операция унарного минуса.

void pand(char *s1, char *s2) – операция побитого И.

void por(char *s1, char *s2) – операция побитого ИЛИ.

void pnot(char*s) – операция отрицания.

void pround(char *s) – функция ROUND.

void pabs(char *s) – функция ABS.

void ppower(char *s1,char *s2) – операция возведения в степень

void pgq(char*s1,char*s2) – операция больше или равно.

void plq(char*s1,char*s2) – операция меньше или равно.

void pgt(char*s1,char*s2) – операция больше.

void plt(char*s1,char*s2) – операция меньше.

void pnq(char*s1,char*s2) – операция неравно.

void peq(char*s1,char*s2) – операция равно.

3. Тестирование и анализ

Исходный текст:

Результат работы лексического блока:

Результат работы синтаксического блока:

Результат работы генератора кодов:

Результат работы сгенерированной программы:

Как видим, все результаты верны.

Заключение

В процессе разработки процессора были получены навыки программирования на языке C++. Также были изучены принципы работы трехблочного компилятора (состоящего из  лексического, синтаксического блоков и генератора кода), обратная польская запись и проч. и р-ичная библиотека.