feature/fact_knowledge_base #7
@ -9,11 +9,6 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
obelisk::KnowledgeBase::KnowledgeBase(const char* filename)
|
|
||||||
{
|
|
||||||
KnowledgeBase(filename, DEFAULT_FLAGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
obelisk::KnowledgeBase::KnowledgeBase(const char* filename, int flags)
|
obelisk::KnowledgeBase::KnowledgeBase(const char* filename, int flags)
|
||||||
{
|
{
|
||||||
filename_ = std::move(filename);
|
filename_ = std::move(filename);
|
||||||
@ -66,6 +61,33 @@ void obelisk::KnowledgeBase::createTable(std::function<const char*()> function)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int obelisk::KnowledgeBase::addEntities(std::vector<obelisk::Entity>& entities)
|
||||||
|
{
|
||||||
|
for (auto& entity : entities)
|
||||||
|
{
|
||||||
|
entity.insertEntity(dbConnection_);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int obelisk::KnowledgeBase::addVerbs(std::vector<obelisk::Verb>& verbs)
|
||||||
|
{
|
||||||
|
for (auto& verb : verbs)
|
||||||
|
{
|
||||||
|
verb.insertVerb(dbConnection_);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int obelisk::KnowledgeBase::addFacts(std::vector<obelisk::Fact>& facts)
|
||||||
|
{
|
||||||
|
for (auto& fact : facts)
|
||||||
|
{
|
||||||
|
fact.insertFact(dbConnection_);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: log files?
|
// TODO: log files?
|
||||||
void obelisk::KnowledgeBase::logSqliteError(int result)
|
void obelisk::KnowledgeBase::logSqliteError(int result)
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
#ifndef OBELISK_KNOWLEDGE_BASE_H
|
#ifndef OBELISK_KNOWLEDGE_BASE_H
|
||||||
#define OBELISK_KNOWLEDGE_BASE_H
|
#define OBELISK_KNOWLEDGE_BASE_H
|
||||||
|
|
||||||
|
#include "models/entity.h"
|
||||||
|
#include "models/fact.h"
|
||||||
|
#include "models/verb.h"
|
||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace obelisk
|
namespace obelisk
|
||||||
@ -22,16 +27,19 @@ namespace obelisk
|
|||||||
void createTable(std::function<const char*()> function);
|
void createTable(std::function<const char*()> function);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
KnowledgeBase(const char* filename);
|
|
||||||
KnowledgeBase(const char* filename, int flags);
|
KnowledgeBase(const char* filename, int flags);
|
||||||
|
|
||||||
|
KnowledgeBase(const char* filename) :
|
||||||
|
KnowledgeBase(filename,
|
||||||
|
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~KnowledgeBase();
|
~KnowledgeBase();
|
||||||
|
|
||||||
template<typename T, typename U>
|
int addEntities(std::vector<obelisk::Entity>& entities);
|
||||||
int addFacts(std::string verb, T leftEntities, U rightEntities);
|
int addVerbs(std::vector<obelisk::Verb>& verbs);
|
||||||
// TODO: add parameter for fact
|
int addFacts(std::vector<obelisk::Fact>& facts);
|
||||||
template<typename T, typename U>
|
|
||||||
int addRules(std::string verb, T leftEntities, U rightEntities);
|
|
||||||
template<typename T, typename U> int addActions();
|
|
||||||
|
|
||||||
void getDouble(double& result, float var1, float var2);
|
void getDouble(double& result, float var1, float var2);
|
||||||
void getFloat(float& result1, float& result2, double var);
|
void getFloat(float& result1, float& result2, double var);
|
||||||
|
@ -11,7 +11,7 @@ const char* obelisk::Action::createTable()
|
|||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
int obelisk::Action::getId()
|
int& obelisk::Action::getId()
|
||||||
{
|
{
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ void obelisk::Action::setId(int id)
|
|||||||
id_ = id;
|
id_ = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string obelisk::Action::getName()
|
std::string& obelisk::Action::getName()
|
||||||
{
|
{
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
@ -38,10 +38,10 @@ namespace obelisk
|
|||||||
|
|
||||||
static const char* createTable();
|
static const char* createTable();
|
||||||
|
|
||||||
int getId();
|
int& getId();
|
||||||
void setId(int id);
|
void setId(int id);
|
||||||
|
|
||||||
std::string getName();
|
std::string& getName();
|
||||||
void setName(std::string name);
|
void setName(std::string name);
|
||||||
};
|
};
|
||||||
} // namespace obelisk
|
} // namespace obelisk
|
||||||
|
@ -11,7 +11,116 @@ const char* obelisk::Entity::createTable()
|
|||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
int obelisk::Entity::getId()
|
obelisk::Entity obelisk::Entity::selectEntity(sqlite3* dbConnection,
|
||||||
|
std::string name)
|
||||||
|
{
|
||||||
|
// TODO: check if database is open
|
||||||
|
sqlite3_stmt* ppStmt = nullptr;
|
||||||
|
const char* pzTail = nullptr;
|
||||||
|
|
||||||
|
auto result = sqlite3_prepare_v2(dbConnection,
|
||||||
|
"SELECT id, name FROM entity WHERE name=?;",
|
||||||
|
-1,
|
||||||
|
&ppStmt,
|
||||||
|
&pzTail);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: something went wrong throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pzTail != nullptr)
|
||||||
|
{
|
||||||
|
// TODO: Something was not used... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_bind_text(ppStmt, 1, name.c_str(), -1, SQLITE_TRANSIENT);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_step(ppStmt);
|
||||||
|
if (result != SQLITE_DONE)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
auto id = sqlite3_column_int(ppStmt, 0);
|
||||||
|
std::string name((char*) sqlite3_column_text(ppStmt, 1));
|
||||||
|
|
||||||
|
result = sqlite3_finalize(ppStmt);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
return Entity(id, name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = sqlite3_finalize(ppStmt);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
return Entity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int obelisk::Entity::insertEntity(sqlite3* dbConnection)
|
||||||
|
{
|
||||||
|
// TODO: check if database is open
|
||||||
|
|
||||||
|
if (selectEntity(dbConnection, getName()).getId() != 0)
|
||||||
|
{
|
||||||
|
// TODO: already exists in database, throw an error? Or skip past it?
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_stmt* ppStmt = nullptr;
|
||||||
|
const char* pzTail = nullptr;
|
||||||
|
|
||||||
|
auto result = sqlite3_prepare_v2(dbConnection,
|
||||||
|
"INSERT INTO entity (name) VALUES (?);",
|
||||||
|
-1,
|
||||||
|
&ppStmt,
|
||||||
|
&pzTail);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: something went wrong throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pzTail != nullptr)
|
||||||
|
{
|
||||||
|
// TODO: Something was not used... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
= sqlite3_bind_text(ppStmt, 1, getName().c_str(), -1, SQLITE_TRANSIENT);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_step(ppStmt);
|
||||||
|
if (result != SQLITE_DONE)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
setId((int) sqlite3_last_insert_rowid(dbConnection));
|
||||||
|
|
||||||
|
result = sqlite3_finalize(ppStmt);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int& obelisk::Entity::getId()
|
||||||
{
|
{
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
@ -21,7 +130,7 @@ void obelisk::Entity::setId(int id)
|
|||||||
id_ = id;
|
id_ = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string obelisk::Entity::getName()
|
std::string& obelisk::Entity::getName()
|
||||||
{
|
{
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef OBELISK_MODELS_ENTITY_H
|
#ifndef OBELISK_MODELS_ENTITY_H
|
||||||
#define OBELISK_MODELS_ENTITY_H
|
#define OBELISK_MODELS_ENTITY_H
|
||||||
|
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace obelisk
|
namespace obelisk
|
||||||
@ -38,11 +40,14 @@ namespace obelisk
|
|||||||
|
|
||||||
static const char* createTable();
|
static const char* createTable();
|
||||||
|
|
||||||
int getId();
|
int& getId();
|
||||||
void setId(int id);
|
void setId(int id);
|
||||||
|
|
||||||
std::string getName();
|
std::string& getName();
|
||||||
void setName(std::string name);
|
void setName(std::string name);
|
||||||
|
|
||||||
|
Entity selectEntity(sqlite3* dbConnection, std::string name);
|
||||||
|
int insertEntity(sqlite3* dbConnection);
|
||||||
};
|
};
|
||||||
} // namespace obelisk
|
} // namespace obelisk
|
||||||
|
|
||||||
|
@ -16,7 +16,152 @@ const char* obelisk::Fact::createTable()
|
|||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
int obelisk::Fact::getId()
|
obelisk::Fact obelisk::Fact::selectFact(sqlite3* dbConnection,
|
||||||
|
int idLeftEntity,
|
||||||
|
int idRightEntity,
|
||||||
|
int idVerb)
|
||||||
|
{
|
||||||
|
// TODO: check if database is open
|
||||||
|
|
||||||
|
sqlite3_stmt* ppStmt = nullptr;
|
||||||
|
const char* pzTail = nullptr;
|
||||||
|
|
||||||
|
auto result = sqlite3_prepare_v2(dbConnection,
|
||||||
|
"SELECT id, left_entity, right_entity, verb FROM fact WHERE (left_entity=? AND right_entity=? AND verb=?);",
|
||||||
|
-1,
|
||||||
|
&ppStmt,
|
||||||
|
&pzTail);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: something went wrong throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pzTail != nullptr)
|
||||||
|
{
|
||||||
|
// TODO: Something was not used... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_bind_int(ppStmt, 1, getLeftEntity().getId());
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_bind_int(ppStmt, 2, getRightEntity().getId());
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_bind_int(ppStmt, 3, getVerb().getId());
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_step(ppStmt);
|
||||||
|
if (result != SQLITE_DONE)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
auto id = sqlite3_column_int(ppStmt, 0);
|
||||||
|
auto leftEntity = sqlite3_column_int(ppStmt, 1);
|
||||||
|
auto rightEntity = sqlite3_column_int(ppStmt, 2);
|
||||||
|
auto verb = sqlite3_column_int(ppStmt, 3);
|
||||||
|
|
||||||
|
result = sqlite3_finalize(ppStmt);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
return Fact(id, leftEntity, rightEntity, verb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = sqlite3_finalize(ppStmt);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
return Fact();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int obelisk::Fact::insertFact(sqlite3* dbConnection)
|
||||||
|
{
|
||||||
|
// TODO: make sure database is open
|
||||||
|
|
||||||
|
// check if the fact id exists, based on the ids of the entities and verb
|
||||||
|
if (selectFact(dbConnection,
|
||||||
|
getLeftEntity().getId(),
|
||||||
|
getRightEntity().getId(),
|
||||||
|
getVerb().getId())
|
||||||
|
.getId()
|
||||||
|
!= 0)
|
||||||
|
{
|
||||||
|
// TODO: Verb is already in database, throw an error? Or just skip it?
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: verify that verbId, leftEntityId, and rightEntityId are not 0
|
||||||
|
|
||||||
|
sqlite3_stmt* ppStmt = nullptr;
|
||||||
|
const char* pzTail = nullptr;
|
||||||
|
|
||||||
|
auto result = sqlite3_prepare_v2(dbConnection,
|
||||||
|
"INSERT INTO fact (left_entity, right_entity, verb) VALUES (?, ?, ?);",
|
||||||
|
-1,
|
||||||
|
&ppStmt,
|
||||||
|
&pzTail);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: something went wrong throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pzTail != nullptr)
|
||||||
|
{
|
||||||
|
// TODO: Something was not used... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_bind_int(ppStmt, 1, getLeftEntity().getId());
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_bind_int(ppStmt, 2, getRightEntity().getId());
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_bind_int(ppStmt, 3, getVerb().getId());
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_step(ppStmt);
|
||||||
|
if (result != SQLITE_DONE)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
setId((int) sqlite3_last_insert_rowid(dbConnection));
|
||||||
|
|
||||||
|
result = sqlite3_finalize(ppStmt);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int& obelisk::Fact::getId()
|
||||||
{
|
{
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
@ -26,7 +171,7 @@ void obelisk::Fact::setId(int id)
|
|||||||
id_ = id;
|
id_ = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
obelisk::Entity obelisk::Fact::getLeftEntity()
|
obelisk::Entity& obelisk::Fact::getLeftEntity()
|
||||||
{
|
{
|
||||||
return leftEntity_;
|
return leftEntity_;
|
||||||
}
|
}
|
||||||
@ -36,7 +181,7 @@ void obelisk::Fact::setLeftEntity(obelisk::Entity leftEntity)
|
|||||||
leftEntity_ = leftEntity;
|
leftEntity_ = leftEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
obelisk::Entity obelisk::Fact::getRightEntity()
|
obelisk::Entity& obelisk::Fact::getRightEntity()
|
||||||
{
|
{
|
||||||
return rightEntity_;
|
return rightEntity_;
|
||||||
}
|
}
|
||||||
@ -46,7 +191,7 @@ void obelisk::Fact::setRightEntity(obelisk::Entity rightEntity)
|
|||||||
rightEntity_ = rightEntity;
|
rightEntity_ = rightEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
obelisk::Verb obelisk::Fact::getVerb()
|
obelisk::Verb& obelisk::Fact::getVerb()
|
||||||
{
|
{
|
||||||
return verb_;
|
return verb_;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define OBELISK_MODELS_FACT_H
|
#define OBELISK_MODELS_FACT_H
|
||||||
|
|
||||||
#include "models/entity.h"
|
#include "models/entity.h"
|
||||||
|
#include "models/fact.h"
|
||||||
#include "models/verb.h"
|
#include "models/verb.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -56,17 +57,24 @@ namespace obelisk
|
|||||||
|
|
||||||
static const char* createTable();
|
static const char* createTable();
|
||||||
|
|
||||||
int getId();
|
int& getId();
|
||||||
void setId(int id);
|
void setId(int id);
|
||||||
|
|
||||||
obelisk::Entity getLeftEntity();
|
Entity& getLeftEntity();
|
||||||
void setLeftEntity(obelisk::Entity leftEntity);
|
void setLeftEntity(obelisk::Entity leftEntity);
|
||||||
|
|
||||||
obelisk::Entity getRightEntity();
|
Entity& getRightEntity();
|
||||||
void setRightEntity(obelisk::Entity leftEntity);
|
void setRightEntity(obelisk::Entity leftEntity);
|
||||||
|
|
||||||
obelisk::Verb getVerb();
|
Verb& getVerb();
|
||||||
void setVerb(obelisk::Verb verb);
|
void setVerb(obelisk::Verb verb);
|
||||||
|
|
||||||
|
Fact selectFact(sqlite3* dbConnection,
|
||||||
|
int idLeftEntity,
|
||||||
|
int idRightEntity,
|
||||||
|
int idVerb);
|
||||||
|
|
||||||
|
int insertFact(sqlite3* dbConnection);
|
||||||
};
|
};
|
||||||
} // namespace obelisk
|
} // namespace obelisk
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ const char* obelisk::Rule::createTable()
|
|||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
int obelisk::Rule::getId()
|
int& obelisk::Rule::getId()
|
||||||
{
|
{
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ void obelisk::Rule::setId(int id)
|
|||||||
id_ = id;
|
id_ = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
obelisk::Fact obelisk::Rule::getFact()
|
obelisk::Fact& obelisk::Rule::getFact()
|
||||||
{
|
{
|
||||||
return fact_;
|
return fact_;
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ void obelisk::Rule::setFact(obelisk::Fact fact)
|
|||||||
fact_ = fact;
|
fact_ = fact;
|
||||||
}
|
}
|
||||||
|
|
||||||
obelisk::Fact obelisk::Rule::getReason()
|
obelisk::Fact& obelisk::Rule::getReason()
|
||||||
{
|
{
|
||||||
return reason_;
|
return reason_;
|
||||||
}
|
}
|
||||||
|
@ -45,13 +45,13 @@ namespace obelisk
|
|||||||
|
|
||||||
static const char* createTable();
|
static const char* createTable();
|
||||||
|
|
||||||
int getId();
|
int& getId();
|
||||||
void setId(int id);
|
void setId(int id);
|
||||||
|
|
||||||
obelisk::Fact getFact();
|
obelisk::Fact& getFact();
|
||||||
void setFact(obelisk::Fact fact);
|
void setFact(obelisk::Fact fact);
|
||||||
|
|
||||||
obelisk::Fact getReason();
|
obelisk::Fact& getReason();
|
||||||
void setReason(obelisk::Fact reason);
|
void setReason(obelisk::Fact reason);
|
||||||
};
|
};
|
||||||
} // namespace obelisk
|
} // namespace obelisk
|
||||||
|
@ -16,7 +16,7 @@ const char* obelisk::SuggestAction::createTable()
|
|||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
int obelisk::SuggestAction::getId()
|
int& obelisk::SuggestAction::getId()
|
||||||
{
|
{
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
@ -26,7 +26,7 @@ void obelisk::SuggestAction::setId(int id)
|
|||||||
id_ = id;
|
id_ = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
obelisk::Fact obelisk::SuggestAction::getFact()
|
obelisk::Fact& obelisk::SuggestAction::getFact()
|
||||||
{
|
{
|
||||||
return fact_;
|
return fact_;
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ void obelisk::SuggestAction::setFact(obelisk::Fact fact)
|
|||||||
fact_ = fact;
|
fact_ = fact;
|
||||||
}
|
}
|
||||||
|
|
||||||
obelisk::Action obelisk::SuggestAction::getTrueAction()
|
obelisk::Action& obelisk::SuggestAction::getTrueAction()
|
||||||
{
|
{
|
||||||
return trueAction_;
|
return trueAction_;
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ void obelisk::SuggestAction::setTrueAction(obelisk::Action trueAction)
|
|||||||
trueAction_ = trueAction;
|
trueAction_ = trueAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
obelisk::Action obelisk::SuggestAction::getFalseAction()
|
obelisk::Action& obelisk::SuggestAction::getFalseAction()
|
||||||
{
|
{
|
||||||
return falseAction_;
|
return falseAction_;
|
||||||
}
|
}
|
||||||
|
@ -56,16 +56,16 @@ namespace obelisk
|
|||||||
|
|
||||||
static const char* createTable();
|
static const char* createTable();
|
||||||
|
|
||||||
int getId();
|
int& getId();
|
||||||
void setId(int id);
|
void setId(int id);
|
||||||
|
|
||||||
obelisk::Fact getFact();
|
obelisk::Fact& getFact();
|
||||||
void setFact(obelisk::Fact fact);
|
void setFact(obelisk::Fact fact);
|
||||||
|
|
||||||
obelisk::Action getTrueAction();
|
obelisk::Action& getTrueAction();
|
||||||
void setTrueAction(obelisk::Action trueAction);
|
void setTrueAction(obelisk::Action trueAction);
|
||||||
|
|
||||||
obelisk::Action getFalseAction();
|
obelisk::Action& getFalseAction();
|
||||||
void setFalseAction(obelisk::Action falseAction);
|
void setFalseAction(obelisk::Action falseAction);
|
||||||
};
|
};
|
||||||
} // namespace obelisk
|
} // namespace obelisk
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "models/verb.h"
|
#include "models/verb.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
const char* obelisk::Verb::createTable()
|
const char* obelisk::Verb::createTable()
|
||||||
{
|
{
|
||||||
return R"(
|
return R"(
|
||||||
@ -11,7 +13,116 @@ const char* obelisk::Verb::createTable()
|
|||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
int obelisk::Verb::getId()
|
obelisk::Verb obelisk::Verb::selectVerb(sqlite3* dbConnection, std::string name)
|
||||||
|
{
|
||||||
|
// TODO: check if database is open
|
||||||
|
|
||||||
|
sqlite3_stmt* ppStmt = nullptr;
|
||||||
|
const char* pzTail = nullptr;
|
||||||
|
|
||||||
|
auto result = sqlite3_prepare_v2(dbConnection,
|
||||||
|
"SELECT id, name FROM verb WHERE name=?;",
|
||||||
|
-1,
|
||||||
|
&ppStmt,
|
||||||
|
&pzTail);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: something went wrong throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pzTail != nullptr)
|
||||||
|
{
|
||||||
|
// TODO: Something was not used... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_bind_text(ppStmt, 1, name.c_str(), -1, SQLITE_TRANSIENT);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_step(ppStmt);
|
||||||
|
if (result != SQLITE_DONE)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
auto id = sqlite3_column_int(ppStmt, 0);
|
||||||
|
std::string name((char*) sqlite3_column_text(ppStmt, 1));
|
||||||
|
|
||||||
|
result = sqlite3_finalize(ppStmt);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
return Verb(id, name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = sqlite3_finalize(ppStmt);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
return Verb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int obelisk::Verb::insertVerb(sqlite3* dbConnection)
|
||||||
|
{
|
||||||
|
// TODO: make sure database is open
|
||||||
|
|
||||||
|
if (selectVerb(dbConnection, getName()).getId() != 0)
|
||||||
|
{
|
||||||
|
// TODO: Verb is already in database, throw an error? Or just skip it?
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_stmt* ppStmt = nullptr;
|
||||||
|
const char* pzTail = nullptr;
|
||||||
|
|
||||||
|
auto result = sqlite3_prepare_v2(dbConnection,
|
||||||
|
"INSERT INTO verb (name) VALUES (?);",
|
||||||
|
-1,
|
||||||
|
&ppStmt,
|
||||||
|
&pzTail);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: something went wrong throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pzTail != nullptr)
|
||||||
|
{
|
||||||
|
// TODO: Something was not used... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
= sqlite3_bind_text(ppStmt, 1, getName().c_str(), -1, SQLITE_TRANSIENT);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_step(ppStmt);
|
||||||
|
if (result != SQLITE_DONE)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
setId((int) sqlite3_last_insert_rowid(dbConnection));
|
||||||
|
|
||||||
|
result = sqlite3_finalize(ppStmt);
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
// TODO: Something is wrong... throw an error
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int& obelisk::Verb::getId()
|
||||||
{
|
{
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
@ -21,7 +132,7 @@ void obelisk::Verb::setId(int id)
|
|||||||
id_ = id;
|
id_ = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string obelisk::Verb::getName()
|
std::string& obelisk::Verb::getName()
|
||||||
{
|
{
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef OBELISK_MODELS_VERB_H
|
#ifndef OBELISK_MODELS_VERB_H
|
||||||
#define OBELISK_MODELS_VERB_H
|
#define OBELISK_MODELS_VERB_H
|
||||||
|
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace obelisk
|
namespace obelisk
|
||||||
@ -38,11 +40,14 @@ namespace obelisk
|
|||||||
|
|
||||||
static const char* createTable();
|
static const char* createTable();
|
||||||
|
|
||||||
int getId();
|
int& getId();
|
||||||
void setId(int id);
|
void setId(int id);
|
||||||
|
|
||||||
std::string getName();
|
std::string& getName();
|
||||||
void setName(std::string name);
|
void setName(std::string name);
|
||||||
|
|
||||||
|
Verb selectVerb(sqlite3* dbConnection, std::string name);
|
||||||
|
int insertVerb(sqlite3* dbConnection);
|
||||||
};
|
};
|
||||||
} // namespace obelisk
|
} // namespace obelisk
|
||||||
|
|
||||||
|
@ -8,9 +8,21 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
static void mainLoop()
|
static int mainLoop()
|
||||||
{
|
{
|
||||||
auto parser = std::unique_ptr<obelisk::Parser> {new obelisk::Parser()};
|
auto parser = std::unique_ptr<obelisk::Parser> {new obelisk::Parser()};
|
||||||
|
std::unique_ptr<obelisk::KnowledgeBase> kb;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
kb = std::unique_ptr<obelisk::KnowledgeBase> {
|
||||||
|
new obelisk::KnowledgeBase("cromer.kb")};
|
||||||
|
}
|
||||||
|
catch (obelisk::KnowledgeBaseException& exception)
|
||||||
|
{
|
||||||
|
std::cout << exception.what() << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
// Prime the first token.
|
// Prime the first token.
|
||||||
fprintf(stderr, "ready> ");
|
fprintf(stderr, "ready> ");
|
||||||
@ -22,7 +34,7 @@ static void mainLoop()
|
|||||||
switch (parser->getCurrentToken())
|
switch (parser->getCurrentToken())
|
||||||
{
|
{
|
||||||
case obelisk::Lexer::kTokenEof :
|
case obelisk::Lexer::kTokenEof :
|
||||||
return;
|
return EXIT_SUCCESS;
|
||||||
case ';' : // ignore top-level semicolons.
|
case ';' : // ignore top-level semicolons.
|
||||||
std::cout << "Identifier: "
|
std::cout << "Identifier: "
|
||||||
<< parser->getLexer()->getIdentifier() << std::endl;
|
<< parser->getLexer()->getIdentifier() << std::endl;
|
||||||
@ -31,19 +43,21 @@ static void mainLoop()
|
|||||||
parser->getNextToken();
|
parser->getNextToken();
|
||||||
break;
|
break;
|
||||||
case obelisk::Lexer::kTokenFact :
|
case obelisk::Lexer::kTokenFact :
|
||||||
// parser->handleFactFunction();
|
parser->handleFact(kb);
|
||||||
break;
|
break;
|
||||||
case obelisk::Lexer::kTokenRule :
|
case obelisk::Lexer::kTokenRule :
|
||||||
// parser->handleRuleFunction();
|
// parser->handleRule();
|
||||||
break;
|
break;
|
||||||
case obelisk::Lexer::kTokenAction :
|
case obelisk::Lexer::kTokenAction :
|
||||||
// parser->handleActionFunction();
|
// parser->handleAction();
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
parser->getNextToken();
|
parser->getNextToken();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
@ -79,28 +93,5 @@ int main(int argc, char** argv)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
try
|
return mainLoop();
|
||||||
{
|
|
||||||
auto kb = std::unique_ptr<obelisk::KnowledgeBase> {
|
|
||||||
new obelisk::KnowledgeBase("cromer.kb")};
|
|
||||||
|
|
||||||
/*std::vector<std::string> leftObjects;
|
|
||||||
std::vector<std::string> rightObjects;
|
|
||||||
leftObjects.push_back("chris");
|
|
||||||
leftObjects.push_back("martin");
|
|
||||||
|
|
||||||
rightObjects.push_back("happy");
|
|
||||||
rightObjects.push_back("smart");
|
|
||||||
|
|
||||||
kb->addFacts("is", leftObjects, rightObjects);*/
|
|
||||||
}
|
|
||||||
catch (obelisk::KnowledgeBaseException& exception)
|
|
||||||
{
|
|
||||||
std::cout << exception.what() << std::endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
mainLoop();
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
static void mainLoop();
|
static int mainLoop();
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#include "ast/call_expression_ast.h"
|
#include "ast/call_expression_ast.h"
|
||||||
#include "ast/number_expression_ast.h"
|
#include "ast/number_expression_ast.h"
|
||||||
#include "ast/variable_expression_ast.h"
|
#include "ast/variable_expression_ast.h"
|
||||||
|
#include "models/entity.h"
|
||||||
|
#include "models/fact.h"
|
||||||
|
#include "models/verb.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -212,17 +215,19 @@ std::unique_ptr<obelisk::PrototypeAST> obelisk::Parser::parseExtern()
|
|||||||
return parsePrototype();
|
return parsePrototype();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//action("martin" is "dangerous" then "avoid" or "ignore");
|
||||||
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseAction()
|
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseAction()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//rule("chris" and "martin" is "happy" if "chris" plays "playstation");
|
||||||
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseRule()
|
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseRule()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// fact("chris cromer" and "martin" and "Isabella" can "program" and "speak english");
|
// fact("chris cromer" and "martin" and "Isabella" can "program" and "speak english");
|
||||||
// fact("" and "martin")
|
// fact("" and "martin")
|
||||||
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseFact()
|
void obelisk::Parser::parseFact(std::vector<obelisk::Fact>& facts)
|
||||||
{
|
{
|
||||||
std::stack<char> syntax;
|
std::stack<char> syntax;
|
||||||
|
|
||||||
@ -329,18 +334,68 @@ std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseFact()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
for (auto& leftEntity : leftEntities)
|
||||||
|
{
|
||||||
|
for (auto& rightEntity : rightEntities)
|
||||||
|
{
|
||||||
|
facts.push_back(obelisk::Fact(obelisk::Entity(leftEntity),
|
||||||
|
obelisk::Entity(rightEntity),
|
||||||
|
obelisk::Verb(verb)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obelisk::Parser::handleAction()
|
void obelisk::Parser::handleAction(std::unique_ptr<obelisk::KnowledgeBase>& kb)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void obelisk::Parser::handleRule()
|
void obelisk::Parser::handleRule(std::unique_ptr<obelisk::KnowledgeBase>& kb)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void obelisk::Parser::handleFact()
|
void obelisk::Parser::handleFact(std::unique_ptr<obelisk::KnowledgeBase>& kb)
|
||||||
{
|
{
|
||||||
parseFact();
|
std::vector<obelisk::Fact> facts;
|
||||||
|
parseFact(facts);
|
||||||
|
|
||||||
|
int verbId = 0;
|
||||||
|
for (auto& fact : facts)
|
||||||
|
{
|
||||||
|
// TODO: doesn't work after first insert
|
||||||
|
std::vector<obelisk::Entity> entities {fact.getLeftEntity()};
|
||||||
|
kb->addEntities(entities);
|
||||||
|
fact.setLeftEntity(entities.front());
|
||||||
|
|
||||||
|
entities = {fact.getRightEntity()};
|
||||||
|
kb->addEntities(entities);
|
||||||
|
fact.setRightEntity(entities.front());
|
||||||
|
|
||||||
|
if (verbId == 0)
|
||||||
|
{
|
||||||
|
std::vector<obelisk::Verb> verbs = {fact.getVerb()};
|
||||||
|
kb->addVerbs(verbs);
|
||||||
|
if (verbs.front().getId() != 0)
|
||||||
|
{
|
||||||
|
// The verb was inserted
|
||||||
|
fact.setVerb(verbs.front());
|
||||||
|
verbId = fact.getVerb().getId();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The verb is already already in the knowledge base
|
||||||
|
// TODO: SELECT the verb and save it into verbId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fact.getVerb().setId(verbId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// INSERT INTO fact
|
||||||
|
std::vector<obelisk::Fact> facts {fact};
|
||||||
|
kb->addFacts(facts);
|
||||||
|
fact = facts.front();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fact("chris cromer" and "martin" and "Isabella" can "program" and "speak english");
|
||||||
|
10
src/parser.h
10
src/parser.h
@ -4,7 +4,9 @@
|
|||||||
#include "ast/expression_ast.h"
|
#include "ast/expression_ast.h"
|
||||||
#include "ast/function_ast.h"
|
#include "ast/function_ast.h"
|
||||||
#include "ast/prototype_ast.h"
|
#include "ast/prototype_ast.h"
|
||||||
|
#include "knowledge_base.h"
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
|
#include "models/fact.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -34,7 +36,7 @@ namespace obelisk
|
|||||||
std::unique_ptr<obelisk::PrototypeAST> parseExtern();
|
std::unique_ptr<obelisk::PrototypeAST> parseExtern();
|
||||||
std::unique_ptr<obelisk::ExpressionAST> parseAction();
|
std::unique_ptr<obelisk::ExpressionAST> parseAction();
|
||||||
std::unique_ptr<obelisk::ExpressionAST> parseRule();
|
std::unique_ptr<obelisk::ExpressionAST> parseRule();
|
||||||
std::unique_ptr<obelisk::ExpressionAST> parseFact();
|
void parseFact(std::vector<obelisk::Fact>& facts);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Parser();
|
Parser();
|
||||||
@ -48,9 +50,9 @@ namespace obelisk
|
|||||||
void handleDefinition();
|
void handleDefinition();
|
||||||
void handleExtern();
|
void handleExtern();
|
||||||
void handleTopLevelExpression();
|
void handleTopLevelExpression();
|
||||||
void handleAction();
|
void handleAction(std::unique_ptr<obelisk::KnowledgeBase>& kb);
|
||||||
void handleRule();
|
void handleRule(std::unique_ptr<obelisk::KnowledgeBase>& kb);
|
||||||
void handleFact();
|
void handleFact(std::unique_ptr<obelisk::KnowledgeBase>& kb);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ParserException : public std::exception
|
class ParserException : public std::exception
|
||||||
|
Loading…
Reference in New Issue
Block a user