Компилятор и вм милана
This commit is contained in:
119
lab4/cmilan/src/parser.h
Normal file
119
lab4/cmilan/src/parser.h
Normal 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
|
||||
Reference in New Issue
Block a user