Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <string>
- #include <vector>
- #include <fstream>
- #include <iostream>
- using namespace std;
- const int default_hash = 100;
- // ТАБЛИЦЫ
- // Пара - индексы элемента в таблице идентификаторов
- struct id_pair {
- int hash;
- int id;
- };
- // Структура одного элемента переменной таблицы
- struct elem {
- string name;
- bool type;
- bool data;
- };
- // Структура для подсчета токенов / строк / символов
- struct errorposition
- {
- int symcount = 0;
- int linecount = 1;
- } errpos;
- // Класс постоянных таблиц
- class constantTable {
- public:
- vector<string> table;
- int find(string name) { // возвращает id ключевого слова либо -1
- if (name.length() > 0)
- for (int i = 0; i < table.size(); i++)
- if (table[i] == name)
- return i;
- return -1;
- }
- constantTable(vector<string> tab) {
- table = tab;
- }
- private:
- /*vector<string> table;*/
- } words({ "if", "else", "int" }), sep({ ";", ",", "(", ")" }), ops({ "=", "+", "-", "*", "<", "==", "!=" });
- // Класс констант
- class Constants {
- public:
- vector<int> consts;
- int find_add(int constant) { // поиск или добавление, возвращает ИД
- int i = 0;
- for (; i < consts.size(); i++)
- if (constant == consts[i])
- return i;
- consts.push_back(constant);
- return i;
- }
- private:
- /*vector<int> consts;*/
- } cs;
- // Класс идентификаторов
- class Identificators {
- public:
- vector<vector<elem>> table{ default_hash, vector<elem>() };
- id_pair find_add(string ident) { // поиск или добавление, возвращает пару
- id_pair p;
- p.hash = hashFun(ident);
- if (ident.length() > 0) {
- for (int i = 0; i < table[p.hash].size(); i++)
- if (ident == table[p.hash][i].name) {
- p.id = i;
- return p;
- }
- elem el;
- el.name = ident;
- el.data = 0;
- el.type = 0;
- table[p.hash].push_back(el);
- p.id = table[p.hash].size() - 1;
- return p;
- }
- }
- string find(id_pair p) { // поиск названия по ИД
- for (int i = 0; i < table[p.hash].size(); i++)
- if (i == p.id)
- return table[p.hash][i].name;
- return "";
- }
- bool set_type(id_pair p, int state = 1) { // вернет 0, если установка типа прошла успешно, в противном случае вернет 1
- if (p.id >= table[p.hash].size()) {
- table[p.hash][p.id].type = state;
- return 0;
- }
- return 1;
- }
- int get_type(id_pair p) { // вернет состояние типа или -1
- if (p.id >= table[p.hash].size())
- return table[p.hash][p.id].type;
- return -1;
- }
- bool set_data(id_pair p, int state = 1) {
- if (p.id >= table[p.hash].size()) {
- table[p.hash][p.id].data = state;
- return 0;
- }
- return 1;
- }
- int get_data(id_pair p) {
- if (p.id >= table[p.hash].size())
- return table[p.hash][p.id].data;
- return -1;
- }
- private:
- /*vector<vector<elem>> table{ default_hash, vector<elem>() };*/
- int hashFun(string str) {
- int hash = 0;
- for (int i = 0; i < str.size(); i++)
- hash += str[i];
- return hash % default_hash;
- }
- } id;
- // ПОДПРОГРАММЫ ЛЕКСИЧЕСКОГО АНАЛИЗАТОРА
- // Проверка на букву
- bool isletter(char sym)
- {
- if (sym >= 65 && sym <= 90 || sym >= 97 && sym <= 122)
- return true;
- return false;
- }
- // Проверка на цифру
- bool isdigit(char sym, char& pastsym)
- {
- if (sym >= 48 && sym <= 57)
- return true;
- return false;
- }
- // Проверка на знак
- bool issign(char sym, char& pastsym)
- {
- if (sym == '-')
- {
- pastsym = '-';
- return true;
- }
- return false;
- }
- // Обработка разделителей. Односимвольный токен, либо слово
- void sepwork(vector<vector<int>>& mas, char sym, char& pastsym, ofstream& errors, int& commentstatus, int& state, string& token)
- {
- token = "";
- string tmp(1, sym);
- switch (sym)
- {
- case '\n':
- errpos.linecount++;
- errpos.symcount = 0;
- state = 0;
- break;
- case '-':
- if (mas.size() > 0 && (mas[mas.size() - 1][0] == 3 || mas[mas.size() - 1][0] == 4))
- {
- mas.push_back({ 2, ops.find("-"), 0 });
- state = 0;
- }
- else
- {
- token = sym;
- state = 2;
- }
- break;
- case '=':
- case '!':
- case '/':
- case '*':
- pastsym = sym;
- state = 0;
- break;
- case '\t':
- case ' ':
- state = 0;
- break;
- default:
- int sepid = sep.find(tmp), opsid = ops.find(tmp);
- if (sepid != -1) // Если символ в таблице разделителей
- mas.push_back({ 1, sepid, 0 });
- else if (opsid != -1) // Если символ в таблице операторов / операций
- mas.push_back({ 2, opsid, 0 });
- else
- errors << "Indefined symbol " << sym << " after " << mas.size() << " token in "
- << errpos.linecount << " line, in " << errpos.symcount << " position" << endl;
- state = 0;
- }
- }
- // Обработка двухсимвольных токенов
- void pastsymwork(vector<vector<int>>& mas, char sym, char& pastsym, ofstream& errors, int& commentstatus, int& state, int& flag, int& commentline)
- {
- string tmp(1, pastsym);
- switch (pastsym)
- {
- case '=':
- if (sym == '=')
- {
- flag = 0;
- tmp += sym;
- mas.push_back({ 2, ops.find(tmp), 0 });
- }
- else
- mas.push_back({ 2, ops.find(tmp), 0 });
- break;
- case '!':
- if (sym == '=')
- {
- flag = 0;
- tmp += sym;
- mas.push_back({ 2, ops.find(tmp), 0 });
- }
- else
- errors << "Indefined symbol " << pastsym << " after " << mas.size() << " token in "
- << errpos.linecount << " line, in " << errpos.symcount - 1 << " position" << endl;
- break;
- case '/':
- if (sym == '*' || sym == '/')
- if (sym == '*')
- {
- commentstatus = 2;
- commentline = errpos.linecount;
- }
- else
- commentstatus = 1;
- else
- errors << "Indefined symbol " << pastsym << " after " << mas.size() << " token in "
- << errpos.linecount << " line, in " << errpos.symcount - 1 << " position" << endl;
- break;
- }
- pastsym = 0;
- }
- // Обработка комментариев
- void com(char sym, char& pastsym, int& commentstatus)
- {
- switch (sym)
- {
- case '\n':
- if (commentstatus == 1)
- commentstatus = 0;
- errpos.linecount++;
- errpos.symcount = 0;
- pastsym = 0;
- break;
- case '*':
- pastsym = sym;
- break;
- case '/':
- if (pastsym == '*')
- {
- commentstatus = 0;
- pastsym = 0;
- }
- break;
- default:
- pastsym = 0;
- }
- }
- // Проверка последнего токена перед EOF + обработка незакрытого комментария
- void lastcheck(vector<vector<int>>& mas, string token, int state, int commenstatus, ofstream& errors, int commentline)
- {
- if (state == 1)
- {
- id_pair p = id.find_add(token);
- mas.push_back({ 4, p.hash, p.id });
- }
- else if (state == 2)
- {
- int tableid = cs.find_add(stoi(token));
- mas.push_back({ 3, tableid, 0 });
- }
- if (commenstatus == 2)
- errors << "Comment was open in " << commentline << " line and was not closed" << endl;
- }
- // ПОДПРОГРАММЫ СИНТАКСИЧЕСКОГО АНАЛИЗАТОРА
- int main()
- {
- int state = 0, tableid, commentstatus = 0, flag, commentline = 0;
- // state: 0 - start, 1 - identificators, 2 - constants
- // commentstatus: 0 - откл, 1 - однострочный, 2 - многострочный
- // commentline будет содержать номер строки, в который открыт многострочный комментарий
- char sym, pastsym = 0;
- string token;
- vector<vector<int>> mas(0, vector<int>(3));
- ifstream input("input1.txt");
- ofstream errors("errors.txt");
- while (input.get(sym))
- {
- errpos.symcount++;
- if (commentstatus != 0) // Если комментирование включенно
- com(sym, pastsym, commentstatus);
- else
- {
- flag = 1; // Для корректной обработки == и !=
- // Без flag после вывода == обрабатывается второе равенство как отдельный символ
- if (pastsym != 0)
- pastsymwork(mas, sym, pastsym, errors, commentstatus, state, flag, commentline);
- switch (state)
- {
- // Начальная позиция
- case 0:
- if (isletter(sym))
- {
- token += sym;
- state = 1;
- }
- else if (isdigit(sym))
- {
- token += sym;
- state = 2;
- }
- else if(flag)
- sepwork(mas, sym, pastsym, errors, commentstatus, state, token);
- break;
- // Идентификаторы
- case 1:
- if (isletter(sym) || isdigit(sym))
- token += sym;
- else
- {
- vector<int> vec(3);
- tableid = words.find(token);
- if (tableid != -1)
- vec = { 0, tableid, 0 };
- else
- {
- id_pair p = id.find_add(token);
- vec = { 4, p.hash, p.id };
- }
- mas.push_back(vec);
- sepwork(mas, sym, pastsym, errors, commentstatus, state, token);
- }
- break;
- // Константы
- case 2:
- if (isdigit(sym))
- token += sym;
- else
- {
- if (token == "-")
- {
- mas.push_back({ 2, ops.find(token), 0 });
- sepwork(mas, sym, pastsym, errors, commentstatus, state, token);
- }
- else
- {
- tableid = cs.find_add(stoi(token));
- mas.push_back({ 3, tableid, 0 });
- sepwork(mas, sym, pastsym, errors, commentstatus, state, token);
- }
- }
- break;
- }
- }
- }
- lastcheck(mas, token, state, commentstatus, errors, commentline);
- input.close();
- errors.close();
- for (int i = 0; i < mas.size(); i++)
- {
- switch (mas[i][0])
- {
- case 0:
- cout << words.table[mas[i][1]];
- break;
- case 1:
- cout << sep.table[mas[i][1]];
- break;
- case 2:
- cout << ops.table[mas[i][1]];
- break;
- case 3:
- cout << cs.consts[mas[i][1]];
- break;
- case 4:
- cout << id.table[mas[i][1]][mas[i][2]].name;
- }
- cout << " ";
- }
- cout << endl;
- // На данном этапе лексический и синтаксический анализаторы работают последовательно
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement