#ifndef KB_PARSER_H_
#define KB_PARSER_H_
#include "rdf_rule_core.h"
#include "rdf_date_time.h"
#include "rdf_graph.h"
#include "rule_internal.h"
#include "knowledge_base.h"
#include <istream>
#include <sstream>
#include <fstream>
#include <utility>
#include <cstdlib>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/predicate.hpp>
namespace parser {
// used in load_knowledge_base argument for test cases.
typedef std::vector<rdf::index_triple> triple_array_type;
typedef std::vector<std::string> string_vector_t;
typedef std::map<std::string, string_vector_t> test_data_map_type;
/////////////////////////////////////////////////////////////////////////////////////////
// class kb_builder
//
/////////////////////////////////////////////////////////////////////////////////////////
class kb_builder
{
typedef std::map<std::string, rdf::index_type> name_index_map_t;
public:
kb_builder(
rule::knowledge_base_ptr_type const& knowledge_base_p,
bool verbose):
m_kbase_p(knowledge_base_p),
m_meta_graph_p(m_kbase_p->get_meta_graph()),
m_name_index_map(),
m_expected_triples_p(NULL),
m_failure_triples_p(NULL),
m_test_data_map_p(NULL),
m_parsed_meta_graph(false),
m_asserted_graph_p(),
m_verbose(verbose)
{};
kb_builder(
rule::knowledge_base_ptr_type const& knowledge_base_p,
triple_array_type * expected_triples_p,
triple_array_type * failure_triples_p,
bool verbose):
m_kbase_p(knowledge_base_p),
m_meta_graph_p(m_kbase_p->get_meta_graph()),
m_name_index_map(),
m_expected_triples_p(expected_triples_p),
m_failure_triples_p(failure_triples_p),
m_test_data_map_p(NULL),
m_parsed_meta_graph(false),
m_asserted_graph_p(),
m_verbose(verbose)
{};
kb_builder(
rule::knowledge_base_ptr_type const& knowledge_base_p,
test_data_map_type * test_data_map_type_p,
bool verbose):
m_kbase_p(knowledge_base_p),
m_meta_graph_p(m_kbase_p->get_meta_graph()),
m_name_index_map(),
m_expected_triples_p(NULL),
m_failure_triples_p(NULL),
m_test_data_map_p(test_data_map_type_p),
m_parsed_meta_graph(false),
m_asserted_graph_p(),
m_verbose(verbose)
{};
kb_builder(
rule::knowledge_base_ptr_type const& knowledge_base_p,
rdf::rdf_graph_ptr_type asserted_graph_p,
bool verbose):
m_kbase_p(knowledge_base_p),
m_meta_graph_p(m_kbase_p->get_meta_graph()),
m_name_index_map(),
m_expected_triples_p(NULL),
m_failure_triples_p(NULL),
m_test_data_map_p(NULL),
m_parsed_meta_graph(false),
m_asserted_graph_p(asserted_graph_p),
m_verbose(verbose)
{};
~kb_builder(){};
inline bool
has_asserted_graph()const
{
if(m_asserted_graph_p) return true;
return false;
};
inline bool
is_verbose()const
{
return m_verbose;
};
rule::knowledge_base_ptr_type
get_knowledge_base_ptr()const
{
return m_kbase_p;
};
void
process_schema_statement(std::string const& line);
void
process_assert_triple(std::string const& line);
void
process_import_owl(std::string const& line);
void
process_psearch_session(std::string const& line);
void
process_psearch_db(std::string const& line);
void
process_meta_graph(std::string const& line);
void
process_asserted_graph(std::string const& line);
void
process_knowledge_base_section(std::string const& line);
void
process_knowledge_rule_section_begin()
{};
void
process_knowledge_rule(std::string const& line);
void
process_knowledge_rule_section_end()
{};
void process_for_query (rule::knowledge_rule_ptr_type & rule_p, std::string line);
void process_for_forward (rule::knowledge_rule_ptr_type & rule_p, std::string const& line);
void process_for_backward(rule::knowledge_rule_ptr_type & rule_p, std::string const& line);
void process_body_terms (rule::knowledge_rule_ptr_type & rule_p, std::string const& line);
void process_consequent_terms(rule::knowledge_rule_ptr_type & rule_p, std::string const& line);
/////////////////////////////////////////////////////////////////////////////////////////
// process_term
/////////////////////////////////////////////////////////////////////////////////////////
template<class Functor>
rule::kterm_ptr_type
process_term(rule::knowledge_rule_ptr_type & rule_p, std::string line, Functor const& f);
/////////////////////////////////////////////////////////////////////////////////////////
// process_filter
/////////////////////////////////////////////////////////////////////////////////////////
rule::knowledge_rule::xprsn_ptr_t
process_filter(rule::knowledge_rule_ptr_type & rule_p, std::string line)
{
// remove the first and last square brackets
unsigned int sz = line.size();
if(sz==0 or line[0]!='[' or line[sz-1]!=']')
throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P20, invalid rule syntax - filter term must start with '[' and end with ']'");
line[sz-1] = ')';
line = line.substr(1, sz-1);
return create_expression(rule_p, line);
};
template<class F>
rule::knowledge_rule::xprsn_ptr_t
create_binary_expression_helper(rule::knowledge_rule_ptr_type & rule_p, F const& first, std::string & str);
rule::knowledge_rule::xprsn_ptr_t
create_expression(rule::knowledge_rule_ptr_type & rule_p, std::string & str);
rdf::index_type
create_literal_as_index(std::string l, std::string & rest);
//// create_resource //////////////////////////////////////////////////////////////////////
rdf::index_type
create_resource(std::string const& key, std::string const& name)
{
name_index_map_t::iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) {
rdf::index_type index = m_meta_graph_p->create_resource_as_index(name);
m_name_index_map.insert(name_index_map_t::value_type(key, index));
return index;
}
return itor->second;
};
//// create_text //////////////////////////////////////////////////////////////////////
rdf::index_type
create_text(std::string const& key, std::string const& name)
{
name_index_map_t::iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) {
rdf::index_type index;
if(key.find("bnode:") == 0) {
index = m_meta_graph_p->create_string_literal_as_index(name);
} else {
index = m_meta_graph_p->create_literal_as_index(key, name);
}
m_name_index_map.insert(name_index_map_t::value_type(key, index));
return index;
}
return itor->second;
};
//// create_unset //////////////////////////////////////////////////////////////////////
rdf::index_type
create_unset(std::string const& key)
{
name_index_map_t::iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) {
rdf::index_type index = m_meta_graph_p->create_literal_as_index(key, rdf::internal::no_value());
m_name_index_map.insert(name_index_map_t::value_type(key, index));
return index;
}
return itor->second;
};
//// create_bool //////////////////////////////////////////////////////////////////////
rdf::index_type
create_bool(std::string const& key, std::string const& name)
{
name_index_map_t::iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) {
rdf::index_type index;
if(name == "true" or name == "t" or name == "1") {
index = m_meta_graph_p->create_literal_as_index(name, int(1));
} else {
index = m_meta_graph_p->create_literal_as_index(name, int(0));
}
m_name_index_map.insert(name_index_map_t::value_type(key, index));
return index;
}
return itor->second;
};
//// create_int //////////////////////////////////////////////////////////////////////
rdf::index_type
create_int(std::string const& key, std::string const& name)
{
name_index_map_t::iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) {
rdf::index_type index = m_meta_graph_p->create_literal_as_index(name, boost::lexical_cast<rdf::int_type>(name));
m_name_index_map.insert(name_index_map_t::value_type(key, index));
return index;
}
return itor->second;
};
//// create_uint //////////////////////////////////////////////////////////////////////
rdf::index_type
create_uint(std::string const& key, std::string const& name)
{
name_index_map_t::iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) {
rdf::index_type index = m_meta_graph_p->create_literal_as_index(name+"u", boost::lexical_cast<rdf::u_int_type>(name));
m_name_index_map.insert(name_index_map_t::value_type(key, index));
return index;
}
return itor->second;
};
//// create_real //////////////////////////////////////////////////////////////////////
rdf::index_type
create_real(std::string const& key, std::string const& name)
{
name_index_map_t::iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) {
rdf::index_type index = m_meta_graph_p->create_literal_as_index(name, boost::lexical_cast<rdf::real_type>(name));
m_name_index_map.insert(name_index_map_t::value_type(key, index));
return index;
}
return itor->second;
};
//// create_duration //////////////////////////////////////////////////////////////////////
rdf::index_type
create_duration(std::string const& key, std::string const& name)
{
name_index_map_t::iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) {
rdf::index_type index = m_meta_graph_p->create_literal_as_index(name, rdf::duration_type_from_string(name));
m_name_index_map.insert(name_index_map_t::value_type(key, index));
return index;
}
return itor->second;
};
//// create_time //////////////////////////////////////////////////////////////////////
rdf::index_type
create_time(std::string const& key, std::string const& name)
{
name_index_map_t::iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) {
rdf::index_type index = m_meta_graph_p->create_literal_as_index(name, rdf::time_type_from_string(name));
m_name_index_map.insert(name_index_map_t::value_type(key, index));
return index;
}
return itor->second;
};
//// create_date //////////////////////////////////////////////////////////////////////
rdf::index_type
create_date(std::string const& key, std::string const& name)
{
name_index_map_t::iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) {
rdf::index_type index = m_meta_graph_p->create_literal_as_index(name, rdf::date_type_from_string(name));
m_name_index_map.insert(name_index_map_t::value_type(key, index));
return index;
}
return itor->second;
};
rdf::index_type
get_index(std::string const& key)const
{
name_index_map_t::const_iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) {
// check if this exist in the meta graph
if(m_meta_graph_p->is_resource(key)) return m_meta_graph_p->get_resource(key).get_index();
// else, must be defined in schema section. . .
std::string msg("ERROR-P14, resource '"+key+"' not found - must be defined in schema section before using in rule section");
std::cout << msg << std::endl;
throw rdf::rdf_exception(rdf::parsing_error, msg);
}
return itor->second;
};
bool
is_resource(std::string const& key)const
{
name_index_map_t::const_iterator itor = m_name_index_map.find(key);
if(itor == m_name_index_map.end()) return false;
return true;
};
void
add_expected_triple(rdf::index_triple const& triple)
{
if(m_expected_triples_p) m_expected_triples_p->push_back(triple);
};
void
add_failure_triple(rdf::index_triple const& triple)
{
if(m_failure_triples_p) m_failure_triples_p->push_back(triple);
};
rdf::index_type
get_bnode(std::string const& name)
{
name_index_map_t::iterator itor = m_name_index_map.find(name);
if(itor == m_name_index_map.end()) {
rdf::index_type index = m_meta_graph_p->create_bnode_as_index();
m_name_index_map.insert(name_index_map_t::value_type(name, index));
return index;
}
return itor->second;
};
inline void
set_parsed_meta_graph(bool b)
{
m_parsed_meta_graph = b;
};
inline bool
get_parsed_meta_graph()const
{
return m_parsed_meta_graph;
};
private:
void
process_graph_internal(rdf::rdf_graph_ptr_type & graph_p, std::string const& line);
rule::knowledge_base_ptr_type m_kbase_p;
rdf::rdf_graph_ptr_type m_meta_graph_p;
name_index_map_t m_name_index_map;
triple_array_type * m_expected_triples_p;
triple_array_type * m_failure_triples_p;
test_data_map_type * m_test_data_map_p;
bool m_parsed_meta_graph;
rdf::rdf_graph_ptr_type m_asserted_graph_p;
bool m_verbose;
};
/////////////////////////////////////////////////////////////////////////////////////////
// rule_priority_queue_type
//
// priority queue for printing the rules
/////////////////////////////////////////////////////////////////////////////////////////
struct less_rs
{
inline bool operator()(rule::knowledge_rule_ptr_type const& lhs, rule::knowledge_rule_ptr_type const& rhs)const
{
if(!lhs or !rhs) return false;
if(lhs->get_rule_salience() == rhs->get_rule_salience()) return rhs->get_rule_name() < lhs->get_rule_name();
return lhs->get_rule_salience() < rhs->get_rule_salience();
};
};
typedef std::priority_queue<rule::knowledge_rule_ptr_type, std::vector<rule::knowledge_rule_ptr_type>, less_rs> rule_priority_queue_type;
/////////////////////////////////////////////////////////////////////////////////////////
// load_knowledge_base_internal
//
// main function to load knowledge base
/////////////////////////////////////////////////////////////////////////////////////////
void
load_knowledge_base_internal(std::string const& fname, kb_builder & builder, bool verbose=true);
/////////////////////////////////////////////////////////////////////////////////////////
// load_knowledge_base_from_buffer_internal
//
// main function to load knowledge base
/////////////////////////////////////////////////////////////////////////////////////////
void
load_knowledge_base_from_buffer_internal(std::string const& mem_buffer, kb_builder & builder, bool verbose=true);
/////////////////////////////////////////////////////////////////////////////////////////
// post_load_knowledge_base_internal
//
// main function to load knowledge base
/////////////////////////////////////////////////////////////////////////////////////////
void
post_load_knowledge_base_internal(std::string const& fname, kb_builder & builder, bool verbose=true);
//---------------------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////////////////
// load_knowledge_base
//
// main function to load knowledge base
/////////////////////////////////////////////////////////////////////////////////////////
rule::knowledge_base_ptr_type
load_knowledge_base(std::string const& fname, bool verbose=false);
/////////////////////////////////////////////////////////////////////////////////////////
// load_knowledge_base
//
// main function to load knowledge base
// Use meta_graph_p as the meta data graph of the knowledge base
/////////////////////////////////////////////////////////////////////////////////////////
rule::knowledge_base_ptr_type
load_knowledge_base(std::string const& fname, rdf::rdf_graph_ptr_type & meta_graph_p, bool verbose=false);
/////////////////////////////////////////////////////////////////////////////////////////
// load_knowledge_base
//
// main function to load knowledge base
// Use meta_graph_p as the meta data graph of the knowledge base
// Use asserted_graph for *asserted-graph-begin* section
/////////////////////////////////////////////////////////////////////////////////////////
rule::knowledge_base_ptr_type
load_knowledge_base(std::string const& fname, rdf::rdf_graph_ptr_type & meta_graph_p, rdf::rdf_graph_ptr_type & asserted_graph_p, bool verbose);
/////////////////////////////////////////////////////////////////////////////////////////
// load_knowledge_base
//
// Method for loading knowledge_base with provisions for test cases.
/////////////////////////////////////////////////////////////////////////////////////////
rule::knowledge_base_ptr_type
load_knowledge_base(std::string const& fname, triple_array_type & expected_triples, triple_array_type & failure_triples, bool verbose=false);
/////////////////////////////////////////////////////////////////////////////////////////
// load_knowledge_base
//
// Method for loading knowledge_base with provisions for test cases targeted to psearch.
/////////////////////////////////////////////////////////////////////////////////////////
rule::knowledge_base_ptr_type
load_knowledge_base(std::string const& fname, test_data_map_type & test_data_map, bool verbose);
//---------------------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////////////////
// load_knowledge_base_from_buffer
//
// main function to load knowledge base
/////////////////////////////////////////////////////////////////////////////////////////
rule::knowledge_base_ptr_type
load_knowledge_base_from_buffer(std::string const& mem_buffer, bool verbose=false);
/////////////////////////////////////////////////////////////////////////////////////////
// load_knowledge_base_from_buffer
//
// main function to load knowledge base
// Use meta_graph_p as the meta data graph of the knowledge base
/////////////////////////////////////////////////////////////////////////////////////////
rule::knowledge_base_ptr_type
load_knowledge_base_from_buffer(std::string const& mem_buffer, rdf::rdf_graph_ptr_type & meta_graph_p, bool verbose=false);
/////////////////////////////////////////////////////////////////////////////////////////
// load_knowledge_base_from_buffer
//
// main function to load knowledge base
// Use meta_graph_p as the meta data graph of the knowledge base
// Use asserted_graph for *asserted-graph-begin* section
/////////////////////////////////////////////////////////////////////////////////////////
rule::knowledge_base_ptr_type
load_knowledge_base_from_buffer(std::string const& mem_buffer, rdf::rdf_graph_ptr_type & meta_graph_p, rdf::rdf_graph_ptr_type & asserted_graph_p, bool verbose);
//---------------------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////////////////
// parse_schema_section
//
/////////////////////////////////////////////////////////////////////////////////////////
void
parse_schema_section(std::istream & in, kb_builder & builder, unsigned int & lnum);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_knowledge_base_section
//
/////////////////////////////////////////////////////////////////////////////////////////
void
parse_knowledge_base_section(std::istream & in, kb_builder & builder, unsigned int & lnum);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_knowledge_rule_section
//
/////////////////////////////////////////////////////////////////////////////////////////
void
parse_knowledge_rule_section(std::istream & in, kb_builder & builder, unsigned int & lnum);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_assert_triples_section
//
/////////////////////////////////////////////////////////////////////////////////////////
void
parse_assert_triples_section(std::istream & in, kb_builder & builder, unsigned int & lnum);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_import_owl_section
//
/////////////////////////////////////////////////////////////////////////////////////////
void
parse_import_owl_section(std::istream & in, kb_builder & builder, unsigned int & lnum);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_psearch_db_section
//
/////////////////////////////////////////////////////////////////////////////////////////
void
parse_psearch_db_section(std::istream & in, kb_builder & builder, unsigned int & lnum);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_psearch_session_section
//
/////////////////////////////////////////////////////////////////////////////////////////
void
parse_psearch_session_section(std::istream & in, kb_builder & builder, unsigned int & lnum);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_meta_graph_section
//
/////////////////////////////////////////////////////////////////////////////////////////
void
parse_meta_graph_section(std::istream & in, kb_builder & builder, unsigned int & lnum);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_asserted_graph_section
//
/////////////////////////////////////////////////////////////////////////////////////////
void
parse_asserted_graph_section(std::istream & in, kb_builder & builder, unsigned int & lnum);
/////////////////////////////////////////////////////////////////////////////////////////
// read_line
//
// utility function
/////////////////////////////////////////////////////////////////////////////////////////
bool
read_line(std::istream & in, std::string & line, unsigned int & lnum, std::string const& multi_line_delemit);
/////////////////////////////////////////////////////////////////////////////////////////
// process_file
//
// utility function
/////////////////////////////////////////////////////////////////////////////////////////
void
process_file(std::string const& fname, kb_builder & builder);
/////////////////////////////////////////////////////////////////////////////////////////
// process_stream
//
// utility function
/////////////////////////////////////////////////////////////////////////////////////////
void
process_stream(std::istream & in, std::string const& fname, kb_builder & builder);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_param
//
// utility function
// jpos will be set to the end \" of the param.
// consume_quotes indicates if first and last quote are consumed
/////////////////////////////////////////////////////////////////////////////////////////
std::string
parse_param(std::string str, std::string::size_type & jpos, bool consume_quotes=true);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_param
//
// 'rest' is assigned the text following the end '\"'
/////////////////////////////////////////////////////////////////////////////////////////
std::string
parse_param(std::string line, std::string & rest, bool consume_quotes=true);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_param
//
// just extract the double-quoted params - don't care about the rest of the line
// - will consume the quotes
/////////////////////////////////////////////////////////////////////////////////////////
std::string
parse_param(std::string line);
/////////////////////////////////////////////////////////////////////////////////////////
// tokenize
//
// utility function
/////////////////////////////////////////////////////////////////////////////////////////
void
tokenize(std::string const& str, string_vector_t & tokens, std::string const& delimiters);
/////////////////////////////////////////////////////////////////////////////////////////
// split_at
//
// utility function
/////////////////////////////////////////////////////////////////////////////////////////
void
split_at(std::string const& str, std::string & s1, std::string & s2, std::string const& d);
/////////////////////////////////////////////////////////////////////////////////////////
// next_token
//
// utility function - split next token from the rest
// the double-quotes are not consumed - token will extend untill the end quote
// and token returned with the quotes.
/////////////////////////////////////////////////////////////////////////////////////////
std::string
next_token(std::string str, std::string & rest, std::string const& d);
/////////////////////////////////////////////////////////////////////////////////////////
// class head_functor
//
/////////////////////////////////////////////////////////////////////////////////////////
struct head_functor
{
template<class U, class V, class W>
rule::kterm_ptr_type
operator()(rule::knowledge_rule_ptr_type & rule_p, U const& u, V const& v, W const& w)const
{
std::cout << "process_term: Head term of backward chaining rule must have a known predicate (not a variable) and the subject must be a variable";
throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - Head term of backward chaining rule must have a known predicate (not a variable) and the subject must be a variable.");
};
template<class W>
rule::kterm_ptr_type
operator()(rule::knowledge_rule_ptr_type & rule_p,
std::string const& u, rdf::index_type const v, W const& w)const
{
return rule_p->set_head_term(u, v, w);
};
};
/////////////////////////////////////////////////////////////////////////////////////////
// class consequent_functor
//
/////////////////////////////////////////////////////////////////////////////////////////
struct consequent_functor
{
template<class U, class V, class W>
rule::kterm_ptr_type
operator()(rule::knowledge_rule_ptr_type & rule_p, U const& u, V const& v, W const& w)const
{
return rule_p->add_consequent_term(u, v, w);
};
};
/////////////////////////////////////////////////////////////////////////////////////////
// class body_functor
//
/////////////////////////////////////////////////////////////////////////////////////////
struct body_functor
{
template<class U, class V, class W>
rule::kterm_ptr_type
operator()(rule::knowledge_rule_ptr_type & rule_p, U const& u, V const& v, W const& w)const
{
return rule_p->add_rule_term(u, v, w);
};
template<class U, class V>
rule::kterm_ptr_type
operator()(rule::knowledge_rule_ptr_type & rule_p, U const& u, V const& v,
rule::knowledge_rule::xprsn_ptr_t const& w)const
{
std::cout << "process_term: Cannot have rule terms in body with expression as object!";
throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - process_term: Cannot have rule terms in body with expression as object!");
};
};
/////////////////////////////////////////////////////////////////////////////////////////
// class neg_body_functor
//
/////////////////////////////////////////////////////////////////////////////////////////
struct neg_body_functor
{
template<class U, class V, class W>
rule::kterm_ptr_type
operator()(rule::knowledge_rule_ptr_type & rule_p, U const& u, V const& v, W const& w)const
{
return rule_p->add_negated_rule_term(u, v, w);
};
template<class U, class V>
rule::kterm_ptr_type
operator()(rule::knowledge_rule_ptr_type & rule_p, U const& u, V const& v,
rule::knowledge_rule::xprsn_ptr_t const& w)const
{
std::cout << "process_term: Cannot have rule terms in body with expression as object!";
throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - process_term: Cannot have rule terms in body with expression as object!");
};
};
/////////////////////////////////////////////////////////////////////////////////////////
// kb_builder::process_term
//
/////////////////////////////////////////////////////////////////////////////////////////
template<class Functor>
rule::kterm_ptr_type
kb_builder::process_term(rule::knowledge_rule_ptr_type & rule_p, std::string line, Functor const& f)
{
// remove the first and last parenthesis
boost::trim(line);
if(boost::algorithm::istarts_with(line, "not")) line = line.substr(3);
boost::trim(line);
unsigned int sz = line.size();
if(sz==0 or line[0]!='(' or line[sz-1]!=')')
throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - term must start with '(' and end with ')'");
line = line.substr(1, sz-2);
std::string s, p;
s = next_token(line, line, " ");
if(s[0] == '\"') throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - subject cannot be literal");
if(s[0] == '(') throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - subject cannot an expression");
p = next_token(line, line, " ");
if(p[0] == '\"') throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - predicate cannot be literal");
if(p[0] == '(') throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - predicate cannot an expression");
boost::trim(line);
if(line.size() == 0) throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - cannot find object!");
// subject/predicate can be: var ('?' or '_') or resource
// object can be: var ('?' or '_'), expression ('('), literal ('"'), or resource
bool is_var_s=false, is_var_p=false;
if(s[0]=='?' or s[0]=='_') is_var_s = true;
if(p[0]=='?' or p[0]=='_') is_var_p = true;
if(is_var_s and s.find_first_of(" \t()")!=std::string::npos) {
std::string msg("ERROR-P13, invalid rule syntax, variable '"+s+"' is not valid. Forgot '.'?");
std::cout << msg << std::endl;
throw rdf::rdf_exception(rdf::parsing_error, msg);
}
if(is_var_p and p.find_first_of(" \t()")!=std::string::npos) {
std::string msg("ERROR-P13, invalid rule syntax, variable '"+p+"' is not valid. Forgot '.'?");
std::cout << msg << std::endl;
throw rdf::rdf_exception(rdf::parsing_error, msg);
}
if(line[0]=='?' or line[0]=='_') { // object is var
if(line.find_first_of(" \t()")!=std::string::npos) {
std::string msg("ERROR-P13, invalid rule syntax, variable '"+line+"' is not valid. Forgot '.'?");
std::cout << msg << std::endl;
throw rdf::rdf_exception(rdf::parsing_error, msg);
}
if(is_var_s and is_var_p) return f(rule_p, s, p, line);
if(!is_var_s and is_var_p) return f(rule_p, get_index(s), p, line);
if(is_var_s and !is_var_p) return f(rule_p, s, get_index(p), line);
return f(rule_p, get_index(s), get_index(p), line);
}
if(line[0] == '(') { // object is expression
if(*line.rbegin() != ')') // just to make sure
throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - expression in object must end with ')'");
line = line.substr(1);
rule::knowledge_rule::xprsn_ptr_t xprsn_p = create_expression(rule_p, line);
if(is_var_s and is_var_p) return f(rule_p, s, p, xprsn_p);
if(!is_var_s and is_var_p) return f(rule_p, get_index(s), p, xprsn_p);
if(is_var_s and !is_var_p) return f(rule_p, s, get_index(p), xprsn_p);
return f(rule_p, get_index(s), get_index(p), xprsn_p);
}
// the object must me a named index_type unless it's a quoted literal
rdf::index_type idx_o;
if(line[0] == '\"') {
idx_o = create_literal_as_index(line, line);
// line should now be empty
boost::trim(line);
if(line.size() > 0) {
std::cout << "process_term: unexpected char past the object - missing \".\" ?\n";
throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - unexpected characters past object in term, missing \".\" ?");
}
} else {
idx_o = get_index(line);
}
if(is_var_s and is_var_p) return f(rule_p, s, p, idx_o);
if(!is_var_s and is_var_p) return f(rule_p, get_index(s), p, idx_o);
if(is_var_s and !is_var_p) return f(rule_p, s, get_index(p), idx_o);
// cannot create a rule term with all 3 index_type for s, p, and o!
std::cout << "process_term: Cannot have rule term without variables or expression!";
throw rdf::rdf_exception(rdf::parsing_error, "ERROR-P13, invalid rule syntax - process_term: Cannot have rule term without variables or expression.");
};
}; /* parser namespace */
#endif /*KB_PARSER_H_*/