Initial commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1c85d0e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.idea
+cmake-build-*
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..4fcd8af
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.20)
+project(REFAL)
+
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+set(CMAKE_AUTOUIC ON)
+
+
+find_package(Qt5 COMPONENTS
+ Core
+ REQUIRED)
+
+add_executable(REFAL main.cpp Token.cpp Token.h Matcher.cpp Matcher.h VarContext.cpp VarContext.h)
+target_link_libraries(REFAL
+ Qt::Core
+ )
+
diff --git a/Matcher.cpp b/Matcher.cpp
new file mode 100644
index 0000000..4fc901c
--- /dev/null
+++ b/Matcher.cpp
@@ -0,0 +1,29 @@
+#include "Matcher.h"
+
+MatchResult match(QList<Token> data, QList<Token> pattern, VarContext context) {
+ if (data.empty() && pattern.empty()) {
+ return MatchResult{true, context};
+ }
+
+ Token patternHead = pattern.first();
+ Token dataHead = data.first();
+ pattern.removeFirst();
+
+ if (patternHead.isSym() || patternHead.isIdent()) {
+ if (patternHead == pattern.first()) {
+ data.removeFirst();
+ return match(data, pattern, context);
+ } else {
+ return MatchResult{false, context};
+ }
+ } else if (patternHead.isParen() && dataHead.isParen()) {
+ data.removeFirst();
+ auto result = match(dataHead.parenContent(), patternHead.parenContent(), context);
+
+ if (result.success) {
+ return match(data, pattern, result.context);
+ } else {
+ return MatchResult{false, result.context};
+ }
+ }
+}
diff --git a/Matcher.h b/Matcher.h
new file mode 100644
index 0000000..81f4305
--- /dev/null
+++ b/Matcher.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "Token.h"
+#include "VarContext.h"
+
+struct MatchResult {
+ bool success;
+ VarContext context;
+};
+
+MatchResult match(QList<Token> data, QList<Token> pattern, VarContext context);
diff --git a/Token.cpp b/Token.cpp
new file mode 100644
index 0000000..7cb50e0
--- /dev/null
+++ b/Token.cpp
@@ -0,0 +1,65 @@
+#include "Token.h"
+
+Token::Token(const Token &other) {
+ *this = other;
+}
+
+Token::Token(QChar symbol) {
+ _type = SYM;
+ _charVal = symbol;
+}
+
+Token::Token(QString &&identifier) {
+ _type = IDENT;
+ _stringVal = identifier;
+}
+
+Token::Token(QList<Token> &&parenthesized) {
+ _type = PAREN;
+ _listVal = new QList<Token>(parenthesized);
+}
+
+Token::Token(char varType, const QString &&name) {
+ _type = VAR;
+ _charVal = varType;
+ _stringVal = name;
+}
+
+Token::~Token() {
+ // Стерать нулевые пойнтеры безопасно
+ delete _listVal;
+}
+
+bool Token::isSym() {
+ return _type == SYM;
+}
+
+bool Token::isIdent() {
+ return _type == IDENT;
+}
+
+bool Token::isParen() {
+ return _type == PAREN;
+}
+
+bool Token::isVar() {
+ return _type == VAR;
+}
+
+Token::Token() : Token("Null") {
+}
+
+bool Token::operator==(const Token &other) {
+ return _type == other._type
+ && _stringVal == other._stringVal
+ && _charVal == other._charVal
+ && (_listVal == nullptr || *_listVal == (*other._listVal));
+}
+
+QList<Token> Token::parenContent() {
+ if (isParen() && _listVal) {
+ return *_listVal;
+ } else {
+ return {};
+ }
+}
diff --git a/Token.h b/Token.h
new file mode 100644
index 0000000..bb46127
--- /dev/null
+++ b/Token.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <QList>
+#include <QChar>
+
+class Token {
+public:
+ Token();
+ Token(const Token &other);
+
+ explicit Token(QChar symbol);
+ explicit Token(QString &&identifier);
+ explicit Token(QList<Token> &&parenthesized);
+ Token(char varType, const QString &&name);
+
+ bool operator ==(const Token &other);
+
+ ~Token();
+
+ bool isSym();
+ bool isIdent();
+ bool isParen();
+ bool isVar();
+
+ QList<Token> parenContent();
+
+private:
+ enum Type {
+ SYM, IDENT, PAREN, VAR,
+ };
+
+ int _type = 0;
+ QString _stringVal = "";
+ QList<Token> *_listVal = nullptr;
+ QChar _charVal = 0;
+};
diff --git a/VarContext.cpp b/VarContext.cpp
new file mode 100644
index 0000000..bde30ef
--- /dev/null
+++ b/VarContext.cpp
@@ -0,0 +1,17 @@
+#include "VarContext.h"
+
+void VarContext::add(char t, const QString &&name, const Token &value) {
+ _vars.insert(name, Var{t, value});
+}
+
+char VarContext::exists(const QString &name) {
+ return _vars.contains(name);
+}
+
+Token VarContext::operator[](const QString &name) {
+ return _vars[name].value;
+}
+
+VarContext::VarContext(const VarContext &other) noexcept {
+ _vars = other._vars;
+}
diff --git a/VarContext.h b/VarContext.h
new file mode 100644
index 0000000..afa1b9a
--- /dev/null
+++ b/VarContext.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <QMap>
+#include "Token.h"
+
+class VarContext {
+public:
+ VarContext() = default;
+ VarContext(VarContext const &other) noexcept;
+
+ void add(char t, const QString &&name, const Token &value);
+ char exists(const QString &name);
+ Token operator [](const QString &name);
+
+private:
+ struct Var {
+ Var() = default;
+
+ char t = 0;
+ Token value;
+ };
+
+ QMap<QString, Var> _vars;
+};
\ No newline at end of file
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..6c07880
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,8 @@
+#include <QCoreApplication>
+#include <QDebug>
+
+int main(int argc, char *argv[]) {
+ QCoreApplication a(argc, argv);
+ qDebug() << "Hello World";
+ return QCoreApplication::exec();
+}