Компилятор и вм милана

This commit is contained in:
2025-05-22 15:19:31 +03:00
parent 9cad2ede63
commit 6da094ebbf
48 changed files with 6789 additions and 0 deletions

119
lab4/cmilan/src/parser.h Normal file
View File

@@ -0,0 +1,119 @@
#ifndef CMILAN_PARSER_H
#define CMILAN_PARSER_H
#include "scanner.h"
#include "codegen.h"
#include <iostream>
#include <sstream>
#include <string>
#include <map>
using namespace std;
/* Синтаксический анализатор.
*
* Задачи:
* - проверка корректности программы,
* - генерация кода для виртуальной машины в процессе анализа,
* - простейшее восстановление после ошибок.
*
* Синтаксический анализатор языка Милан.
*
* Парсер с помощью переданного ему при инициализации лексического анализатора
* читает по одной лексеме и на основе грамматики Милана генерирует код для
* стековой виртуальной машины. Синтаксический анализ выполняется методом
* рекурсивного спуска.
*
* При обнаружении ошибки парсер печатает сообщение и продолжает анализ со
* следующего оператора, чтобы в процессе разбора найти как можно больше ошибок.
* Поскольку стратегия восстановления после ошибки очень проста, возможна печать
* сообщений о несуществующих ("наведенных") ошибках или пропуск некоторых
* ошибок без печати сообщений. Если в процессе разбора была найдена хотя бы
* одна ошибка, код для виртуальной машины не печатается.*/
class Parser
{
public:
// Конструктор
// const string& fileName - имя файла с программой для анализа
//
// Конструктор создает экземпляры лексического анализатора и генератора.
Parser(const string& fileName, istream& input)
: output_(cout), error_(false), recovered_(true), lastVar_(0)
{
scanner_ = new Scanner(fileName, input);
codegen_ = new CodeGen(output_);
next();
}
~Parser()
{
delete codegen_;
delete scanner_;
}
void parse(); //проводим синтаксический разбор
private:
typedef map<string, int> VarTable;
//описание блоков.
void program(); //Разбор программы. BEGIN statementList END
void statementList(); // Разбор списка операторов.
void statement(); //разбор оператора.
void expression(); //разбор арифметического выражения.
void term(); //разбор слагаемого.
void factor(); //разбор множителя.
void relation(); //разбор условия.
// Сравнение текущей лексемы с образцом. Текущая позиция в потоке лексем не изменяется.
bool see(Token t)
{
return scanner_->token() == t;
}
// Проверка совпадения текущей лексемы с образцом. Если лексема и образец совпадают,
// лексема изымается из потока.
bool match(Token t)
{
if(scanner_->token() == t) {
scanner_->nextToken();
return true;
}
else {
return false;
}
}
// Переход к следующей лексеме.
void next()
{
scanner_->nextToken();
}
// Обработчик ошибок.
void reportError(const string& message)
{
cerr << "Line " << scanner_->getLineNumber() << ": " << message << endl;
error_ = true;
}
void mustBe(Token t); //проверяем, совпадает ли данная лексема с образцом. Если да, то лексема изымается из потока.
//Иначе создаем сообщение об ошибке и пробуем восстановиться
void recover(Token t); //восстановление после ошибки: идем по коду до тех пор,
//пока не встретим эту лексему или лексему конца файла.
int findOrAddVariable(const string&); //функция пробегает по variables_.
//Если находит нужную переменную - возвращает ее номер, иначе добавляет ее в массив, увеличивает lastVar и возвращает его.
Scanner* scanner_; //лексический анализатор для конструктора
CodeGen* codegen_; //указатель на виртуальную машину
ostream& output_; //выходной поток (в данном случае используем cout)
bool error_; //флаг ошибки. Используется чтобы определить, выводим ли список команд после разбора или нет
bool recovered_; //не используется
VarTable variables_; //массив переменных, найденных в программе
int lastVar_; //номер последней записанной переменной
};
#endif