diff --git a/.gitignore b/.gitignore index ed3680d..f15b582 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.code-workspace .vscode builddir +*.kb diff --git a/compile_commands.json b/compile_commands.json index 70b729b..e5cdbba 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -1,20 +1,62 @@ [ { "directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir", - "command": "clang++ -Isrc/obelisk.p -Isrc -I../src -fcolor-diagnostics -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -O0 -g -MD -MQ src/obelisk.p/obelisk.cpp.o -MF src/obelisk.p/obelisk.cpp.o.d -o src/obelisk.p/obelisk.cpp.o -c ../src/obelisk.cpp", + "command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/obelisk.cpp.o -MF src/obelisk.p/obelisk.cpp.o.d -o src/obelisk.p/obelisk.cpp.o -c ../src/obelisk.cpp", "file": "../src/obelisk.cpp", "output": "src/obelisk.p/obelisk.cpp.o" }, { "directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir", - "command": "clang++ -Isrc/obelisk.p -Isrc -I../src -fcolor-diagnostics -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -O0 -g -MD -MQ src/obelisk.p/lexer.cpp.o -MF src/obelisk.p/lexer.cpp.o.d -o src/obelisk.p/lexer.cpp.o -c ../src/lexer.cpp", + "command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/lexer.cpp.o -MF src/obelisk.p/lexer.cpp.o.d -o src/obelisk.p/lexer.cpp.o -c ../src/lexer.cpp", "file": "../src/lexer.cpp", "output": "src/obelisk.p/lexer.cpp.o" }, { "directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir", - "command": "clang++ -Isrc/obelisk.p -Isrc -I../src -fcolor-diagnostics -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -O0 -g -MD -MQ src/obelisk.p/parser.cpp.o -MF src/obelisk.p/parser.cpp.o.d -o src/obelisk.p/parser.cpp.o -c ../src/parser.cpp", + "command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/parser.cpp.o -MF src/obelisk.p/parser.cpp.o.d -o src/obelisk.p/parser.cpp.o -c ../src/parser.cpp", "file": "../src/parser.cpp", "output": "src/obelisk.p/parser.cpp.o" + }, + { + "directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir", + "command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/knowledge_base.cpp.o -MF src/obelisk.p/knowledge_base.cpp.o.d -o src/obelisk.p/knowledge_base.cpp.o -c ../src/knowledge_base.cpp", + "file": "../src/knowledge_base.cpp", + "output": "src/obelisk.p/knowledge_base.cpp.o" + }, + { + "directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir", + "command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_action.cpp.o -MF src/obelisk.p/models_action.cpp.o.d -o src/obelisk.p/models_action.cpp.o -c ../src/models/action.cpp", + "file": "../src/models/action.cpp", + "output": "src/obelisk.p/models_action.cpp.o" + }, + { + "directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir", + "command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_entity.cpp.o -MF src/obelisk.p/models_entity.cpp.o.d -o src/obelisk.p/models_entity.cpp.o -c ../src/models/entity.cpp", + "file": "../src/models/entity.cpp", + "output": "src/obelisk.p/models_entity.cpp.o" + }, + { + "directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir", + "command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_fact.cpp.o -MF src/obelisk.p/models_fact.cpp.o.d -o src/obelisk.p/models_fact.cpp.o -c ../src/models/fact.cpp", + "file": "../src/models/fact.cpp", + "output": "src/obelisk.p/models_fact.cpp.o" + }, + { + "directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir", + "command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_rule.cpp.o -MF src/obelisk.p/models_rule.cpp.o.d -o src/obelisk.p/models_rule.cpp.o -c ../src/models/rule.cpp", + "file": "../src/models/rule.cpp", + "output": "src/obelisk.p/models_rule.cpp.o" + }, + { + "directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir", + "command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_suggest_action.cpp.o -MF src/obelisk.p/models_suggest_action.cpp.o.d -o src/obelisk.p/models_suggest_action.cpp.o -c ../src/models/suggest_action.cpp", + "file": "../src/models/suggest_action.cpp", + "output": "src/obelisk.p/models_suggest_action.cpp.o" + }, + { + "directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir", + "command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_verb.cpp.o -MF src/obelisk.p/models_verb.cpp.o.d -o src/obelisk.p/models_verb.cpp.o -c ../src/models/verb.cpp", + "file": "../src/models/verb.cpp", + "output": "src/obelisk.p/models_verb.cpp.o" } ] diff --git a/src/knowledge_base.cpp b/src/knowledge_base.cpp index b70d004..ce47572 100644 --- a/src/knowledge_base.cpp +++ b/src/knowledge_base.cpp @@ -1,10 +1,14 @@ #include "knowledge_base.h" +#include "models/action.h" +#include "models/entity.h" +#include "models/fact.h" +#include "models/rule.h" +#include "models/suggest_action.h" +#include "models/verb.h" +#include #include -const std::string obelisk::Sql::create_facts_table - = "CREATE TABLE fact (id INT PRIMARY KEY NOT NULL);"; - obelisk::KnowledgeBase::KnowledgeBase(const char* filename) { KnowledgeBase(filename, DEFAULT_FLAGS); @@ -15,28 +19,51 @@ obelisk::KnowledgeBase::KnowledgeBase(const char* filename, int flags) filename_ = std::move(filename); flags_ = std::move(flags); + std::filesystem::path path {filename}; + auto dbExists = std::filesystem::exists(path); + auto result = sqlite3_open_v2(filename, &dbConnection_, flags, NULL); if (result != SQLITE_OK) { logSqliteError(result); } - char* tmp; - result = sqlite3_exec(dbConnection_, - obelisk::Sql::create_facts_table.c_str(), - NULL, - NULL, - &tmp); - if (tmp) + if (!dbExists) { - std::string errmsg(tmp); - throw obelisk::KnowledgeBaseException(errmsg); + createTable(obelisk::Action::createTable); + createTable(obelisk::Entity::createTable); + createTable(obelisk::Verb::createTable); + createTable(obelisk::Fact::createTable); + createTable(obelisk::Rule::createTable); + createTable(obelisk::SuggestAction::createTable); } } obelisk::KnowledgeBase::~KnowledgeBase() { - sqlite3_close_v2(dbConnection_); + if (dbConnection_) + { + sqlite3_close_v2(dbConnection_); + } +} + +void obelisk::KnowledgeBase::createTable(std::function function) +{ + char* tmp; + auto result = sqlite3_exec(dbConnection_, function(), NULL, NULL, &tmp); + if (result != SQLITE_OK) + { + logSqliteError(result); + if (tmp) + { + std::string errmsg(tmp); + throw obelisk::KnowledgeBaseException(errmsg); + } + else + { + throw obelisk::KnowledgeBaseException(); + } + } } // TODO: log files? @@ -45,15 +72,15 @@ void obelisk::KnowledgeBase::logSqliteError(int result) std::cout << sqlite3_errstr(result) << std::endl; } -void obelisk::KnowledgeBase::getFloat(float* result1, - float* result2, +void obelisk::KnowledgeBase::getFloat(float& result1, + float& result2, double var) { - *result1 = (float) var; - *result2 = (float) (var - (double) *result1); + result1 = (float) var; + result2 = (float) (var - (double) result1); } -void obelisk::KnowledgeBase::getDouble(double* result, float var1, float var2) +void obelisk::KnowledgeBase::getDouble(double& result, float var1, float var2) { - *result = (double) ((double) var2 + (double) var1); + result = (double) ((double) var2 + (double) var1); } diff --git a/src/knowledge_base.h b/src/knowledge_base.h index aa8f09b..52e742f 100644 --- a/src/knowledge_base.h +++ b/src/knowledge_base.h @@ -3,6 +3,7 @@ #include +#include #include #include @@ -14,10 +15,12 @@ namespace obelisk const int DEFAULT_FLAGS = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; const char* filename_; - sqlite3* dbConnection_; + sqlite3* dbConnection_ = nullptr; int flags_; void logSqliteError(int result); + void createTable(std::function function); + public: KnowledgeBase(const char* filename); KnowledgeBase(const char* filename, int flags); @@ -30,23 +33,22 @@ namespace obelisk int addRules(std::string verb, T leftEntities, U rightEntities); template int addActions(); - void getDouble(double* result, float var1, float var2); - void getFloat(float* result1, float* result2, double var); - }; - - class Sql - { - public: - static const std::string create_facts_table; + void getDouble(double& result, float var1, float var2); + void getFloat(float& result1, float& result2, double var); }; class KnowledgeBaseException : public std::exception { private: - std::string errorMessage_; + const std::string errorMessage_; public: - KnowledgeBaseException(std::string errorMessage) : + KnowledgeBaseException() : + errorMessage_("an unknown error ocurred") + { + } + + KnowledgeBaseException(const std::string& errorMessage) : errorMessage_(errorMessage) { } diff --git a/src/lexer.cpp b/src/lexer.cpp index 6955b60..cd62d75 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -8,7 +8,7 @@ int obelisk::Lexer::getToken() while (isspace(lastChar)) { - lastChar = getchar(); + lastChar = std::getc(stdin); } if (isalpha(lastChar)) @@ -20,6 +20,21 @@ int obelisk::Lexer::getToken() appendIdentifier(lastChar); } + if (getIdentifier() == "fact") + { + return Token::kTokenFact; + } + + if (getIdentifier() == "rule") + { + return Token::kTokenFact; + } + + if (getIdentifier() == "action") + { + return Token::kTokenAction; + } + if (getIdentifier() == "def") { return Token::kTokenDef; @@ -90,12 +105,12 @@ void obelisk::Lexer::commentLine(int* lastChar) while (*lastChar != EOF && *lastChar != '\n' && *lastChar != '\r'); } -std::string obelisk::Lexer::getIdentifier() +const std::string& obelisk::Lexer::getIdentifier() { return identifier_; } -void obelisk::Lexer::setIdentifier(const std::string identifier) +void obelisk::Lexer::setIdentifier(const std::string& identifier) { identifier_ = identifier; } diff --git a/src/lexer.h b/src/lexer.h index 20a0c96..c82b949 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -3,16 +3,16 @@ #include +// TODO: add error handling namespace obelisk { - class Lexer { private: std::string identifier_; double numberValue_; - void setIdentifier(const std::string identifier); + void setIdentifier(const std::string& identifier); void eraseIdentifier(); void appendIdentifier(int lastChar); void setNumberValue(double numberValue); @@ -21,12 +21,12 @@ namespace obelisk public: enum Token { - kTokenInvalid = -1, - kTokenEof = -2, + kTokenEof = -1, // commands - kTokenFact = -3, - kTokenRule = -4, + kTokenFact = -2, + kTokenRule = -3, + kTokenAction = -4, kTokenDef = -5, kTokenExtern = -6, @@ -38,7 +38,7 @@ namespace obelisk int getToken(); - std::string getIdentifier(); + const std::string& getIdentifier(); double getNumberValue(); }; } // namespace obelisk diff --git a/src/meson.build b/src/meson.build index d7c5d50..0474fe3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -10,6 +10,9 @@ sqlite3 = dependency('sqlite3') subdir('ast') obelisk_sources += obelisk_ast_sources +subdir('models') +obelisk_sources += obelisk_model_sources + executable('obelisk', obelisk_sources, dependencies : [sqlite3], diff --git a/src/models/action.cpp b/src/models/action.cpp new file mode 100644 index 0000000..620b6e6 --- /dev/null +++ b/src/models/action.cpp @@ -0,0 +1,32 @@ +#include "models/action.h" + +const char* obelisk::Action::createTable() +{ + return R"( + CREATE TABLE "action" ( + "id" INTEGER NOT NULL UNIQUE, + "name" TEXT NOT NULL CHECK(trim(name) != '') UNIQUE, + PRIMARY KEY("id" AUTOINCREMENT) + ); + )"; +} + +int obelisk::Action::getId() +{ + return id_; +} + +void obelisk::Action::setId(int id) +{ + id_ = id; +} + +std::string obelisk::Action::getName() +{ + return name_; +} + +void obelisk::Action::setName(std::string name) +{ + name_ = name; +} diff --git a/src/models/action.h b/src/models/action.h new file mode 100644 index 0000000..d24ba8c --- /dev/null +++ b/src/models/action.h @@ -0,0 +1,49 @@ +#ifndef OBELISK_MODELS_ACTION_H +#define OBELISK_MODELS_ACTION_H + +#include + +namespace obelisk +{ + class Action + { + private: + int id_; + std::string name_; + + public: + Action() : + id_(0), + name_("") + { + } + + Action(int id) : + id_(id), + name_("") + { + } + + Action(std::string name) : + id_(0), + name_(name) + { + } + + Action(int id, std::string name) : + id_(id), + name_(name) + { + } + + static const char* createTable(); + + int getId(); + void setId(int id); + + std::string getName(); + void setName(std::string name); + }; +} // namespace obelisk + +#endif diff --git a/src/models/entity.cpp b/src/models/entity.cpp index c2d29bd..3345e47 100644 --- a/src/models/entity.cpp +++ b/src/models/entity.cpp @@ -1,12 +1,14 @@ #include "models/entity.h" -obelisk::Entity::Entity() +const char* obelisk::Entity::createTable() { -} - -obelisk::Entity::Entity(std::string name) -{ - name = name; + return R"( + CREATE TABLE "entity" ( + "id" INTEGER NOT NULL UNIQUE, + "name" TEXT NOT NULL CHECK(trim(name) != '') UNIQUE, + PRIMARY KEY("id" AUTOINCREMENT) + ); + )"; } int obelisk::Entity::getId() @@ -26,5 +28,5 @@ std::string obelisk::Entity::getName() void obelisk::Entity::setName(std::string name) { - name_ = name_; + name_ = name; } diff --git a/src/models/entity.h b/src/models/entity.h index 4663fbf..b73f7c9 100644 --- a/src/models/entity.h +++ b/src/models/entity.h @@ -12,8 +12,31 @@ namespace obelisk std::string name_; public: - Entity(); - Entity(std::string name); + Entity() : + id_(0), + name_("") + { + } + + Entity(int id) : + id_(id), + name_("") + { + } + + Entity(std::string name) : + id_(0), + name_(name) + { + } + + Entity(int id, std::string name) : + id_(id), + name_(name) + { + } + + static const char* createTable(); int getId(); void setId(int id); diff --git a/src/models/fact.cpp b/src/models/fact.cpp new file mode 100644 index 0000000..132c80b --- /dev/null +++ b/src/models/fact.cpp @@ -0,0 +1,57 @@ +#include "models/fact.h" + +const char* obelisk::Fact::createTable() +{ + return R"( + CREATE TABLE "fact" ( + "id" INTEGER NOT NULL UNIQUE, + "left_entity" INTEGER NOT NULL, + "right_entity" INTEGER NOT NULL, + "verb" INTEGER NOT NULL, + PRIMARY KEY("id" AUTOINCREMENT), + FOREIGN KEY("verb") REFERENCES "verb"("id") ON DELETE RESTRICT, + FOREIGN KEY("right_entity") REFERENCES "entity"("id") ON DELETE RESTRICT, + FOREIGN KEY("left_entity") REFERENCES "entity"("id") ON DELETE RESTRICT + ); + )"; +} + +int obelisk::Fact::getId() +{ + return id_; +} + +void obelisk::Fact::setId(int id) +{ + id_ = id; +} + +obelisk::Entity obelisk::Fact::getLeftEntity() +{ + return leftEntity_; +} + +void obelisk::Fact::setLeftEntity(obelisk::Entity leftEntity) +{ + leftEntity_ = leftEntity; +} + +obelisk::Entity obelisk::Fact::getRightEntity() +{ + return rightEntity_; +} + +void obelisk::Fact::setRightEntity(obelisk::Entity rightEntity) +{ + rightEntity_ = rightEntity; +} + +obelisk::Verb obelisk::Fact::getVerb() +{ + return verb_; +} + +void obelisk::Fact::setVerb(obelisk::Verb verb) +{ + verb_ = verb; +} diff --git a/src/models/fact.h b/src/models/fact.h new file mode 100644 index 0000000..6553058 --- /dev/null +++ b/src/models/fact.h @@ -0,0 +1,73 @@ +#ifndef OBELISK_MODELS_FACT_H +#define OBELISK_MODELS_FACT_H + +#include "models/entity.h" +#include "models/verb.h" + +#include + +namespace obelisk +{ + class Fact + { + private: + int id_; + obelisk::Entity leftEntity_; + obelisk::Entity rightEntity_; + obelisk::Verb verb_; + + public: + Fact() : + id_(0), + leftEntity_(), + rightEntity_(), + verb_() + { + } + + Fact(int id) : + id_(id), + leftEntity_(), + rightEntity_(), + verb_() + { + } + + Fact(obelisk::Entity leftEntity, + obelisk::Entity rightEntity, + obelisk::Verb verb) : + id_(0), + leftEntity_(leftEntity), + rightEntity_(rightEntity), + verb_(verb) + { + } + + Fact(int id, + obelisk::Entity leftEntity, + obelisk::Entity rightEntity, + obelisk::Verb verb) : + id_(id), + leftEntity_(leftEntity), + rightEntity_(rightEntity), + verb_(verb) + { + } + + static const char* createTable(); + + int getId(); + void setId(int id); + + obelisk::Entity getLeftEntity(); + void setLeftEntity(obelisk::Entity leftEntity); + + obelisk::Entity getRightEntity(); + void setRightEntity(obelisk::Entity leftEntity); + + obelisk::Verb getVerb(); + void setVerb(obelisk::Verb verb); + }; +} // namespace obelisk + +#endif diff --git a/src/models/meson.build b/src/models/meson.build new file mode 100644 index 0000000..e49c83c --- /dev/null +++ b/src/models/meson.build @@ -0,0 +1,8 @@ +obelisk_model_sources = files( + 'action.cpp', + 'entity.cpp', + 'fact.cpp', + 'rule.cpp', + 'suggest_action.cpp', + 'verb.cpp' +) diff --git a/src/models/rule.cpp b/src/models/rule.cpp new file mode 100644 index 0000000..3282743 --- /dev/null +++ b/src/models/rule.cpp @@ -0,0 +1,45 @@ +#include "models/rule.h" + +const char* obelisk::Rule::createTable() +{ + return R"( + CREATE TABLE "rule" ( + "id" INTEGER NOT NULL UNIQUE, + "fact" INTEGER NOT NULL, + "reason" INTEGER NOT NULL CHECK("reason" != "fact"), + PRIMARY KEY("id" AUTOINCREMENT), + FOREIGN KEY("fact") REFERENCES "fact"("id") ON DELETE RESTRICT, + FOREIGN KEY("reason") REFERENCES "fact"("id") ON DELETE RESTRICT + ); + )"; +} + +int obelisk::Rule::getId() +{ + return id_; +} + +void obelisk::Rule::setId(int id) +{ + id_ = id; +} + +obelisk::Fact obelisk::Rule::getFact() +{ + return fact_; +} + +void obelisk::Rule::setFact(obelisk::Fact fact) +{ + fact_ = fact; +} + +obelisk::Fact obelisk::Rule::getReason() +{ + return reason_; +} + +void obelisk::Rule::setReason(obelisk::Fact reason) +{ + reason_ = reason; +} diff --git a/src/models/rule.h b/src/models/rule.h new file mode 100644 index 0000000..f120896 --- /dev/null +++ b/src/models/rule.h @@ -0,0 +1,59 @@ +#ifndef OBELISK_MODELS_RULE_H +#define OBELISK_MODELS_RULE_H + +#include "models/fact.h" + +#include + +namespace obelisk +{ + class Rule + { + private: + int id_; + obelisk::Fact fact_; + obelisk::Fact reason_; + + public: + Rule() : + id_(0), + fact_(), + reason_() + { + } + + Rule(int id) : + id_(id), + fact_(), + reason_() + { + } + + Rule(obelisk::Fact fact, obelisk::Fact reason) : + id_(0), + fact_(fact), + reason_(reason) + { + } + + Rule(int id, obelisk::Fact fact, obelisk::Fact reason) : + id_(id), + fact_(fact), + reason_(reason) + { + } + + static const char* createTable(); + + int getId(); + void setId(int id); + + obelisk::Fact getFact(); + void setFact(obelisk::Fact fact); + + obelisk::Fact getReason(); + void setReason(obelisk::Fact reason); + }; +} // namespace obelisk + +#endif diff --git a/src/models/suggest_action.cpp b/src/models/suggest_action.cpp new file mode 100644 index 0000000..1b6c6e6 --- /dev/null +++ b/src/models/suggest_action.cpp @@ -0,0 +1,57 @@ +#include "models/suggest_action.h" + +const char* obelisk::SuggestAction::createTable() +{ + return R"( + CREATE TABLE "suggest_action" ( + "id" INTEGER NOT NULL UNIQUE, + "fact" INTEGER NOT NULL, + "true_action" INTEGER NOT NULL, + "false_action" INTEGER NOT NULL, + PRIMARY KEY("id" AUTOINCREMENT), + FOREIGN KEY("fact") REFERENCES "fact"("id") ON DELETE RESTRICT, + FOREIGN KEY("true_action") REFERENCES "action"("id") ON DELETE RESTRICT, + FOREIGN KEY("false_action") REFERENCES "action"("id") ON DELETE RESTRICT + ); + )"; +} + +int obelisk::SuggestAction::getId() +{ + return id_; +} + +void obelisk::SuggestAction::setId(int id) +{ + id_ = id; +} + +obelisk::Fact obelisk::SuggestAction::getFact() +{ + return fact_; +} + +void obelisk::SuggestAction::setFact(obelisk::Fact fact) +{ + fact_ = fact; +} + +obelisk::Action obelisk::SuggestAction::getTrueAction() +{ + return trueAction_; +} + +void obelisk::SuggestAction::setTrueAction(obelisk::Action trueAction) +{ + trueAction_ = trueAction; +} + +obelisk::Action obelisk::SuggestAction::getFalseAction() +{ + return falseAction_; +} + +void obelisk::SuggestAction::setFalseAction(obelisk::Action falseAction) +{ + falseAction_ = falseAction; +} diff --git a/src/models/suggest_action.h b/src/models/suggest_action.h new file mode 100644 index 0000000..6b33e88 --- /dev/null +++ b/src/models/suggest_action.h @@ -0,0 +1,73 @@ +#ifndef OBELISK_MODELS_SUGGEST_ACTION_H +#define OBELISK_MODELS_SUGGEST_ACTION_H + +#include "models/action.h" +#include "models/fact.h" + +#include + +namespace obelisk +{ + class SuggestAction + { + private: + int id_; + obelisk::Fact fact_; + obelisk::Action trueAction_; + obelisk::Action falseAction_; + + public: + SuggestAction() : + id_(0), + fact_(), + trueAction_(), + falseAction_() + { + } + + SuggestAction(int id) : + id_(id), + fact_(), + trueAction_(), + falseAction_() + { + } + + SuggestAction(obelisk::Fact fact, + obelisk::Action trueAction, + obelisk::Action falseAction) : + id_(0), + fact_(fact), + trueAction_(trueAction), + falseAction_(falseAction) + { + } + + SuggestAction(int id, + obelisk::Fact fact, + obelisk::Action trueAction, + obelisk::Action falseAction) : + id_(id), + fact_(fact), + trueAction_(trueAction), + falseAction_(falseAction) + { + } + + static const char* createTable(); + + int getId(); + void setId(int id); + + obelisk::Fact getFact(); + void setFact(obelisk::Fact fact); + + obelisk::Action getTrueAction(); + void setTrueAction(obelisk::Action trueAction); + + obelisk::Action getFalseAction(); + void setFalseAction(obelisk::Action falseAction); + }; +} // namespace obelisk + +#endif diff --git a/src/models/verb.cpp b/src/models/verb.cpp index eab0251..ac9aeb9 100644 --- a/src/models/verb.cpp +++ b/src/models/verb.cpp @@ -1,18 +1,14 @@ #include "models/verb.h" -obelisk::Verb::Verb() +const char* obelisk::Verb::createTable() { -} - -obelisk::Verb::Verb(std::string verb) -{ - verb_ = verb; -} - -obelisk::Verb::Verb(int id, std::string verb) -{ - id_ = id; - verb_ = verb; + return R"( + CREATE TABLE "verb" ( + "id" INTEGER NOT NULL UNIQUE, + "name" TEXT NOT NULL CHECK(trim(name) != "") UNIQUE, + PRIMARY KEY("id" AUTOINCREMENT) + ); + )"; } int obelisk::Verb::getId() @@ -25,12 +21,12 @@ void obelisk::Verb::setId(int id) id_ = id; } -std::string obelisk::Verb::getVerb() +std::string obelisk::Verb::getName() { - return verb_; + return name_; } -void obelisk::Verb::setVerb(std::string verb) +void obelisk::Verb::setName(std::string name) { - verb_ = verb; + name_ = name; } diff --git a/src/models/verb.h b/src/models/verb.h index 1919bef..dfb3a6e 100644 --- a/src/models/verb.h +++ b/src/models/verb.h @@ -9,18 +9,40 @@ namespace obelisk { private: int id_; - std::string verb_; + std::string name_; public: - Verb(); - Verb(std::string verb); - Verb(int id, std::string verb); + Verb() : + id_(0), + name_("") + { + } + + Verb(int id) : + id_(id), + name_("") + { + } + + Verb(std::string name) : + id_(0), + name_(name) + { + } + + Verb(int id, std::string name) : + id_(id), + name_(name) + { + } + + static const char* createTable(); int getId(); void setId(int id); - std::string getVerb(); - void setVerb(std::string verb); + std::string getName(); + void setName(std::string name); }; } // namespace obelisk diff --git a/src/obelisk.cpp b/src/obelisk.cpp index 5e46be6..47c695a 100644 --- a/src/obelisk.cpp +++ b/src/obelisk.cpp @@ -6,10 +6,11 @@ #include #include #include +#include static void mainLoop() { - obelisk::Parser* parser = new obelisk::Parser(); + auto parser = std::unique_ptr {new obelisk::Parser()}; // Prime the first token. fprintf(stderr, "ready> "); @@ -22,10 +23,6 @@ static void mainLoop() { case obelisk::Lexer::kTokenEof : return; - case obelisk::Lexer::kTokenInvalid : - std::cerr << "Invalid token!\n"; - parser->getNextToken(); - return; case ';' : // ignore top-level semicolons. std::cout << "Identifier: " << parser->getLexer()->getIdentifier() << std::endl; @@ -33,6 +30,15 @@ static void mainLoop() << std::endl; parser->getNextToken(); break; + case obelisk::Lexer::kTokenFact : + // parser->handleFactFunction(); + break; + case obelisk::Lexer::kTokenRule : + // parser->handleRuleFunction(); + break; + case obelisk::Lexer::kTokenAction : + // parser->handleActionFunction(); + break; default : parser->getNextToken(); break; @@ -47,9 +53,36 @@ int main(int argc, char** argv) std::cout << argv[i] << std::endl; } + // This can be used to store a double as 2 floats in the database, then restore it back to a double. + // Inspired by Godot's double precision on the GPU to render large worlds. + /*try + { + float first; + float second; + double var = 0.123456789012345; + + obelisk::KnowledgeBase* kb = new obelisk::KnowledgeBase("cromer.kb"); + kb->getFloat(first, second, var); + std::cout << std::setprecision(std::numeric_limits::digits10) + << "Double: " << var << std::endl + << "First: " << first << std::endl + << "Second: " << second << std::endl; + var = 0.0; + kb->getDouble(var, first, second); + std::cout << std::setprecision(std::numeric_limits::digits10) + << "Double: " << var << std::endl + << "First: " << first << std::endl + << "Second: " << second << std::endl; + } + catch (obelisk::KnowledgeBaseException& exception) + { + return EXIT_FAILURE; + }*/ + try { - obelisk::KnowledgeBase* kb = new obelisk::KnowledgeBase("cromer.kb"); + auto kb = std::unique_ptr { + new obelisk::KnowledgeBase("cromer.kb")}; /*std::vector leftObjects; std::vector rightObjects; @@ -67,23 +100,6 @@ int main(int argc, char** argv) return EXIT_FAILURE; } - // This can be used to store a double as 2 floats in the database, then restore it back to a double. - // Inspired by Godot's double precision on the GPU to render large worlds. - /*float first; - float second; - double var = 0.123456789012345; - kb->getFloat(&first, &second, var); - std::cout << std::setprecision(std::numeric_limits::digits10) - << "Double: " << var << std::endl - << "First: " << first << std::endl - << "Second: " << second << std::endl; - var = 0.0; - kb->getDouble(&var, first, second); - std::cout << std::setprecision(std::numeric_limits::digits10) - << "Double: " << var << std::endl - << "First: " << first << std::endl - << "Second: " << second << std::endl;*/ - mainLoop(); return EXIT_SUCCESS; diff --git a/src/parser.cpp b/src/parser.cpp index 9c783b5..c553891 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3,29 +3,16 @@ #include "ast/variable_expression_ast.h" #include "parser.h" +#include +#include +#include + obelisk::Parser::Parser() { - lexer_ = new obelisk::Lexer(); + lexer_ = std::unique_ptr {new obelisk::Lexer()}; } -obelisk::Parser::Parser(obelisk::Lexer* lexer) -{ - if (lexer != nullptr) - { - lexer_ = lexer; - } - else - { - Parser(); - } -} - -obelisk::Parser::~Parser() -{ - delete lexer_; -} - -obelisk::Lexer* obelisk::Parser::getLexer() +std::unique_ptr& obelisk::Parser::getLexer() { return lexer_; } @@ -91,7 +78,7 @@ std::unique_ptr obelisk::Parser::parseNumberExpression() auto result = std::make_unique( getLexer()->getNumberValue()); getNextToken(); - return std::move(result); + return result; } std::unique_ptr @@ -223,3 +210,164 @@ std::unique_ptr obelisk::Parser::parseExtern() getNextToken(); return parsePrototype(); } + +std::unique_ptr obelisk::Parser::parseAction() +{ + //action(is "dangerous" then "avoid" or "ignore"); + getNextToken(); + if (getCurrentToken() != '(') + { + // TODO: throw an error + } +} + +std::unique_ptr obelisk::Parser::parseRule() +{ + //rule("player" can "die" if "enemy1" is "dangerous"); + getNextToken(); + if (getCurrentToken() != '(') + { + // TODO: throw an error + } + while (true) //left side of Rule + { + getNextToken(); + if (getCurrentToken() != '"') + { + //TODO: throw an error + } + + /*if (getCurrentToken() == ')') // TODO: break if not string and not "and" + { + // TODO: save the verb + break; + }*/ + } + while (true) //right side of Ruke + { + getNextToken(); + if (getCurrentToken() != '"') + { + //TODO: throw an error + } + + if (getCurrentToken() == ')') + { + // TODO: save the verb + break; + } + } +} + +// fact("chris cromer" and "martin" and "Isabella" can "program" and "speak english"); +// fact("" and "martin") +std::unique_ptr obelisk::Parser::parseFact() +{ + std::stack syntax; + + getNextToken(); + if (getCurrentToken() != '(') + { + // TODO: throw an error + } + + syntax.push('('); + + // (" + + bool getEntity {true}; + std::vector leftEntities; + std::vector rightEntities; + std::string entityName {""}; + std::string verb {""}; + getNextToken(); + while (true) //left side of fact + { + if (getEntity) + { + if (getCurrentToken() == '"') + { + if (syntax.top() != '"') + { + // open a double quote + syntax.push('"'); + getNextToken(); + } + else if (syntax.top() == '"') + { + // close a double quote + syntax.pop(); + if (verb == "") + { + leftEntities.push_back(entityName); + } + else + { + rightEntities.push_back(entityName); + } + entityName = ""; + getEntity = false; + getNextToken(); + continue; + } + } + + if (syntax.top() == '"') + { + if (entityName != "") + { + entityName += " "; + } + entityName += getLexer()->getIdentifier(); + } + getNextToken(); + } + else + { + if (getCurrentToken() == ')') + { + // TODO: throw an error if verb is empty + // TODO: throw an error if rightEntities has 0 elements + break; + } + + if (getCurrentToken() == '"') + { + // TODO: throw and error because there is an unexpected double quote. + break; + } + + if (getLexer()->getIdentifier() == "and") + { + getNextToken(); + getEntity = true; + continue; + } + else + { + verb = getLexer()->getIdentifier(); + getEntity = true; + continue; + } + } + } + + return nullptr; +} + +void obelisk::Parser::handleAction() +{ +} + +void obelisk::Parser::handleRule() +{ +} + +void obelisk::Parser::handleFact() +{ + parseFact(); +} + +void obelisk::Parser::insertFact() +{ +} diff --git a/src/parser.h b/src/parser.h index 2a00bbc..8738ee1 100644 --- a/src/parser.h +++ b/src/parser.h @@ -13,7 +13,7 @@ namespace obelisk class Parser { private: - obelisk::Lexer* lexer_; + std::unique_ptr lexer_; int currentToken_; void setCurrentToken(int currentToken); @@ -32,13 +32,14 @@ namespace obelisk std::unique_ptr parseDefinition(); std::unique_ptr parseTopLevelExpression(); std::unique_ptr parseExtern(); + std::unique_ptr parseAction(); + std::unique_ptr parseRule(); + std::unique_ptr parseFact(); public: Parser(); - Parser(obelisk::Lexer* lexer); - ~Parser(); - obelisk::Lexer* getLexer(); + std::unique_ptr& getLexer(); int getCurrentToken(); @@ -47,6 +48,9 @@ namespace obelisk void handleDefinition(); void handleExtern(); void handleTopLevelExpression(); + void handleAction(); + void handleRule(); + void handleFact(); }; } // namespace obelisk