feature/kb #14
@ -89,7 +89,7 @@ int obelisk::mainLoop(const std::vector<std::string>& sourceFiles, const std::st
|
|||||||
// parser->handleRule();
|
// parser->handleRule();
|
||||||
break;
|
break;
|
||||||
case obelisk::Lexer::kTokenAction :
|
case obelisk::Lexer::kTokenAction :
|
||||||
// parser->handleAction();
|
parser->handleAction(kb);
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
parser->getNextToken();
|
parser->getNextToken();
|
||||||
|
364
src/parser.cpp
364
src/parser.cpp
@ -1,9 +1,6 @@
|
|||||||
#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>
|
||||||
@ -214,11 +211,205 @@ std::unique_ptr<obelisk::PrototypeAST> obelisk::Parser::parseExtern()
|
|||||||
return parsePrototype();
|
return parsePrototype();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseAction()
|
void obelisk::Parser::parseAction(obelisk::SuggestAction& suggestAction)
|
||||||
{
|
{
|
||||||
|
std::stack<char> syntax;
|
||||||
|
|
||||||
|
getNextToken();
|
||||||
|
if (getCurrentToken() != '(')
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("expected '(' but got '" + std::to_string(getCurrentToken()) + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
syntax.push('(');
|
||||||
|
|
||||||
|
getNextToken();
|
||||||
|
if (getLexer()->getIdentifier() != "if")
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("expected 'if' but got '" + getLexer()->getIdentifier() + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getEntity {true};
|
||||||
|
std::string leftEntity {""};
|
||||||
|
std::string rightEntity {""};
|
||||||
|
std::string trueAction {""};
|
||||||
|
std::string falseAction {""};
|
||||||
|
std::string entityName {""};
|
||||||
|
std::string verb {""};
|
||||||
|
getNextToken();
|
||||||
|
|
||||||
|
// get the entity side of statement
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
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 == "")
|
||||||
|
{
|
||||||
|
leftEntity = entityName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rightEntity = entityName;
|
||||||
|
}
|
||||||
|
entityName = "";
|
||||||
|
getEntity = false;
|
||||||
|
getNextToken();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syntax.top() == '"')
|
||||||
|
{
|
||||||
|
if (entityName != "")
|
||||||
|
{
|
||||||
|
entityName += " ";
|
||||||
|
}
|
||||||
|
entityName += getLexer()->getIdentifier();
|
||||||
|
}
|
||||||
|
getNextToken();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (getCurrentToken() == ')')
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("unexpected ')'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getCurrentToken() == '"')
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("unexpected '\"'");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getLexer()->getIdentifier() == "and")
|
||||||
|
{
|
||||||
|
getNextToken();
|
||||||
|
getEntity = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (getLexer()->getIdentifier() == "then")
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
verb = getLexer()->getIdentifier();
|
||||||
|
// TODO: make sure verb is alphabetic
|
||||||
|
getEntity = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the action side of statement
|
||||||
|
bool getAction {true};
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (getAction)
|
||||||
|
{
|
||||||
|
if (getCurrentToken() == '"')
|
||||||
|
{
|
||||||
|
if (syntax.top() != '"')
|
||||||
|
{
|
||||||
|
// open a double quote
|
||||||
|
syntax.push('"');
|
||||||
|
getNextToken();
|
||||||
|
}
|
||||||
|
else if (syntax.top() == '"')
|
||||||
|
{
|
||||||
|
// close a double quote
|
||||||
|
syntax.pop();
|
||||||
|
if (trueAction == "")
|
||||||
|
{
|
||||||
|
trueAction = entityName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
falseAction = entityName;
|
||||||
|
}
|
||||||
|
entityName = "";
|
||||||
|
getAction = false;
|
||||||
|
getNextToken();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syntax.top() == '"')
|
||||||
|
{
|
||||||
|
if (entityName != "")
|
||||||
|
{
|
||||||
|
entityName += " ";
|
||||||
|
}
|
||||||
|
entityName += getLexer()->getIdentifier();
|
||||||
|
}
|
||||||
|
getNextToken();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (getCurrentToken() == ')')
|
||||||
|
{
|
||||||
|
// closing parenthesis found, make sure we have everything needed
|
||||||
|
if (syntax.top() != '(')
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("unexpected ')'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
syntax.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trueAction == "")
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("missing true action");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (falseAction == "")
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("missing false action");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getCurrentToken() == '"')
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("unexpected '\"'");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getLexer()->getIdentifier() == "or")
|
||||||
|
{
|
||||||
|
getNextToken();
|
||||||
|
getAction = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
getAction = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suggestAction.setFact(
|
||||||
|
obelisk::Fact(obelisk::Entity(leftEntity), obelisk::Entity(rightEntity), obelisk::Verb(verb)));
|
||||||
|
suggestAction.setTrueAction(obelisk::Action(trueAction));
|
||||||
|
suggestAction.setTrueAction(obelisk::Action(falseAction));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseRule()
|
void obelisk::Parser::parseRule(std::vector<obelisk::Rule>& rules)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +431,7 @@ void obelisk::Parser::parseFact(std::vector<obelisk::Fact>& facts)
|
|||||||
std::string entityName {""};
|
std::string entityName {""};
|
||||||
std::string verb {""};
|
std::string verb {""};
|
||||||
getNextToken();
|
getNextToken();
|
||||||
while (true) //left side of fact
|
while (true)
|
||||||
{
|
{
|
||||||
if (getEntity)
|
if (getEntity)
|
||||||
{
|
{
|
||||||
@ -286,6 +477,15 @@ void obelisk::Parser::parseFact(std::vector<obelisk::Fact>& facts)
|
|||||||
if (getCurrentToken() == ')')
|
if (getCurrentToken() == ')')
|
||||||
{
|
{
|
||||||
// closing parenthesis found, make sure we have everything needed
|
// closing parenthesis found, make sure we have everything needed
|
||||||
|
if (syntax.top() != '(')
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("unexpected ')'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
syntax.pop();
|
||||||
|
}
|
||||||
|
|
||||||
if (verb == "")
|
if (verb == "")
|
||||||
{
|
{
|
||||||
throw obelisk::ParserException("verb is empty");
|
throw obelisk::ParserException("verb is empty");
|
||||||
@ -300,6 +500,7 @@ void obelisk::Parser::parseFact(std::vector<obelisk::Fact>& facts)
|
|||||||
{
|
{
|
||||||
throw obelisk::ParserException("missing right side entities");
|
throw obelisk::ParserException("missing right side entities");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,6 +538,22 @@ void obelisk::Parser::parseFact(std::vector<obelisk::Fact>& facts)
|
|||||||
|
|
||||||
void obelisk::Parser::handleAction(std::unique_ptr<obelisk::KnowledgeBase>& kb)
|
void obelisk::Parser::handleAction(std::unique_ptr<obelisk::KnowledgeBase>& kb)
|
||||||
{
|
{
|
||||||
|
obelisk::SuggestAction suggestAction;
|
||||||
|
parseAction(suggestAction);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
insertEntity(kb, suggestAction.getFact().getLeftEntity());
|
||||||
|
insertEntity(kb, suggestAction.getFact().getRightEntity());
|
||||||
|
insertVerb(kb, suggestAction.getFact().getVerb());
|
||||||
|
insertFact(kb, suggestAction.getFact());
|
||||||
|
|
||||||
|
// TODO: insert the actions, then insert the suggested action
|
||||||
|
}
|
||||||
|
catch (obelisk::ParserException& exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void obelisk::Parser::handleRule(std::unique_ptr<obelisk::KnowledgeBase>& kb)
|
void obelisk::Parser::handleRule(std::unique_ptr<obelisk::KnowledgeBase>& kb)
|
||||||
@ -346,88 +563,103 @@ void obelisk::Parser::handleRule(std::unique_ptr<obelisk::KnowledgeBase>& kb)
|
|||||||
void obelisk::Parser::handleFact(std::unique_ptr<obelisk::KnowledgeBase>& kb)
|
void obelisk::Parser::handleFact(std::unique_ptr<obelisk::KnowledgeBase>& kb)
|
||||||
{
|
{
|
||||||
std::vector<obelisk::Fact> facts;
|
std::vector<obelisk::Fact> facts;
|
||||||
parseFact(facts);
|
try
|
||||||
|
{
|
||||||
|
parseFact(facts);
|
||||||
|
}
|
||||||
|
catch (obelisk::ParserException& exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
int verbId = 0;
|
int verbId = 0;
|
||||||
for (auto& fact : facts)
|
for (auto& fact : facts)
|
||||||
{
|
{
|
||||||
std::vector<obelisk::Entity> entities {fact.getLeftEntity()};
|
try
|
||||||
kb->addEntities(entities);
|
|
||||||
fact.setLeftEntity(entities.front());
|
|
||||||
|
|
||||||
// the id was not inserted, so check if it exists in the database
|
|
||||||
if (fact.getLeftEntity().getId() == 0)
|
|
||||||
{
|
{
|
||||||
obelisk::Entity entity = fact.getLeftEntity();
|
insertEntity(kb, fact.getLeftEntity());
|
||||||
kb->getEntity(entity);
|
insertEntity(kb, fact.getRightEntity());
|
||||||
if (entity.getId() == 0)
|
|
||||||
{
|
|
||||||
throw obelisk::ParserException("left entity could not be inserted into the database");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fact.setLeftEntity(entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch (obelisk::ParserException& exception)
|
||||||
entities = {fact.getRightEntity()};
|
|
||||||
kb->addEntities(entities);
|
|
||||||
fact.setRightEntity(entities.front());
|
|
||||||
|
|
||||||
if (fact.getRightEntity().getId() == 0)
|
|
||||||
{
|
{
|
||||||
obelisk::Entity entity = fact.getRightEntity();
|
throw;
|
||||||
kb->getEntity(entity);
|
|
||||||
if (entity.getId() == 0)
|
|
||||||
{
|
|
||||||
throw obelisk::ParserException("right entity could not be inserted into the database");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fact.setRightEntity(entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbId == 0)
|
if (verbId == 0)
|
||||||
{
|
{
|
||||||
std::vector<obelisk::Verb> verbs = {fact.getVerb()};
|
try
|
||||||
kb->addVerbs(verbs);
|
|
||||||
if (verbs.front().getId() != 0)
|
|
||||||
{
|
{
|
||||||
fact.setVerb(verbs.front());
|
insertVerb(kb, fact.getVerb());
|
||||||
verbId = fact.getVerb().getId();
|
|
||||||
}
|
}
|
||||||
else
|
catch (obelisk::ParserException& exception)
|
||||||
{
|
{
|
||||||
obelisk::Verb verb = fact.getVerb();
|
throw;
|
||||||
kb->getVerb(verb);
|
|
||||||
if (verb.getId() == 0)
|
|
||||||
{
|
|
||||||
throw obelisk::ParserException("verb could not be inserted into the database");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fact.setVerb(verb);
|
|
||||||
verbId = fact.getVerb().getId();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
verbId = fact.getVerb().getId();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fact.getVerb().setId(verbId);
|
fact.getVerb().setId(verbId);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<obelisk::Fact> facts {fact};
|
try
|
||||||
kb->addFacts(facts);
|
|
||||||
fact = facts.front();
|
|
||||||
|
|
||||||
if (fact.getId() == 0)
|
|
||||||
{
|
{
|
||||||
kb->getFact(fact);
|
insertFact(kb, fact);
|
||||||
if (fact.getId() == 0)
|
}
|
||||||
{
|
catch (obelisk::ParserException& exception)
|
||||||
throw obelisk::ParserException("fact could not be inserted into the database");
|
{
|
||||||
}
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void obelisk::Parser::insertEntity(std::unique_ptr<obelisk::KnowledgeBase>& kb, obelisk::Entity& entity)
|
||||||
|
{
|
||||||
|
std::vector<obelisk::Entity> entities {entity};
|
||||||
|
kb->addEntities(entities);
|
||||||
|
entity = std::move(entities.front());
|
||||||
|
|
||||||
|
// the id was not inserted, so check if it exists in the database
|
||||||
|
if (entity.getId() == 0)
|
||||||
|
{
|
||||||
|
kb->getEntity(entity);
|
||||||
|
if (entity.getId() == 0)
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("entity could not be inserted into the database");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void obelisk::Parser::insertVerb(std::unique_ptr<obelisk::KnowledgeBase>& kb, obelisk::Verb& verb)
|
||||||
|
{
|
||||||
|
std::vector<obelisk::Verb> verbs {verb};
|
||||||
|
kb->addVerbs(verbs);
|
||||||
|
verb = std::move(verbs.front());
|
||||||
|
|
||||||
|
// the id was not inserted, so check if it exists in the database
|
||||||
|
if (verb.getId() == 0)
|
||||||
|
{
|
||||||
|
kb->getVerb(verb);
|
||||||
|
if (verb.getId() == 0)
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("verb could not be inserted into the database");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void obelisk::Parser::insertFact(std::unique_ptr<obelisk::KnowledgeBase>& kb, obelisk::Fact& fact)
|
||||||
|
{
|
||||||
|
std::vector<obelisk::Fact> facts {fact};
|
||||||
|
kb->addFacts(facts);
|
||||||
|
fact = std::move(facts.front());
|
||||||
|
|
||||||
|
// the id was not inserted, so check if it exists in the database
|
||||||
|
if (fact.getId() == 0)
|
||||||
|
{
|
||||||
|
kb->getFact(fact);
|
||||||
|
if (fact.getId() == 0)
|
||||||
|
{
|
||||||
|
throw obelisk::ParserException("fact could not be inserted into the database");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
src/parser.h
13
src/parser.h
@ -6,7 +6,12 @@
|
|||||||
#include "ast/prototype_ast.h"
|
#include "ast/prototype_ast.h"
|
||||||
#include "knowledge_base.h"
|
#include "knowledge_base.h"
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
|
#include "models/action.h"
|
||||||
|
#include "models/entity.h"
|
||||||
#include "models/fact.h"
|
#include "models/fact.h"
|
||||||
|
#include "models/rule.h"
|
||||||
|
#include "models/suggest_action.h"
|
||||||
|
#include "models/verb.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -32,8 +37,8 @@ namespace obelisk
|
|||||||
std::unique_ptr<obelisk::FunctionAST> parseDefinition();
|
std::unique_ptr<obelisk::FunctionAST> parseDefinition();
|
||||||
std::unique_ptr<obelisk::FunctionAST> parseTopLevelExpression();
|
std::unique_ptr<obelisk::FunctionAST> parseTopLevelExpression();
|
||||||
std::unique_ptr<obelisk::PrototypeAST> parseExtern();
|
std::unique_ptr<obelisk::PrototypeAST> parseExtern();
|
||||||
std::unique_ptr<obelisk::ExpressionAST> parseAction();
|
void parseAction(obelisk::SuggestAction& suggestAction);
|
||||||
std::unique_ptr<obelisk::ExpressionAST> parseRule();
|
void parseRule(std::vector<obelisk::Rule>& rules);
|
||||||
void parseFact(std::vector<obelisk::Fact>& facts);
|
void parseFact(std::vector<obelisk::Fact>& facts);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -55,6 +60,10 @@ namespace obelisk
|
|||||||
void handleAction(std::unique_ptr<obelisk::KnowledgeBase>& kb);
|
void handleAction(std::unique_ptr<obelisk::KnowledgeBase>& kb);
|
||||||
void handleRule(std::unique_ptr<obelisk::KnowledgeBase>& kb);
|
void handleRule(std::unique_ptr<obelisk::KnowledgeBase>& kb);
|
||||||
void handleFact(std::unique_ptr<obelisk::KnowledgeBase>& kb);
|
void handleFact(std::unique_ptr<obelisk::KnowledgeBase>& kb);
|
||||||
|
|
||||||
|
void insertEntity(std::unique_ptr<obelisk::KnowledgeBase>& kb, obelisk::Entity& entity);
|
||||||
|
void insertVerb(std::unique_ptr<obelisk::KnowledgeBase>& kb, obelisk::Verb& verb);
|
||||||
|
void insertFact(std::unique_ptr<obelisk::KnowledgeBase>& kb, obelisk::Fact& fact);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ParserException : public std::exception
|
class ParserException : public std::exception
|
||||||
|
Loading…
Reference in New Issue
Block a user