Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <string>
- using std::string;
- /**
- * Типы лексем
- * Keyword - ключевое слово
- * Delimiter - разделитель
- * Sign - арифметический знак
- * Const - константа
- * Var - переменная
- */
- enum LexemeType : int { Keyword = 0, Sign = 1, Delimiter = 2, Var = 3, Const = 4};
- struct Lexeme {
- int type;
- int subtype; // Одно из KeywordType::, SignType::, DelimiterType::
- string name; // Название лексемы
- Lexeme(int type, int subtype, string name) :
- type(type),
- subtype(subtype),
- name(name)
- {};
- int getType() { return type; }
- int getSubtype() { return subtype; }
- string getName() { return name; }
- };
- enum KeywordType : int { If, Else, For, While };
- enum SignType : int { Add, Sub, Mul, Div, Equal, isEqual };
- enum DelimiterType : int { OpenBracket, CloseBracket, Space, Semicolon };
- enum VariableType : int { Undefined, Int, Float };
- /**
- * Переменная
- * @constructor name - название переменной
- * @constructor vartype - тип значения ?? Знаем ли мы тип во время лексического анализа
- */
- struct Variable : public Lexeme {
- VariableType vartype; // Тип переменной
- bool init; // Инициализированна ли переменная
- size_t data; // Данные переменной
- Variable(string name, VariableType vartype = VariableType::Undefined) :
- Lexeme(LexemeType::Var, 0, name),
- vartype(vartype),
- init(false),
- data(0)
- {};
- /** Геттеры */
- bool isInit() { return init; }
- VariableType getVarType() { return vartype; }
- string getName() { return name; }
- size_t getData() { return data; }
- /** Сеттеры */
- void setVarType(VariableType new_vartype) {
- vartype = new_vartype;
- }
- void setData(size_t new_data) {
- init = true;
- data = new_data;
- }
- };
- /**
- * Константа
- * @constructor name - название константы
- * @constructor vartype - тип значения ?? Знаем ли мы тип во время лексического анализа
- * @constructor data - данные константы ?? Знаем ли мы данные во время лексического анализа
- */
- struct Constant : public Lexeme {
- VariableType vartype;
- size_t data; // Данные переменной
- Constant(string name, VariableType vartype = VariableType::Undefined, size_t data = 0) :
- Lexeme(LexemeType::Const, 0, name),
- vartype(vartype),
- data(data)
- {};
- /** Геттеры */
- VariableType getVarType() { return vartype; }
- string getName() { return name; }
- size_t getData() { return data; }
- /** Сеттеры */
- };
- #pragma once
- #include <cassert>
- #include <string>
- #include <vector>
- #include <map>
- #include "Lexemes.hpp"
- using std::string;
- using std::vector;
- using std::pair;
- using std::map;
- class LexemesTables {
- public:
- vector<Lexeme> keywords; // Ключевые слова
- vector<Lexeme> delimiters; // Разделители
- vector<Lexeme> signs; // Арифметические знаки
- vector<Variable> variables; // Переменные
- vector<Constant> constants; // Константы
- LexemesTables();
- /**
- * Поиск лексемы среди константных таблиц
- * По строке или номеру таблицы и позиции в таблице
- */
- Lexeme* getLexeme(const string& name);
- Lexeme* getLexeme(int type, int subtype);
- /**
- * Добавляем/получаем переменную в таблице переменных
- * int - позиция в таблице
- */
- int addVariable(Variable &variable);
- Variable* getVariable(int position);
- Variable* getVariable(string name);
- int addConstant(Constant &constant);
- Constant* getConstant(int position);
- Constant* getConstant(string name);
- };
- #include "LexemesTables.hpp"
- LexemesTables::LexemesTables() {
- // Добавляем ключевые слова
- keywords = {
- {Lexeme(LexemeType::Keyword, KeywordType::If, "if" )},
- {Lexeme(LexemeType::Keyword, KeywordType::Else, "else" )},
- {Lexeme(LexemeType::Keyword, KeywordType::For, "for" )},
- {Lexeme(LexemeType::Keyword, KeywordType::While, "while")},
- };
- // Добавляем знаки
- signs = {
- {Lexeme(LexemeType::Sign, SignType::Add, "+" )},
- {Lexeme(LexemeType::Sign, SignType::Sub, "-" )},
- {Lexeme(LexemeType::Sign, SignType::Mul, "*" )},
- {Lexeme(LexemeType::Sign, SignType::Div, "/" )},
- {Lexeme(LexemeType::Sign, SignType::isEqual, "==")},
- {Lexeme(LexemeType::Sign, SignType::Equal, "=" )},
- };
- // Добавляем разделители
- delimiters = {
- {Lexeme(LexemeType::Delimiter, DelimiterType::OpenBracket, "(")},
- {Lexeme(LexemeType::Delimiter, DelimiterType::CloseBracket, ")")},
- {Lexeme(LexemeType::Delimiter, DelimiterType::Space, " ")},
- {Lexeme(LexemeType::Delimiter, DelimiterType::Semicolon, ";")},
- };
- }
- Lexeme* LexemesTables::getLexeme(const string& name) {
- for (auto& keyword : keywords) {
- if (keyword.getName() == name) return &keyword;
- }
- for (auto& sign : signs) {
- if (sign.getName() == name) return &sign;
- }
- for (auto& delimiter : delimiters) {
- if (delimiter.getName() == name) return &delimiter;
- }
- return nullptr;
- }
- Lexeme* LexemesTables::getLexeme(int type, int subtype) {
- switch (type) {
- case LexemeType::Keyword: return &keywords.at(subtype);
- case LexemeType::Delimiter: return &delimiters.at(subtype);
- case LexemeType::Sign: return &signs.at(subtype);
- }
- return nullptr;
- }
- int LexemesTables::addVariable(Variable &variable) {
- // TODO: нельзя добавлять существующую переменную
- variables.push_back(variable);
- return variables.size() - 1;
- }
- Variable* LexemesTables::getVariable(int position) {
- if (variables.size() < position) return nullptr;
- return &(variables[position]);
- }
- Variable* LexemesTables::getVariable(string name) {
- for (auto &variable : variables) {
- if (variable.getName() == name) return &variable;
- }
- return nullptr;
- };
- int LexemesTables::addConstant(Constant &constant) {
- constants.push_back(constant);
- return constants.size() - 1;
- }
- Constant* LexemesTables::getConstant(int position) {
- if (constants.size() < position) return nullptr;
- return &constants[position];
- }
- Constant* LexemesTables::getConstant(string name) {
- for (auto &constant : constants) {
- if (constant.getName() == name) return &constant;
- }
- return nullptr;
- }
- int main() {
- return 0;
- }
- #pragma once
- #include "stdafx.hpp"
- #include "../src/LexemesTables.hpp"
- TEST_CLASS(LexemesTest) {
- public:
- /** Проверка функций, которые возвращают table_id и position*/
- TEST_METHOD(SimpleLexemeTest) {
- string word = "if";
- Lexeme lexeme(LexemeType::Keyword, KeywordType::If, word);
- Assert::AreEqual(lexeme.getType(), (int)LexemeType::Keyword);
- Assert::AreEqual(lexeme.getSubtype(), (int)KeywordType::If);
- Assert::AreEqual(lexeme.getName(), word);
- }
- TEST_METHOD(LexemeTest) {
- string word;
- Lexeme sign_lexeme(LexemeType::Sign, SignType::Add, word);
- Assert::AreEqual(sign_lexeme.getType(), (int)LexemeType::Sign);
- Assert::AreEqual(sign_lexeme.getSubtype(), (int)SignType::Add);
- word = " ";
- Lexeme delim_lexeme(LexemeType::Delimiter, DelimiterType::Space, word);
- Assert::AreEqual(delim_lexeme.getType(), (int)LexemeType::Delimiter);
- Assert::AreEqual(delim_lexeme.getSubtype(), (int)DelimiterType::Space);
- }
- TEST_METHOD(VariableLexemeTest) {
- string name = "my_variable";
- Variable var(name);
- Assert::AreEqual(var.getName(), name);
- Assert::AreEqual(var.getType(), (int)LexemeType::Var);
- Assert::AreEqual(var.getVarType(), VariableType::Undefined);
- Assert::AreEqual(var.isInit(), false);
- Assert::AreEqual(var.getData(), (size_t) 0);
- var.setVarType(VariableType::Int);
- var.setData(12);
- Assert::AreEqual(var.getVarType(), VariableType::Int);
- Assert::AreEqual(var.getData(), (size_t) 12);
- }
- TEST_METHOD(ConstantLexemeTest) {
- string name = "my_constant";
- Constant constant(name, VariableType::Int, 5);
- Assert::AreEqual(constant.getName(), name);
- Assert::AreEqual(constant.getType(), (int)LexemeType::Const);
- Assert::AreEqual(constant.getVarType(), VariableType::Int);
- Assert::AreEqual(constant.getData(), (size_t) 5);
- }
- };
- #pragma once
- #include "stdafx.hpp"
- #include "../src/LexemesTables.cpp"
- using namespace Microsoft::VisualStudio::CppUnitTestFramework;
- TEST_CLASS(LexemesTablesTest) {
- public:
- /** Поиск в константных таблицах */
- TEST_METHOD(GetConstantLexemeByName) {
- LexemesTables tables;
- Lexeme* lexeme = tables.getLexeme("NOT FOUND LEXEME");
- Assert::IsNull(lexeme);
- lexeme = tables.getLexeme("if");
- Assert::AreEqual(lexeme->getType(), (int)LexemeType::Keyword);
- Assert::AreEqual(lexeme->getSubtype(), (int)KeywordType::If);
- lexeme = tables.getLexeme(" ");
- Assert::AreEqual(lexeme->getType(), (int)LexemeType::Delimiter);
- Assert::AreEqual(lexeme->getSubtype(), (int) DelimiterType::Space);
- }
- /** Поиск в константных таблицах по id:position */
- TEST_METHOD(GetConstantLexemeById) {
- LexemesTables tables;
- Lexeme* lexeme = tables.getLexeme("if");
- Assert::IsNotNull(lexeme);
- Assert::AreEqual(lexeme->getType(), (int)LexemeType::Keyword);
- Assert::AreEqual(lexeme->getSubtype(), (int)KeywordType::If);
- Lexeme* second = tables.getLexeme(lexeme->getType(), lexeme->getSubtype());
- Assert::IsNotNull(second);
- }
- /** Тесты переменной */
- TEST_METHOD(VariableLexemesTablesTest) {
- LexemesTables tables;
- string name = "my_variable";
- // Переменной не существует
- Variable* var_ptr = tables.getVariable(name);
- Assert::IsNull(var_ptr);
- // Добавили переменную и получили её позицию в таблице переменных
- Variable var(name);
- int position = tables.addVariable(var);
- // Переменная существует
- var_ptr = tables.getVariable(name);
- Assert::IsNotNull(var_ptr);
- Assert::AreEqual(var_ptr->getName(), name);
- // Получаем переменную по её позиции в таблице переменных
- var_ptr = tables.getVariable(position);
- Assert::IsNotNull(var_ptr);
- Assert::AreEqual(var_ptr->getName(), name);
- }
- };
Advertisement