Skip to content

Commit

Permalink
(#290) Перенес методы из AlgExpression в Regex,
Browse files Browse the repository at this point in the history
добавил класс для юнит тестов
  • Loading branch information
dak151449 committed Nov 10, 2023
1 parent 6978ad8 commit 62a0944
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 65 deletions.
29 changes: 29 additions & 0 deletions apps/UnitTestsApp/include/UnitTestsApp/UnitTests.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

Check notice on line 1 in apps/UnitTestsApp/include/UnitTestsApp/UnitTests.h

View workflow job for this annotation

GitHub Actions / cpp-linter

Run clang-format on apps/UnitTestsApp/include/UnitTestsApp/UnitTests.h

File apps/UnitTestsApp/include/UnitTestsApp/UnitTests.h does not conform to Custom style guidelines. (lines 16, 17, 18, 19, 21, 22, 23, 24, 26, 27, 28)

#include "AutomatonToImage/AutomatonToImage.h"

Check failure on line 3 in apps/UnitTestsApp/include/UnitTestsApp/UnitTests.h

View workflow job for this annotation

GitHub Actions / cpp-linter

/apps/UnitTestsApp/include/UnitTestsApp/UnitTests.h:3:10 [clang-diagnostic-error]

'AutomatonToImage/AutomatonToImage.h' file not found
#include "InputGenerator/RegexGenerator.h"
#include "Interpreter/Interpreter.h"
#include "Objects/AlgExpression.h"
#include "Objects/FiniteAutomaton.h"
#include "Objects/Grammar.h"
#include "Objects/Language.h"
#include "Objects/Regex.h"
#include "Objects/TransformationMonoid.h"
#include "Tester/Tester.h"
#include "gtest/gtest.h"
#include <functional>

class UnitTests

Check warning on line 16 in apps/UnitTestsApp/include/UnitTestsApp/UnitTests.h

View workflow job for this annotation

GitHub Actions / cpp-linter

/apps/UnitTestsApp/include/UnitTestsApp/UnitTests.h:16:7 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'UnitTests' is non-const and globally accessible, consider making it const
{
public:
UnitTests(){};

static int InitTests(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
};

using Lexeme = AlgExpression::Lexeme;
using LexemeType = AlgExpression::Lexeme::Type;
static std::vector<Lexeme> parse_string(std::string str) {return AlgExpression::parse_string(str);};
};
29 changes: 13 additions & 16 deletions apps/UnitTestsApp/src/UnitTests.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
#include "AutomatonToImage/AutomatonToImage.h"
#include "InputGenerator/RegexGenerator.h"
#include "Interpreter/Interpreter.h"
#include "Objects/FiniteAutomaton.h"
#include "Objects/Grammar.h"
#include "Objects/Language.h"
#include "Objects/Regex.h"
#include "Objects/TransformationMonoid.h"
#include "Tester/Tester.h"
#include "gtest/gtest.h"
#include <functional>
#include "UnitTestsApp/UnitTests.h"

Check notice on line 1 in apps/UnitTestsApp/src/UnitTests.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

Run clang-format on apps/UnitTestsApp/src/UnitTests.cpp

File apps/UnitTestsApp/src/UnitTests.cpp does not conform to Custom style guidelines. (lines 28, 251)

Check failure on line 1 in apps/UnitTestsApp/src/UnitTests.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/apps/UnitTestsApp/src/UnitTests.cpp:1:10 [clang-diagnostic-error]

'UnitTestsApp/UnitTests.h' file not found

TEST(ParseStringTest, Test_regex_lexer) {

Check warning on line 3 in apps/UnitTestsApp/src/UnitTests.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/apps/UnitTestsApp/src/UnitTests.cpp:3:1 [modernize-use-trailing-return-type]

use a trailing return type for this function

Check warning on line 3 in apps/UnitTestsApp/src/UnitTests.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/apps/UnitTestsApp/src/UnitTests.cpp:3:21 [readability-named-parameter]

all parameters should be named in a function
using L = AlgExpression::Lexeme::Type;
// using L = AlgExpression::Lexeme::Type;

struct Test {

Check warning on line 6 in apps/UnitTestsApp/src/UnitTests.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/apps/UnitTestsApp/src/UnitTests.cpp:6:9 [cppcoreguidelines-pro-type-member-init]

constructor does not initialize these fields: regex_str, want_err
string regex_str;
Expand All @@ -30,20 +20,27 @@ TEST(ParseStringTest, Test_regex_lexer) {
{"&", true},
{"&1", false, 1},
{"[b[a]:1&1]:2&2", false, 11},
// тесты на отрицание
{"^a", false, 2},
{"a^|b", true},
{"d^*^b", true},
{"d|^|b", true},
{"a^", false, 4}, // a . ^ eps
{"a|(c^)", false, 8}, // a | ( c . ^ eps )
};

for (const auto& t : tests) {
stringstream message;
message << "Case: " << t.regex_str << ", WantErr: " << t.want_err;
SCOPED_TRACE(message.str());

vector<AlgExpression::Lexeme> l = AlgExpression::parse_string(t.regex_str);
vector<UnitTests::Lexeme> l = UnitTests::parse_string(t.regex_str);
ASSERT_FALSE(l.empty());

if (t.want_err) {
ASSERT_EQ(L::error, l[0].type);
ASSERT_EQ(UnitTests::LexemeType::error, l[0].type);
} else {
ASSERT_NE(L::error, l[0].type);
ASSERT_NE(UnitTests::LexemeType::error, l[0].type);
ASSERT_EQ(t.lexemes_len, l.size());
// TODO: добавить проверку содержимого l
}
Expand Down Expand Up @@ -493,4 +490,4 @@ TEST(TestCaseName, Test_GlaisterShallit) {
check_classes_number("a(b|c)(a|b)(b|c)", 5);
check_classes_number("abc|bca", 6);
check_classes_number("abc|bbc", 4);
}
}
4 changes: 2 additions & 2 deletions apps/UnitTestsApp/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "UnitTestsApp/Example.h"

Check failure on line 1 in apps/UnitTestsApp/src/main.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/apps/UnitTestsApp/src/main.cpp:1:10 [clang-diagnostic-error]

'UnitTestsApp/Example.h' file not found
#include "UnitTestsApp/UnitTests.h"
#include "gtest/gtest.h"
#include <iostream>
#include <thread>
Expand All @@ -7,6 +8,5 @@ using namespace std;
int main(int argc, char** argv) {
cout << "Unit Tests\n";
// Тестирование
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
return UnitTests::InitTests(argc, argv);
}
10 changes: 0 additions & 10 deletions libs/Objects/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
# Set the project name
project(Objects)

include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)

set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

# Create a sources variable with a link to all cpp files to compile
set(SOURCES
src/TransformationMonoid.cpp
Expand All @@ -35,5 +26,4 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME}
Fraction
AutomatonToImage
gtest
)
8 changes: 3 additions & 5 deletions libs/Objects/include/Objects/AlgExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

#include "BaseObject.h"
#include "iLogTemplate.h"
#include "gtest/gtest.h"
#include <map>
#include <unordered_map>

class AlgExpression : public BaseObject {
FRIEND_TEST(ParseStringTest, Test_regex_lexer);

protected:
struct Lexeme {
Expand All @@ -18,7 +16,7 @@ class AlgExpression : public BaseObject {
alt, // |
conc, // .
star, // *
minus, // ^
negative, // ^
symb, // alphabet symbol
eps, // Epsilon
squareBrL, // [
Expand All @@ -42,7 +40,7 @@ class AlgExpression : public BaseObject {
conc,
// Unary:
star,
minus,
negative,
// Terminal:
symb,
// [i]
Expand Down Expand Up @@ -91,7 +89,6 @@ class AlgExpression : public BaseObject {
AlgExpression* scan_symb(const vector<Lexeme>&, int, int);
AlgExpression* scan_eps(const vector<Lexeme>&, int, int);
AlgExpression* scan_par(const vector<Lexeme>&, int, int);
AlgExpression* scan_minus(const vector<Lexeme>&, int, int);
static void update_balance(const AlgExpression::Lexeme&, int&);

// список листьев дерева regex
Expand Down Expand Up @@ -135,4 +132,5 @@ class AlgExpression : public BaseObject {

friend class FiniteAutomaton;
friend class Tester;
friend class UnitTests;
};
5 changes: 5 additions & 0 deletions libs/Objects/include/Objects/Regex.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class Regex : public AlgExpression {
void normalize_this_regex(const vector<pair<Regex, Regex>>&); // переписывание regex по
// пользовательским правилам

// Построение из вектора лексем дерева регулярного выражения
// 2 и 3 аргумент - это начальный и конечный индекс рассматриваемых лексем в векторе
Regex* expr(const vector<Lexeme>&, int, int) override;
Regex* scan_minus(const vector<Lexeme>&, int, int);

public:
Regex() = default;
Regex(const string&);
Expand Down
42 changes: 10 additions & 32 deletions libs/Objects/src/AlgExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ string AlgExpression::to_txt() const {
// ставим скобки при итерации, если символов > 1
str1 = "(" + str1 + ")";
break;
case Type::minus:
case Type::negative:
symb = '^';
return symb + str1;
default:
Expand Down Expand Up @@ -164,7 +164,7 @@ string AlgExpression::type_to_str() const {
return "*";
case Type::symb:
return "symb";
case Type::minus:
case Type::negative:
return "^";
default:
break;
Expand Down Expand Up @@ -241,7 +241,7 @@ vector<AlgExpression::Lexeme> AlgExpression::parse_string(string str) {
Lexeme lexeme;
switch (c) {
case '^':
lexeme.type = Lexeme::Type::minus;
lexeme.type = Lexeme::Type::negative;
break;
case '(':
lexeme.type = Lexeme::Type::parL;
Expand Down Expand Up @@ -284,11 +284,14 @@ vector<AlgExpression::Lexeme> AlgExpression::parse_string(string str) {
brackets_are_empty = false;
break;
case '|':
if (index != 0 && lexemes.back().type == Lexeme::Type::negative)
return {Lexeme::Type::error};
lexeme.type = Lexeme::Type::alt;
break;
case '*':
if (index == 0 || (index != 0 && (lexemes.back().type == Lexeme::Type::star ||
lexemes.back().type == Lexeme::Type::alt)))
lexemes.back().type == Lexeme::Type::alt ||
lexemes.back().type == Lexeme::Type::negative)))
return {Lexeme::Type::error};
lexeme.type = Lexeme::Type::star;
break;
Expand Down Expand Up @@ -339,7 +342,7 @@ vector<AlgExpression::Lexeme> AlgExpression::parse_string(string str) {
// AlgExpression::Lexeme right
lexeme.type == Lexeme::Type::symb || lexeme.type == Lexeme::Type::parL ||
lexeme.type == Lexeme::Type::squareBrL || lexeme.type == Lexeme::Type::ref ||
lexeme.type == Lexeme::Type::minus)) {
lexeme.type == Lexeme::Type::negative)) {
// We place . between
lexemes.emplace_back(Lexeme::Type::conc);
}
Expand All @@ -348,7 +351,7 @@ vector<AlgExpression::Lexeme> AlgExpression::parse_string(string str) {
((lexeme.type == Lexeme::Type::alt &&
(lexemes.back().type == Lexeme::Type::parL ||
lexemes.back().type == Lexeme::Type::squareBrL)) ||
(lexemes.back().type == Lexeme::Type::alt &&
((lexemes.back().type == Lexeme::Type::alt || lexemes.back().type == Lexeme::Type::negative) &&
(lexeme.type == Lexeme::Type::parR || lexeme.type == Lexeme::Type::squareBrR ||
lexeme.type == Lexeme::Type::alt)))) {
// We place eps between
Expand Down Expand Up @@ -386,7 +389,7 @@ vector<AlgExpression::Lexeme> AlgExpression::parse_string(string str) {
lexemes.insert(lexemes.begin(), {Lexeme::Type::eps});
}

if (lexemes.back().type == Lexeme::Type::alt) {
if (lexemes.back().type == Lexeme::Type::alt || lexemes.back().type == Lexeme::Type::negative) {
lexemes.emplace_back(Lexeme::Type::eps);
}

Expand Down Expand Up @@ -431,9 +434,6 @@ AlgExpression* AlgExpression::expr(const vector<AlgExpression::Lexeme>& lexemes,
if (!p) {
p = scan_conc(lexemes, index_start, index_end);
}
if (!p) {
p = scan_minus(lexemes, index_start, index_end);
}
if (!p) {
p = scan_star(lexemes, index_start, index_end);
}
Expand All @@ -453,28 +453,6 @@ void AlgExpression::update_balance(const AlgExpression::Lexeme& l, int& balance)
}
}

AlgExpression* AlgExpression::scan_minus(const vector<AlgExpression::Lexeme>& lexemes,
int index_start, int index_end) {
AlgExpression* p = nullptr;

if (lexemes[index_start].type != Lexeme::Type::minus) {
return nullptr;
}

AlgExpression* l = expr(lexemes, index_start + 1, index_end);
if (l == nullptr) {
delete l;
return nullptr;
}
p = make();
p->term_l = l;
p->value = lexemes[index_start];
p->type = minus;

p->alphabet = l->alphabet;
return p;
}

AlgExpression* AlgExpression::scan_conc(const vector<AlgExpression::Lexeme>& lexemes,
int index_start, int index_end) {
AlgExpression* p = nullptr;
Expand Down
49 changes: 49 additions & 0 deletions libs/Objects/src/Regex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,55 @@ template <typename T> vector<Regex*> Regex::cast(vector<T*> ptrs) {
return regexPointers;
}

Regex* Regex::expr(const vector<AlgExpression::Lexeme>& lexemes, int index_start,
int index_end) {
AlgExpression* p;
p = scan_symb(lexemes, index_start, index_end);
if (!p) {
p = scan_eps(lexemes, index_start, index_end);
}

if (!p) {
p = scan_alt(lexemes, index_start, index_end);
}
if (!p) {
p = scan_conc(lexemes, index_start, index_end);
}
if (!p) {
p = scan_minus(lexemes, index_start, index_end);
}
if (!p) {
p = scan_star(lexemes, index_start, index_end);
}
if (!p) {
p = scan_par(lexemes, index_start, index_end);
}

return cast(p);
}

Regex* Regex::scan_minus(const vector<AlgExpression::Lexeme>& lexemes,
int index_start, int index_end) {
Regex* p = nullptr;

if (lexemes[index_start].type != Lexeme::Type::negative) {
return nullptr;
}

Regex* l = expr(lexemes, index_start + 1, index_end);
if (l == nullptr) {
delete l;
return nullptr;
}
p = make();
p->term_l = l;
p->value = lexemes[index_start];
p->type = negative;

p->alphabet = l->alphabet;
return p;
}

// возвращает пару <вектор сотсояний, max_index>
pair<vector<State>, int> Regex::get_thompson(int max_index) const {
string str; // идентификатор состояния
Expand Down

0 comments on commit 62a0944

Please sign in to comment.