Files
mathlogic/lab4/cmilan/src/parser.h

120 lines
5.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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