From dc210ee6eba3b1d173808bd858113f6abd90bff1 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Wed, 16 Mar 2016 21:35:35 -0400 Subject: Added word derivational relationships (kind of eh at the moment) and moved verbly into its own directory --- lib/adjective.cpp | 690 +++++++++++++++++++++++++++++++++++ lib/adjective.h | 143 ++++++++ lib/adverb.cpp | 468 ++++++++++++++++++++++++ lib/adverb.h | 95 +++++ lib/c++14.h | 35 ++ lib/data.cpp | 50 +++ lib/data.h | 49 +++ lib/noun.cpp | 1032 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/noun.h | 183 ++++++++++ lib/token.cpp | 53 +++ lib/token.h | 313 ++++++++++++++++ lib/util.h | 53 +++ lib/verb.cpp | 193 ++++++++++ lib/verb.h | 73 ++++ lib/verbly.h | 14 + lib/word.cpp | 32 ++ lib/word.h | 35 ++ 17 files changed, 3511 insertions(+) create mode 100644 lib/adjective.cpp create mode 100644 lib/adjective.h create mode 100644 lib/adverb.cpp create mode 100644 lib/adverb.h create mode 100644 lib/c++14.h create mode 100644 lib/data.cpp create mode 100644 lib/data.h create mode 100644 lib/noun.cpp create mode 100644 lib/noun.h create mode 100644 lib/token.cpp create mode 100644 lib/token.h create mode 100644 lib/util.h create mode 100644 lib/verb.cpp create mode 100644 lib/verb.h create mode 100644 lib/verbly.h create mode 100644 lib/word.cpp create mode 100644 lib/word.h (limited to 'lib') diff --git a/lib/adjective.cpp b/lib/adjective.cpp new file mode 100644 index 0000000..b2b53e4 --- /dev/null +++ b/lib/adjective.cpp @@ -0,0 +1,690 @@ +#include "verbly.h" + +namespace verbly { + + adjective::adjective(const data& _data, int _id) : word(_data, _id) + { + + } + + std::string adjective::base_form() const + { + return _base_form; + } + + std::string adjective::comparative_form() const + { + return _comparative_form; + } + + std::string adjective::superlative_form() const + { + return _superlative_form; + } + + adjective::positioning adjective::position() const + { + return _position; + } + + bool adjective::has_comparative_form() const + { + return !_comparative_form.empty(); + } + + bool adjective::has_superlative_form() const + { + return !_superlative_form.empty(); + } + + bool adjective::has_position() const + { + return _position != adjective::positioning::undefined; + } + + adjective_query adjective::antonyms() const + { + return _data.adjectives().antonym_of(*this); + } + + adjective_query adjective::synonyms() const + { + return _data.adjectives().synonym_of(*this); + } + + adjective_query adjective::generalizations() const + { + return _data.adjectives().generalization_of(*this); + } + + adjective_query adjective::specifications() const + { + return _data.adjectives().specification_of(*this); + } + + noun_query adjective::anti_pertainyms() const + { + return _data.nouns().anti_pertainym_of(*this); + } + + adverb_query adjective::mannernyms() const + { + return _data.adverbs().mannernym_of(*this); + } + + noun_query adjective::attributes() const + { + return _data.nouns().attribute_of(*this); + } + + adjective_query::adjective_query(const data& _data) : _data(_data) + { + + } + + adjective_query& adjective_query::limit(int _limit) + { + if ((_limit > 0) || (_limit == unlimited)) + { + this->_limit = _limit; + } + + return *this; + } + + adjective_query& adjective_query::random(bool _random) + { + this->_random = _random; + + return *this; + } + + adjective_query& adjective_query::except(const adjective& _word) + { + _except.push_back(_word); + + return *this; + } + + adjective_query& adjective_query::rhymes_with(const word& _word) + { + for (auto rhyme : _word.rhyme_phonemes()) + { + _rhymes.push_back(rhyme); + } + + if (dynamic_cast(&_word) != nullptr) + { + _except.push_back(dynamic_cast(_word)); + } + + return *this; + } + + adjective_query& adjective_query::has_pronunciation(bool _has_prn) + { + this->_has_prn = _has_prn; + + return *this; + } + + adjective_query& adjective_query::is_variant(bool _is_variant) + { + this->_is_variant = _is_variant; + + return *this; + } + + adjective_query& adjective_query::variant_of(const noun& _noun) + { + _variant_of.push_back(_noun); + + return *this; + } + + adjective_query& adjective_query::not_variant_of(const noun& _noun) + { + _not_variant_of.push_back(_noun); + + return *this; + } + + adjective_query& adjective_query::has_antonyms(bool _is_antonymic) + { + this->_is_antonymic = _is_antonymic; + + return *this; + } + + adjective_query& adjective_query::antonym_of(const adjective& _adj) + { + _antonym_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::not_antonym_of(const adjective& _adj) + { + _not_antonym_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::has_synonyms(bool _is_synonymic) + { + this->_is_synonymic = _is_synonymic; + + return *this; + } + + adjective_query& adjective_query::synonym_of(const adjective& _adj) + { + _synonym_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::not_synonym_of(const adjective& _adj) + { + _not_synonym_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::is_generalization(bool _is_generalization) + { + this->_is_generalization = _is_generalization; + + return *this; + } + + adjective_query& adjective_query::generalization_of(const adjective& _adj) + { + _generalization_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::not_generalization_of(const adjective& _adj) + { + _not_generalization_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::is_specification(bool _is_specification) + { + this->_is_specification = _is_specification; + + return *this; + } + + adjective_query& adjective_query::specification_of(const adjective& _adj) + { + _specification_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::not_specification_of(const adjective& _adj) + { + _not_specification_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::is_pertainymic(bool _is_pertainymic) + { + this->_is_pertainymic = _is_pertainymic; + + return *this; + } + + adjective_query& adjective_query::pertainym_of(const noun& _noun) + { + _pertainym_of.push_back(_noun); + + return *this; + } + + adjective_query& adjective_query::is_mannernymic(bool _is_mannernymic) + { + this->_is_mannernymic = _is_mannernymic; + + return *this; + } + + adjective_query& adjective_query::anti_mannernym_of(const adverb& _adv) + { + _anti_mannernym_of.push_back(_adv); + + return *this; + } + + adjective_query& adjective_query::derived_from(const word& _w) + { + if (dynamic_cast(&_w) != nullptr) + { + _derived_from_adjective.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _derived_from_adverb.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _derived_from_noun.push_back(dynamic_cast(_w)); + } + + return *this; + } + + adjective_query& adjective_query::not_derived_from(const word& _w) + { + if (dynamic_cast(&_w) != nullptr) + { + _not_derived_from_adjective.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _not_derived_from_adverb.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _not_derived_from_noun.push_back(dynamic_cast(_w)); + } + + return *this; + } + + std::list adjective_query::run() const + { + std::stringstream construct; + construct << "SELECT adjective_id, base_form, comparative, superlative, position FROM adjectives"; + std::list conditions; + + if (_has_prn) + { + conditions.push_back("adjective_id IN (SELECT adjective_id FROM adjective_pronunciations)"); + } + + if (!_rhymes.empty()) + { + std::list clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); + std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + for (auto except : _except) + { + conditions.push_back("adjective_id != @EXCID"); + } + + if (_requires_comparative_form) + { + conditions.push_back("comparative IS NOT NULL"); + } + + if (_requires_superlative_form) + { + conditions.push_back("superlative IS NOT NULL"); + } + + if (_position != adjective::positioning::undefined) + { + switch (_position) + { + case adjective::positioning::predicate: conditions.push_back("position = 'p'"); break; + case adjective::positioning::attributive: conditions.push_back("position = 'a'"); break; + case adjective::positioning::postnominal: conditions.push_back("position = 'i'"); break; + } + } + + if (_is_variant) + { + conditions.push_back("adjective_id IN (SELECT adjective_id FROM variation)"); + } + + if (!_variant_of.empty()) + { + std::list clauses(_variant_of.size(), "noun_id = @ATTRID"); + std::string cond = "adjective_id IN (SELECT adjective_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_variant_of.empty()) + { + std::list clauses(_not_variant_of.size(), "noun_id = @NATTRID"); + std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_antonymic) + { + conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); + } + + if (!_antonym_of.empty()) + { + std::list clauses(_antonym_of.size(), "adjective_1_id = @ANTID"); + std::string cond = "adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_antonym_of.empty()) + { + std::list clauses(_not_antonym_of.size(), "adjective_1_id = @NANTID"); + std::string cond = "adjective_id NOT IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_synonymic) + { + conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); + } + + if (!_synonym_of.empty()) + { + std::list clauses(_synonym_of.size(), "adjective_1_id = @SYNID"); + std::string cond = "adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_synonym_of.empty()) + { + std::list clauses(_not_synonym_of.size(), "adjective_1_id = @NSYNID"); + std::string cond = "adjective_id NOT IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_generalization) + { + conditions.push_back("adjective_id IN (SELECT general_id FROM specification)"); + } + + if (!_generalization_of.empty()) + { + std::list clauses(_generalization_of.size(), "specific_id = @SPECID"); + std::string cond = "adjective_id IN (SELECT general_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_generalization_of.empty()) + { + std::list clauses(_not_generalization_of.size(), "specific_id = @NSPECID"); + std::string cond = "adjective_id NOT IN (SELECT general_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_specification) + { + conditions.push_back("adjective_id IN (SELECT specific_id FROM specification)"); + } + + if (!_specification_of.empty()) + { + std::list clauses(_specification_of.size(), "general_id = @GENID"); + std::string cond = "adjective_id IN (SELECT specific_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_specification_of.empty()) + { + std::list clauses(_not_specification_of.size(), "general_id = @NGENID"); + std::string cond = "adjective_id NOT IN (SELECT specific_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_pertainymic) + { + conditions.push_back("adjective_id IN (SELECT pertainym_id FROM pertainymy)"); + } + + if (!_pertainym_of.empty()) + { + std::list clauses(_pertainym_of.size(), "noun_id = @APERID"); + std::string cond = "adjective_id IN (SELECT pertainym_id FROM pertainymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_mannernymic) + { + conditions.push_back("adjective_id IN (SELECT adjective_id FROM mannernymy)"); + } + + if (!_anti_mannernym_of.empty()) + { + std::list clauses(_anti_mannernym_of.size(), "mannernym_id = @MANID"); + std::string cond = "adjective_id IN (SELECT adjective_id FROM mannernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_derived_from_adjective.empty()) + { + std::list clauses(_derived_from_adjective.size(), "adjective_2_id = @DERADJ"); + std::string cond = "adjective_id IN (SELECT adjective_1_id FROM adjective_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_derived_from_adjective.empty()) + { + std::list clauses(_not_derived_from_adjective.size(), "adjective_2_id = @NDERADJ"); + std::string cond = "adjective_id NOT IN (SELECT adjective_1_id FROM adjective_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_derived_from_adverb.empty()) + { + std::list clauses(_derived_from_adverb.size(), "adverb_id = @DERADV"); + std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_derived_from_adverb.empty()) + { + std::list clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV"); + std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_derived_from_noun.empty()) + { + std::list clauses(_derived_from_noun.size(), "noun_id = @DERN"); + std::string cond = "adjective_id IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_derived_from_noun.empty()) + { + std::list clauses(_not_derived_from_noun.size(), "noun_id = @NDERN"); + std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!conditions.empty()) + { + construct << " WHERE "; + construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); + } + + if (_random) + { + construct << " ORDER BY RANDOM()"; + } + + if (_limit != unlimited) + { + construct << " LIMIT " << _limit; + } + + sqlite3_stmt* ppstmt; + std::string query = construct.str(); + if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) + { + throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); + } + + if (!_rhymes.empty()) + { + int i = 0; + for (auto rhyme : _rhymes) + { + std::string rhymer = "%" + rhyme; + sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); + + i++; + } + } + + for (auto except : _except) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); + } + + for (auto attribute : _variant_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ATTRID"), attribute._id); + } + + for (auto attribute : _not_variant_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NATTRID"), attribute._id); + } + + for (auto antonym : _antonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); + } + + for (auto antonym : _not_antonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); + } + + for (auto synonym : _synonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); + } + + for (auto synonym : _not_synonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); + } + + for (auto specific : _generalization_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SPECID"), specific._id); + } + + for (auto specific : _not_generalization_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSPECID"), specific._id); + } + + for (auto general : _specification_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GENID"), general._id); + } + + for (auto general : _not_specification_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NGENID"), general._id); + } + + for (auto n : _pertainym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@APERID"), n._id); + } + + for (auto mannernym : _anti_mannernym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MANID"), mannernym._id); + } + + for (auto adj : _derived_from_adjective) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); + } + + for (auto adj : _not_derived_from_adjective) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); + } + + for (auto adv : _derived_from_adverb) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); + } + + for (auto adv : _not_derived_from_adverb) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); + } + + for (auto n : _derived_from_noun) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); + } + + for (auto n : _not_derived_from_noun) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); + } + + std::list output; + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + adjective tnc {_data, sqlite3_column_int(ppstmt, 0)}; + tnc._base_form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 1))); + + if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) + { + tnc._comparative_form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 2))); + } + + if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) + { + tnc._superlative_form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 3))); + } + + if (sqlite3_column_type(ppstmt, 4) != SQLITE_NULL) + { + std::string adjpos(reinterpret_cast(sqlite3_column_text(ppstmt, 4))); + if (adjpos == "p") + { + tnc._position = adjective::positioning::predicate; + } else if (adjpos == "a") + { + tnc._position = adjective::positioning::attributive; + } else if (adjpos == "i") + { + tnc._position = adjective::positioning::postnominal; + } + } + + output.push_back(tnc); + } + + sqlite3_finalize(ppstmt); + + for (auto& adjective : output) + { + query = "SELECT pronunciation FROM adjective_pronunciations WHERE adjective_id = ?"; + if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) + { + throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); + } + + sqlite3_bind_int(ppstmt, 1, adjective._id); + + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + std::string pronunciation(reinterpret_cast(sqlite3_column_text(ppstmt, 0))); + auto phonemes = verbly::split>(pronunciation, " "); + + adjective.pronunciations.push_back(phonemes); + } + + sqlite3_finalize(ppstmt); + } + + return output; + } + +}; diff --git a/lib/adjective.h b/lib/adjective.h new file mode 100644 index 0000000..3dcab9b --- /dev/null +++ b/lib/adjective.h @@ -0,0 +1,143 @@ +#ifndef ADJECTIVE_H_87B3FB75 +#define ADJECTIVE_H_87B3FB75 + +namespace verbly { + + class adjective_query; + class adverb_query; + class noun_query; + + class adjective : public word { + public: + enum class positioning { + undefined, + predicate, + attributive, + postnominal + }; + + private: + std::string _base_form; + std::string _comparative_form; + std::string _superlative_form; + positioning _position = positioning::undefined; + + friend class adjective_query; + + public: + adjective(const data& _data, int _id); + + std::string base_form() const; + std::string comparative_form() const; + std::string superlative_form() const; + positioning position() const; + + bool has_comparative_form() const; + bool has_superlative_form() const; + bool has_position() const; + + adjective_query antonyms() const; + adjective_query synonyms() const; + adjective_query generalizations() const; + adjective_query specifications() const; + noun_query anti_pertainyms() const; + adverb_query mannernyms() const; + noun_query attributes() const; + }; + + class adjective_query { + public: + adjective_query(const data& _data); + + adjective_query& limit(int _limit); + adjective_query& random(bool _random); + adjective_query& except(const adjective& _word); + adjective_query& rhymes_with(const word& _word); + adjective_query& has_pronunciation(bool _has_prn); + + adjective_query& requires_comparative_form(bool req); + adjective_query& requires_superlative_form(bool req); + adjective_query& position(adjective::positioning pos); + + adjective_query& is_variant(bool _is_variant); + adjective_query& variant_of(const noun& _noun); + adjective_query& not_variant_of(const noun& _noun); + + adjective_query& has_antonyms(bool _is_antonymic); + adjective_query& antonym_of(const adjective& _adj); + adjective_query& not_antonym_of(const adjective& _adj); + + adjective_query& has_synonyms(bool _is_synonymic); + adjective_query& synonym_of(const adjective& _adj); + adjective_query& not_synonym_of(const adjective& _adj); + + adjective_query& is_generalization(bool _is_generalization); + adjective_query& generalization_of(const adjective& _adj); + adjective_query& not_generalization_of(const adjective& _adj); + + adjective_query& is_specification(bool _is_specification); + adjective_query& specification_of(const adjective& _adj); + adjective_query& not_specification_of(const adjective& _adj); + + adjective_query& is_pertainymic(bool _is_pertainymic); + adjective_query& pertainym_of(const noun& _noun); + + adjective_query& is_mannernymic(bool _is_mannernymic); + adjective_query& anti_mannernym_of(const adverb& _adv); + + adjective_query& derived_from(const word& _w); + adjective_query& not_derived_from(const word& _w); + + std::list run() const; + + const static int unlimited = -1; + + protected: + const data& _data; + int _limit = unlimited; + bool _random = false; + std::list _rhymes; + std::list _except; + bool _has_prn = false; + + bool _requires_comparative_form = false; + bool _requires_superlative_form = false; + adjective::positioning _position = adjective::positioning::undefined; + + bool _is_variant = false; + std::list _variant_of; + std::list _not_variant_of; + + bool _is_antonymic = false; + std::list _antonym_of; + std::list _not_antonym_of; + + bool _is_synonymic = false; + std::list _synonym_of; + std::list _not_synonym_of; + + bool _is_generalization = false; + std::list _generalization_of; + std::list _not_generalization_of; + + bool _is_specification = false; + std::list _specification_of; + std::list _not_specification_of; + + bool _is_pertainymic = false; + std::list _pertainym_of; + + bool _is_mannernymic = false; + std::list _anti_mannernym_of; + + std::list _derived_from_adjective; + std::list _not_derived_from_adjective; + std::list _derived_from_adverb; + std::list _not_derived_from_adverb; + std::list _derived_from_noun; + std::list _not_derived_from_noun; + }; + +}; + +#endif /* end of include guard: ADJECTIVE_H_87B3FB75 */ diff --git a/lib/adverb.cpp b/lib/adverb.cpp new file mode 100644 index 0000000..8fcddad --- /dev/null +++ b/lib/adverb.cpp @@ -0,0 +1,468 @@ +#include "verbly.h" + +namespace verbly { + + adverb::adverb(const data& _data, int _id) : word(_data, _id) + { + + } + + std::string adverb::base_form() const + { + return _base_form; + } + + std::string adverb::comparative_form() const + { + return _comparative_form; + } + + std::string adverb::superlative_form() const + { + return _superlative_form; + } + + bool adverb::has_comparative_form() const + { + return !_comparative_form.empty(); + } + + bool adverb::has_superlative_form() const + { + return !_superlative_form.empty(); + } + + adverb_query adverb::antonyms() const + { + return _data.adverbs().antonym_of(*this); + } + + adverb_query adverb::synonyms() const + { + return _data.adverbs().synonym_of(*this); + } + + adjective_query adverb::anti_mannernyms() const + { + return _data.adjectives().anti_mannernym_of(*this); + } + + adverb_query::adverb_query(const data& _data) : _data(_data) + { + + } + + adverb_query& adverb_query::limit(int _limit) + { + if ((_limit > 0) || (_limit == unlimited)) + { + this->_limit = _limit; + } + + return *this; + } + + adverb_query& adverb_query::random(bool _random) + { + this->_random = _random; + + return *this; + } + + adverb_query& adverb_query::except(const adverb& _word) + { + _except.push_back(_word); + + return *this; + } + + adverb_query& adverb_query::rhymes_with(const word& _word) + { + for (auto rhyme : _word.rhyme_phonemes()) + { + _rhymes.push_back(rhyme); + } + + if (dynamic_cast(&_word) != nullptr) + { + _except.push_back(dynamic_cast(_word)); + } + + return *this; + } + + adverb_query& adverb_query::has_pronunciation(bool _has_prn) + { + this->_has_prn = _has_prn; + + return *this; + } + + adverb_query& adverb_query::requires_comparative_form(bool _arg) + { + _requires_comparative_form = _arg; + + return *this; + } + + adverb_query& adverb_query::requires_superlative_form(bool _arg) + { + _requires_superlative_form = _arg; + + return *this; + } + + adverb_query& adverb_query::has_antonyms(bool _arg) + { + _has_antonyms = _arg; + + return *this; + } + + adverb_query& adverb_query::antonym_of(const adverb& _adv) + { + _antonym_of.push_back(_adv); + + return *this; + } + + adverb_query& adverb_query::not_antonym_of(const adverb& _adv) + { + _not_antonym_of.push_back(_adv); + + return *this; + } + + adverb_query& adverb_query::has_synonyms(bool _arg) + { + _has_synonyms = _arg; + + return *this; + } + + adverb_query& adverb_query::synonym_of(const adverb& _adv) + { + _synonym_of.push_back(_adv); + + return *this; + } + + adverb_query& adverb_query::not_synonym_of(const adverb& _adv) + { + _not_synonym_of.push_back(_adv); + + return *this; + } + + adverb_query& adverb_query::is_mannernymic(bool _arg) + { + _is_mannernymic = _arg; + + return *this; + } + + adverb_query& adverb_query::mannernym_of(const adjective& _adj) + { + _mannernym_of.push_back(_adj); + + return *this; + } + + adverb_query& adverb_query::derived_from(const word& _w) + { + if (dynamic_cast(&_w) != nullptr) + { + _derived_from_adjective.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _derived_from_adverb.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _derived_from_noun.push_back(dynamic_cast(_w)); + } + + return *this; + } + + adverb_query& adverb_query::not_derived_from(const word& _w) + { + if (dynamic_cast(&_w) != nullptr) + { + _not_derived_from_adjective.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _not_derived_from_adverb.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _not_derived_from_noun.push_back(dynamic_cast(_w)); + } + + return *this; + } + + std::list adverb_query::run() const + { + std::stringstream construct; + construct << "SELECT adverb_id, base_form, comparative, superlative FROM adverbs"; + std::list conditions; + + if (_has_prn) + { + conditions.push_back("adverb_id IN (SELECT adverb_id FROM adverb_pronunciations)"); + } + + if (!_rhymes.empty()) + { + std::list clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); + std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + for (auto except : _except) + { + conditions.push_back("adverb_id != @EXCID"); + } + + if (_requires_comparative_form) + { + conditions.push_back("comparative IS NOT NULL"); + } + + if (_requires_superlative_form) + { + conditions.push_back("superlative IS NOT NULL"); + } + + if (_has_antonyms) + { + conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy)"); + } + + if (!_antonym_of.empty()) + { + std::list clauses(_antonym_of.size(), "adverb_1_id = @ANTID"); + std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_antonym_of.empty()) + { + std::list clauses(_not_antonym_of.size(), "adverb_1_id = @NANTID"); + std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_has_synonyms) + { + conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy)"); + } + + if (!_synonym_of.empty()) + { + std::list clauses(_synonym_of.size(), "adverb_1_id = @SYNID"); + std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_synonym_of.empty()) + { + std::list clauses(_not_synonym_of.size(), "adverb_1_id = @NSYNID"); + std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_mannernymic) + { + conditions.push_back("adverb_id IN (SELECT mannernym_id FROM mannernymy)"); + } + + if (!_mannernym_of.empty()) + { + std::list clauses(_mannernym_of.size(), "adjective_id = @AMANID"); + std::string cond = "adverb_id IN (SELECT mannernym_id FROM mannernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_derived_from_adjective.empty()) + { + std::list clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ"); + std::string cond = "adverb_id IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_derived_from_adjective.empty()) + { + std::list clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ"); + std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_derived_from_adverb.empty()) + { + std::list clauses(_derived_from_adverb.size(), "adverb_2_id = @DERADV"); + std::string cond = "adverb_id IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_derived_from_adverb.empty()) + { + std::list clauses(_not_derived_from_adverb.size(), "adverb_2_id = @NDERADV"); + std::string cond = "adverb_id NOT IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_derived_from_noun.empty()) + { + std::list clauses(_derived_from_noun.size(), "noun_id = @DERN"); + std::string cond = "adverb_id IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_derived_from_noun.empty()) + { + std::list clauses(_not_derived_from_noun.size(), "noun_id = @NDERN"); + std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!conditions.empty()) + { + construct << " WHERE "; + construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); + } + + if (_random) + { + construct << " ORDER BY RANDOM()"; + } + + if (_limit != unlimited) + { + construct << " LIMIT " << _limit; + } + + sqlite3_stmt* ppstmt; + std::string query = construct.str(); + if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) + { + throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); + } + + if (!_rhymes.empty()) + { + int i = 0; + for (auto rhyme : _rhymes) + { + std::string rhymer = "%" + rhyme; + sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); + + i++; + } + } + + for (auto except : _except) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); + } + + for (auto antonym : _antonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); + } + + for (auto antonym : _not_antonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); + } + + for (auto synonym : _synonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); + } + + for (auto synonym : _not_synonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); + } + + for (auto adj : _mannernym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@AMANID"), adj._id); + } + + for (auto adj : _derived_from_adjective) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); + } + + for (auto adj : _not_derived_from_adjective) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); + } + + for (auto adv : _derived_from_adverb) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); + } + + for (auto adv : _not_derived_from_adverb) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); + } + + for (auto n : _derived_from_noun) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); + } + + for (auto n : _not_derived_from_noun) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); + } + + std::list output; + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + adverb tnc {_data, sqlite3_column_int(ppstmt, 0)}; + tnc._base_form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 1))); + + if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) + { + tnc._comparative_form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 2))); + } + + if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) + { + tnc._superlative_form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 3))); + } + + output.push_back(tnc); + } + + sqlite3_finalize(ppstmt); + + for (auto& adverb : output) + { + query = "SELECT pronunciation FROM adverb_pronunciations WHERE adverb_id = ?"; + if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) + { + throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); + } + + sqlite3_bind_int(ppstmt, 1, adverb._id); + + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + std::string pronunciation(reinterpret_cast(sqlite3_column_text(ppstmt, 0))); + auto phonemes = verbly::split>(pronunciation, " "); + + adverb.pronunciations.push_back(phonemes); + } + + sqlite3_finalize(ppstmt); + } + + return output; + } + +}; diff --git a/lib/adverb.h b/lib/adverb.h new file mode 100644 index 0000000..65e3c5c --- /dev/null +++ b/lib/adverb.h @@ -0,0 +1,95 @@ +#ifndef ADVERB_H_86F8302F +#define ADVERB_H_86F8302F + +namespace verbly { + + class adverb : public word { + private: + std::string _base_form; + std::string _comparative_form; + std::string _superlative_form; + + friend class adverb_query; + + public: + adverb(const data& _data, int _id); + + std::string base_form() const; + std::string comparative_form() const; + std::string superlative_form() const; + + bool has_comparative_form() const; + bool has_superlative_form() const; + + adverb_query antonyms() const; + adverb_query synonyms() const; + adjective_query anti_mannernyms() const; + + adverb_query& derived_from(const word& _w); + adverb_query& not_derived_from(const word& _w); + }; + + class adverb_query { + public: + adverb_query(const data& _data); + + adverb_query& limit(int _limit); + adverb_query& random(bool _random); + adverb_query& except(const adverb& _word); + adverb_query& rhymes_with(const word& _word); + adverb_query& has_pronunciation(bool _has_prn); + + adverb_query& requires_comparative_form(bool _arg); + adverb_query& requires_superlative_form(bool _arg); + + adverb_query& has_antonyms(bool _arg); + adverb_query& antonym_of(const adverb& _adv); + adverb_query& not_antonym_of(const adverb& _adv); + + adverb_query& has_synonyms(bool _arg); + adverb_query& synonym_of(const adverb& _adv); + adverb_query& not_synonym_of(const adverb& _adv); + + adverb_query& is_mannernymic(bool _arg); + adverb_query& mannernym_of(const adjective& _adj); + + adverb_query& derived_from(const word& _w); + adverb_query& not_derived_from(const word& _w); + + std::list run() const; + + const static int unlimited = -1; + + private: + const data& _data; + int _limit = unlimited; + bool _random = false; + std::list _rhymes; + std::list _except; + bool _has_prn = false; + + bool _requires_comparative_form = false; + bool _requires_superlative_form = false; + + bool _has_antonyms = false; + std::list _antonym_of; + std::list _not_antonym_of; + + bool _has_synonyms = false; + std::list _synonym_of; + std::list _not_synonym_of; + + bool _is_mannernymic = false; + std::list _mannernym_of; + + std::list _derived_from_adjective; + std::list _not_derived_from_adjective; + std::list _derived_from_adverb; + std::list _not_derived_from_adverb; + std::list _derived_from_noun; + std::list _not_derived_from_noun; + }; + +}; + +#endif /* end of include guard: ADVERB_H_86F8302F */ diff --git a/lib/c++14.h b/lib/c++14.h new file mode 100644 index 0000000..b3efbe2 --- /dev/null +++ b/lib/c++14.h @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +namespace std { + template struct _Unique_if { + typedef unique_ptr _Single_object; + }; + + template struct _Unique_if { + typedef unique_ptr _Unknown_bound; + }; + + template struct _Unique_if { + typedef void _Known_bound; + }; + + template + typename _Unique_if::_Single_object + make_unique(Args&&... args) { + return unique_ptr(new T(std::forward(args)...)); + } + + template + typename _Unique_if::_Unknown_bound + make_unique(size_t n) { + typedef typename remove_extent::type U; + return unique_ptr(new U[n]()); + } + + template + typename _Unique_if::_Known_bound + make_unique(Args&&...) = delete; +} diff --git a/lib/data.cpp b/lib/data.cpp new file mode 100644 index 0000000..57a8850 --- /dev/null +++ b/lib/data.cpp @@ -0,0 +1,50 @@ +#include "verbly.h" + +namespace verbly { + + data::data(std::string datafile) + { + if (sqlite3_open_v2(datafile.c_str(), &ppdb, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK) + { + throw std::invalid_argument(sqlite3_errmsg(ppdb)); + } + } + + data::data(data&& other) + { + ppdb = other.ppdb; + } + + data& data::operator=(data&& other) + { + ppdb = other.ppdb; + + return *this; + } + + data::~data() + { + sqlite3_close_v2(ppdb); + } + + verb_query data::verbs() const + { + return verb_query(*this); + } + + adjective_query data::adjectives() const + { + return adjective_query(*this); + } + + adverb_query data::adverbs() const + { + return adverb_query(*this); + } + + noun_query data::nouns() const + { + return noun_query(*this); + } + +}; diff --git a/lib/data.h b/lib/data.h new file mode 100644 index 0000000..37092d7 --- /dev/null +++ b/lib/data.h @@ -0,0 +1,49 @@ +#ifndef DATA_H_C4AEC3DD +#define DATA_H_C4AEC3DD + +#include +#include + +namespace verbly { + + class data; + class word; + class adjective; + class noun; + class verb; + class adverb; + class adjective_query; + class adverb_query; + class noun_query; + class verb_query; + + class data { + private: + sqlite3* ppdb; + + friend class adjective_query; + friend class noun_query; + friend class verb_query; + friend class adverb_query; + + public: + data(std::string datafile); + + data(const data& other) = delete; + data& operator=(const data& other) = delete; + + data(data&& other); + data& operator=(data&& other); + + ~data(); + + verb_query verbs() const; + adjective_query adjectives() const; + adverb_query adverbs() const; + noun_query nouns() const; + + }; + +}; + +#endif /* end of include guard: DATA_H_C4AEC3DD */ diff --git a/lib/noun.cpp b/lib/noun.cpp new file mode 100644 index 0000000..43fda2e --- /dev/null +++ b/lib/noun.cpp @@ -0,0 +1,1032 @@ +#include "verbly.h" + +namespace verbly { + + noun::noun(const data& _data, int _id) : word(_data, _id) + { + + } + + std::string noun::base_form() const + { + return _singular; + } + + std::string noun::singular_form() const + { + return _singular; + } + + std::string noun::plural_form() const + { + return _plural; + } + + bool noun::has_plural_form() const + { + return !_plural.empty(); + } + + noun_query noun::hypernyms() const + { + return _data.nouns().hypernym_of(*this); + } + + noun_query noun::hyponyms() const + { + return _data.nouns().hyponym_of(*this); + } + + noun_query noun::part_meronyms() const + { + return _data.nouns().part_meronym_of(*this); + } + + noun_query noun::part_holonyms() const + { + return _data.nouns().part_holonym_of(*this); + } + + noun_query noun::substance_meronyms() const + { + return _data.nouns().substance_meronym_of(*this); + } + + noun_query noun::substance_holonyms() const + { + return _data.nouns().substance_holonym_of(*this); + } + + noun_query noun::member_meronyms() const + { + return _data.nouns().member_meronym_of(*this); + } + + noun_query noun::member_holonyms() const + { + return _data.nouns().member_holonym_of(*this); + } + + noun_query noun::classes() const + { + return _data.nouns().class_of(*this); + } + + noun_query noun::instances() const + { + return _data.nouns().instance_of(*this); + } + + noun_query noun::synonyms() const + { + return _data.nouns().synonym_of(*this); + } + + noun_query noun::antonyms() const + { + return _data.nouns().antonym_of(*this); + } + + adjective_query noun::pertainyms() const + { + return _data.adjectives().pertainym_of(*this); + } + + adjective_query noun::variations() const + { + return _data.adjectives().variant_of(*this); + } + + noun_query::noun_query(const data& _data) : _data(_data) + { + + } + + noun_query& noun_query::limit(int _limit) + { + if ((_limit > 0) || (_limit == unlimited)) + { + this->_limit = _limit; + } + + return *this; + } + + noun_query& noun_query::random(bool _random) + { + this->_random = _random; + + return *this; + } + + noun_query& noun_query::except(const noun& _word) + { + _except.push_back(_word); + + return *this; + } + + noun_query& noun_query::rhymes_with(const word& _word) + { + for (auto rhyme : _word.rhyme_phonemes()) + { + _rhymes.push_back(rhyme); + } + + if (dynamic_cast(&_word) != nullptr) + { + _except.push_back(dynamic_cast(_word)); + } + + return *this; + } + + noun_query& noun_query::has_pronunciation(bool _has_prn) + { + this->_has_prn = _has_prn; + + return *this; + } + + noun_query& noun_query::is_hypernym(bool _arg) + { + _is_hypernym = _arg; + + return *this; + } + + noun_query& noun_query::hypernym_of(const noun& _noun) + { + _hypernym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_hypernym_of(const noun& _noun) + { + _not_hypernym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_hyponym(bool _arg) + { + _is_hyponym = _arg; + + return *this; + } + + noun_query& noun_query::hyponym_of(const noun& _noun) + { + _hyponym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_hyponym_of(const noun& _noun) + { + _not_hyponym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_part_meronym(bool _arg) + { + _is_part_meronym = _arg; + + return *this; + } + + noun_query& noun_query::part_meronym_of(const noun& _noun) + { + _part_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_part_meronym_of(const noun& _noun) + { + _not_part_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_part_holonym(bool _arg) + { + _is_part_holonym = _arg; + + return *this; + } + + noun_query& noun_query::part_holonym_of(const noun& _noun) + { + _part_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_part_holonym_of(const noun& _noun) + { + _not_part_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_substance_meronym(bool _arg) + { + _is_substance_meronym = _arg; + + return *this; + } + + noun_query& noun_query::substance_meronym_of(const noun& _noun) + { + _substance_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_substance_meronym_of(const noun& _noun) + { + _not_substance_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_substance_holonym(bool _arg) + { + _is_substance_holonym = _arg; + + return *this; + } + + noun_query& noun_query::substance_holonym_of(const noun& _noun) + { + _substance_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_substance_holonym_of(const noun& _noun) + { + _not_substance_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_member_meronym(bool _arg) + { + _is_member_meronym = _arg; + + return *this; + } + + noun_query& noun_query::member_meronym_of(const noun& _noun) + { + _member_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_member_meronym_of(const noun& _noun) + { + _not_member_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_member_holonym(bool _arg) + { + _is_member_holonym = _arg; + + return *this; + } + + noun_query& noun_query::member_holonym_of(const noun& _noun) + { + _member_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_member_holonym_of(const noun& _noun) + { + _not_member_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_proper(bool _arg) + { + _is_proper = _arg; + + return *this; + } + + noun_query& noun_query::is_not_proper(bool _arg) + { + _is_not_proper = _arg; + + return *this; + } + + noun_query& noun_query::instance_of(const noun& _noun) + { + _instance_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_instance_of(const noun& _noun) + { + _not_instance_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_class(bool _arg) + { + _is_class = _arg; + + return *this; + } + + noun_query& noun_query::class_of(const noun& _noun) + { + _class_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_class_of(const noun& _noun) + { + _not_class_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::has_synonyms(bool _arg) + { + _has_synonyms = _arg; + + return *this; + } + + noun_query& noun_query::synonym_of(const noun& _noun) + { + _synonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_synonym_of(const noun& _noun) + { + _not_synonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::has_antonyms(bool _arg) + { + _has_antonyms = _arg; + + return *this; + } + + noun_query& noun_query::antonym_of(const noun& _noun) + { + _antonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_antonym_of(const noun& _noun) + { + _not_antonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::has_pertainym(bool _arg) + { + _has_pertainym = _arg; + + return *this; + } + + noun_query& noun_query::anti_pertainym_of(const adjective& _adj) + { + _anti_pertainym_of.push_back(_adj); + + return *this; + } + + noun_query& noun_query::is_attribute(bool _arg) + { + _is_attribute = _arg; + + return *this; + } + + noun_query& noun_query::attribute_of(const adjective& _adj) + { + _attribute_of.push_back(_adj); + + return *this; + } + + noun_query& noun_query::derived_from(const word& _w) + { + if (dynamic_cast(&_w) != nullptr) + { + _derived_from_adjective.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _derived_from_adverb.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _derived_from_noun.push_back(dynamic_cast(_w)); + } + + return *this; + } + + noun_query& noun_query::not_derived_from(const word& _w) + { + if (dynamic_cast(&_w) != nullptr) + { + _not_derived_from_adjective.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _not_derived_from_adverb.push_back(dynamic_cast(_w)); + } else if (dynamic_cast(&_w) != nullptr) + { + _not_derived_from_noun.push_back(dynamic_cast(_w)); + } + + return *this; + } + + std::list noun_query::run() const + { + std::stringstream construct; + construct << "SELECT noun_id, singular, plural FROM nouns"; + std::list conditions; + + if (_has_prn) + { + conditions.push_back("noun_id IN (SELECT noun_id FROM noun_pronunciations)"); + } + + if (!_rhymes.empty()) + { + std::list clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); + std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + for (auto except : _except) + { + conditions.push_back("noun_id != @EXCID"); + } + + if (_is_hypernym) + { + conditions.push_back("noun_id IN (SELECT hypernym_id FROM hypernymy)"); + } + + if (!_hypernym_of.empty()) + { + std::list clauses(_hypernym_of.size(), "hyponym_id = @HYPO"); + std::string cond = "noun_id IN (SELECT hypernym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_hypernym_of.empty()) + { + std::list clauses(_not_hypernym_of.size(), "hyponym_id = @NHYPO"); + std::string cond = "noun_id NOT IN (SELECT hypernym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_hyponym) + { + conditions.push_back("noun_id IN (SELECT hyponym_id FROM hypernymy)"); + } + + if (!_hyponym_of.empty()) + { + std::list clauses(_hyponym_of.size(), "hypernym_id = @HYPER"); + std::string cond = "noun_id IN (SELECT hyponym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_hyponym_of.empty()) + { + std::list clauses(_not_hyponym_of.size(), "hypernym_id = @NHYPER"); + std::string cond = "noun_id NOT IN (SELECT hyponym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_part_meronym) + { + conditions.push_back("noun_id IN (SELECT meronym_id FROM part_meronymy)"); + } + + if (!_part_meronym_of.empty()) + { + std::list clauses(_part_meronym_of.size(), "holonym_id = @PHOLO"); + std::string cond = "noun_id IN (SELECT meronym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_part_meronym_of.empty()) + { + std::list clauses(_not_part_meronym_of.size(), "holonym_id = @NPHOLO"); + std::string cond = "noun_id NOT IN (SELECT meronym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_part_holonym) + { + conditions.push_back("noun_id IN (SELECT holonym_id FROM part_meronymy)"); + } + + if (!_part_holonym_of.empty()) + { + std::list clauses(_part_holonym_of.size(), "meronym_id = @PMERO"); + std::string cond = "noun_id IN (SELECT holonym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_part_holonym_of.empty()) + { + std::list clauses(_not_part_holonym_of.size(), "meronym_id = @NPMERO"); + std::string cond = "noun_id NOT IN (SELECT holonym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_substance_meronym) + { + conditions.push_back("noun_id IN (SELECT meronym_id FROM substance_meronymy)"); + } + + if (!_substance_meronym_of.empty()) + { + std::list clauses(_substance_meronym_of.size(), "holonym_id = @SHOLO"); + std::string cond = "noun_id IN (SELECT meronym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_substance_meronym_of.empty()) + { + std::list clauses(_not_substance_meronym_of.size(), "holonym_id = @NSHOLO"); + std::string cond = "noun_id NOT IN (SELECT meronym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_substance_holonym) + { + conditions.push_back("noun_id IN (SELECT holonym_id FROM substance_meronymy)"); + } + + if (!_substance_holonym_of.empty()) + { + std::list clauses(_substance_holonym_of.size(), "meronym_id = @SMERO"); + std::string cond = "noun_id IN (SELECT holonym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_substance_holonym_of.empty()) + { + std::list clauses(_not_substance_holonym_of.size(), "meronym_id = @NSMERO"); + std::string cond = "noun_id NOT IN (SELECT holonym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_member_meronym) + { + conditions.push_back("noun_id IN (SELECT meronym_id FROM member_meronymy)"); + } + + if (!_member_meronym_of.empty()) + { + std::list clauses(_member_meronym_of.size(), "holonym_id = @MHOLO"); + std::string cond = "noun_id IN (SELECT meronym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_member_meronym_of.empty()) + { + std::list clauses(_not_member_meronym_of.size(), "holonym_id = @NMHOLO"); + std::string cond = "noun_id NOT IN (SELECT meronym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_member_holonym) + { + conditions.push_back("noun_id IN (SELECT holonym_id FROM member_meronym)"); + } + + if (!_member_holonym_of.empty()) + { + std::list clauses(_member_holonym_of.size(), "meronym_id = @MMERO"); + std::string cond = "noun_id IN (SELECT holonym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_member_holonym_of.empty()) + { + std::list clauses(_not_member_holonym_of.size(), "meronym_id = @NMMERO"); + std::string cond = "noun_id NOT IN (SELECT holonym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_proper) + { + conditions.push_back("noun_id IN (SELECT instance_id FROM instantiation)"); + } + + if (_is_not_proper) + { + conditions.push_back("noun_id NOT IN (SELECT instance_id FROM instantiation)"); + } + + if (!_instance_of.empty()) + { + std::list clauses(_instance_of.size(), "class_id = @CLSID"); + std::string cond = "noun_id IN (SELECT instance_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_instance_of.empty()) + { + std::list clauses(_not_instance_of.size(), "class_id = @NCLSID"); + std::string cond = "noun_id NOT IN (SELECT instance_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_class) + { + conditions.push_back("noun_id IN (SELECT class_id FROM instantiation)"); + } + + if (!_class_of.empty()) + { + std::list clauses(_class_of.size(), "instance_id = @INSID"); + std::string cond = "noun_id IN (SELECT class_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_class_of.empty()) + { + std::list clauses(_not_class_of.size(), "instance_id = @NINSID"); + std::string cond = "noun_id NOT IN (SELECT class_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_has_synonyms) + { + conditions.push_back("noun_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); + } + + if (!_synonym_of.empty()) + { + std::list clauses(_synonym_of.size(), "adjective_1_id = @SYNID"); + std::string cond = "noun_id IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_synonym_of.empty()) + { + std::list clauses(_not_synonym_of.size(), "adjective_1_id = @NSYNID"); + std::string cond = "noun_id NOT IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_has_antonyms) + { + conditions.push_back("noun_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); + } + + if (!_antonym_of.empty()) + { + std::list clauses(_antonym_of.size(), "adjective_1_id = @ANTID"); + std::string cond = "noun_id IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_antonym_of.empty()) + { + std::list clauses(_not_antonym_of.size(), "adjective_1_id = @NANTID"); + std::string cond = "noun_id NOT IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_has_pertainym) + { + conditions.push_back("noun_id IN (SELECT noun_id FROM pertainymy)"); + } + + if (!_anti_pertainym_of.empty()) + { + std::list clauses(_anti_pertainym_of.size(), "pertainym_id = @PERID"); + std::string cond = "noun_id IN (SELECT noun_id FROM pertainymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_attribute) + { + conditions.push_back("noun_id IN (SELECT noun_id FROM variation)"); + } + + if (!_attribute_of.empty()) + { + std::list clauses(_attribute_of.size(), "adjective_id = @VALID"); + std::string cond = "noun_id IN (SELECT noun_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_derived_from_adjective.empty()) + { + std::list clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ"); + std::string cond = "noun_id IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_derived_from_adjective.empty()) + { + std::list clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ"); + std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_derived_from_adverb.empty()) + { + std::list clauses(_derived_from_adverb.size(), "adverb_id = @DERADV"); + std::string cond = "noun_id IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_derived_from_adverb.empty()) + { + std::list clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV"); + std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_derived_from_noun.empty()) + { + std::list clauses(_derived_from_noun.size(), "noun_2_id = @DERN"); + std::string cond = "noun_id IN (SELECT noun_1_id FROM noun_noun_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_derived_from_noun.empty()) + { + std::list clauses(_not_derived_from_noun.size(), "noun_2_id = @NDERN"); + std::string cond = "noun_id NOT IN (SELECT noun_1_id FROM noun_noun_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!conditions.empty()) + { + construct << " WHERE "; + construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); + } + + if (_random) + { + construct << " ORDER BY RANDOM()"; + } + + if (_limit != unlimited) + { + construct << " LIMIT " << _limit; + } + + sqlite3_stmt* ppstmt; + std::string query = construct.str(); + if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) + { + throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); + } + + if (!_rhymes.empty()) + { + int i = 0; + for (auto rhyme : _rhymes) + { + std::string rhymer = "%" + rhyme; + sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); + + i++; + } + } + + for (auto except : _except) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); + } + + for (auto hyponym : _hypernym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPO"), hyponym._id); + } + + for (auto hyponym : _not_hypernym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NHYPO"), hyponym._id); + } + + for (auto hypernym : _hyponym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPER"), hypernym._id); + } + + for (auto hypernym : _not_hyponym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NHYPER"), hypernym._id); + } + + for (auto holonym : _part_meronym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PHOLO"), holonym._id); + } + + for (auto holonym : _not_part_meronym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NPHOLO"), holonym._id); + } + + for (auto meronym : _part_holonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PMERO"), meronym._id); + } + + for (auto meronym : _not_part_holonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NPMERO"), meronym._id); + } + + for (auto holonym : _substance_meronym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SHOLO"), holonym._id); + } + + for (auto holonym : _not_substance_meronym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSHOLO"), holonym._id); + } + + for (auto meronym : _substance_holonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SMERO"), meronym._id); + } + + for (auto meronym : _not_substance_holonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSMERO"), meronym._id); + } + + for (auto holonym : _member_meronym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MHOLO"), holonym._id); + } + + for (auto holonym : _not_member_meronym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NMHOLO"), holonym._id); + } + + for (auto meronym : _member_holonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MMERO"), meronym._id); + } + + for (auto meronym : _not_member_holonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NMMERO"), meronym._id); + } + + for (auto cls : _instance_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@CLSID"), cls._id); + } + + for (auto cls : _not_instance_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NCLSID"), cls._id); + } + + for (auto inst : _class_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@INSID"), inst._id); + } + + for (auto inst : _not_class_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NINSID"), inst._id); + } + + for (auto synonym : _synonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); + } + + for (auto synonym : _not_synonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); + } + + for (auto antonym : _antonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); + } + + for (auto antonym : _not_antonym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); + } + + for (auto pertainym : _anti_pertainym_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PERID"), pertainym._id); + } + + for (auto value : _attribute_of) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@VALID"), value._id); + } + + for (auto adj : _derived_from_adjective) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); + } + + for (auto adj : _not_derived_from_adjective) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); + } + + for (auto adv : _derived_from_adverb) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); + } + + for (auto adv : _not_derived_from_adverb) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); + } + + for (auto n : _derived_from_noun) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); + } + + for (auto n : _not_derived_from_noun) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); + } + + std::list output; + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + noun tnc {_data, sqlite3_column_int(ppstmt, 0)}; + tnc._singular = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 1))); + + if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) + { + tnc._plural = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 2))); + } + + output.push_back(tnc); + } + + sqlite3_finalize(ppstmt); + + for (auto& noun : output) + { + query = "SELECT pronunciation FROM noun_pronunciations WHERE noun_id = ?"; + if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) + { + throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); + } + + sqlite3_bind_int(ppstmt, 1, noun._id); + + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + std::string pronunciation(reinterpret_cast(sqlite3_column_text(ppstmt, 0))); + auto phonemes = verbly::split>(pronunciation, " "); + + noun.pronunciations.push_back(phonemes); + } + + sqlite3_finalize(ppstmt); + } + + return output; + } + +}; diff --git a/lib/noun.h b/lib/noun.h new file mode 100644 index 0000000..da76866 --- /dev/null +++ b/lib/noun.h @@ -0,0 +1,183 @@ +#ifndef NOUN_H_24A03C83 +#define NOUN_H_24A03C83 + +namespace verbly { + + class noun : public word { + private: + std::string _singular; + std::string _plural; + + friend class noun_query; + + public: + noun(const data& _data, int _id); + + std::string base_form() const; + std::string singular_form() const; + std::string plural_form() const; + + bool has_plural_form() const; + + noun_query hypernyms() const; + noun_query hyponyms() const; + noun_query part_meronyms() const; + noun_query part_holonyms() const; + noun_query substance_meronyms() const; + noun_query substance_holonyms() const; + noun_query member_meronyms() const; + noun_query member_holonyms() const; + noun_query classes() const; + noun_query instances() const; + noun_query synonyms() const; + noun_query antonyms() const; + adjective_query pertainyms() const; + adjective_query variations() const; + }; + + class noun_query { + public: + noun_query(const data& _data); + + noun_query& limit(int _limit); + noun_query& random(bool _random); + noun_query& except(const noun& _word); + noun_query& rhymes_with(const word& _word); + noun_query& has_pronunciation(bool _has_prn); + + noun_query& is_hypernym(bool _arg); + noun_query& hypernym_of(const noun& _noun); + noun_query& not_hypernym_of(const noun& _noun); + + noun_query& is_hyponym(bool _arg); + noun_query& hyponym_of(const noun& _noun); + noun_query& not_hyponym_of(const noun& _noun); + + noun_query& is_part_meronym(bool _arg); + noun_query& part_meronym_of(const noun& _noun); + noun_query& not_part_meronym_of(const noun& _noun); + + noun_query& is_part_holonym(bool _arg); + noun_query& part_holonym_of(const noun& _noun); + noun_query& not_part_holonym_of(const noun& _noun); + + noun_query& is_substance_meronym(bool _arg); + noun_query& substance_meronym_of(const noun& _noun); + noun_query& not_substance_meronym_of(const noun& _noun); + + noun_query& is_substance_holonym(bool _arg); + noun_query& substance_holonym_of(const noun& _noun); + noun_query& not_substance_holonym_of(const noun& _noun); + + noun_query& is_member_meronym(bool _arg); + noun_query& member_meronym_of(const noun& _noun); + noun_query& not_member_meronym_of(const noun& _noun); + + noun_query& is_member_holonym(bool _arg); + noun_query& member_holonym_of(const noun& _noun); + noun_query& not_member_holonym_of(const noun& _noun); + + noun_query& is_proper(bool _arg); + noun_query& is_not_proper(bool _arg); + noun_query& instance_of(const noun& _noun); + noun_query& not_instance_of(const noun& _noun); + + noun_query& is_class(bool _arg); + noun_query& class_of(const noun& _noun); + noun_query& not_class_of(const noun& _noun); + + noun_query& has_synonyms(bool _arg); + noun_query& synonym_of(const noun& _noun); + noun_query& not_synonym_of(const noun& _noun); + + noun_query& has_antonyms(bool _arg); + noun_query& antonym_of(const noun& _noun); + noun_query& not_antonym_of(const noun& _noun); + + noun_query& has_pertainym(bool _arg); + noun_query& anti_pertainym_of(const adjective& _adj); + + noun_query& is_attribute(bool _arg); + noun_query& attribute_of(const adjective& _adj); + + noun_query& derived_from(const word& _w); + noun_query& not_derived_from(const word& _w); + + std::list run() const; + + const static int unlimited = -1; + + private: + const data& _data; + int _limit = unlimited; + bool _random = false; + std::list _rhymes; + std::list _except; + bool _has_prn = false; + + bool _is_hypernym = false; + std::list _hypernym_of; + std::list _not_hypernym_of; + + bool _is_hyponym = false; + std::list _hyponym_of; + std::list _not_hyponym_of; + + bool _is_part_meronym = false; + std::list _part_meronym_of; + std::list _not_part_meronym_of; + + bool _is_substance_meronym = false; + std::list _substance_meronym_of; + std::list _not_substance_meronym_of; + + bool _is_member_meronym = false; + std::list _member_meronym_of; + std::list _not_member_meronym_of; + + bool _is_part_holonym = false; + std::list _part_holonym_of; + std::list _not_part_holonym_of; + + bool _is_substance_holonym = false; + std::list _substance_holonym_of; + std::list _not_substance_holonym_of; + + bool _is_member_holonym = false; + std::list _member_holonym_of; + std::list _not_member_holonym_of; + + bool _is_proper = false; + bool _is_not_proper = false; + std::list _instance_of; + std::list _not_instance_of; + + bool _is_class = false; + std::list _class_of; + std::list _not_class_of; + + bool _has_synonyms = false; + std::list _synonym_of; + std::list _not_synonym_of; + + bool _has_antonyms = false; + std::list _antonym_of; + std::list _not_antonym_of; + + bool _has_pertainym = false; + std::list _anti_pertainym_of; + + bool _is_attribute = false; + std::list _attribute_of; + + std::list _derived_from_adjective; + std::list _not_derived_from_adjective; + std::list _derived_from_adverb; + std::list _not_derived_from_adverb; + std::list _derived_from_noun; + std::list _not_derived_from_noun; + }; + +}; + +#endif /* end of include guard: NOUN_H_24A03C83 */ diff --git a/lib/token.cpp b/lib/token.cpp new file mode 100644 index 0000000..aa8f50e --- /dev/null +++ b/lib/token.cpp @@ -0,0 +1,53 @@ +#include "verbly.h" + +namespace verbly { + + token::token(token::type _type) : _type(_type) + { + + } + + token::type token::token_type() const + { + return _type; + } + + verb_token::verb_token(const class verb& _verb) : token(token::type::verb), _verb(&_verb) + { + + } + + const class verb& verb_token::verb() const + { + return *_verb; + } + + verb_token& verb_token::inflect(verb_token::inflection infl) + { + _inflection = infl; + return *this; + } + + bool verb_token::complete() const + { + return true; + } + + std::string verb_token::compile() const + { + switch (_inflection) + { + case inflection::infinitive: return _verb->infinitive_form(); + case inflection::past_tense: return _verb->past_tense_form(); + case inflection::past_participle: return _verb->past_participle_form(); + case inflection::ing_form: return _verb->ing_form(); + case inflection::s_form: return _verb->s_form(); + } + } + + token* verb_token::copy() const + { + return new verb_token(*this); + } + +}; diff --git a/lib/token.h b/lib/token.h new file mode 100644 index 0000000..44d99cb --- /dev/null +++ b/lib/token.h @@ -0,0 +1,313 @@ +#ifndef TOKEN_H_AD62C505 +#define TOKEN_H_AD62C505 + +#include +#include +#include + +namespace verbly { + + class verb; + + class selrestr { + }; + + class synrestr { + }; + + enum class fillin_type { + noun_phrase, + participle_phrase, + adjective, + adverb + }; + + class token { + public: + enum class type { + verb, + fillin, + string, + utterance + }; + + protected: + // General + type _type; + + token(type _type); + + public: + enum type token_type() const; + + virtual bool complete() const = 0; + virtual std::string compile() const = 0; + virtual token* copy() const = 0; + }; + + class verb_token : public token { + public: + enum class inflection { + infinitive, + past_tense, + past_participle, + ing_form, + s_form + }; + + private: + // Verb + const verb* _verb; + inflection _inflection = inflection::infinitive; + + public: + verb_token(const class verb& _verb); + + const class verb& verb() const; + + verb_token& inflect(inflection infl); + + bool complete() const; + + std::string compile() const; + + token* copy() const; + }; + + class utterance_token : public token { + private: + // Utterance + std::list> utterance; + + public: + typedef std::list>::iterator iterator; + /*class iterator { + private: + friend class utterance_token; + + std::list>::iterator it; + + public: + iterator(std::list>::iterator it) : it(it) + { + + } + + iterator& operator++() + { + ++it; + return *this; + } + + iterator& operator--() + { + --it; + return *this; + } + + bool operator==(const iterator& other) const + { + return it == other.it; + } + + bool operator!=(const iterator& other) const + { + return it != other.it; + } + + token& operator*() + { + return **it; + } + + token& operator->() + { + return **it; + } + };*/ + + utterance_token(std::initializer_list tkns) : token(token::type::utterance) + { + for (auto tkn : tkns) + { + utterance.push_back(std::unique_ptr(tkn)); + } + } + + utterance_token(const utterance_token& other) : token(token::type::utterance) + { + for (auto& tkn : other.utterance) + { + utterance.push_back(std::unique_ptr(tkn->copy())); + } + } + + utterance_token(utterance_token&& other) : token(token::type::utterance), utterance(std::move(other.utterance)) + { + + } + + utterance_token& operator=(const utterance_token& other) + { + utterance.clear(); + + for (auto& tkn : other.utterance) + { + utterance.push_back(std::unique_ptr(tkn->copy())); + } + + return *this; + } + + utterance_token& operator=(utterance_token&& other) + { + utterance = std::move(other.utterance); + + return *this; + } + + iterator begin() + { + return std::begin(utterance); + } + + iterator end() + { + return std::end(utterance); + } + + void erase(iterator it) + { + utterance.erase(it); + } + + bool complete() const + { + return std::all_of(std::begin(utterance), std::end(utterance), [] (const std::unique_ptr& tkn) { + return tkn->complete(); + }); + } + + std::string compile() const + { + std::stringstream result; + for (auto& t : utterance) + { + if (t->complete()) + { + result << t->compile() << " "; + } else { + return "Could not compile!"; + } + } + + std::string output = result.str(); + if (output != "") + { + output.pop_back(); + } + + return output; + } + + token* copy() const + { + return new utterance_token(*this); + } + }; + + class fillin_token : public token { + private: + // Fillin + std::string m_theme; + fillin_type m_fillin_type; + + public: + fillin_token(fillin_type ft) : token(token::type::fillin), m_fillin_type(ft) + { + + } + +/* void synrestrs(std::initializer_list ins) + { + m_synrestrs = std::set(ins); + } + + std::set& synrestrs() + { + return m_synrestrs; + } + + void selrestrs(std::initializer_list ins) + { + m_selrestrs = std::set(ins); + } + + std::set& selrestrs() + { + return m_selrestrs; + }*/ + + fillin_token theme(std::string theme) + { + m_theme = theme; + + return *this; + } + + std::string& theme() + { + return m_theme; + } + + fillin_type fillin_type() const + { + return m_fillin_type; + } + + bool complete() const + { + return false; + } + + std::string compile() const + { + return ""; + } + + token* copy() const + { + return new fillin_token(*this); + } + }; + + class string_token : public token { + private: + // String + std::string str; + + public: + string_token(std::string str) : token(token::type::string), str(str) + { + + } + + bool complete() const + { + return true; + } + + std::string compile() const + { + return str; + } + + token* copy() const + { + return new string_token(*this); + } + }; + +}; + +#endif /* end of include guard: TOKEN_H_AD62C505 */ diff --git a/lib/util.h b/lib/util.h new file mode 100644 index 0000000..815b47c --- /dev/null +++ b/lib/util.h @@ -0,0 +1,53 @@ +#ifndef UTIL_H_15DDCA2D +#define UTIL_H_15DDCA2D + +#include +#include +#include + +namespace verbly { + + template + std::string implode(InputIterator first, InputIterator last, std::string delimiter) + { + std::stringstream result; + + for (InputIterator it = first; it != last; it++) + { + if (it != first) + { + result << delimiter; + } + + result << *it; + } + + return result.str(); + } + + template + Container split(std::string input, std::string delimiter) + { + Container result; + + while (!input.empty()) + { + int divider = input.find(" "); + if (divider == std::string::npos) + { + result.push_back(input); + + input = ""; + } else { + result.push_back(input.substr(0, divider)); + + input = input.substr(divider+1); + } + } + + return result; + } + +}; + +#endif /* end of include guard: UTIL_H_15DDCA2D */ diff --git a/lib/verb.cpp b/lib/verb.cpp new file mode 100644 index 0000000..23f7c92 --- /dev/null +++ b/lib/verb.cpp @@ -0,0 +1,193 @@ +#include "verbly.h" + +namespace verbly { + + verb::verb(const data& _data, int _id) : word(_data, _id) + { + + } + + std::string verb::base_form() const + { + return _infinitive; + } + + std::string verb::infinitive_form() const + { + return _infinitive; + } + + std::string verb::past_tense_form() const + { + return _past_tense; + } + + std::string verb::past_participle_form() const + { + return _past_participle; + } + + std::string verb::ing_form() const + { + return _ing_form; + } + + std::string verb::s_form() const + { + return _s_form; + } + + verb_query::verb_query(const data& _data) : _data(_data) + { + + } + + verb_query& verb_query::limit(int _limit) + { + if ((_limit > 0) || (_limit == unlimited)) + { + this->_limit = _limit; + } + + return *this; + } + + verb_query& verb_query::random(bool _random) + { + this->_random = _random; + + return *this; + } + + verb_query& verb_query::except(const verb& _word) + { + _except.push_back(_word); + + return *this; + } + + verb_query& verb_query::rhymes_with(const word& _word) + { + for (auto rhyme : _word.rhyme_phonemes()) + { + _rhymes.push_back(rhyme); + } + + if (dynamic_cast(&_word) != nullptr) + { + _except.push_back(dynamic_cast(_word)); + } + + return *this; + } + + verb_query& verb_query::has_pronunciation(bool _has_prn) + { + this->_has_prn = _has_prn; + + return *this; + } + + std::list verb_query::run() const + { + std::stringstream construct; + construct << "SELECT verb_id, infinitive, past_tense, past_participle, ing_form, s_form FROM verbs"; + std::list conditions; + + if (_has_prn) + { + conditions.push_back("verb_id IN (SELECT verb_id FROM verb_pronunciations)"); + } + + if (!_rhymes.empty()) + { + std::list clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); + std::string cond = "verb_id IN (SELECT verb_id FROM verb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + for (auto except : _except) + { + conditions.push_back("verb_id != @EXCID"); + } + + if (!conditions.empty()) + { + construct << " WHERE "; + construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); + } + + if (_random) + { + construct << " ORDER BY RANDOM()"; + } + + if (_limit != unlimited) + { + construct << " LIMIT " << _limit; + } + + sqlite3_stmt* ppstmt; + std::string query = construct.str(); + if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) + { + throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); + } + + if (!_rhymes.empty()) + { + int i = 0; + for (auto rhyme : _rhymes) + { + std::string rhymer = "%" + rhyme; + sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); + + i++; + } + } + + for (auto except : _except) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); + } + + std::list output; + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + verb tnc {_data, sqlite3_column_int(ppstmt, 0)}; + tnc._infinitive = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 1))); + tnc._past_tense = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 2))); + tnc._past_participle = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 3))); + tnc._ing_form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 4))); + tnc._s_form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 5))); + + output.push_back(tnc); + } + + sqlite3_finalize(ppstmt); + + for (auto& verb : output) + { + query = "SELECT pronunciation FROM verb_pronunciations WHERE verb_id = ?"; + if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) + { + throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); + } + + sqlite3_bind_int(ppstmt, 1, verb._id); + + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + std::string pronunciation(reinterpret_cast(sqlite3_column_text(ppstmt, 0))); + auto phonemes = verbly::split>(pronunciation, " "); + + verb.pronunciations.push_back(phonemes); + } + + sqlite3_finalize(ppstmt); + } + + return output; + } + +}; diff --git a/lib/verb.h b/lib/verb.h new file mode 100644 index 0000000..7cc87e2 --- /dev/null +++ b/lib/verb.h @@ -0,0 +1,73 @@ +#ifndef VERB_H_BCC929AD +#define VERB_H_BCC929AD + +namespace verbly { + + /*class frame_part { + + }; + + class frame { + private: + std::list content; + std::map::iterator>> predicates; + + public: + frame(std::list content) : content(content) + { + + } + + std::unique_ptr make_utterance() const + { + + } + };*/ + + class verb : public word { + private: + std::string _infinitive; + std::string _past_tense; + std::string _past_participle; + std::string _ing_form; + std::string _s_form; + + friend class verb_query; + + public: + verb(const data& _data, int _id); + + std::string base_form() const; + std::string infinitive_form() const; + std::string past_tense_form() const; + std::string past_participle_form() const; + std::string ing_form() const; + std::string s_form() const; + }; + + class verb_query { + public: + verb_query(const data& _data); + + verb_query& limit(int _limit); + verb_query& random(bool _random); + verb_query& except(const verb& _word); + verb_query& rhymes_with(const word& _word); + verb_query& has_pronunciation(bool _has_prn); + + std::list run() const; + + const static int unlimited = -1; + + private: + const data& _data; + int _limit = unlimited; + bool _random = false; + std::list _rhymes; + std::list _except; + bool _has_prn = false; + }; + +}; + +#endif /* end of include guard: VERB_H_BCC929AD */ diff --git a/lib/verbly.h b/lib/verbly.h new file mode 100644 index 0000000..b9f5367 --- /dev/null +++ b/lib/verbly.h @@ -0,0 +1,14 @@ +#ifndef VERBLY_H_5B39CE50 +#define VERBLY_H_5B39CE50 + +#include "c++14.h" +#include "util.h" +#include "token.h" +#include "data.h" +#include "word.h" +#include "verb.h" +#include "adverb.h" +#include "adjective.h" +#include "noun.h" + +#endif /* end of include guard: VERBLY_H_5B39CE50 */ diff --git a/lib/word.cpp b/lib/word.cpp new file mode 100644 index 0000000..c50e7d3 --- /dev/null +++ b/lib/word.cpp @@ -0,0 +1,32 @@ +#include "verbly.h" + +namespace verbly { + + word::word(const data& _data, int _id) : _data(_data), _id(_id) + { + + } + + std::list word::rhyme_phonemes() const + { + std::list result; + + for (auto pronunciation : pronunciations) + { + auto phemstrt = std::find_if(std::begin(pronunciation), std::end(pronunciation), [] (std::string phoneme) { + return phoneme.find("1") != std::string::npos; + }); + + std::stringstream rhymer; + for (auto it = phemstrt; it != std::end(pronunciation); it++) + { + rhymer << " " << *it; + } + + result.push_back(rhymer.str()); + } + + return result; + } + +}; diff --git a/lib/word.h b/lib/word.h new file mode 100644 index 0000000..23ddb2b --- /dev/null +++ b/lib/word.h @@ -0,0 +1,35 @@ +#ifndef WORD_H_8FC89498 +#define WORD_H_8FC89498 + +namespace verbly { + + class adjective_query; + class verb_query; + class adverb_query; + + template + class query; + + class word { + protected: + const data& _data; + int _id; + + std::list> pronunciations; + + word(const data& _data, int _id); + + friend class adjective_query; + friend class verb_query; + friend class noun_query; + friend class adverb_query; + + public: + virtual std::string base_form() const = 0; + + std::list rhyme_phonemes() const; + }; + +}; + +#endif /* end of include guard: WORD_H_8FC89498 */ -- cgit 1.4.1